Skip to content

Commit 52e97d6

Browse files
committed
Diagnose attempts to use tuples with noncopyable elements.
These aren't fully supported yet. rdar://108024586
1 parent 159385e commit 52e97d6

File tree

9 files changed

+65
-7
lines changed

9 files changed

+65
-7
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5372,6 +5372,8 @@ ERROR(tuple_single_element,none,
53725372
ERROR(tuple_pack_element_label,none,
53735373
"cannot use label with pack expansion tuple element",
53745374
())
5375+
ERROR(tuple_move_only_not_supported,none,
5376+
"tuples with noncopyable elements are not supported", ())
53755377
ERROR(vararg_not_allowed,none,
53765378
"variadic parameter cannot appear outside of a function parameter list",
53775379
())

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ EXPERIMENTAL_FEATURE(MoveOnlyClasses, true)
122122
EXPERIMENTAL_FEATURE(NoImplicitCopy, true)
123123
EXPERIMENTAL_FEATURE(OldOwnershipOperatorSpellings, true)
124124
EXPERIMENTAL_FEATURE(MoveOnlyEnumDeinits, true)
125+
EXPERIMENTAL_FEATURE(MoveOnlyTuples, true)
125126

126127
EXPERIMENTAL_FEATURE(OneWayClosureParameters, false)
127128
EXPERIMENTAL_FEATURE(TypeWitnessSystemInference, false)

lib/AST/ASTPrinter.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3271,6 +3271,10 @@ static bool usesFeatureMoveOnlyClasses(Decl *decl) {
32713271
return isa<ClassDecl>(decl) && usesFeatureMoveOnly(decl);
32723272
}
32733273

3274+
static bool usesFeatureMoveOnlyTuples(Decl *decl) {
3275+
return false;
3276+
}
3277+
32743278
static bool usesFeatureNoImplicitCopy(Decl *decl) {
32753279
return decl->isNoImplicitCopy();
32763280
}

lib/Sema/MiscDiagnostics.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,10 +334,16 @@ static void diagSyntacticUseRestrictions(const Expr *E, const DeclContext *DC,
334334
}
335335
}
336336

337-
// Diagnose tuple expressions with duplicate element label.
338337
if (auto *tupleExpr = dyn_cast<TupleExpr>(E)) {
338+
// Diagnose tuple expressions with duplicate element label.
339339
diagnoseDuplicateLabels(tupleExpr->getLoc(),
340340
tupleExpr->getElementNames());
341+
342+
// Diagnose attempts to form a tuple with any noncopyable elements.
343+
if (E->getType()->isPureMoveOnly()
344+
&& !Ctx.LangOpts.hasFeature(Feature::MoveOnlyTuples)) {
345+
Ctx.Diags.diagnose(E->getLoc(), diag::tuple_move_only_not_supported);
346+
}
341347
}
342348

343349
// Specially diagnose some checked casts that are illegal.

lib/Sema/TypeCheckType.cpp

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4668,12 +4668,22 @@ NeverNullType TypeResolver::resolveTupleType(TupleTypeRepr *repr,
46684668

46694669
bool hadError = false;
46704670
bool foundDupLabel = false;
4671+
Optional<unsigned> moveOnlyElementIndex = None;
46714672
for (unsigned i = 0, end = repr->getNumElements(); i != end; ++i) {
46724673
auto *tyR = repr->getElementType(i);
46734674

46744675
auto ty = resolveType(tyR, elementOptions);
4675-
if (ty->hasError())
4676+
if (ty->hasError()) {
46764677
hadError = true;
4678+
}
4679+
// Tuples with move-only elements aren't yet supported.
4680+
// Track the presence of a noncopyable field for diagnostic purposes.
4681+
// We don't need to re-diagnose if a tuple contains another tuple, though,
4682+
// since we should've diagnosed the inner tuple already.
4683+
if (ty->isPureMoveOnly() && !moveOnlyElementIndex.has_value()
4684+
&& !isa<TupleTypeRepr>(tyR)) {
4685+
moveOnlyElementIndex = i;
4686+
}
46774687

46784688
auto eltName = repr->getElementName(i);
46794689

@@ -4722,6 +4732,13 @@ NeverNullType TypeResolver::resolveTupleType(TupleTypeRepr *repr,
47224732
!elements[0].getType()->is<PackExpansionType>())
47234733
return ParenType::get(ctx, elements[0].getType());
47244734
}
4735+
4736+
if (moveOnlyElementIndex.has_value()
4737+
&& !options.contains(TypeResolutionFlags::SILType)
4738+
&& !ctx.LangOpts.hasFeature(Feature::MoveOnlyTuples)) {
4739+
diagnose(repr->getElementType(*moveOnlyElementIndex)->getLoc(),
4740+
diag::tuple_move_only_not_supported);
4741+
}
47254742

47264743
return TupleType::get(elements, ctx);
47274744
}

