You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
[CS] Preserve compatibility for collection coercions
Previously we could allow some invalid coercions to
sneak past Sema. In most cases these would either
cause crashes later down the pipeline or
miscompiles. However, for coercions between
collections, we emitted somewhat reasonable code
that performed a force cast.
This commit aims to preserve compatibility with
those collection coercions that previously
compiled, and emits a warning telling the user to
use either 'as?' or 'as!' instead.
// Don't fix the simple case where no type variable is introduced, that was
288
+
// always disallowed.
289
+
_ = arr as[String] // expected-error {{cannot convert value of type '[Int]' to type '[String]' in coercion}}
290
+
// expected-note@-1 {{arguments to generic parameter 'Element' ('Int' and 'String') are expected to be equal}}
291
+
_ = dict as[String:String] // expected-error {{cannot convert value of type '[String : Int]' to type '[String : String]' in coercion}}
292
+
// expected-note@-1 {{arguments to generic parameter 'Value' ('Int' and 'String') are expected to be equal}}
293
+
_ = dict as[String:String]? // expected-error {{cannot convert value of type '[String : Int]' to type '[String : String]?' in coercion}}
294
+
_ =(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]'}}
295
+
// expected-note@-1 {{coalesce using '??' to provide a default when the optional value contains 'nil'}}
296
+
// expected-note@-2 {{force-unwrap using '!' to abort execution if the optional value contains 'nil'}}
297
+
_ = set asSet<String> // expected-error {{cannot convert value of type 'Set<Int>' to type 'Set<String>' in coercion}}
298
+
// expected-note@-1 {{arguments to generic parameter 'Element' ('Int' and 'String') are expected to be equal}}
299
+
300
+
// Apply the compatibility logic when a type variable is introduced. It's
301
+
// unfortunate that this means we'll temporarily accept code we didn't before,
302
+
// but it at least means we shouldn't break compatibility with anything.
303
+
_ =id(arr)as[String] // expected-warning {{coercion from '[Int]' to '[String]' may fail; use 'as?' or 'as!' instead}}
304
+
305
+
_ =(arr ??[])as[String] // expected-warning {{coercion from '[Int]' to '[String]' may fail; use 'as?' or 'as!' instead}}
306
+
// expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type '[Int]', so the right side is never used}}
307
+
_ =(arr ??[]??[])as[String] // expected-warning {{coercion from '[Int]' to '[String]' may fail; use 'as?' or 'as!' instead}}
308
+
// expected-warning@-1 2{{left side of nil coalescing operator '??' has non-optional type '[Int]', so the right side is never used}}
309
+
_ =(optArr ??[])as[String] // expected-warning {{coercion from '[Int]' to '[String]' may fail; use 'as?' or 'as!' instead}}
310
+
311
+
// Allow the coercion to increase optionality.
312
+
_ =(arr ??[])as[String]? // expected-warning {{coercion from '[Int]' to '[String]?' may fail; use 'as?' or 'as!' instead}}
313
+
// expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type '[Int]', so the right side is never used}}
314
+
_ =(arr ??[])as[String?]? // expected-warning {{coercion from '[Int]' to '[String?]?' may fail; use 'as?' or 'as!' instead}}
315
+
// expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type '[Int]', so the right side is never used}}
316
+
_ =(arr ??[])as[String??]?? // expected-warning {{coercion from '[Int]' to '[String??]??' may fail; use 'as?' or 'as!' instead}}
317
+
// expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type '[Int]', so the right side is never used}}
318
+
_ =(dict ??[:])as[String:String?]? // expected-warning {{coercion from '[String : Int]' to '[String : String?]?' may fail; use 'as?' or 'as!' instead}}
319
+
// expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type '[String : Int]', so the right side is never used}}
320
+
_ =(set ??[])asSet<String>?? // expected-warning {{coercion from 'Set<Int>' to 'Set<String>??' may fail; use 'as?' or 'as!' instead}}
321
+
// expected-warning@-1 {{left side of nil coalescing operator '??' has non-optional type 'Set<Int>', so the right side is never used}}
322
+
323
+
// Allow the coercion to decrease optionality.
324
+
_ =ohno(ohno(ohno(arr)))as[String] // expected-warning {{coercion from '[Int]???' to '[String]' may fail; use 'as?' or 'as!' instead}}
325
+
_ =ohno(ohno(ohno(arr)))as[Int] // expected-warning {{coercion from '[Int]???' to '[Int]' may fail; use 'as?' or 'as!' instead}}
326
+
_ =ohno(ohno(ohno(Set<Int>())))asSet<String> // expected-warning {{coercion from 'Set<Int>???' to 'Set<String>' may fail; use 'as?' or 'as!' instead}}
327
+
_ =ohno(ohno(ohno(["":""])))as[Int:String] // expected-warning {{coercion from '[String : String]???' to '[Int : String]' may fail; use 'as?' or 'as!' instead}}
328
+
_ =ohno(ohno(ohno(dict)))as[String:Int] // expected-warning {{coercion from '[String : Int]???' to '[String : Int]' may fail; use 'as?' or 'as!' instead}}
329
+
330
+
// In this case the array literal can be inferred to be [String], so totally
331
+
// valid.
332
+
_ =([]??[])as[String] // expected-warning {{left side of nil coalescing operator '??' has non-optional type '[String]', so the right side is never used}}
333
+
_ =(([]asOptional)??[])as[String]
334
+
335
+
// The array can also be inferred to be [Any].
336
+
_ =([]??[])asArray // expected-warning {{left side of nil coalescing operator '??' has non-optional type '[Any]', so the right side is never used}}
0 commit comments