@@ -3908,9 +3908,8 @@ bool ConstraintSystem::repairFailures(
3908
3908
// If the result type of the coercion has an value to optional conversion
3909
3909
// we can instead suggest the conditional downcast as it is safer in
3910
3910
// 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) {
3914
3913
ConversionRestrictionKind restrictionKind;
3915
3914
Type type1, type2;
3916
3915
std::tie (type1, type2, restrictionKind) = restriction;
@@ -6717,7 +6716,9 @@ static bool isCastToExpressibleByNilLiteral(ConstraintSystem &cs, Type fromType,
6717
6716
static ConstraintFix *maybeWarnAboutExtraneousCast (
6718
6717
ConstraintSystem &cs, Type origFromType, Type origToType, Type fromType,
6719
6718
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,
6721
6722
ConstraintLocatorBuilder locator) {
6722
6723
6723
6724
auto last = locator.last ();
@@ -6739,6 +6740,18 @@ static ConstraintFix *maybeWarnAboutExtraneousCast(
6739
6740
// "from" could be less optional than "to" e.g. `0 as Any?`, so
6740
6741
// we need to store the difference as a signed integer.
6741
6742
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
+
6742
6755
// Removing the optionality from to type when the force cast expr is an IUO.
6743
6756
const auto *const TR = castExpr->getCastTypeRepr ();
6744
6757
if (isExpr<ForcedCheckedCastExpr>(anchor) && TR &&
@@ -6894,7 +6907,7 @@ ConstraintSystem::simplifyCheckedCastConstraint(
6894
6907
6895
6908
if (auto *fix = maybeWarnAboutExtraneousCast (
6896
6909
*this , origFromType, origToType, fromType, toType, fromOptionals,
6897
- toOptionals, flags, locator)) {
6910
+ toOptionals, ConstraintRestrictions, flags, locator)) {
6898
6911
(void )recordFix (fix);
6899
6912
}
6900
6913
};
@@ -6962,7 +6975,7 @@ ConstraintSystem::simplifyCheckedCastConstraint(
6962
6975
// succeed or fail.
6963
6976
if (auto *fix = maybeWarnAboutExtraneousCast (
6964
6977
*this , origFromType, origToType, fromType, toType, fromOptionals,
6965
- toOptionals, flags, locator)) {
6978
+ toOptionals, ConstraintRestrictions, flags, locator)) {
6966
6979
(void )recordFix (fix);
6967
6980
}
6968
6981
@@ -11372,7 +11385,8 @@ ConstraintSystem::simplifyRestrictedConstraint(
11372
11385
addFixConstraint (fix, matchKind, type1, type2, locator);
11373
11386
}
11374
11387
11375
- ConstraintRestrictions.push_back (std::make_tuple (type1, type2, restriction));
11388
+ ConstraintRestrictions.push_back (
11389
+ std::make_tuple (type1.getPointer (), type2.getPointer (), restriction));
11376
11390
return SolutionKind::Solved;
11377
11391
}
11378
11392
case SolutionKind::Unsolved:
0 commit comments