mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Merge pull request #85188 from hamishknight/tuple-trouble
[CS] Upgrade a couple of tuple warnings to error for future lang mode
This commit is contained in:
@@ -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; "
|
||||
@@ -7833,9 +7833,14 @@ 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", ())
|
||||
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"
|
||||
"; this will be an error in a future Swift language mode",
|
||||
(StringRef, StringRef))
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// MARK: Implicit conversion diagnostics
|
||||
|
||||
@@ -3458,7 +3458,8 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// 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)
|
||||
|
||||
@@ -5822,6 +5822,7 @@ Expr *ExprRewriter::coerceTupleToTuple(Expr *expr,
|
||||
|
||||
// Convert each OpaqueValueExpr to the correct type.
|
||||
SmallVector<Expr *, 4> converted;
|
||||
SmallVector<Identifier, 4> origLabels;
|
||||
SmallVector<Identifier, 4> labels;
|
||||
SmallVector<TupleTypeElt, 4> convertedElts;
|
||||
|
||||
@@ -5829,6 +5830,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);
|
||||
@@ -5836,8 +5838,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
|
||||
@@ -5849,6 +5850,7 @@ Expr *ExprRewriter::coerceTupleToTuple(Expr *expr,
|
||||
|
||||
converted.push_back(toElt);
|
||||
labels.push_back(toLabel);
|
||||
origLabels.push_back(fromLabel);
|
||||
convertedElts.emplace_back(toEltType, toLabel);
|
||||
}
|
||||
|
||||
@@ -5856,8 +5858,28 @@ 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<Identifier> &labels,
|
||||
SmallVectorImpl<char> &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);
|
||||
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -3009,7 +3009,8 @@ public:
|
||||
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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,31 +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-
|
||||
|
||||
func consume<T>(_ x: T) {} // Suppress unused variable warnings
|
||||
// REQUIRES: swift7
|
||||
|
||||
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 consume<T>(_ x: T) {} // Suppress unused variable warnings
|
||||
|
||||
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_initialization() {
|
||||
let a = (x: 1, y: 2)
|
||||
let b: (y: Int, x: Int)
|
||||
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_through_call() {
|
||||
func foo(_ : (x: Int, y: Int)) {}
|
||||
foo((y: 5, x: 10)) // expected-warning {{expression shuffles the elements of this tuple}}
|
||||
}
|
||||
func shuffle_raw_label(_ t: (`a b`: Int, `c d`: Int)) {
|
||||
let _: (`c d`: Int, `a b`: Int) = t
|
||||
// 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_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_destructuring() {
|
||||
let a = (x: 1, y: 2)
|
||||
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))
|
||||
}
|
||||
|
||||
// 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))
|
||||
}
|
||||
func shuffle_through_call() {
|
||||
func foo(_ : (x: Int, y: Int)) {}
|
||||
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-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-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))
|
||||
}
|
||||
|
||||
33
test/Constraints/tuple_subtype_label_mismatch.swift
Normal file
33
test/Constraints/tuple_subtype_label_mismatch.swift
Normal file
@@ -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
|
||||
}
|
||||
@@ -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; this will be an error in a future Swift language mode}}
|
||||
}
|
||||
|
||||
func ff_implicitCollectionUpcast(_ derived: [Derived]) -> [Base] {
|
||||
|
||||
@@ -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; this will be an error in a future Swift language mode}}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
@@ -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; 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 {{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; this will be an error in a future Swift language mode}}
|
||||
|
||||
_ = c1; _ = c2; _ = c3; _ = c4
|
||||
}
|
||||
|
||||
@@ -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; this will be an error in a future Swift language mode}}
|
||||
|
||||
struct f6_S {
|
||||
subscript(op : (Int, Int) -> Int) -> Int {
|
||||
|
||||
@@ -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; this will be an error in a future Swift language mode}}
|
||||
funcdecl1(123, 444)
|
||||
|
||||
// Calls.
|
||||
|
||||
@@ -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; this will be an error in a future Swift language mode}}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user