Skip to content

Commit 814a4ee

Browse files
committed
Diagnose attempts to use tuples with noncopyable elements.
These aren't fully supported yet. rdar://108024586
1 parent bd2ff38 commit 814a4ee

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
@@ -5367,6 +5367,8 @@ ERROR(tuple_single_element,none,
53675367
ERROR(tuple_pack_element_label,none,
53685368
"cannot use label with pack expansion tuple element",
53695369
())
5370+
ERROR(tuple_move_only_not_supported,none,
5371+
"tuples with noncopyable elements are not supported", ())
53705372
ERROR(vararg_not_allowed,none,
53715373
"variadic parameter cannot appear outside of a function parameter list",
53725374
())

include/swift/Basic/Features.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ EXPERIMENTAL_FEATURE(MoveOnlyClasses, true)
123123
EXPERIMENTAL_FEATURE(NoImplicitCopy, true)
124124
EXPERIMENTAL_FEATURE(OldOwnershipOperatorSpellings, true)
125125
EXPERIMENTAL_FEATURE(MoveOnlyEnumDeinits, true)
126+
EXPERIMENTAL_FEATURE(MoveOnlyTuples, true)
126127

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

lib/AST/ASTPrinter.cpp

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

3278+
static bool usesFeatureMoveOnlyTuples(Decl *decl) {
3279+
return false;
3280+
}
3281+
32783282
static bool usesFeatureNoImplicitCopy(Decl *decl) {
32793283
return decl->isNoImplicitCopy();
32803284
}

lib/Sema/MiscDiagnostics.cpp

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

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

342348
// 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
@@ -4660,12 +4660,22 @@ NeverNullType TypeResolver::resolveTupleType(TupleTypeRepr *repr,
46604660

46614661
bool hadError = false;
46624662
bool foundDupLabel = false;
4663+
Optional<unsigned> moveOnlyElementIndex = None;
46634664
for (unsigned i = 0, end = repr->getNumElements(); i != end; ++i) {
46644665
auto *tyR = repr->getElementType(i);
46654666

46664667
auto ty = resolveType(tyR, elementOptions);
4667-
if (ty->hasError())
4668+
if (ty->hasError()) {
46684669
hadError = true;
4670+
}
4671+
// Tuples with move-only elements aren't yet supported.
4672+
// Track the presence of a noncopyable field for diagnostic purposes.
4673+
// We don't need to re-diagnose if a tuple contains another tuple, though,
4674+
// since we should've diagnosed the inner tuple already.
4675+
if (ty->isPureMoveOnly() && !moveOnlyElementIndex.has_value()
4676+
&& !isa<TupleTypeRepr>(tyR)) {
4677+
moveOnlyElementIndex = i;
4678+
}
46694679

46704680
auto eltName = repr->getElementName(i);
46714681

@@ -4714,6 +4724,13 @@ NeverNullType TypeResolver::resolveTupleType(TupleTypeRepr *repr,
47144724
!elements[0].getType()->is<PackExpansionType>())
47154725
return ParenType::get(ctx, elements[0].getType());
47164726
}
4727+
4728+
if (moveOnlyElementIndex.has_value()
4729+
&& !options.contains(TypeResolutionFlags::SILType)
4730+
&& !ctx.LangOpts.hasFeature(Feature::MoveOnlyTuples)) {
4731+
diagnose(repr->getElementType(*moveOnlyElementIndex)->getLoc(),
4732+
diag::tuple_move_only_not_supported);
4733+
}
47174734

47184735
return TupleType::get(elements, ctx);
47194736
}

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)