Skip to content

Commit 506cd7d

Browse files
committed
[ConstraintSystem] Let optional chaining infer a type from sub-expression even with contextual mismatch
Just like in case of `try?` it makes it easier to distinguish between missing optional unwrap and contextual type mismatch.
1 parent fb0a484 commit 506cd7d

File tree

2 files changed

+23
-10
lines changed

2 files changed

+23
-10
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1958,12 +1958,12 @@ bool ContextualFailure::diagnoseAsError() {
19581958
if (diagnoseYieldByReferenceMismatch())
19591959
return true;
19601960

1961-
if (auto *OTE = dyn_cast<OptionalTryExpr>(anchor)) {
1962-
auto tryType = fromType->getOptionalObjectType();
1963-
if (tryType->isEqual(toType)) {
1961+
if (isa<OptionalTryExpr>(anchor) || isa<OptionalEvaluationExpr>(anchor)) {
1962+
auto objectType = fromType->getOptionalObjectType();
1963+
if (objectType->isEqual(toType)) {
19641964
auto &cs = getConstraintSystem();
1965-
MissingOptionalUnwrapFailure failure(cs, getType(OTE), toType,
1966-
cs.getConstraintLocator(OTE));
1965+
MissingOptionalUnwrapFailure failure(cs, getType(anchor), toType,
1966+
cs.getConstraintLocator(anchor));
19671967
if (failure.diagnoseAsError())
19681968
return true;
19691969
}

lib/Sema/CSSimplify.cpp

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2596,6 +2596,15 @@ repairViaOptionalUnwrap(ConstraintSystem &cs, Type fromType, Type toType,
25962596
if (!anchor)
25972597
return false;
25982598

2599+
bool possibleContextualMismatch = false;
2600+
// If this is a conversion to a non-optional contextual type e.g.
2601+
// `let _: Bool = try? foo()` and `foo()` produces `Int`
2602+
// we should diagnose it as type mismatch instead of missing unwrap.
2603+
if (auto last = locator.last()) {
2604+
possibleContextualMismatch = last->is<LocatorPathElt::ContextualType>() &&
2605+
!toType->getOptionalObjectType();
2606+
}
2607+
25992608
// `OptionalEvaluationExpr` doesn't add a new level of
26002609
// optionality but it could be hiding concrete types
26012610
// behind itself which we can use to better understand
@@ -2612,7 +2621,12 @@ repairViaOptionalUnwrap(ConstraintSystem &cs, Type fromType, Type toType,
26122621
// other type e.g. contextual type or a parameter type,
26132622
// let's use `Bind` to match object types because
26142623
// object type of the optinal chain is a type variable.
2615-
if (matchKind >= ConstraintKind::Conversion)
2624+
//
2625+
// One exception is contextual conversion - in such cases
2626+
// let's give optional chain a chance to infer its inner type
2627+
// first, that makes it much easier to diagnose contextual
2628+
// mismatch vs. missing optional unwrap.
2629+
if (!possibleContextualMismatch && matchKind >= ConstraintKind::Conversion)
26162630
matchKind = ConstraintKind::Bind;
26172631
}
26182632

@@ -2644,13 +2658,12 @@ repairViaOptionalUnwrap(ConstraintSystem &cs, Type fromType, Type toType,
26442658
// language mode, so we can safely try to bind its
26452659
// object type to contextual type without risk of
26462660
// causing more optionality mismatches down the road.
2647-
auto last = locator.last();
2661+
//
26482662
// For contextual conversions let's give `try?` a chance to
26492663
// infer inner type which, if incorrect, should result in
26502664
// contextual conversion failure instead of optional unwrap.
2651-
matchKind = last && last->is<LocatorPathElt::ContextualType>()
2652-
? ConstraintKind::Conversion
2653-
: ConstraintKind::Bind;
2665+
matchKind = possibleContextualMismatch ? ConstraintKind::Conversion
2666+
: ConstraintKind::Bind;
26542667
}
26552668
}
26562669

0 commit comments

Comments
 (0)