Skip to content

Commit 3e1b01a

Browse files
authored
Merge pull request swiftlang#35098 from xedin/dont-precompute-default-bindings
[CSBindings] Don't generate bindings for defaults
2 parents 81ef1bd + b7bdda4 commit 3e1b01a

File tree

3 files changed

+138
-59
lines changed

3 files changed

+138
-59
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 81 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -4741,7 +4741,7 @@ class ConstraintSystem {
47414741
Optional<llvm::SmallPtrSet<Constraint *, 4>> TransitiveProtocols;
47424742

47434743
/// The set of constraints which would be used to infer default types.
4744-
llvm::TinyPtrVector<Constraint *> Defaults;
4744+
llvm::SmallDenseMap<CanType, Constraint *, 2> Defaults;
47454745

47464746
/// The set of constraints which delay attempting this type variable.
47474747
llvm::TinyPtrVector<Constraint *> DelayedBy;
@@ -4772,7 +4772,7 @@ class ConstraintSystem {
47724772

47734773
/// Determine whether the set of bindings is non-empty.
47744774
explicit operator bool() const {
4775-
return !Bindings.empty() || isDirectHole();
4775+
return !Bindings.empty() || !Defaults.empty() || isDirectHole();
47764776
}
47774777

47784778
/// Determine whether attempting this type variable should be
@@ -4822,7 +4822,8 @@ class ConstraintSystem {
48224822
if (!CS.shouldAttemptFixes())
48234823
return false;
48244824

4825-
return Bindings.empty() && TypeVar->getImpl().canBindToHole();
4825+
return Bindings.empty() && Defaults.empty() &&
4826+
TypeVar->getImpl().canBindToHole();
48264827
}
48274828

48284829
/// Determine if the bindings only constrain the type variable from above
@@ -4838,19 +4839,45 @@ class ConstraintSystem {
48384839
});
48394840
}
48404841

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+
auto numDefaultable = llvm::count_if(
4847+
Defaults, [](const std::pair<CanType, Constraint *> &entry) {
4848+
return entry.second->getKind() == ConstraintKind::Defaultable;
4849+
});
4850+
4851+
// Short-circuit unviable checks if there are no defaultable bindings.
4852+
if (numDefaultable == 0)
4853+
return 0;
4854+
4855+
// Defaultable constraint is unviable if its type is covered by
4856+
// an existing direct or transitive binding.
4857+
auto unviable =
4858+
llvm::count_if(Bindings, [&](const PotentialBinding &binding) {
4859+
auto type = binding.BindingType->getCanonicalType();
4860+
auto def = Defaults.find(type);
4861+
return def != Defaults.end()
4862+
? def->second->getKind() == ConstraintKind::Defaultable
4863+
: false;
4864+
});
4865+
4866+
assert(numDefaultable >= unviable);
4867+
return numDefaultable - unviable;
48484868
}
48494869

