@@ -5065,63 +5065,6 @@ bool ConstraintSystem::repairFailures(
5065
5065
if (!anchor)
5066
5066
return false;
5067
5067
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
-
5125
5068
// This could be:
5126
5069
// - `InOutExpr` used with r-value e.g. `foo(&x)` where `x` is a `let`.
5127
5070
// - `ForceValueExpr` e.g. `foo.bar! = 42` where `bar` or `foo` are
@@ -6456,6 +6399,64 @@ bool ConstraintSystem::repairFailures(
6456
6399
break;
6457
6400
}
6458
6401
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
+ }
6459
6460
default:
6460
6461
break;
6461
6462
}
@@ -6974,7 +6975,8 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
6974
6975
ArrayRef<LocatorPathElt> path) {
6975
6976
// E.g. contextual conversion from coercion/cast
6976
6977
// to some other type.
6977
- if (!path.empty())
6978
+ if (!(path.empty() ||
6979
+ path.back().is<LocatorPathElt::CoercionOperand>()))
6978
6980
return false;
6979
6981
6980
6982
return isExpr<CoerceExpr>(anchor) || isExpr<IsExpr>(anchor) ||
@@ -11339,7 +11341,7 @@ ConstraintSystem::simplifyBridgingConstraint(Type type1,
11339
11341
11340
11342
SmallVector<LocatorPathElt, 4> elts;
11341
11343
auto anchor = locator.getLocatorParts(elts);
11342
- if (! elts.empty())
11344
+ if (elts.empty() || !elts.back().is<LocatorPathElt::CoercionOperand> ())
11343
11345
return false;
11344
11346
11345
11347
auto *coercion = getAsExpr<CoerceExpr>(anchor);
0 commit comments