@@ -318,6 +318,14 @@ enum TypeVariableOptions {
318318
319319 // / Whether the type variable can be bound only to a pack expansion type.
320320 TVO_PackExpansion = 0x40 ,
321+
322+ // / Whether the hole for this type variable origates from a different
323+ // / type variable in its equivalence class.
324+ // / FIXME: This is an unfortunate hack due to the fact that choosing a
325+ // / different representative changes binding order and regresses a bunch of
326+ // / test cases. Once binding order is made more resilient we ought to be able
327+ // / to remove this.
328+ TVO_NonRepresentativeHole = 0x80 ,
321329};
322330
323331enum class KeyPathMutability : uint8_t {
@@ -397,6 +405,12 @@ class TypeVariableType::Implementation {
397405 // / Whether this type variable can bind only to PackExpansionType.
398406 bool isPackExpansion () const { return getRawOptions () & TVO_PackExpansion; }
399407
408+ // / Whether the hole for this type variable origates from a different
409+ // / type variable in its equivalence class.
410+ bool isNonRepresentativeHole () const {
411+ return getRawOptions () & TVO_NonRepresentativeHole;
412+ }
413+
400414 // / Whether this type variable prefers a subtype binding over a supertype
401415 // / binding.
402416 bool prefersSubtypeBinding () const {
@@ -565,28 +579,40 @@ class TypeVariableType::Implementation {
565579 otherRep->getImpl ().recordBinding (*trail);
566580 otherRep->getImpl ().ParentOrFixed = getTypeVariable ();
567581
582+ auto &bits = getTypeVariable ()->Bits .TypeVariableType ;
583+
568584 if (canBindToLValue () && !otherRep->getImpl ().canBindToLValue ()) {
569585 if (trail)
570586 recordBinding (*trail);
571- getTypeVariable ()-> Bits . TypeVariableType .Options &= ~TVO_CanBindToLValue;
587+ bits .Options &= ~TVO_CanBindToLValue;
572588 }
573589
574590 if (canBindToInOut () && !otherRep->getImpl ().canBindToInOut ()) {
575591 if (trail)
576592 recordBinding (*trail);
577- getTypeVariable ()-> Bits . TypeVariableType .Options &= ~TVO_CanBindToInOut;
593+ bits .Options &= ~TVO_CanBindToInOut;
578594 }
579595
580596 if (canBindToNoEscape () && !otherRep->getImpl ().canBindToNoEscape ()) {
581597 if (trail)
582598 recordBinding (*trail);
583- getTypeVariable ()-> Bits . TypeVariableType .Options &= ~TVO_CanBindToNoEscape;
599+ bits .Options &= ~TVO_CanBindToNoEscape;
584600 }
585601
586602 if (canBindToPack () && !otherRep->getImpl ().canBindToPack ()) {
587603 if (trail)
588604 recordBinding (*trail);
589- getTypeVariable ()->Bits .TypeVariableType .Options &= ~TVO_CanBindToPack;
605+ bits.Options &= ~TVO_CanBindToPack;
606+ }
607+
608+ // If we're merging a non-hole with a hole, add the flag to allow binding
609+ // to a hole. This type variable then becomes a "non-representative" hole,
610+ // which is an unfortunate hack necessary to preserve binding order. See
611+ // the comment on `TVO_NonRepresentativeHole` for more info.
612+ if (!canBindToHole () && otherRep->getImpl ().canBindToHole ()) {
613+ if (trail)
614+ recordBinding (*trail);
615+ bits.Options |= (TVO_CanBindToHole | TVO_NonRepresentativeHole);
590616 }
591617 }
592618
@@ -701,6 +727,7 @@ class TypeVariableType::Implementation {
701727 ENTRY (TVO_PrefersSubtypeBinding, " " );
702728 ENTRY (TVO_CanBindToPack, " pack" );
703729 ENTRY (TVO_PackExpansion, " pack expansion" );
730+ ENTRY (TVO_NonRepresentativeHole, " non-rep hole" );
704731 }
705732 #undef ENTRY
706733 }
@@ -3419,6 +3446,14 @@ class ConstraintSystem {
34193446 getImplicitValueConversionLocator (ConstraintLocatorBuilder root,
34203447 ConversionRestrictionKind restriction);
34213448
3449+ // / Retrieve the type variable that represents the originating hole in the
3450+ // / equivalence class for a given type variable.
3451+ TypeVariableType *getHoleTypeVar (TypeVariableType *tv);
3452+
3453+ // / Retrieve the locator for the hole that represents the originating hole in
3454+ // / the equivalence class for a given type variable.
3455+ ConstraintLocator *getHoleLocator (TypeVariableType *tv);
3456+
34223457 // / Lookup and return parent associated with given expression.
34233458 Expr *getParentExpr (Expr *expr) {
34243459 if (auto result = getExprDepthAndParent (expr))
0 commit comments