48504870
static BindingScore formBindingScore(const PotentialBindings &b) {
4851-
auto numDefaults = b.getNumDefaultableBindings();
4871+
// If there are no bindings available but this type
4872+
// variable represents a closure - let's consider it
4873+
// as having a single non-default binding - that would
4874+
// be a type inferred based on context.
4875+
// It's considered to be non-default for purposes of
4876+
// ranking because we'd like to prioritize resolving
4877+
// closures to gain more information from their bodies.
48524878
auto numNonDefaultableBindings =
4853-
b.isDirectHole() ? 0 : b.Bindings.size() - numDefaults;
4879+
!b.Bindings.empty() ? b.Bindings.size()
4880+
: b.TypeVar->getImpl().isClosureType() ? 1 : 0;
48544881

48554882
return std::make_tuple(b.isHole(),
48564883
numNonDefaultableBindings == 0,
@@ -4874,10 +4901,8 @@ class ConstraintSystem {
48744901
if (yScore < xScore)
48754902
return false;
48764903

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);
4904+
auto xDefaults = x.getNumViableDefaultableBindings();
4905+
auto yDefaults = y.getNumViableDefaultableBindings();
48814906

48824907
// If there is a difference in number of default types,
48834908
// prioritize bindings with fewer of them.
@@ -4922,6 +4947,8 @@ class ConstraintSystem {
49224947
}
49234948
}
49244949

4950+
void addDefault(Constraint *constraint);
4951+
49254952
/// Add a potential binding to the list of bindings,
49264953
/// coalescing supertype bounds when we are able to compute the meet.
49274954
void addPotentialBinding(PotentialBinding binding,
@@ -5014,34 +5041,46 @@ class ConstraintSystem {
50145041
if (involvesTypeVariables())
50155042
out << "involves_type_vars ";
50165043

5017-
auto numDefaultable = getNumDefaultableBindings();
5044+
auto numDefaultable = getNumViableDefaultableBindings();
50185045
if (numDefaultable > 0)
50195046
out << "#defaultable_bindings=" << numDefaultable << " ";
50205047

50215048
PrintOptions PO;
50225049
PO.PrintTypesForDebugging = true;
5050+
5051+
auto printBinding = [&](const PotentialBinding &binding) {
5052+
auto type = binding.BindingType;
5053+
switch (binding.Kind) {
5054+
case AllowedBindingKind::Exact:
5055+
break;
5056+
5057+
case AllowedBindingKind::Subtypes:
5058+
out << "(subtypes of) ";
5059+
break;
5060+
5061+
case AllowedBindingKind::Supertypes:
5062+
out << "(supertypes of) ";
5063+
break;
5064+
}
5065+
if (auto *literal = binding.getDefaultedLiteralProtocol())
5066+
out << "(default from " << literal->getName() << ") ";
5067+
out << type.getString(PO);
5068+
};
5069+
50235070
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 << "; "; });
5071+
interleave(Bindings, printBinding, [&]() { out << "; "; });
50445072
out << "}";
5073+
5074+
if (!Defaults.empty()) {
5075+
out << " defaults={";
5076+
for (const auto &entry : Defaults) {
5077+
auto *constraint = entry.second;
5078+
PotentialBinding binding{constraint->getSecondType(),
5079+
AllowedBindingKind::Exact, constraint};
5080+
printBinding(binding);
5081+
}
5082+
out << "}";
5083+
}
50455084
}
50465085

50475086
void dump(ConstraintSystem *cs,
@@ -5839,6 +5878,9 @@ class TypeVarBindingProducer : public BindingProducer<TypeVariableBinding> {
58395878

58405879
TypeVariableType *TypeVar;
58415880
llvm::SmallVector<Binding, 8> Bindings;
5881+
/// The set of defaults to attempt once producer
5882+
/// runs out of direct & transitive bindings.
5883+
llvm::SmallVector<Constraint *, 4> DelayedDefaults;
58425884

58435885
// The index pointing to the offset in the bindings
58445886
// generator is currently at, `numTries` represents
@@ -5886,6 +5928,8 @@ class TypeVarBindingProducer : public BindingProducer<TypeVariableBinding> {
58865928
/// Check whether binding type is required to either conform to
58875929
/// `ExpressibleByNilLiteral` protocol or be wrapped into an optional type.
58885930
bool requiresOptionalAdjustment(const Binding &binding) const;
5931+
5932+
Binding getDefaultBinding(Constraint *constraint) const;
58895933
};
58905934

58915935
/// Iterator over disjunction choices, makes it

lib/Sema/CSBindings.cpp

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -319,7 +319,8 @@ void ConstraintSystem::PotentialBindings::inferTransitiveBindings(
319319
});
320320

321321
// Infer transitive defaults.
322-
llvm::copy(bindings.Defaults, std::back_inserter(Defaults));
322+
for (const auto &def : bindings.Defaults)
323+
addDefault(def.second);
323324

324325
// TODO: We shouldn't need this in the future.
325326
if (entry.second->getKind() != ConstraintKind::Subtype)
@@ -513,24 +514,6 @@ void ConstraintSystem::PotentialBindings::inferDefaultTypes(
513514
: AllowedBindingKind::Supertypes,
514515
constraint});
515516
}
516-
517-
/// Add defaultable constraints.
518-
for (auto *constraint : Defaults) {
519-
Type type = constraint->getSecondType();
520-
if (!existingTypes.insert(type->getCanonicalType()).second)
521-
continue;
522-
523-
if (constraint->getKind() == ConstraintKind::DefaultClosureType) {
524-
// If there are no other possible bindings for this closure
525-
// let's default it to the type inferred from its parameters/body,
526-
// otherwise we should only attempt contextual types as a
527-
// top-level closure type.
528-
if (!Bindings.empty())
529-
continue;
530-
}
531-
532-
addPotentialBinding({type, AllowedBindingKind::Exact, constraint});
533-
}
534517
}
535518

