Skip to content

Commit de1bd2d

Browse files
[SR-16058][Sema] Consider wrapping type variable layers of optionality when warning about checked casts
1 parent 3f37fc0 commit de1bd2d

File tree

2 files changed

+26
-6
lines changed

2 files changed

+26
-6
lines changed

lib/Sema/CSSimplify.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7467,13 +7467,20 @@ static ConstraintFix *maybeWarnAboutExtraneousCast(
74677467
// we need to store the difference as a signed integer.
74687468
int extraOptionals = fromOptionals.size() - toOptionals.size();
74697469

7470-
// "from" expression could be a type variable with value-to-optional
7471-
// restrictions that we have to account for optionality mismatch.
7470+
// "from" expression could be a type variable wrapped in an optional e.g.
7471+
// Optional<$T0>. So when that is the case we have to add this additional
7472+
// optionality levels to from type.
74727473
const auto subExprType = cs.getType(castExpr->getSubExpr());
7473-
if (cs.hasConversionRestriction(fromType, subExprType,
7474-
ConversionRestrictionKind::ValueToOptional)) {
7475-
extraOptionals++;
7476-
origFromType = OptionalType::get(origFromType);
7474+
if (subExprType->getOptionalObjectType()) {
7475+
SmallVector<Type, 4> subExprOptionals;
7476+
const auto unwrappedSubExprType =
7477+
subExprType->lookThroughAllOptionalTypes(subExprOptionals);
7478+
if (unwrappedSubExprType->is<TypeVariableType>()) {
7479+
extraOptionals += subExprOptionals.size();
7480+
for (size_t i = 0; i != subExprOptionals.size(); ++i) {
7481+
origFromType = OptionalType::get(origFromType);
7482+
}
7483+
}
74777484
}
74787485

74797486
// Removing the optionality from to type when the force cast expr is an IUO.

test/Constraints/casts.swift

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -680,3 +680,16 @@ func test_SR_15562() {
680680
// expected-error@-1{{left side of mutating operator has immutable type 'Int'}}
681681
}
682682
}
683+
684+
// SR-16058
685+
extension Dictionary {
686+
func SR16058(_: Key) -> Value?? { nil }
687+
}
688+
func SR_16058_tests() {
689+
let dict: [Int: String?] = [:]
690+
let foo: Int? = 1
691+
let _: String? = foo.flatMap { dict[$0] } as? String // OK
692+
693+
// More than one optionality wrapping
694+
let _: String? = foo.flatMap { dict.SR16058(_: $0) } as? String // OK
695+
}

0 commit comments

Comments
 (0)