@@ -2395,13 +2395,6 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
2395
2395
continue ;
2396
2396
}
2397
2397
2398
- // If the first thing we found is a fix, add a "don't fix" marker.
2399
- if (conversionsOrFixes.empty ()) {
2400
- constraints.push_back (
2401
- Constraint::createFixed (*this , constraintKind, FixKind::None,
2402
- type1, type2, fixedLocator));
2403
- }
2404
-
2405
2398
auto fix = *potential.getFix ();
2406
2399
constraints.push_back (
2407
2400
Constraint::createFixed (*this , constraintKind, fix, type1, type2,
@@ -4193,7 +4186,21 @@ ConstraintSystem::simplifyApplicableFnConstraint(
4193
4186
ConstraintLocatorBuilder outerLocator =
4194
4187
getConstraintLocator (anchor, parts, locator.getSummaryFlags ());
4195
4188
4196
- retry:
4189
+ unsigned unwrapCount = 0 ;
4190
+ if (shouldAttemptFixes ()) {
4191
+ // If we have an optional type, try forcing it to see if that
4192
+ // helps. Note that we only deal with function and metatype types
4193
+ // below, so there is no reason not to attempt to strip these off
4194
+ // immediately.
4195
+ while (auto objectType2 = desugar2->getOptionalObjectType ()) {
4196
+ type2 = objectType2;
4197
+ desugar2 = type2->getDesugaredType ();
4198
+
4199
+ // Track how many times we do this so that we can record a fix for each.
4200
+ ++unwrapCount;
4201
+ }
4202
+ }
4203
+
4197
4204
// For a function, bind the output and convert the argument to the input.
4198
4205
auto func1 = type1->castTo <FunctionType>();
4199
4206
if (auto func2 = dyn_cast<FunctionType>(desugar2)) {
@@ -4221,6 +4228,11 @@ ConstraintSystem::simplifyApplicableFnConstraint(
4221
4228
== SolutionKind::Error)
4222
4229
return SolutionKind::Error;
4223
4230
4231
+ // Record any fixes we attempted to get to the correct solution.
4232
+ while (unwrapCount-- > 0 )
4233
+ if (recordFix (FixKind::ForceOptional, getConstraintLocator (locator)))
4234
+ return SolutionKind::Error;
4235
+
4224
4236
return SolutionKind::Solved;
4225
4237
}
4226
4238
@@ -4231,23 +4243,18 @@ ConstraintSystem::simplifyApplicableFnConstraint(
4231
4243
return formUnsolved ();
4232
4244
4233
4245
// Construct the instance from the input arguments.
4234
- return simplifyConstructionConstraint (instance2, func1, subflags,
4246
+ auto simplified = simplifyConstructionConstraint (instance2, func1, subflags,
4235
4247
/* FIXME?*/ DC,
4236
4248
FunctionRefKind::SingleApply,
4237
4249
getConstraintLocator (outerLocator));
4238
- }
4239
-
4240
- if (!shouldAttemptFixes ())
4241
- return SolutionKind::Error;
4242
4250
4243
- // If we're coming from an optional type, unwrap the optional and try again.
4244
- if (auto objectType2 = desugar2->getOptionalObjectType ()) {
4245
- if (recordFix (FixKind::ForceOptional, getConstraintLocator (locator)))
4246
- return SolutionKind::Error;
4251
+ // Record any fixes we attempted to get to the correct solution.
4252
+ if (simplified == SolutionKind::Solved)
4253
+ while (unwrapCount-- > 0 )
4254
+ if (recordFix (FixKind::ForceOptional, getConstraintLocator (locator)))
4255
+ return SolutionKind::Error;
4247
4256
4248
- type2 = objectType2;
4249
- desugar2 = type2->getDesugaredType ();
4250
- goto retry;
4257
+ return simplified;
4251
4258
}
4252
4259
4253
4260
return SolutionKind::Error;
@@ -4729,15 +4736,15 @@ bool ConstraintSystem::recordFix(Fix fix, ConstraintLocatorBuilder locator) {
4729
4736
}
4730
4737
4731
4738
// Record the fix.
4732
- if (fix.getKind () != FixKind::None) {
4733
- // Increase the score. If this would make the current solution worse than
4734
- // the best solution we've seen already, stop now.
4735
- increaseScore (SK_Fix);
4736
- if (worseThanBestSolution ())
4737
- return true ;
4738
4739
4739
- Fixes.push_back ({fix, getConstraintLocator (locator)});
4740
- }
4740
+ // Increase the score. If this would make the current solution worse than
4741
+ // the best solution we've seen already, stop now.
4742
+ increaseScore (SK_Fix);
4743
+ if (worseThanBestSolution ())
4744
+ return true ;
4745
+
4746
+ Fixes.push_back ({fix, getConstraintLocator (locator)});
4747
+
4741
4748
return false ;
4742
4749
}
4743
4750
@@ -4746,31 +4753,40 @@ ConstraintSystem::simplifyFixConstraint(Fix fix, Type type1, Type type2,
4746
4753
ConstraintKind matchKind,
4747
4754
TypeMatchOptions flags,
4748
4755
ConstraintLocatorBuilder locator) {
4749
- if (recordFix (fix, locator))
4750
- return SolutionKind::Error;
4751
-
4752
4756
// Try with the fix.
4753
4757
TypeMatchOptions subflags =
4754
4758
getDefaultDecompositionOptions (flags) | TMF_ApplyingFix;
4755
4759
switch (fix.getKind ()) {
4756
- case FixKind::None:
4757
- return matchTypes (type1, type2, matchKind, subflags, locator);
4758
-
4759
4760
case FixKind::ForceOptional:
4760
- case FixKind::OptionalChaining:
4761
+ case FixKind::OptionalChaining: {
4761
4762
// Assume that '!' was applied to the first type.
4762
- return matchTypes (type1->getRValueObjectType ()->getOptionalObjectType (),
4763
- type2, matchKind, subflags, locator);
4763
+ auto result =
4764
+ matchTypes (type1->getRValueObjectType ()->getOptionalObjectType (), type2,
4765
+ matchKind, subflags, locator);
4766
+ if (result == SolutionKind::Solved)
4767
+ if (recordFix (fix, locator))
4768
+ return SolutionKind::Error;
4764
4769
4770
+ return result;
4771
+ }
4765
4772
case FixKind::ForceDowncast:
4766
4773
// These work whenever they are suggested.
4774
+ if (recordFix (fix, locator))
4775
+ return SolutionKind::Error;
4776
+
4767
4777
return SolutionKind::Solved;
4768
4778
4769
- case FixKind::AddressOf:
4779
+ case FixKind::AddressOf: {
4770
4780
// Assume that '&' was applied to the first type, turning an lvalue into
4771
4781
// an inout.
4772
- return matchTypes (InOutType::get (type1->getRValueType ()), type2,
4773
- matchKind, subflags, locator);
4782
+ auto result = matchTypes (InOutType::get (type1->getRValueType ()), type2,
4783
+ matchKind, subflags, locator);
4784
+ if (result == SolutionKind::Solved)
4785
+ if (recordFix (fix, locator))
4786
+ return SolutionKind::Error;
4787
+
4788
+ return result;
4789
+ }
4774
4790
4775
4791
case FixKind::CoerceToCheckedCast:
4776
4792
llvm_unreachable (" handled elsewhere" );
0 commit comments