From 1781faba1aa35bf0ebd7b50e9b4639502bcba304 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Wed, 29 Oct 2025 15:14:23 +0000 Subject: [PATCH 1/4] [CS] Upgrade tuple label mismatch warning to error for future lang mode I missed upgrading this to an error for Swift 6 mode, let's upgrade it to an error for a future language mode. It's important we reject these cases since we're otherwise allowing subtyping to be a weaker constraint than conversion. --- include/swift/AST/DiagnosticsSema.def | 6 ++-- include/swift/Sema/CSFix.h | 3 +- lib/Sema/CSDiagnostics.cpp | 5 +-- lib/Sema/CSDiagnostics.h | 3 +- test/Constraints/tuple.swift | 21 ------------ .../tuple_subtype_label_mismatch.swift | 33 +++++++++++++++++++ 6 files changed, 43 insertions(+), 28 deletions(-) create mode 100644 test/Constraints/tuple_subtype_label_mismatch.swift diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 87d6440a32e15..b5466173068c4 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -1586,9 +1586,9 @@ WARNING(coercion_may_fail_warning,none, "coercion from %0 to %1 may fail; use 'as?' or 'as!' instead", (Type, Type)) -WARNING(tuple_label_mismatch_warning,none, - "tuple conversion from %0 to %1 mismatches labels", - (Type, Type)) +ERROR(tuple_label_mismatch,none, + "tuple conversion from %0 to %1 mismatches labels", + (Type, Type)) ERROR(missing_explicit_conversion,none, "%0 is not implicitly convertible to %1; " diff --git a/include/swift/Sema/CSFix.h b/include/swift/Sema/CSFix.h index 0955ec9868816..e347c4a6877ba 100644 --- a/include/swift/Sema/CSFix.h +++ b/include/swift/Sema/CSFix.h @@ -3458,7 +3458,8 @@ class AllowInvalidStaticMemberRefOnProtocolMetatype final } }; -/// Emit a warning for mismatched tuple labels. +/// Emit a warning for mismatched tuple labels, which is upgraded to an error +/// for a future language mode. class AllowTupleLabelMismatch final : public ContextualMismatch { AllowTupleLabelMismatch(ConstraintSystem &cs, Type fromType, Type toType, ConstraintLocator *locator) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 78498d1ec9691..975b57d9125d2 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -9419,8 +9419,9 @@ bool InvalidWeakAttributeUse::diagnoseAsError() { } bool TupleLabelMismatchWarning::diagnoseAsError() { - emitDiagnostic(diag::tuple_label_mismatch_warning, getFromType(), getToType()) - .highlight(getSourceRange()); + emitDiagnostic(diag::tuple_label_mismatch, getFromType(), getToType()) + .highlight(getSourceRange()) + .warnUntilFutureSwiftVersion(); return true; } diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index b1816b51d2b21..f25f798adedbf 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -3009,7 +3009,8 @@ class InvalidWeakAttributeUse final : public FailureDiagnostic { bool diagnoseAsError() override; }; -/// Emit a warning for mismatched tuple labels. +/// Emit a warning for mismatched tuple labels, which is upgraded to an error +/// for a future language mode. class TupleLabelMismatchWarning final : public ContextualFailure { public: TupleLabelMismatchWarning(const Solution &solution, Type fromType, diff --git a/test/Constraints/tuple.swift b/test/Constraints/tuple.swift index 51187eed1be35..7d7952a424d4a 100644 --- a/test/Constraints/tuple.swift +++ b/test/Constraints/tuple.swift @@ -342,27 +342,6 @@ optionalTuple = (bignum, 1) // expected-error {{cannot assign value of type '(In optionalTuple = optionalTuple2 // expected-error {{cannot assign value of type '(Int64, Int)?' to type '(Int, Int)?'}} // expected-note@-1 {{arguments to generic parameter 'Wrapped' ('(Int64, Int)' and '(Int, Int)') are expected to be equal}} -func testTupleLabelMismatchFuncConversion(fn1: @escaping ((x: Int, y: Int)) -> Void, - fn2: @escaping () -> (x: Int, Int)) { - // Warn on mismatches - let _: ((a: Int, b: Int)) -> Void = fn1 // expected-warning {{tuple conversion from '(a: Int, b: Int)' to '(x: Int, y: Int)' mismatches labels}} - let _: ((x: Int, b: Int)) -> Void = fn1 // expected-warning {{tuple conversion from '(x: Int, b: Int)' to '(x: Int, y: Int)' mismatches labels}} - - let _: () -> (y: Int, Int) = fn2 // expected-warning {{tuple conversion from '(x: Int, Int)' to '(y: Int, Int)' mismatches labels}} - let _: () -> (y: Int, k: Int) = fn2 // expected-warning {{tuple conversion from '(x: Int, Int)' to '(y: Int, k: Int)' mismatches labels}} - - // Attempting to shuffle has always been illegal here - let _: () -> (y: Int, x: Int) = fn2 // expected-error {{cannot convert value of type '() -> (x: Int, Int)' to specified type '() -> (y: Int, x: Int)'}} - - // Losing labels is okay though. - let _: () -> (Int, Int) = fn2 - - // Gaining labels also okay. - let _: ((x: Int, Int)) -> Void = fn1 - let _: () -> (x: Int, y: Int) = fn2 - let _: () -> (Int, y: Int) = fn2 -} - func testTupleLabelMismatchKeyPath() { // FIXME: The warning should be upgraded to an error for key paths. let _: KeyPath<(x: Int, y: Int), Int> = \(a: Int, b: Int).x diff --git a/test/Constraints/tuple_subtype_label_mismatch.swift b/test/Constraints/tuple_subtype_label_mismatch.swift new file mode 100644 index 0000000000000..55d8edd0091b3 --- /dev/null +++ b/test/Constraints/tuple_subtype_label_mismatch.swift @@ -0,0 +1,33 @@ +// RUN: %target-typecheck-verify-swift -language-mode 6 -verify-additional-prefix swift6- +// RUN: %target-typecheck-verify-swift -language-mode 7 -verify-additional-prefix swift7- +// REQUIRES: swift7 + +func testTupleLabelMismatchFuncConversion(fn1: @escaping ((x: Int, y: Int)) -> Void, + fn2: @escaping () -> (x: Int, Int)) { + // Warn on mismatches in Swift 6, upgrading to an error for Swift 7 + let _: ((a: Int, b: Int)) -> Void = fn1 + // expected-swift6-warning@-1 {{tuple conversion from '(a: Int, b: Int)' to '(x: Int, y: Int)' mismatches labels}} + // expected-swift7-error@-2 {{tuple conversion from '(a: Int, b: Int)' to '(x: Int, y: Int)' mismatches labels}} + let _: ((x: Int, b: Int)) -> Void = fn1 + // expected-swift6-warning@-1 {{tuple conversion from '(x: Int, b: Int)' to '(x: Int, y: Int)' mismatches labels}} + // expected-swift7-error@-2 {{tuple conversion from '(x: Int, b: Int)' to '(x: Int, y: Int)' mismatches labels}} + + let _: () -> (y: Int, Int) = fn2 + // expected-swift6-warning@-1 {{tuple conversion from '(x: Int, Int)' to '(y: Int, Int)' mismatches labels}} + // expected-swift7-error@-2 {{tuple conversion from '(x: Int, Int)' to '(y: Int, Int)' mismatches labels}} + let _: () -> (y: Int, k: Int) = fn2 + // expected-swift6-warning@-1 {{tuple conversion from '(x: Int, Int)' to '(y: Int, k: Int)' mismatches labels}} + // expected-swift7-error@-2 {{tuple conversion from '(x: Int, Int)' to '(y: Int, k: Int)' mismatches labels}} + + // Attempting to shuffle has always been illegal here + let _: () -> (y: Int, x: Int) = fn2 + // expected-error@-1 {{cannot convert value of type '() -> (x: Int, Int)' to specified type '() -> (y: Int, x: Int)'}} + + // Losing labels is okay though. + let _: () -> (Int, Int) = fn2 + + // Gaining labels also okay. + let _: ((x: Int, Int)) -> Void = fn1 + let _: () -> (x: Int, y: Int) = fn2 + let _: () -> (Int, y: Int) = fn2 +} From 6510eb024a9b43295c18fa60b42e6bb487b19277 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Wed, 29 Oct 2025 15:14:23 +0000 Subject: [PATCH 2/4] [test] Fix indentation in `tuple_shuffle.swift` --- test/Constraints/tuple_shuffle.swift | 48 ++++++++++++++-------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/test/Constraints/tuple_shuffle.swift b/test/Constraints/tuple_shuffle.swift index 2d27f19cf6770..dce2d5890c7e1 100644 --- a/test/Constraints/tuple_shuffle.swift +++ b/test/Constraints/tuple_shuffle.swift @@ -1,31 +1,31 @@ // RUN: %target-typecheck-verify-swift -swift-version 5 - func consume(_ x: T) {} // Suppress unused variable warnings +func consume(_ x: T) {} // Suppress unused variable warnings - func shuffle_through_initialization() { - let a = (x: 1, y: 2) - let b: (y: Int, x: Int) - b = a // expected-warning {{expression shuffles the elements of this tuple}} - consume(b) - } +func shuffle_through_initialization() { + let a = (x: 1, y: 2) + let b: (y: Int, x: Int) + b = a // expected-warning {{expression shuffles the elements of this tuple}} + consume(b) +} - func shuffle_through_destructuring() { - let a = (x: 1, y: 2) - let (y: b, x: c) = a // expected-warning {{expression shuffles the elements of this tuple}} - consume((b, c)) - } +func shuffle_through_destructuring() { + let a = (x: 1, y: 2) + let (y: b, x: c) = a // expected-warning {{expression shuffles the elements of this tuple}} + consume((b, c)) +} - func shuffle_through_call() { - func foo(_ : (x: Int, y: Int)) {} - foo((y: 5, x: 10)) // expected-warning {{expression shuffles the elements of this tuple}} - } +func shuffle_through_call() { + func foo(_ : (x: Int, y: Int)) {} + foo((y: 5, x: 10)) // expected-warning {{expression shuffles the elements of this tuple}} +} - func shuffle_through_cast() { - let x = ((a: Int(), b: Int()) as (b: Int, a: Int)).0 // expected-warning {{expression shuffles the elements of this tuple}} +func shuffle_through_cast() { + let x = ((a: Int(), b: Int()) as (b: Int, a: Int)).0 // expected-warning {{expression shuffles the elements of this tuple}} - // Ah, the famous double-shuffle - let (c1, (c2, c3)): (c: Int, (b: Int, a: Int)) = ((a: Int(), b: Int()), c: Int()) - // expected-warning@-1 {{expression shuffles the elements of this tuple}} - // expected-warning@-2 {{expression shuffles the elements of this tuple}} - consume((x, c1, c2, c3)) - } + // Ah, the famous double-shuffle + let (c1, (c2, c3)): (c: Int, (b: Int, a: Int)) = ((a: Int(), b: Int()), c: Int()) + // expected-warning@-1 {{expression shuffles the elements of this tuple}} + // expected-warning@-2 {{expression shuffles the elements of this tuple}} + consume((x, c1, c2, c3)) +} From 24347812f50127c70c3696a31c5baddc93867eef Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Wed, 29 Oct 2025 15:14:23 +0000 Subject: [PATCH 3/4] [Diag] Reword the tuple shuffle diagnostic "reorder" seems a bit less jargony than "shuffle", and include the labels that are being reordered. --- include/swift/AST/DiagnosticsSema.def | 6 ++--- lib/Sema/CSApply.cpp | 24 +++++++++++++++---- test/Constraints/tuple_shuffle.swift | 17 ++++++++----- test/Parse/omit_return.swift | 2 +- test/Parse/omit_return_ifdecl.swift | 2 +- .../diag_unowned_immediate_deallocation.swift | 6 ++--- test/decl/func/operator.swift | 2 +- test/expr/closure/closures.swift | 2 +- test/expr/expressions.swift | 2 +- 9 files changed, 42 insertions(+), 21 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index b5466173068c4..490f47411926e 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -7833,9 +7833,9 @@ ERROR(result_builder_buildpartialblock_accumulated_not_accessible,none, // MARK: Tuple Shuffle Diagnostics //------------------------------------------------------------------------------ - WARNING(warn_reordering_tuple_shuffle_deprecated,Deprecation, - "expression shuffles the elements of this tuple; " - "this behavior is deprecated", ()) +WARNING(warn_reordering_tuple_shuffle_deprecated,Deprecation, + "implicit reordering of tuple elements from '%0' to '%1' is deprecated", + (StringRef, StringRef)) //------------------------------------------------------------------------------ // MARK: Implicit conversion diagnostics diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index e6de2b0a5a83a..8494b99b3c560 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -5818,6 +5818,7 @@ Expr *ExprRewriter::coerceTupleToTuple(Expr *expr, // Convert each OpaqueValueExpr to the correct type. SmallVector converted; + SmallVector origLabels; SmallVector labels; SmallVector convertedElts; @@ -5825,6 +5826,7 @@ Expr *ExprRewriter::coerceTupleToTuple(Expr *expr, for (unsigned i = 0, e = sources.size(); i != e; ++i) { unsigned source = sources[i]; auto *fromElt = destructured[source]; + auto fromLabel = fromTuple->getElement(i).getName(); // Actually convert the source element. auto toEltType = toTuple->getElementType(i); @@ -5832,8 +5834,7 @@ Expr *ExprRewriter::coerceTupleToTuple(Expr *expr, // If we're shuffling positions and labels, we have to warn about this // conversion. - if (i != sources[i] && - fromTuple->getElement(i).getName() != toLabel) + if (i != sources[i] && fromLabel != toLabel) anythingShuffled = true; auto *toElt @@ -5845,6 +5846,7 @@ Expr *ExprRewriter::coerceTupleToTuple(Expr *expr, converted.push_back(toElt); labels.push_back(toLabel); + origLabels.push_back(fromLabel); convertedElts.emplace_back(toEltType, toLabel); } @@ -5852,8 +5854,22 @@ Expr *ExprRewriter::coerceTupleToTuple(Expr *expr, // will form the shuffle for now, but a future compiler should decline to // do so and begin the process of removing them altogether. if (anythingShuffled) { - ctx.Diags.diagnose( - expr->getLoc(), diag::warn_reordering_tuple_shuffle_deprecated); + auto concatLabels = [](SmallVectorImpl &labels, + SmallVectorImpl &out) { + llvm::raw_svector_ostream OS(out); + for (auto label : labels) { + DeclName(label).print(OS, /*skipEmpty*/ false, /*escapeIfNeeded*/ true); + OS << ':'; + } + }; + SmallString<16> fromLabelStr; + concatLabels(origLabels, fromLabelStr); + SmallString<16> toLabelStr; + concatLabels(labels, toLabelStr); + + ctx.Diags.diagnose(expr->getLoc(), + diag::warn_reordering_tuple_shuffle_deprecated, + fromLabelStr, toLabelStr); } // Create the result tuple, written in terms of the destructured diff --git a/test/Constraints/tuple_shuffle.swift b/test/Constraints/tuple_shuffle.swift index dce2d5890c7e1..5c50c554fc0b3 100644 --- a/test/Constraints/tuple_shuffle.swift +++ b/test/Constraints/tuple_shuffle.swift @@ -5,27 +5,32 @@ func consume(_ x: T) {} // Suppress unused variable warnings func shuffle_through_initialization() { let a = (x: 1, y: 2) let b: (y: Int, x: Int) - b = a // expected-warning {{expression shuffles the elements of this tuple}} + b = a // expected-warning {{implicit reordering of tuple elements from 'x:y:' to 'y:x:' is deprecated}} consume(b) } +func shuffle_raw_label(_ t: (`a b`: Int, `c d`: Int)) { + let _: (`c d`: Int, `a b`: Int) = t + // expected-warning@-1 {{implicit reordering of tuple elements from '`a b`:`c d`:' to '`c d`:`a b`:' is deprecated}} +} + func shuffle_through_destructuring() { let a = (x: 1, y: 2) - let (y: b, x: c) = a // expected-warning {{expression shuffles the elements of this tuple}} + let (y: b, x: c) = a // expected-warning {{implicit reordering of tuple elements from 'x:y:' to 'y:x:' is deprecated}} consume((b, c)) } func shuffle_through_call() { func foo(_ : (x: Int, y: Int)) {} - foo((y: 5, x: 10)) // expected-warning {{expression shuffles the elements of this tuple}} + foo((y: 5, x: 10)) // expected-warning {{implicit reordering of tuple elements from 'y:x:' to 'x:y:' is deprecated}} } func shuffle_through_cast() { - let x = ((a: Int(), b: Int()) as (b: Int, a: Int)).0 // expected-warning {{expression shuffles the elements of this tuple}} + let x = ((a: Int(), b: Int()) as (b: Int, a: Int)).0 // expected-warning {{implicit reordering of tuple elements from 'a:b:' to 'b:a:' is deprecated}} // Ah, the famous double-shuffle let (c1, (c2, c3)): (c: Int, (b: Int, a: Int)) = ((a: Int(), b: Int()), c: Int()) - // expected-warning@-1 {{expression shuffles the elements of this tuple}} - // expected-warning@-2 {{expression shuffles the elements of this tuple}} + // expected-warning@-1 {{implicit reordering of tuple elements from 'a:b:' to 'b:a:' is deprecated}} + // expected-warning@-2 {{implicit reordering of tuple elements from '_:c:' to 'c:_:' is deprecated}} consume((x, c1, c2, c3)) } diff --git a/test/Parse/omit_return.swift b/test/Parse/omit_return.swift index e18d8e0d67221..a7fef807d2a88 100644 --- a/test/Parse/omit_return.swift +++ b/test/Parse/omit_return.swift @@ -474,7 +474,7 @@ func ff_implicitInjectIntoOptionalExpr(_ int: Int) -> Int? { } func ff_implicitTupleShuffle(_ input: (one: Int, two: Int)) -> (two: Int, one: Int) { - input // expected-warning {{expression shuffles the elements of this tuple; this behavior is deprecated}} + input // expected-warning {{implicit reordering of tuple elements from 'one:two:' to 'two:one:' is deprecated}} } func ff_implicitCollectionUpcast(_ derived: [Derived]) -> [Base] { diff --git a/test/Parse/omit_return_ifdecl.swift b/test/Parse/omit_return_ifdecl.swift index 27dd699806962..3269644284c66 100644 --- a/test/Parse/omit_return_ifdecl.swift +++ b/test/Parse/omit_return_ifdecl.swift @@ -676,7 +676,7 @@ func ff_implicitInjectIntoOptionalExpr(_ int: Int) -> Int? { func ff_implicitTupleShuffle(_ input: (one: Int, two: Int)) -> (two: Int, one: Int) { #if true - input // expected-warning {{expression shuffles the elements of this tuple; this behavior is deprecated}} + input // expected-warning {{implicit reordering of tuple elements from 'one:two:' to 'two:one:' is deprecated}} #endif } diff --git a/test/Sema/diag_unowned_immediate_deallocation.swift b/test/Sema/diag_unowned_immediate_deallocation.swift index 315a23c9e989c..a21cf0c58fa2f 100644 --- a/test/Sema/diag_unowned_immediate_deallocation.swift +++ b/test/Sema/diag_unowned_immediate_deallocation.swift @@ -452,10 +452,10 @@ func testGenericWeakClassDiag() { // The diagnostic doesn't currently support tuple shuffles. func testDontDiagnoseThroughTupleShuffles() { unowned let (c1, (c2, c3)): (c: C, (b: C, a: C)) = ((a: D(), b: C()), c: D()) - // expected-warning@-1 {{expression shuffles the elements of this tuple; this behavior is deprecated}} - // expected-warning@-2 {{expression shuffles the elements of this tuple; this behavior is deprecated}} + // expected-warning@-1 {{implicit reordering of tuple elements from 'a:b:' to 'b:a:' is deprecated}} + // expected-warning@-2 {{implicit reordering of tuple elements from '_:c:' to 'c:_:' is deprecated}} unowned let c4 = ((a: C(), b: C()) as (b: C, a: C)).0 - // expected-warning@-1 {{expression shuffles the elements of this tuple; this behavior is deprecated}} + // expected-warning@-1 {{implicit reordering of tuple elements from 'a:b:' to 'b:a:' is deprecated}} _ = c1; _ = c2; _ = c3; _ = c4 } diff --git a/test/decl/func/operator.swift b/test/decl/func/operator.swift index d6f9f04b471a3..269b0408548b0 100644 --- a/test/decl/func/operator.swift +++ b/test/decl/func/operator.swift @@ -155,7 +155,7 @@ var f2 : (Int) -> Int = (+-+) var f3 : (inout Int) -> Int = (-+-) // expected-error{{ambiguous use of operator '-+-'}} var f4 : (inout Int, Int) -> Int = (+-+=) var r5 : (a : (Int, Int) -> Int, b : (Int, Int) -> Int) = (+, -) -var r6 : (a : (Int, Int) -> Int, b : (Int, Int) -> Int) = (b : +, a : -) // expected-warning {{expression shuffles the elements of this tuple; this behavior is deprecated}} +var r6 : (a : (Int, Int) -> Int, b : (Int, Int) -> Int) = (b : +, a : -) // expected-warning {{implicit reordering of tuple elements from 'b:a:' to 'a:b:' is deprecated}} struct f6_S { subscript(op : (Int, Int) -> Int) -> Int { diff --git a/test/expr/closure/closures.swift b/test/expr/closure/closures.swift index 8e13cfd346726..eb84ee636bb6c 100644 --- a/test/expr/closure/closures.swift +++ b/test/expr/closure/closures.swift @@ -56,7 +56,7 @@ func funcdecl5(_ a: Int, _ y: Int) { var b = a.1+a.f // Tuple expressions with named elements. - var i : (y : Int, x : Int) = (x : 42, y : 11) // expected-warning {{expression shuffles the elements of this tuple; this behavior is deprecated}} + var i : (y : Int, x : Int) = (x : 42, y : 11) // expected-warning {{implicit reordering of tuple elements from 'x:y:' to 'y:x:' is deprecated}} funcdecl1(123, 444) // Calls. diff --git a/test/expr/expressions.swift b/test/expr/expressions.swift index 878b73a439553..1532b7b47e1c3 100644 --- a/test/expr/expressions.swift +++ b/test/expr/expressions.swift @@ -194,7 +194,7 @@ func test5() { let c: (a: Int, b: Int) = (1,2) - let _: (b: Int, a: Int) = c // expected-warning {{expression shuffles the elements of this tuple; this behavior is deprecated}} + let _: (b: Int, a: Int) = c // expected-warning {{implicit reordering of tuple elements from 'a:b:' to 'b:a:' is deprecated}} } From 00d8774032cf700de6934fc5f976f75426b4d4a0 Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Wed, 29 Oct 2025 15:14:23 +0000 Subject: [PATCH 4/4] [Sema] Upgrade tuple shuffle warning to error in future lang mode This has been deprecated for a while now, flip it to an error for a future language mode. --- include/swift/AST/DiagnosticsSema.def | 7 ++++- lib/Sema/CSApply.cpp | 12 ++++++-- test/Constraints/tuple_shuffle.swift | 30 ++++++++++++++----- test/Parse/omit_return.swift | 2 +- test/Parse/omit_return_ifdecl.swift | 2 +- .../diag_unowned_immediate_deallocation.swift | 6 ++-- test/decl/func/operator.swift | 2 +- test/expr/closure/closures.swift | 2 +- test/expr/expressions.swift | 2 +- 9 files changed, 45 insertions(+), 20 deletions(-) diff --git a/include/swift/AST/DiagnosticsSema.def b/include/swift/AST/DiagnosticsSema.def index 490f47411926e..4b95dc4fcf6e9 100644 --- a/include/swift/AST/DiagnosticsSema.def +++ b/include/swift/AST/DiagnosticsSema.def @@ -7833,8 +7833,13 @@ ERROR(result_builder_buildpartialblock_accumulated_not_accessible,none, // MARK: Tuple Shuffle Diagnostics //------------------------------------------------------------------------------ +ERROR(reordering_tuple_shuffle,none, + "cannot implicitly reorder tuple elements from '%0' to '%1'", + (StringRef, StringRef)) + WARNING(warn_reordering_tuple_shuffle_deprecated,Deprecation, - "implicit reordering of tuple elements from '%0' to '%1' is deprecated", + "implicit reordering of tuple elements from '%0' to '%1' is deprecated" + "; this will be an error in a future Swift language mode", (StringRef, StringRef)) //------------------------------------------------------------------------------ diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 8494b99b3c560..c7116226d1c08 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -5867,9 +5867,15 @@ Expr *ExprRewriter::coerceTupleToTuple(Expr *expr, SmallString<16> toLabelStr; concatLabels(labels, toLabelStr); - ctx.Diags.diagnose(expr->getLoc(), - diag::warn_reordering_tuple_shuffle_deprecated, - fromLabelStr, toLabelStr); + using namespace version; + if (ctx.isSwiftVersionAtLeast(Version::getFutureMajorLanguageVersion())) { + ctx.Diags.diagnose(expr->getLoc(), diag::reordering_tuple_shuffle, + fromLabelStr, toLabelStr); + } else { + ctx.Diags.diagnose(expr->getLoc(), + diag::warn_reordering_tuple_shuffle_deprecated, + fromLabelStr, toLabelStr); + } } // Create the result tuple, written in terms of the destructured diff --git a/test/Constraints/tuple_shuffle.swift b/test/Constraints/tuple_shuffle.swift index 5c50c554fc0b3..f8a265b284444 100644 --- a/test/Constraints/tuple_shuffle.swift +++ b/test/Constraints/tuple_shuffle.swift @@ -1,36 +1,50 @@ -// RUN: %target-typecheck-verify-swift -swift-version 5 +// RUN: %target-typecheck-verify-swift -swift-version 6 -verify-additional-prefix swift6- +// RUN: %target-typecheck-verify-swift -swift-version 7 -verify-additional-prefix swift7- + +// REQUIRES: swift7 func consume(_ x: T) {} // Suppress unused variable warnings func shuffle_through_initialization() { let a = (x: 1, y: 2) let b: (y: Int, x: Int) - b = a // expected-warning {{implicit reordering of tuple elements from 'x:y:' to 'y:x:' is deprecated}} + b = a + // expected-swift6-warning@-1 {{implicit reordering of tuple elements from 'x:y:' to 'y:x:' is deprecated; this will be an error in a future Swift language mode}} + // expected-swift7-error@-2 {{cannot implicitly reorder tuple elements from 'x:y:' to 'y:x:'}} consume(b) } func shuffle_raw_label(_ t: (`a b`: Int, `c d`: Int)) { let _: (`c d`: Int, `a b`: Int) = t - // expected-warning@-1 {{implicit reordering of tuple elements from '`a b`:`c d`:' to '`c d`:`a b`:' is deprecated}} + // expected-swift6-warning@-1 {{implicit reordering of tuple elements from '`a b`:`c d`:' to '`c d`:`a b`:' is deprecated; this will be an error in a future Swift language mode}} + // expected-swift7-error@-2 {{cannot implicitly reorder tuple elements from '`a b`:`c d`:' to '`c d`:`a b`:'}} } func shuffle_through_destructuring() { let a = (x: 1, y: 2) - let (y: b, x: c) = a // expected-warning {{implicit reordering of tuple elements from 'x:y:' to 'y:x:' is deprecated}} + let (y: b, x: c) = a + // expected-swift6-warning@-1 {{implicit reordering of tuple elements from 'x:y:' to 'y:x:' is deprecated; this will be an error in a future Swift language mode}} + // expected-swift7-error@-2 {{cannot implicitly reorder tuple elements from 'x:y:' to 'y:x:'}} consume((b, c)) } func shuffle_through_call() { func foo(_ : (x: Int, y: Int)) {} - foo((y: 5, x: 10)) // expected-warning {{implicit reordering of tuple elements from 'y:x:' to 'x:y:' is deprecated}} + foo((y: 5, x: 10)) + // expected-swift6-warning@-1 {{implicit reordering of tuple elements from 'y:x:' to 'x:y:' is deprecated; this will be an error in a future Swift language mode}} + // expected-swift7-error@-2 {{cannot implicitly reorder tuple elements from 'y:x:' to 'x:y:'}} } func shuffle_through_cast() { - let x = ((a: Int(), b: Int()) as (b: Int, a: Int)).0 // expected-warning {{implicit reordering of tuple elements from 'a:b:' to 'b:a:' is deprecated}} + let x = ((a: Int(), b: Int()) as (b: Int, a: Int)).0 + // expected-swift6-warning@-1 {{implicit reordering of tuple elements from 'a:b:' to 'b:a:' is deprecated; this will be an error in a future Swift language mode}} + // expected-swift7-error@-2 {{cannot implicitly reorder tuple elements from 'a:b:' to 'b:a:'}} // Ah, the famous double-shuffle let (c1, (c2, c3)): (c: Int, (b: Int, a: Int)) = ((a: Int(), b: Int()), c: Int()) - // expected-warning@-1 {{implicit reordering of tuple elements from 'a:b:' to 'b:a:' is deprecated}} - // expected-warning@-2 {{implicit reordering of tuple elements from '_:c:' to 'c:_:' is deprecated}} + // expected-swift6-warning@-1 {{implicit reordering of tuple elements from 'a:b:' to 'b:a:' is deprecated; this will be an error in a future Swift language mode}} + // expected-swift6-warning@-2 {{implicit reordering of tuple elements from '_:c:' to 'c:_:' is deprecated; this will be an error in a future Swift language mode}} + // expected-swift7-error@-3 {{cannot implicitly reorder tuple elements from 'a:b:' to 'b:a:'}} + // expected-swift7-error@-4 {{cannot implicitly reorder tuple elements from '_:c:' to 'c:_:'}} consume((x, c1, c2, c3)) } diff --git a/test/Parse/omit_return.swift b/test/Parse/omit_return.swift index a7fef807d2a88..e19c241e5d623 100644 --- a/test/Parse/omit_return.swift +++ b/test/Parse/omit_return.swift @@ -474,7 +474,7 @@ func ff_implicitInjectIntoOptionalExpr(_ int: Int) -> Int? { } func ff_implicitTupleShuffle(_ input: (one: Int, two: Int)) -> (two: Int, one: Int) { - input // expected-warning {{implicit reordering of tuple elements from 'one:two:' to 'two:one:' is deprecated}} + input // expected-warning {{implicit reordering of tuple elements from 'one:two:' to 'two:one:' is deprecated; this will be an error in a future Swift language mode}} } func ff_implicitCollectionUpcast(_ derived: [Derived]) -> [Base] { diff --git a/test/Parse/omit_return_ifdecl.swift b/test/Parse/omit_return_ifdecl.swift index 3269644284c66..3d0beca5cb00b 100644 --- a/test/Parse/omit_return_ifdecl.swift +++ b/test/Parse/omit_return_ifdecl.swift @@ -676,7 +676,7 @@ func ff_implicitInjectIntoOptionalExpr(_ int: Int) -> Int? { func ff_implicitTupleShuffle(_ input: (one: Int, two: Int)) -> (two: Int, one: Int) { #if true - input // expected-warning {{implicit reordering of tuple elements from 'one:two:' to 'two:one:' is deprecated}} + input // expected-warning {{implicit reordering of tuple elements from 'one:two:' to 'two:one:' is deprecated; this will be an error in a future Swift language mode}} #endif } diff --git a/test/Sema/diag_unowned_immediate_deallocation.swift b/test/Sema/diag_unowned_immediate_deallocation.swift index a21cf0c58fa2f..523bca378e645 100644 --- a/test/Sema/diag_unowned_immediate_deallocation.swift +++ b/test/Sema/diag_unowned_immediate_deallocation.swift @@ -452,10 +452,10 @@ func testGenericWeakClassDiag() { // The diagnostic doesn't currently support tuple shuffles. func testDontDiagnoseThroughTupleShuffles() { unowned let (c1, (c2, c3)): (c: C, (b: C, a: C)) = ((a: D(), b: C()), c: D()) - // expected-warning@-1 {{implicit reordering of tuple elements from 'a:b:' to 'b:a:' is deprecated}} - // expected-warning@-2 {{implicit reordering of tuple elements from '_:c:' to 'c:_:' is deprecated}} + // expected-warning@-1 {{implicit reordering of tuple elements from 'a:b:' to 'b:a:' is deprecated; this will be an error in a future Swift language mode}} + // expected-warning@-2 {{implicit reordering of tuple elements from '_:c:' to 'c:_:' is deprecated; this will be an error in a future Swift language mode}} unowned let c4 = ((a: C(), b: C()) as (b: C, a: C)).0 - // expected-warning@-1 {{implicit reordering of tuple elements from 'a:b:' to 'b:a:' is deprecated}} + // expected-warning@-1 {{implicit reordering of tuple elements from 'a:b:' to 'b:a:' is deprecated; this will be an error in a future Swift language mode}} _ = c1; _ = c2; _ = c3; _ = c4 } diff --git a/test/decl/func/operator.swift b/test/decl/func/operator.swift index 269b0408548b0..8564c2c212a85 100644 --- a/test/decl/func/operator.swift +++ b/test/decl/func/operator.swift @@ -155,7 +155,7 @@ var f2 : (Int) -> Int = (+-+) var f3 : (inout Int) -> Int = (-+-) // expected-error{{ambiguous use of operator '-+-'}} var f4 : (inout Int, Int) -> Int = (+-+=) var r5 : (a : (Int, Int) -> Int, b : (Int, Int) -> Int) = (+, -) -var r6 : (a : (Int, Int) -> Int, b : (Int, Int) -> Int) = (b : +, a : -) // expected-warning {{implicit reordering of tuple elements from 'b:a:' to 'a:b:' is deprecated}} +var r6 : (a : (Int, Int) -> Int, b : (Int, Int) -> Int) = (b : +, a : -) // expected-warning {{implicit reordering of tuple elements from 'b:a:' to 'a:b:' is deprecated; this will be an error in a future Swift language mode}} struct f6_S { subscript(op : (Int, Int) -> Int) -> Int { diff --git a/test/expr/closure/closures.swift b/test/expr/closure/closures.swift index eb84ee636bb6c..b8af7e06c653c 100644 --- a/test/expr/closure/closures.swift +++ b/test/expr/closure/closures.swift @@ -56,7 +56,7 @@ func funcdecl5(_ a: Int, _ y: Int) { var b = a.1+a.f // Tuple expressions with named elements. - var i : (y : Int, x : Int) = (x : 42, y : 11) // expected-warning {{implicit reordering of tuple elements from 'x:y:' to 'y:x:' is deprecated}} + var i : (y : Int, x : Int) = (x : 42, y : 11) // expected-warning {{implicit reordering of tuple elements from 'x:y:' to 'y:x:' is deprecated; this will be an error in a future Swift language mode}} funcdecl1(123, 444) // Calls. diff --git a/test/expr/expressions.swift b/test/expr/expressions.swift index 1532b7b47e1c3..b4416db19c5bd 100644 --- a/test/expr/expressions.swift +++ b/test/expr/expressions.swift @@ -194,7 +194,7 @@ func test5() { let c: (a: Int, b: Int) = (1,2) - let _: (b: Int, a: Int) = c // expected-warning {{implicit reordering of tuple elements from 'a:b:' to 'b:a:' is deprecated}} + let _: (b: Int, a: Int) = c // expected-warning {{implicit reordering of tuple elements from 'a:b:' to 'b:a:' is deprecated; this will be an error in a future Swift language mode}} }