@@ -3037,7 +3037,9 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
3037
3037
Expr *fromExpr,
3038
3038
SourceRange diagToRange) {
3039
3039
// Determine whether we should suppress diagnostics.
3040
- const bool suppressDiagnostics = contextKind == CheckedCastContextKind::None;
3040
+ const bool suppressDiagnostics =
3041
+ contextKind == CheckedCastContextKind::None ||
3042
+ contextKind == CheckedCastContextKind::CollectionElement;
3041
3043
assert ((suppressDiagnostics || diagLoc.isValid ()) &&
3042
3044
" diagnostics require a valid source location" );
3043
3045
@@ -3101,7 +3103,18 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
3101
3103
.highlight (diagFromRange)
3102
3104
.highlight (diagToRange);
3103
3105
}
3104
- return CheckedCastKind::Unresolved;
3106
+
3107
+ // In the context of collection element we just return a value cast
3108
+ // becasue there may be situation where this can be convertible
3109
+ // at runtime. e.g.
3110
+ //
3111
+ // func f(a: [Any], b: [AnyObject]) {
3112
+ // _ = a is [String?] // Ok
3113
+ // - = b is [String?] // Ok
3114
+ // }
3115
+ return (contextKind != CheckedCastContextKind::CollectionElement)
3116
+ ? CheckedCastKind::Unresolved
3117
+ : CheckedCastKind::ValueCast;
3105
3118
}
3106
3119
3107
3120
toType = toValueType;
@@ -3132,6 +3145,7 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
3132
3145
!fromType->isEqual (toType) && !isConvertibleTo (fromType, toType, dc);
3133
3146
3134
3147
switch (contextKind) {
3148
+ case CheckedCastContextKind::CollectionElement:
3135
3149
case CheckedCastContextKind::None:
3136
3150
llvm_unreachable (" suppressing diagnostics" );
3137
3151
@@ -3249,12 +3263,8 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
3249
3263
3250
3264
auto checkElementCast = [&](Type fromElt, Type toElt,
3251
3265
CheckedCastKind castKind) -> CheckedCastKind {
3252
- // Let's not emit diagnostic when the element type is erased because
3253
- // we can't statically know if element is convertible.
3254
- if (fromElt->isAny () || toElt->isAny ())
3255
- return castKind;
3256
-
3257
- switch (typeCheckCheckedCast (fromElt, toElt, CheckedCastContextKind::None,
3266
+ switch (typeCheckCheckedCast (fromElt, toElt,
3267
+ CheckedCastContextKind::CollectionElement,
3258
3268
dc, SourceLoc (), nullptr , SourceRange ())) {
3259
3269
case CheckedCastKind::Coercion:
3260
3270
return CheckedCastKind::Coercion;
@@ -3428,6 +3438,7 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
3428
3438
case CheckedCastContextKind::EnumElementPattern:
3429
3439
case CheckedCastContextKind::IsExpr:
3430
3440
case CheckedCastContextKind::None:
3441
+ case CheckedCastContextKind::CollectionElement:
3431
3442
break ;
3432
3443
}
3433
3444
}
0 commit comments