@@ -2597,6 +2597,68 @@ bool ConstraintSystem::isAsynchronousContext(DeclContext *dc) {
2597
2597
return false ;
2598
2598
}
2599
2599
2600
+ void ConstraintSystem::buildDisjunctionForOptionalVsUnderlying (
2601
+ Type boundTy, Type ty, ConstraintLocator *locator) {
2602
+ // NOTE: If we use other locator kinds for these disjunctions, we
2603
+ // need to account for it in solution scores for forced-unwraps.
2604
+ assert (locator->getPath ().back ().getKind () ==
2605
+ ConstraintLocator::ImplicitlyUnwrappedDisjunctionChoice ||
2606
+ locator->getPath ().back ().getKind () ==
2607
+ ConstraintLocator::DynamicLookupResult);
2608
+ assert (!ty->is <InOutType>());
2609
+ auto rvalueTy = ty->getWithoutSpecifierType ();
2610
+
2611
+ // If the type to bind is a placeholder, we can propagate it, as we don't know
2612
+ // whether it can be optional or non-optional, and we would have already
2613
+ // recorded a fix for it.
2614
+ if (rvalueTy->isPlaceholder ()) {
2615
+ addConstraint (ConstraintKind::Bind, boundTy, ty, locator);
2616
+ return ;
2617
+ }
2618
+
2619
+ // Create the constraint to bind to the optional type and make it the favored
2620
+ // choice.
2621
+ auto *bindToOptional =
2622
+ Constraint::create (*this , ConstraintKind::Bind, boundTy, ty, locator);
2623
+ bindToOptional->setFavored ();
2624
+
2625
+ Type underlyingType;
2626
+ if (auto *fnTy = ty->getAs <AnyFunctionType>())
2627
+ underlyingType = replaceFinalResultTypeWithUnderlying (fnTy);
2628
+ else if (auto *typeVar = rvalueTy->getAs <TypeVariableType>()) {
2629
+ auto *locator = typeVar->getImpl ().getLocator ();
2630
+
2631
+ // If `ty` hasn't been resolved yet, we need to allocate a type variable to
2632
+ // represent an object type of a future optional, and add a constraint
2633
+ // between `ty` and `underlyingType` to model it.
2634
+ underlyingType = createTypeVariable (
2635
+ getConstraintLocator (locator, LocatorPathElt::GenericArgument (0 )),
2636
+ TVO_PrefersSubtypeBinding | TVO_CanBindToLValue |
2637
+ TVO_CanBindToNoEscape);
2638
+
2639
+ // Using a `typeVar` here because l-value is going to be applied
2640
+ // to the underlying type below.
2641
+ addConstraint (ConstraintKind::OptionalObject, typeVar, underlyingType,
2642
+ locator);
2643
+ } else {
2644
+ underlyingType = rvalueTy->getOptionalObjectType ();
2645
+ }
2646
+
2647
+ assert (underlyingType);
2648
+
2649
+ if (ty->is <LValueType>())
2650
+ underlyingType = LValueType::get (underlyingType);
2651
+
2652
+ auto *bindToUnderlying = Constraint::create (*this , ConstraintKind::Bind,
2653
+ boundTy, underlyingType, locator);
2654
+
2655
+ llvm::SmallVector<Constraint *, 2 > choices = {bindToOptional,
2656
+ bindToUnderlying};
2657
+
2658
+ // Create the disjunction
2659
+ addDisjunctionConstraint (choices, locator, RememberChoice);
2660
+ }
2661
+
2600
2662
void ConstraintSystem::bindOverloadType (
2601
2663
const SelectedOverload &overload, Type boundType,
2602
2664
ConstraintLocator *locator, DeclContext *useDC,
0 commit comments