Skip to content

Commit 8ea2a69

Browse files
[TypeCheckConstraints] Creating new CheckedCastContextKind::CollectionElement to be able to verify special cases within typeCheckCheckedCast for collection elements
1 parent b09e34a commit 8ea2a69

File tree

3 files changed

+24
-8
lines changed

3 files changed

+24
-8
lines changed

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3037,7 +3037,9 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
30373037
Expr *fromExpr,
30383038
SourceRange diagToRange) {
30393039
// 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;
30413043
assert((suppressDiagnostics || diagLoc.isValid()) &&
30423044
"diagnostics require a valid source location");
30433045

@@ -3101,7 +3103,18 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
31013103
.highlight(diagFromRange)
31023104
.highlight(diagToRange);
31033105
}
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;
31053118
}
31063119

31073120
toType = toValueType;
@@ -3132,6 +3145,7 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
31323145
!fromType->isEqual(toType) && !isConvertibleTo(fromType, toType, dc);
31333146

31343147
switch (contextKind) {
3148+
case CheckedCastContextKind::CollectionElement:
31353149
case CheckedCastContextKind::None:
31363150
llvm_unreachable("suppressing diagnostics");
31373151

@@ -3249,12 +3263,8 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
32493263

32503264
auto checkElementCast = [&](Type fromElt, Type toElt,
32513265
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,
32583268
dc, SourceLoc(), nullptr, SourceRange())) {
32593269
case CheckedCastKind::Coercion:
32603270
return CheckedCastKind::Coercion;
@@ -3428,6 +3438,7 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
34283438
case CheckedCastContextKind::EnumElementPattern:
34293439
case CheckedCastContextKind::IsExpr:
34303440
case CheckedCastContextKind::None:
3441+
case CheckedCastContextKind::CollectionElement:
34313442
break;
34323443
}
34333444
}

lib/Sema/TypeChecker.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,8 @@ enum class CheckedCastContextKind {
341341
IsPattern,
342342
/// An enum-element pattern.
343343
EnumElementPattern,
344+
/// A collection element type.
345+
CollectionElement,
344346
};
345347

346348
namespace TypeChecker {

test/Constraints/casts.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,9 +379,12 @@ func tests_SR13088_false_positive_always_fail_casts() {
379379

380380
// SR-7187
381381
let a: [Any] = [String?.some("hello") as Any, String?.none as Any]
382+
let b: [AnyObject] = [String?.some("hello") as AnyObject, String?.none as AnyObject]
382383

383384
_ = a is [String?] // Ok
384385
_ = a as? [String?] // Ok
386+
_ = b is [String?] // Ok
387+
_ = b as? [String?] // Ok
385388

386389
// SR-13035
387390
func SR13035<SomeError: SR13035Error>(_ mockResult: Result<String, ChildError>, _: Result<String, SomeError>) {

0 commit comments

Comments
 (0)