@@ -3908,9 +3908,8 @@ bool ConstraintSystem::repairFailures(
39083908 // If the result type of the coercion has an value to optional conversion
39093909 // we can instead suggest the conditional downcast as it is safer in
39103910 // situations like conditional binding.
3911- auto useConditionalCast = llvm::any_of (
3912- ConstraintRestrictions,
3913- [&](std::tuple<Type, Type, ConversionRestrictionKind> restriction) {
3911+ auto useConditionalCast =
3912+ llvm::any_of (ConstraintRestrictions, [&](auto &restriction) {
39143913 ConversionRestrictionKind restrictionKind;
39153914 Type type1, type2;
39163915 std::tie (type1, type2, restrictionKind) = restriction;
@@ -6717,7 +6716,9 @@ static bool isCastToExpressibleByNilLiteral(ConstraintSystem &cs, Type fromType,
67176716static ConstraintFix *maybeWarnAboutExtraneousCast (
67186717 ConstraintSystem &cs, Type origFromType, Type origToType, Type fromType,
67196718 Type toType, SmallVector<Type, 4 > fromOptionals,
6720- SmallVector<Type, 4 > toOptionals, ConstraintSystem::TypeMatchOptions flags,
6719+ SmallVector<Type, 4 > toOptionals,
6720+ const std::vector<ConversionRestriction> &constraintRestrictions,
6721+ ConstraintSystem::TypeMatchOptions flags,
67216722 ConstraintLocatorBuilder locator) {
67226723
67236724 auto last = locator.last ();
@@ -6739,6 +6740,18 @@ static ConstraintFix *maybeWarnAboutExtraneousCast(
67396740 // "from" could be less optional than "to" e.g. `0 as Any?`, so
67406741 // we need to store the difference as a signed integer.
67416742 int extraOptionals = fromOptionals.size () - toOptionals.size ();
6743+
6744+ // "from" expression could be a type variable with value-to-optional
6745+ // restrictions that we have to account for optionality mismatch.
6746+ const auto subExprType = cs.getType (castExpr->getSubExpr ());
6747+ if (llvm::is_contained (
6748+ constraintRestrictions,
6749+ std::make_tuple (fromType.getPointer (), subExprType.getPointer (),
6750+ ConversionRestrictionKind::ValueToOptional))) {
6751+ extraOptionals++;
6752+ origFromType = OptionalType::get (origFromType);
6753+ }
6754+
67426755 // Removing the optionality from to type when the force cast expr is an IUO.
67436756 const auto *const TR = castExpr->getCastTypeRepr ();
67446757 if (isExpr<ForcedCheckedCastExpr>(anchor) && TR &&
@@ -6894,7 +6907,7 @@ ConstraintSystem::simplifyCheckedCastConstraint(
68946907
68956908 if (auto *fix = maybeWarnAboutExtraneousCast (
68966909 *this , origFromType, origToType, fromType, toType, fromOptionals,
6897- toOptionals, flags, locator)) {
6910+ toOptionals, ConstraintRestrictions, flags, locator)) {
68986911 (void )recordFix (fix);
68996912 }
69006913 };
@@ -6962,7 +6975,7 @@ ConstraintSystem::simplifyCheckedCastConstraint(
69626975 // succeed or fail.
69636976 if (auto *fix = maybeWarnAboutExtraneousCast (
69646977 *this , origFromType, origToType, fromType, toType, fromOptionals,
6965- toOptionals, flags, locator)) {
6978+ toOptionals, ConstraintRestrictions, flags, locator)) {
69666979 (void )recordFix (fix);
69676980 }
69686981
@@ -11372,7 +11385,8 @@ ConstraintSystem::simplifyRestrictedConstraint(
1137211385 addFixConstraint (fix, matchKind, type1, type2, locator);
1137311386 }
1137411387
11375- ConstraintRestrictions.push_back (std::make_tuple (type1, type2, restriction));
11388+ ConstraintRestrictions.push_back (
11389+ std::make_tuple (type1.getPointer (), type2.getPointer (), restriction));
1137611390 return SolutionKind::Solved;
1137711391 }
1137811392 case SolutionKind::Unsolved:
0 commit comments