@@ -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