@@ -4725,6 +4725,9 @@ class ConstraintSystem {
4725
4725
using BindingScore =
4726
4726
std::tuple<bool , bool , bool , bool , bool , unsigned char , int >;
4727
4727
4728
+ // / The constraint system this type variable and its bindings belong to.
4729
+ ConstraintSystem &CS;
4730
+
4728
4731
TypeVariableType *TypeVar;
4729
4732
4730
4733
// / The set of potential bindings.
@@ -4764,10 +4767,13 @@ class ConstraintSystem {
4764
4767
llvm::SmallMapVector<TypeVariableType *, Constraint *, 4 > SupertypeOf;
4765
4768
llvm::SmallMapVector<TypeVariableType *, Constraint *, 4 > EquivalentTo;
4766
4769
4767
- PotentialBindings (TypeVariableType *typeVar) : TypeVar(typeVar) {}
4770
+ PotentialBindings (ConstraintSystem &cs, TypeVariableType *typeVar)
4771
+ : CS(cs), TypeVar(typeVar) {}
4768
4772
4769
4773
// / 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
+ }
4771
4777
4772
4778
// / Determine whether attempting this type variable should be
4773
4779
// / delayed until the rest of the constraint system is considered
@@ -4791,17 +4797,34 @@ class ConstraintSystem {
4791
4797
// / `bind param` are present in the system.
4792
4798
bool isPotentiallyIncomplete () const ;
4793
4799
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.
4797
4804
bool isHole () const {
4805
+ if (isDirectHole ())
4806
+ return true ;
4807
+
4798
4808
if (Bindings.size () != 1 )
4799
4809
return false ;
4800
4810
4801
- auto &binding = Bindings.front ();
4811
+ const auto &binding = Bindings.front ();
4802
4812
return binding.BindingType ->is <HoleType>();
4803
4813
}
4804
4814
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
+
4805
4828
// / Determine if the bindings only constrain the type variable from above
4806
4829
// / with an existential type; such a binding is not very helpful because
4807
4830
// / it's impossible to enumerate the existential type's subtypes.
@@ -4816,22 +4839,26 @@ class ConstraintSystem {
4816
4839
}
4817
4840
4818
4841
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
+ });
4822
4848
}
4823
4849
4824
4850
static BindingScore formBindingScore (const PotentialBindings &b) {
4825
4851
auto numDefaults = b.getNumDefaultableBindings ();
4826
- auto hasNoDefaultableBindings = b.Bindings .size () > numDefaults;
4852
+ auto numNonDefaultableBindings =
4853
+ b.isDirectHole () ? 0 : b.Bindings .size () - numDefaults;
4827
4854
4828
4855
return std::make_tuple (b.isHole (),
4829
- !hasNoDefaultableBindings ,
4856
+ numNonDefaultableBindings == 0 ,
4830
4857
b.isDelayed (),
4831
4858
b.isSubtypeOfExistentialType (),
4832
4859
b.involvesTypeVariables (),
4833
4860
static_cast <unsigned char >(b.LiteralBinding ),
4834
- -(b. Bindings . size () - numDefaults) );
4861
+ -numNonDefaultableBindings );
4835
4862
}
4836
4863
4837
4864
// / Compare two sets of bindings, where \c x < y indicates that
@@ -4847,8 +4874,10 @@ class ConstraintSystem {
4847
4874
if (yScore < xScore)
4848
4875
return false ;
4849
4876
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);
4852
4881
4853
4882
// If there is a difference in number of default types,
4854
4883
// prioritize bindings with fewer of them.
@@ -4972,6 +5001,8 @@ class ConstraintSystem {
4972
5001
void dump (llvm::raw_ostream &out,
4973
5002
unsigned indent = 0 ) const LLVM_ATTRIBUTE_USED {
4974
5003
out.indent (indent);
5004
+ if (isDirectHole ())
5005
+ out << " hole " ;
4975
5006
if (isPotentiallyIncomplete ())
4976
5007
out << " potentially_incomplete " ;
4977
5008
if (isDelayed ())
@@ -5826,8 +5857,7 @@ class TypeVarBindingProducer : public BindingProducer<TypeVariableBinding> {
5826
5857
public:
5827
5858
using Element = TypeVariableBinding;
5828
5859
5829
- TypeVarBindingProducer (ConstraintSystem &cs,
5830
- ConstraintSystem::PotentialBindings &bindings);
5860
+ TypeVarBindingProducer (ConstraintSystem::PotentialBindings &bindings);
5831
5861
5832
5862
// / Retrieve a set of bindings available in the current state.
5833
5863
ArrayRef<Binding> getCurrentBindings () const { return Bindings; }
0 commit comments