536519
void ConstraintSystem::PotentialBindings::finalize(
@@ -575,7 +558,7 @@ ConstraintSystem::determineBestBindings() {
575558
if (shouldAttemptFixes() && typeVar->getImpl().canBindToHole())
576559
return true;
577560

578-
return bindings || !bindings.Defaults.empty() ||
561+
return bindings ||
579562
llvm::any_of(bindings.Protocols, [&](Constraint *constraint) {
580563
return bool(
581564
TypeChecker::getDefaultType(constraint->getProtocol(), DC));
@@ -654,6 +637,11 @@ findInferableTypeVars(Type type,
654637
type.walk(Walker(typeVars));
655638
}
656639

640+
void ConstraintSystem::PotentialBindings::addDefault(Constraint *constraint) {
641+
auto defaultTy = constraint->getSecondType();
642+
Defaults.insert({defaultTy->getCanonicalType(), constraint});
643+
}
644+
657645
void ConstraintSystem::PotentialBindings::addPotentialBinding(
658646
PotentialBinding binding, bool allowJoinMeet) {
659647
assert(!binding.BindingType->is<ErrorType>());
@@ -1025,7 +1013,8 @@ bool ConstraintSystem::PotentialBindings::infer(
10251013
// type from context e.g. parameter type of a function call),
10261014
// we need to test type with and without l-value after
10271015
// delaying bindings for as long as possible.
1028-
if (isExpr<ForceValueExpr>(anchor) && !type->is<LValueType>()) {
1016+
if (isExpr<ForceValueExpr>(anchor) &&
1017+
TypeVar->getImpl().canBindToLValue() && !type->is<LValueType>()) {
10291018
addPotentialBinding(binding->withType(LValueType::get(type)));
10301019
DelayedBy.push_back(constraint);
10311020
}
@@ -1094,7 +1083,7 @@ bool ConstraintSystem::PotentialBindings::infer(
10941083
// Do these in a separate pass.
10951084
if (cs.getFixedTypeRecursive(constraint->getFirstType(), true)
10961085
->getAs<TypeVariableType>() == TypeVar) {
1097-
Defaults.push_back(constraint);
1086+
addDefault(constraint);
10981087
}
10991088
break;
11001089

@@ -1358,6 +1347,22 @@ bool TypeVarBindingProducer::computeNext() {
13581347
}
13591348
}
13601349

1350+
if (NumTries == 0) {
1351+
// Add defaultable constraints (if any).
1352+
for (auto *constraint : DelayedDefaults) {
1353+
if (constraint->getKind() == ConstraintKind::DefaultClosureType) {
1354+
// If there are no other possible bindings for this closure
1355+
// let's default it to the type inferred from its parameters/body,
1356+
// otherwise we should only attempt contextual types as a
1357+
// top-level closure type.
1358+
if (!ExploredTypes.empty())
1359+
continue;
1360+
}
1361+
1362+
addNewBinding(getDefaultBinding(constraint));
1363+
}
1364+
}
1365+
13611366
if (newBindings.empty())
13621367
return false;
13631368

lib/Sema/ConstraintSystem.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5372,6 +5372,24 @@ TypeVarBindingProducer::TypeVarBindingProducer(
53725372
if (Any) {
53735373
Bindings.push_back(*Any);
53745374
}
5375+
5376+
{
5377+
bool noBindings = Bindings.empty();
5378+
5379+
for (const auto &entry : bindings.Defaults) {
5380+
auto *constraint = entry.second;
5381+
if (noBindings) {
5382+
// If there are no direct or transitive bindings to attempt
5383+
// let's add defaults to the list right away.
5384+
Bindings.push_back(getDefaultBinding(constraint));
5385+
} else {
5386+
// Otherwise let's delay attempting default bindings
5387+
// until all of the direct & transitive bindings and
5388+
// their derivatives have been attempted.
5389+
DelayedDefaults.push_back(constraint);
5390+
}
5391+
}
5392+
}
53755393
}
53765394

53775395
bool TypeVarBindingProducer::requiresOptionalAdjustment(
@@ -5403,3 +5421,15 @@ bool TypeVarBindingProducer::requiresOptionalAdjustment(
54035421

54045422
return false;
54055423
}
5424+
5425+
ConstraintSystem::PotentialBinding
5426+
TypeVarBindingProducer::getDefaultBinding(Constraint *constraint) const {
5427+
assert(constraint->getKind() == ConstraintKind::Defaultable ||
5428+
constraint->getKind() == ConstraintKind::DefaultClosureType);
5429+
5430+
auto type = constraint->getSecondType();
5431+
Binding binding{type, BindingKind::Exact, constraint};
5432+
return requiresOptionalAdjustment(binding)
5433+
? binding.withType(OptionalType::get(type))
5434+
: binding;
5435+
}

0 commit comments

Comments
 (0)