@@ -4741,7 +4741,7 @@ class ConstraintSystem {
4741
4741
Optional<llvm::SmallPtrSet<Constraint *, 4 >> TransitiveProtocols;
4742
4742
4743
4743
// / The set of constraints which would be used to infer default types.
4744
- llvm::TinyPtrVector< Constraint *> Defaults;
4744
+ llvm::SmallDenseMap<CanType, Constraint *, 2 > Defaults;
4745
4745
4746
4746
// / The set of constraints which delay attempting this type variable.
4747
4747
llvm::TinyPtrVector<Constraint *> DelayedBy;
@@ -4772,7 +4772,7 @@ class ConstraintSystem {
4772
4772
4773
4773
// / Determine whether the set of bindings is non-empty.
4774
4774
explicit operator bool () const {
4775
- return !Bindings.empty () || isDirectHole ();
4775
+ return !Bindings.empty () || !Defaults. empty () || isDirectHole ();
4776
4776
}
4777
4777
4778
4778
// / Determine whether attempting this type variable should be
@@ -4822,7 +4822,8 @@ class ConstraintSystem {
4822
4822
if (!CS.shouldAttemptFixes ())
4823
4823
return false ;
4824
4824
4825
- return Bindings.empty () && TypeVar->getImpl ().canBindToHole ();
4825
+ return Bindings.empty () && Defaults.empty () &&
4826
+ TypeVar->getImpl ().canBindToHole ();
4826
4827
}
4827
4828
4828
4829
// / Determine if the bindings only constrain the type variable from above
@@ -4838,19 +4839,38 @@ class ConstraintSystem {
4838
4839
});
4839
4840
}
4840
4841
4841
- unsigned getNumDefaultableBindings () const {
4842
- return isDirectHole ()
4843
- ? 1
4844
- : llvm::count_if (Bindings,
4845
- [](const PotentialBinding &binding) {
4846
- return binding.isDefaultableBinding ();
4847
- });
4842
+ unsigned getNumViableDefaultableBindings () const {
4843
+ if (isDirectHole ())
4844
+ return 1 ;
4845
+
4846
+ // We might want to consider adding this as a field to `PotentialBindings`
4847
+ // and collect this information as new bindings become available but,
4848
+ // since we are moving towards incremental model, which implies that
4849
+ // `PotentialBindings` would stay alive for a long time, it's not
4850
+ // immediately clear whether storage overhead of keeping this set just
4851
+ // for ranking is worth it.
4852
+ llvm::SmallPtrSet<CanType, 4 > discoveredTypes;
4853
+ for (const auto &binding : Bindings)
4854
+ discoveredTypes.insert (binding.BindingType ->getCanonicalType ());
4855
+
4856
+ return llvm::count_if (
4857
+ Defaults, [&](const std::pair<CanType, Constraint *> &def) {
4858
+ return def.second ->getKind () == ConstraintKind::Defaultable &&
4859
+ discoveredTypes.count (def.first ) == 0 ;
4860
+ });
4848
4861
}
4849
4862
4850
4863
static BindingScore formBindingScore (const PotentialBindings &b) {
4851
- auto numDefaults = b.getNumDefaultableBindings ();
4864
+ // If there are no bindings available but this type
4865
+ // variable represents a closure - let's consider it
4866
+ // as having a single non-default binding - that would
4867
+ // be a type inferred based on context.
4868
+ // It's considered to be non-default for purposes of
4869
+ // ranking because we'd like to prioritize resolving
4870
+ // closures to gain more information from their bodies.
4852
4871
auto numNonDefaultableBindings =
4853
- b.isDirectHole () ? 0 : b.Bindings .size () - numDefaults;
4872
+ !b.Bindings .empty () ? b.Bindings .size ()
4873
+ : b.TypeVar ->getImpl ().isClosureType () ? 1 : 0 ;
4854
4874
4855
4875
return std::make_tuple (b.isHole (),
4856
4876
numNonDefaultableBindings == 0 ,
@@ -4874,10 +4894,8 @@ class ConstraintSystem {
4874
4894
if (yScore < xScore)
4875
4895
return false ;
4876
4896
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);
4897
+ auto xDefaults = x.getNumViableDefaultableBindings ();
4898
+ auto yDefaults = y.getNumViableDefaultableBindings ();
4881
4899
4882
4900
// If there is a difference in number of default types,
4883
4901
// prioritize bindings with fewer of them.
@@ -4922,6 +4940,8 @@ class ConstraintSystem {
4922
4940
}
4923
4941
}
4924
4942
4943
+ void addDefault (Constraint *constraint);
4944
+
4925
4945
// / Add a potential binding to the list of bindings,
4926
4946
// / coalescing supertype bounds when we are able to compute the meet.
4927
4947
void addPotentialBinding (PotentialBinding binding,
@@ -5014,34 +5034,46 @@ class ConstraintSystem {
5014
5034
if (involvesTypeVariables ())
5015
5035
out << " involves_type_vars " ;
5016
5036
5017
- auto numDefaultable = getNumDefaultableBindings ();
5037
+ auto numDefaultable = getNumViableDefaultableBindings ();
5018
5038
if (numDefaultable > 0 )
5019
5039
out << " #defaultable_bindings=" << numDefaultable << " " ;
5020
5040
5021
5041
PrintOptions PO;
5022
5042
PO.PrintTypesForDebugging = true ;
5043
+
5044
+ auto printBinding = [&](const PotentialBinding &binding) {
5045
+ auto type = binding.BindingType ;
5046
+ switch (binding.Kind ) {
5047
+ case AllowedBindingKind::Exact:
5048
+ break ;
5049
+
5050
+ case AllowedBindingKind::Subtypes:
5051
+ out << " (subtypes of) " ;
5052
+ break ;
5053
+
5054
+ case AllowedBindingKind::Supertypes:
5055
+ out << " (supertypes of) " ;
5056
+ break ;
5057
+ }
5058
+ if (auto *literal = binding.getDefaultedLiteralProtocol ())
5059
+ out << " (default from " << literal->getName () << " ) " ;
5060
+ out << type.getString (PO);
5061
+ };
5062
+
5023
5063
out << " bindings={" ;
5024
- interleave (Bindings,
5025
- [&](const PotentialBinding &binding) {
5026
- auto type = binding.BindingType ;
5027
- switch (binding.Kind ) {
5028
- case AllowedBindingKind::Exact:
5029
- break ;
5030
-
5031
- case AllowedBindingKind::Subtypes:
5032
- out << " (subtypes of) " ;
5033
- break ;
5034
-
5035
- case AllowedBindingKind::Supertypes:
5036
- out << " (supertypes of) " ;
5037
- break ;
5038
- }
5039
- if (auto *literal = binding.getDefaultedLiteralProtocol ())
5040
- out << " (default from " << literal->getName () << " ) " ;
5041
- out << type.getString (PO);
5042
- },
5043
- [&]() { out << " ; " ; });
5064
+ interleave (Bindings, printBinding, [&]() { out << " ; " ; });
5044
5065
out << " }" ;
5066
+
5067
+ if (!Defaults.empty ()) {
5068
+ out << " defaults={" ;
5069
+ for (const auto &entry : Defaults) {
5070
+ auto *constraint = entry.second ;
5071
+ PotentialBinding binding{constraint->getSecondType (),
5072
+ AllowedBindingKind::Exact, constraint};
5073
+ printBinding (binding);
5074
+ }
5075
+ out << " }" ;
5076
+ }
5045
5077
}
5046
5078
5047
5079
void dump (ConstraintSystem *cs,
@@ -5839,6 +5871,9 @@ class TypeVarBindingProducer : public BindingProducer<TypeVariableBinding> {
5839
5871
5840
5872
TypeVariableType *TypeVar;
5841
5873
llvm::SmallVector<Binding, 8 > Bindings;
5874
+ // / The set of defaults to attempt once producer
5875
+ // / runs out of direct & transitive bindings.
5876
+ llvm::SmallVector<Constraint *, 4 > DelayedDefaults;
5842
5877
5843
5878
// The index pointing to the offset in the bindings
5844
5879
// generator is currently at, `numTries` represents
@@ -5886,6 +5921,8 @@ class TypeVarBindingProducer : public BindingProducer<TypeVariableBinding> {
5886
5921
// / Check whether binding type is required to either conform to
5887
5922
// / `ExpressibleByNilLiteral` protocol or be wrapped into an optional type.
5888
5923
bool requiresOptionalAdjustment (const Binding &binding) const ;
5924
+
5925
+ Binding getDefaultBinding (Constraint *constraint) const ;
5889
5926
};
5890
5927
5891
5928
// / Iterator over disjunction choices, makes it
0 commit comments