test/Constraints/moveonly_constraints.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,7 @@ func checkStdlibTypes(_ mo: __shared MO) {
226226
let _: [MO] = // expected-error {{move-only type 'MO' cannot be used with generics yet}}
227227
[]
228228
let _: [String: MO] = // expected-error {{move-only type 'MO' cannot be used with generics yet}}
229-
["hello" : MO()]
229+
["hello" : MO()] // expected-error{{tuples with noncopyable elements are not supported}}
230230

231231
// i think this one's only caught b/c of the 'Any' change
232232
_ = [MO()] // expected-error {{move-only type 'MO' cannot be used with generics yet}}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// RUN: %target-swift-frontend -typecheck -verify %s
2+
3+
// Tuples with noncopyable elements are not yet supported. Make sure we reject
4+
// them when code attempts to form such a type explicitly or by inference.
5+
6+
@_moveOnly struct Butt {
7+
var x: Int
8+
}
9+
10+
@_moveOnly
11+
struct Foo {
12+
var t: (Int, Butt) // expected-error{{tuples with noncopyable elements are not supported}}
13+
}
14+
@_moveOnly
15+
struct Bar<T> {
16+
var t: (T, Butt) // expected-error{{tuples with noncopyable elements are not supported}}
17+
var u: (Int, (T, Butt)) // expected-error{{tuples with noncopyable elements are not supported}}
18+
}
19+
20+
func inferredTuples<T>(x: Int, y: borrowing Butt, z: T) {
21+
let a = (x, y) // expected-error{{tuples with noncopyable elements are not supported}}
22+
let b = (y, z) // expected-error{{tuples with noncopyable elements are not supported}}
23+
let c = (x, y, z) // expected-error{{tuples with noncopyable elements are not supported}}
24+
_ = a
25+
_ = b
26+
_ = c
27+
}

test/Interpreter/moveonly.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,6 @@ Tests.test("global destroyed once") {
4848
expectEqual(0, LifetimeTracked.instances)
4949
}
5050

51-
// TODO (rdar://107494072): Move-only types with deinits declared inside
52-
// functions sometimes lose their deinit function.
53-
// When that's fixed, FD2 can be moved back inside the test closure below.
5451
@_moveOnly
5552
struct FD2 {
5653
var field = 5
@@ -83,6 +80,10 @@ Tests.test("deinit not called in init when assigned") {
8380
}
8481
}
8582

83+
do {
84+
let haver = FDHaver()
85+
let _ = haver
86+
}
8687
do {
8788
let haver = FDHaver2()
8889
let _ = haver

test/SILOptimizer/moveonly_addresschecker_destructure_through_deinit_diagnostics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-emit-sil -sil-verify-all -verify -enable-experimental-feature MoveOnlyClasses %s
1+
// RUN: %target-swift-emit-sil -sil-verify-all -verify -enable-experimental-feature MoveOnlyClasses -enable-experimental-feature MoveOnlyTuples %s
22

33
// This test validates that we properly emit errors if we partially invalidate
44
// through a type with a deinit.

0 commit comments

Comments
 (0)