Skip to content

Commit df913c9

Browse files
Merge pull request #42050 from LucianoPAlmeida/SR-16058-casts
[SR-16058][Sema] Consider wrapping type variable layers of optionality when warning about checked casts
2 parents bf303ab + de1bd2d commit df913c9

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
@@ -7501,13 +7501,20 @@ static ConstraintFix *maybeWarnAboutExtraneousCast(
75017501
// we need to store the difference as a signed integer.
75027502
int extraOptionals = fromOptionals.size() - toOptionals.size();
75037503

7504-
// "from" expression could be a type variable with value-to-optional
7505-
// restrictions that we have to account for optionality mismatch.
7504+
// "from" expression could be a type variable wrapped in an optional e.g.
7505+
// Optional<$T0>. So when that is the case we have to add this additional
7506+
// optionality levels to from type.
75067507
const auto subExprType = cs.getType(castExpr->getSubExpr());
7507-
if (cs.hasConversionRestriction(fromType, subExprType,
7508-
ConversionRestrictionKind::ValueToOptional)) {
7509-
extraOptionals++;
7510-
origFromType = OptionalType::get(origFromType);
7508+
if (subExprType->getOptionalObjectType()) {
7509+
SmallVector<Type, 4> subExprOptionals;
7510+
const auto unwrappedSubExprType =
7511+
subExprType->lookThroughAllOptionalTypes(subExprOptionals);
7512+
if (unwrappedSubExprType->is<TypeVariableType>()) {
7513+
extraOptionals += subExprOptionals.size();
7514+
for (size_t i = 0; i != subExprOptionals.size(); ++i) {
7515+
origFromType = OptionalType::get(origFromType);
7516+
}
7517+
}
75117518
}
75127519

75137520
// 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)