@@ -5065,63 +5065,6 @@ bool ConstraintSystem::repairFailures(
50655065 if (!anchor)
50665066 return false;
50675067
5068- if (auto *coercion = getAsExpr<CoerceExpr>(anchor)) {
5069- // Coercion from T.Type to T.Protocol.
5070- if (hasConversionOrRestriction(
5071- ConversionRestrictionKind::MetatypeToExistentialMetatype))
5072- return false;
5073-
5074- if (hasConversionOrRestriction(ConversionRestrictionKind::Superclass))
5075- return false;
5076-
5077- // Let's check whether the sub-expression is an optional type which
5078- // is possible to unwrap (either by force or `??`) to satisfy the cast,
5079- // otherwise we'd have to fallback to force downcast.
5080- if (repairViaOptionalUnwrap(*this, lhs, rhs, matchKind,
5081- conversionsOrFixes,
5082- getConstraintLocator(coercion->getSubExpr())))
5083- return true;
5084-
5085- // If the result type of the coercion has an value to optional conversion
5086- // we can instead suggest the conditional downcast as it is safer in
5087- // situations like conditional binding.
5088- auto useConditionalCast =
5089- llvm::any_of(ConstraintRestrictions, [&](const auto &restriction) {
5090- Type type1, type2;
5091- std::tie(type1, type2) = restriction.first;
5092- auto restrictionKind = restriction.second;
5093-
5094- if (restrictionKind != ConversionRestrictionKind::ValueToOptional)
5095- return false;
5096-
5097- return rhs->isEqual(type1);
5098- });
5099-
5100- // Repair a coercion ('as') with a runtime checked cast ('as!' or 'as?').
5101- if (auto *coerceToCheckCastFix =
5102- CoerceToCheckedCast::attempt(*this, lhs, rhs, useConditionalCast,
5103- getConstraintLocator(locator))) {
5104- conversionsOrFixes.push_back(coerceToCheckCastFix);
5105- return true;
5106- }
5107-
5108- // If it has a deep equality restriction, defer the diagnostic to
5109- // GenericMismatch.
5110- if (hasConversionOrRestriction(ConversionRestrictionKind::DeepEquality) &&
5111- !hasConversionOrRestriction(
5112- ConversionRestrictionKind::OptionalToOptional)) {
5113- return false;
5114- }
5115-
5116- if (hasConversionOrRestriction(ConversionRestrictionKind::Existential))
5117- return false;
5118-
5119- auto *fix = ContextualMismatch::create(*this, lhs, rhs,
5120- getConstraintLocator(locator));
5121- conversionsOrFixes.push_back(fix);
5122- return true;
5123- }
5124-
51255068 // This could be:
51265069 // - `InOutExpr` used with r-value e.g. `foo(&x)` where `x` is a `let`.
51275070 // - `ForceValueExpr` e.g. `foo.bar! = 42` where `bar` or `foo` are
@@ -6456,6 +6399,64 @@ bool ConstraintSystem::repairFailures(
64566399 break;
64576400 }
64586401
6402+ case ConstraintLocator::CoercionOperand: {
6403+ auto *coercion = castToExpr<CoerceExpr>(anchor);
6404+
6405+ // Coercion from T.Type to T.Protocol.
6406+ if (hasConversionOrRestriction(
6407+ ConversionRestrictionKind::MetatypeToExistentialMetatype))
6408+ return false;
6409+
6410+ if (hasConversionOrRestriction(ConversionRestrictionKind::Superclass))
6411+ return false;
6412+
6413+ // Let's check whether the sub-expression is an optional type which
6414+ // is possible to unwrap (either by force or `??`) to satisfy the cast,
6415+ // otherwise we'd have to fallback to force downcast.
6416+ if (repairViaOptionalUnwrap(*this, lhs, rhs, matchKind,
6417+ conversionsOrFixes,
6418+ getConstraintLocator(coercion->getSubExpr())))
6419+ return true;
6420+
6421+ // If the result type of the coercion has an value to optional conversion
6422+ // we can instead suggest the conditional downcast as it is safer in
6423+ // situations like conditional binding.
6424+ auto useConditionalCast =
6425+ llvm::any_of(ConstraintRestrictions, [&](const auto &restriction) {
6426+ Type type1, type2;
6427+ std::tie(type1, type2) = restriction.first;
6428+ auto restrictionKind = restriction.second;
6429+
6430+ if (restrictionKind != ConversionRestrictionKind::ValueToOptional)
6431+ return false;
6432+
6433+ return rhs->isEqual(type1);
6434+ });
6435+
6436+ // Repair a coercion ('as') with a runtime checked cast ('as!' or 'as?').
6437+ if (auto *coerceToCheckCastFix =
6438+ CoerceToCheckedCast::attempt(*this, lhs, rhs, useConditionalCast,
6439+ getConstraintLocator(locator))) {
6440+ conversionsOrFixes.push_back(coerceToCheckCastFix);
6441+ return true;
6442+ }
6443+
6444+ // If it has a deep equality restriction, defer the diagnostic to
6445+ // GenericMismatch.
6446+ if (hasConversionOrRestriction(ConversionRestrictionKind::DeepEquality) &&
6447+ !hasConversionOrRestriction(
6448+ ConversionRestrictionKind::OptionalToOptional)) {
6449+ return false;
6450+ }
6451+
6452+ if (hasConversionOrRestriction(ConversionRestrictionKind::Existential))
6453+ return false;
6454+
6455+ auto *fix = ContextualMismatch::create(*this, lhs, rhs,
6456+ getConstraintLocator(locator));
6457+ conversionsOrFixes.push_back(fix);
6458+ return true;
6459+ }
64596460 default:
64606461 break;
64616462 }
@@ -6974,7 +6975,8 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
69746975 ArrayRef<LocatorPathElt> path) {
69756976 // E.g. contextual conversion from coercion/cast
69766977 // to some other type.
6977- if (!path.empty())
6978+ if (!(path.empty() ||
6979+ path.back().is<LocatorPathElt::CoercionOperand>()))
69786980 return false;
69796981
69806982 return isExpr<CoerceExpr>(anchor) || isExpr<IsExpr>(anchor) ||
@@ -11339,7 +11341,7 @@ ConstraintSystem::simplifyBridgingConstraint(Type type1,
1133911341
1134011342 SmallVector<LocatorPathElt, 4> elts;
1134111343 auto anchor = locator.getLocatorParts(elts);
11342- if (! elts.empty())
11344+ if (elts.empty() || !elts.back().is<LocatorPathElt::CoercionOperand> ())
1134311345 return false;
1134411346
1134511347 auto *coercion = getAsExpr<CoerceExpr>(anchor);
0 commit comments