@@ -4725,6 +4725,9 @@ class ConstraintSystem {
47254725 using BindingScore =
47264726 std::tuple<bool , bool , bool , bool , bool , unsigned char , int >;
47274727
4728+ // / The constraint system this type variable and its bindings belong to.
4729+ ConstraintSystem &CS;
4730+
47284731 TypeVariableType *TypeVar;
47294732
47304733 // / The set of potential bindings.
@@ -4764,10 +4767,13 @@ class ConstraintSystem {
47644767 llvm::SmallMapVector<TypeVariableType *, Constraint *, 4 > SupertypeOf;
47654768 llvm::SmallMapVector<TypeVariableType *, Constraint *, 4 > EquivalentTo;
47664769
4767- PotentialBindings (TypeVariableType *typeVar) : TypeVar(typeVar) {}
4770+ PotentialBindings (ConstraintSystem &cs, TypeVariableType *typeVar)
4771+ : CS(cs), TypeVar(typeVar) {}
47684772
47694773 // / Determine whether the set of bindings is non-empty.
4770- explicit operator bool () const { return !Bindings.empty (); }
4774+ explicit operator bool () const {
4775+ return !Bindings.empty () || isDirectHole ();
4776+ }
47714777
47724778 // / Determine whether attempting this type variable should be
47734779 // / delayed until the rest of the constraint system is considered
@@ -4791,17 +4797,34 @@ class ConstraintSystem {
47914797 // / `bind param` are present in the system.
47924798 bool isPotentiallyIncomplete () const ;
47934799
4794- // / If there is only one binding and it's to a hole type, consider
4795- // / this type variable to be a hole in a constraint system regardless
4796- // / of where hole type originated.
4800+ // / If this type variable doesn't have any viable bindings, or
4801+ // / if there is only one binding and it's a hole type, consider
4802+ // / this type variable to be a hole in a constraint system
4803+ // / regardless of where hole type originated.
47974804 bool isHole () const {
4805+ if (isDirectHole ())
4806+ return true ;
4807+
47984808 if (Bindings.size () != 1 )
47994809 return false ;
48004810
4801- auto &binding = Bindings.front ();
4811+ const auto &binding = Bindings.front ();
48024812 return binding.BindingType ->is <HoleType>();
48034813 }
48044814
4815+ // / Determines whether the only possible binding for this type variable
4816+ // / would be a hole type. This is different from `isHole` method because
4817+ // / type variable could also acquire a hole type transitively if one
4818+ // / of the type variables in its subtype/equivalence chain has been
4819+ // / bound to a hole type.
4820+ bool isDirectHole () const {
4821+ // Direct holes are only allowed in "diagnostic mode".
4822+ if (!CS.shouldAttemptFixes ())
4823+ return false ;
4824+
4825+ return Bindings.empty () && TypeVar->getImpl ().canBindToHole ();
4826+ }
4827+
48054828 // / Determine if the bindings only constrain the type variable from above
48064829 // / with an existential type; such a binding is not very helpful because
48074830 // / it's impossible to enumerate the existential type's subtypes.
@@ -4816,22 +4839,26 @@ class ConstraintSystem {
48164839 }
48174840
48184841 unsigned getNumDefaultableBindings () const {
4819- return llvm::count_if (Bindings, [](const PotentialBinding &binding) {
4820- return binding.isDefaultableBinding ();
4821- });
4842+ return isDirectHole ()
4843+ ? 1
4844+ : llvm::count_if (Bindings,
4845+ [](const PotentialBinding &binding) {
4846+ return binding.isDefaultableBinding ();
4847+ });
48224848 }
48234849
48244850 static BindingScore formBindingScore (const PotentialBindings &b) {
48254851 auto numDefaults = b.getNumDefaultableBindings ();
4826- auto hasNoDefaultableBindings = b.Bindings .size () > numDefaults;
4852+ auto numNonDefaultableBindings =
4853+ b.isDirectHole () ? 0 : b.Bindings .size () - numDefaults;
48274854
48284855 return std::make_tuple (b.isHole (),
4829- !hasNoDefaultableBindings ,
4856+ numNonDefaultableBindings == 0 ,
48304857 b.isDelayed (),
48314858 b.isSubtypeOfExistentialType (),
48324859 b.involvesTypeVariables (),
48334860 static_cast <unsigned char >(b.LiteralBinding ),
4834- -(b. Bindings . size () - numDefaults) );
4861+ -numNonDefaultableBindings );
48354862 }
48364863
48374864 // / Compare two sets of bindings, where \c x < y indicates that
@@ -4847,8 +4874,10 @@ class ConstraintSystem {
48474874 if (yScore < xScore)
48484875 return false ;
48494876
4850- auto xDefaults = x.Bindings .size () + std::get<6 >(xScore);
4851- auto yDefaults = y.Bindings .size () + std::get<6 >(yScore);
4877+ auto xDefaults =
4878+ x.isDirectHole () ? 1 : x.Bindings .size () + std::get<6 >(xScore);
4879+ auto yDefaults =
4880+ y.isDirectHole () ? 1 : y.Bindings .size () + std::get<6 >(yScore);
48524881
48534882 // If there is a difference in number of default types,
48544883 // prioritize bindings with fewer of them.
@@ -4972,6 +5001,8 @@ class ConstraintSystem {
49725001 void dump (llvm::raw_ostream &out,
49735002 unsigned indent = 0 ) const LLVM_ATTRIBUTE_USED {
49745003 out.indent (indent);
5004+ if (isDirectHole ())
5005+ out << " hole " ;
49755006 if (isPotentiallyIncomplete ())
49765007 out << " potentially_incomplete " ;
49775008 if (isDelayed ())
@@ -5826,8 +5857,7 @@ class TypeVarBindingProducer : public BindingProducer<TypeVariableBinding> {
58265857public:
58275858 using Element = TypeVariableBinding;
58285859
5829- TypeVarBindingProducer (ConstraintSystem &cs,
5830- ConstraintSystem::PotentialBindings &bindings);
5860+ TypeVarBindingProducer (ConstraintSystem::PotentialBindings &bindings);
58315861
58325862 // / Retrieve a set of bindings available in the current state.
58335863 ArrayRef<Binding> getCurrentBindings () const { return Bindings; }
0 commit comments