Skip to content

Commit 04b37ae

Browse files
committed
[CS] Don't apply compatibility logic in Swift 6 mode
This was only intended to preserve compatibility for cases where the constraint system may have previously accepted invalid code. Drop it in Swift 6 mode such that invalid collection coercions become errors.
1 parent 63c094c commit 04b37ae

File tree

2 files changed

+82
-4
lines changed

2 files changed

+82
-4
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9555,17 +9555,17 @@ ConstraintSystem::simplifyBridgingConstraint(Type type1,
95559555
// we generated somewhat reasonable code that performed a force cast. To
95569556
// maintain compatibility with that behavior, allow the coercion between
95579557
// two collections, but add a warning fix telling the user to use as! or as?
9558-
// instead.
9558+
// instead. In Swift 6 mode, this becomes an error.
95599559
//
95609560
// We only need to perform this compatibility logic if this is a coercion of
95619561
// something that isn't a collection expr (as collection exprs would have
95629562
// crashed in codegen due to CSApply peepholing them). Additionally, the LHS
95639563
// type must be a (potentially optional) type variable, as only such a
95649564
// constraint could have been previously been left unsolved.
9565-
//
9566-
// FIXME: Once we get a new language version, change this condition to only
9567-
// preserve compatibility for Swift 5.x mode.
95689565
auto canUseCompatFix = [&]() {
9566+
if (Context.isSwiftVersionAtLeast(6))
9567+
return false;
9568+
95699569
if (!rawType1->lookThroughAllOptionalTypes()->isTypeVariableOrMember())
95709570
return false;
95719571

test/Constraints/casts_swift6.swift

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// RUN: %target-typecheck-verify-swift -enable-objc-interop -swift-version 6
2+
3+
// -swift-version 6 is currently asserts-only
4+
// REQUIRES: asserts
5+
6+
func id<T>(_ x: T) -> T { x }
7+
func ohno<T>(_ x: T) -> T? { nil }
8+
9+
// Swift 6 version of the test in casts.swift
10+
func test_compatibility_coercions(_ arr: [Int], _ optArr: [Int]?, _ dict: [String: Int], _ set: Set<Int>, _ i: Int, _ stringAnyDict: [String: Any]) {
11+
// These have always been fine.
12+
_ = arr as [Any]?
13+
_ = dict as [String: Int]?
14+
_ = set as Set<Int>
15+
16+
// These have always been errors.
17+
_ = arr as [String] // expected-error {{cannot convert value of type '[Int]' to type '[String]' in coercion}}
18+
// expected-note@-1 {{arguments to generic parameter 'Element' ('Int' and 'String') are expected to be equal}}
19+
_ = dict as [String: String] // expected-error {{cannot convert value of type '[String : Int]' to type '[String : String]' in coercion}}
20+
// expected-note@-1 {{arguments to generic parameter 'Value' ('Int' and 'String') are expected to be equal}}
21+
_ = dict as [String: String]? // expected-error {{'[String : Int]' is not convertible to '[String : String]?'}}
22+
// expected-note@-1 {{did you mean to use 'as!' to force downcast?}} {{12-14=as!}}
23+
_ = (dict as [String: Int]?) as [String: Int] // expected-error {{value of optional type '[String : Int]?' must be unwrapped to a value of type '[String : Int]'}}
24+
// expected-note@-1 {{coalesce using '??' to provide a default when the optional value contains 'nil'}}
25+
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
26+
_ = set as Set<String> // expected-error {{cannot convert value of type 'Set<Int>' to type 'Set<String>' in coercion}}
27+
// expected-note@-1 {{arguments to generic parameter 'Element' ('Int' and 'String') are expected to be equal}}
28+
29+
// Make sure we error on the following in Swift 6 mode.
30+
31+
// FIXME: Bad diagnostics (SR-15843)
32+
_ = id(arr) as [String] // expected-error {{type of expression is ambiguous without more context}}
33+
_ = (arr ?? []) as [String] // expected-error {{type of expression is ambiguous without more context}}
34+
_ = (arr ?? [] ?? []) as [String] // expected-error {{type of expression is ambiguous without more context}}
35+
_ = (optArr ?? []) as [String] // expected-error {{type of expression is ambiguous without more context}}
36+
37+
_ = (arr ?? []) as [String]? // expected-error {{'[Int]' is not convertible to '[String]?'}}
38+
// expected-note@-1 {{did you mean to use 'as!' to force downcast?}}
39+
_ = (arr ?? []) as [String?]? // expected-error {{'[Int]' is not convertible to '[String?]?'}}
40+
// expected-note@-1 {{did you mean to use 'as!' to force downcast?}}
41+
_ = (arr ?? []) as [String??]?? // expected-error {{'[Int]' is not convertible to '[String??]??'}}
42+
// expected-note@-1 {{did you mean to use 'as!' to force downcast?}}
43+
_ = (dict ?? [:]) as [String: String?]? // expected-error {{'[String : Int]' is not convertible to '[String : String?]?'}}
44+
// expected-note@-1 {{did you mean to use 'as!' to force downcast?}}
45+
_ = (set ?? []) as Set<String>?? // expected-error {{'Set<Int>' is not convertible to 'Set<String>??'}}
46+
// expected-note@-1 {{did you mean to use 'as!' to force downcast?}}
47+
48+
_ = ohno(ohno(ohno(arr))) as [String] // expected-error {{cannot convert value of type '[Int]???' to type '[String]' in coercion}}
49+
_ = ohno(ohno(ohno(arr))) as [Int] // expected-error {{cannot convert value of type '[Int]???' to type '[Int]' in coercion}}
50+
_ = ohno(ohno(ohno(Set<Int>()))) as Set<String> // expected-error {{cannot convert value of type 'Set<Int>???' to type 'Set<String>' in coercion}}
51+
_ = ohno(ohno(ohno(["": ""]))) as [Int: String] // expected-error {{cannot convert value of type '[String : String]???' to type '[Int : String]' in coercion}}
52+
_ = ohno(ohno(ohno(dict))) as [String: Int] // expected-error {{cannot convert value of type '[String : Int]???' to type '[String : Int]' in coercion}}
53+
54+
// In this case the array literal can be inferred to be [String], so totally
55+
// valid.
56+
_ = ([] ?? []) as [String] // expected-warning {{left side of nil coalescing operator '??' has non-optional type '[String]', so the right side is never used}}
57+
_ = (([] as Optional) ?? []) as [String]
58+
59+
// The array can also be inferred to be [Any].
60+
_ = ([] ?? []) as Array // expected-warning {{left side of nil coalescing operator '??' has non-optional type '[Any]', so the right side is never used}}
61+
62+
// Cases from rdar://88334481
63+
typealias Magic<T> = T
64+
_ = [i] as [String] // expected-error {{cannot convert value of type 'Int' to expected element type 'String'}}
65+
_ = [i] as Magic as [String] // expected-error {{cannot convert value of type 'Int' to expected element type 'String'}}
66+
_ = ([i]) as Magic as [String] // expected-error {{cannot convert value of type 'Int' to expected element type 'String'}}
67+
_ = [i: i] as [String: Any] // expected-error {{cannot convert value of type 'Int' to expected dictionary key type 'String'}}
68+
_ = ([i: i]) as [String: Any] // expected-error {{cannot convert value of type 'Int' to expected dictionary key type 'String'}}
69+
_ = [i: stringAnyDict] as [String: Any] // expected-error {{cannot convert value of type 'Int' to expected dictionary key type 'String'}}
70+
71+
_ = [i].self as Magic as [String] // expected-error {{cannot convert value of type 'Int' to expected element type 'String'}}
72+
_ = (try [i]) as Magic as [String] // expected-error {{cannot convert value of type 'Int' to expected element type 'String'}}
73+
// expected-warning@-1 {{no calls to throwing functions occur within 'try' expression}}
74+
75+
// These are wrong, but make sure we don't warn about the value cast always succeeding.
76+
_ = [i: i] as! [String: Any]
77+
_ = [i: stringAnyDict] as! [String: Any]
78+
}

0 commit comments

Comments
 (0)