Skip to content

Commit 13c919b

Browse files
authored
Merge pull request #86031 from slavapestov/binding-set-constructor-speedup
Sema: Simplify BindingSet construction
2 parents 3de0ae6 + 9a68d4a commit 13c919b

File tree

12 files changed

+274
-162
lines changed

12 files changed

+274
-162
lines changed

include/swift/Sema/CSBindings.h

Lines changed: 45 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,8 @@ struct PotentialBinding {
152152
};
153153

154154
struct LiteralRequirement {
155+
/// The literal protocol.
156+
ProtocolDecl *Protocol;
155157
/// The source of the literal requirement.
156158
Constraint *Source;
157159
/// The default type associated with this literal (if any).
@@ -164,17 +166,23 @@ struct LiteralRequirement {
164166
/// this points to the source of the binding.
165167
mutable Constraint *CoveredBy = nullptr;
166168

167-
LiteralRequirement(Constraint *source, Type defaultTy, bool isDirect)
168-
: Source(source), DefaultType(defaultTy), IsDirectRequirement(isDirect) {}
169+
LiteralRequirement(ProtocolDecl *protocol, Constraint *source,
170+
Type defaultTy, bool isDirect)
171+
: Protocol(protocol), Source(source), DefaultType(defaultTy),
172+
IsDirectRequirement(isDirect) {}
169173

170174
Constraint *getSource() const { return Source; }
171175

172-
ProtocolDecl *getProtocol() const { return Source->getProtocol(); }
176+
ProtocolDecl *getProtocol() const { return Protocol; }
173177

174178
bool isCovered() const { return bool(CoveredBy); }
175179

176180
bool isDirectRequirement() const { return IsDirectRequirement; }
177181

182+
void setDirectRequirement(bool isDirectRequirement) {
183+
IsDirectRequirement = isDirectRequirement;
184+
}
185+
178186
bool hasDefaultType() const { return bool(DefaultType); }
179187

180188
Type getDefaultType() const {
@@ -241,6 +249,16 @@ struct PotentialBindings {
241249
llvm::SmallVector<std::pair<TypeVariableType *, Constraint *>, 4> SupertypeOf;
242250
llvm::SmallVector<std::pair<TypeVariableType *, Constraint *>, 4> EquivalentTo;
243251

252+
/// The set of protocol conformance requirements imposed on this type variable.
253+
llvm::SmallVector<Constraint *, 4> Protocols;
254+
255+
/// The set of unique literal protocol requirements placed on this
256+
/// type variable.
257+
llvm::SmallVector<LiteralRequirement, 2> Literals;
258+
259+
/// The set of fallback constraints imposed on this type variable.
260+
llvm::SmallVector<Constraint *, 2> Defaults;
261+
244262
ASTNode AssociatedCodeCompletionToken = ASTNode();
245263

246264
/// Add a potential binding to the list of bindings,
@@ -256,7 +274,14 @@ struct PotentialBindings {
256274
});
257275
}
258276

259-
private:
277+
ArrayRef<Constraint *> getConformanceRequirements() const {
278+
return Protocols;
279+
}
280+
281+
void inferFromLiteral(ConstraintSystem &CS,
282+
TypeVariableType *TypeVar,
283+
Constraint *literal);
284+
260285
/// Attempt to infer a new binding and other useful information
261286
/// (i.e. whether bindings should be delayed) from the given
262287
/// relational constraint.
@@ -265,7 +290,6 @@ struct PotentialBindings {
265290
TypeVariableType *TypeVar,
266291
Constraint *constraint);
267292

268-
public:
269293
void infer(ConstraintSystem &CS,
270294
TypeVariableType *TypeVar,
271295
Constraint *constraint);
@@ -365,18 +389,15 @@ class BindingSet {
365389
public:
366390
swift::SmallSetVector<PotentialBinding, 4> Bindings;
367391

368-
/// The set of protocol conformance requirements placed on this type variable.
369-
llvm::SmallVector<Constraint *, 4> Protocols;
370-
371392
/// The set of unique literal protocol requirements placed on this
372393
/// type variable or inferred transitively through subtype chains.
373394
///
374395
/// Note that ordering is important when it comes to bindings, we'd
375396
/// like to add any "direct" default types first to attempt them
376397
/// before transitive ones.
377-
llvm::SmallMapVector<ProtocolDecl *, LiteralRequirement, 2> Literals;
398+
llvm::SmallVector<LiteralRequirement, 2> Literals;
378399

379-
llvm::SmallDenseMap<CanType, Constraint *, 2> Defaults;
400+
llvm::SmallVector<Constraint *, 2> Defaults;
380401

381402
/// The set of transitive protocol requirements inferred through
382403
/// subtype/conversion/equivalence relations with other type variables.
@@ -389,8 +410,6 @@ class BindingSet {
389410

390411
BindingSet(const BindingSet &other) = delete;
391412

392-
ConstraintSystem &getConstraintSystem() const { return CS; }
393-
394413
TypeVariableType *getTypeVariable() const { return TypeVar; }
395414

396415
/// Check whether this binding set belongs to a type variable
@@ -457,7 +476,7 @@ class BindingSet {
457476
// Literal requirements always result in a subtype/supertype
458477
// relationship to a concrete type.
459478
if (llvm::any_of(Literals, [](const auto &literal) {
460-
return literal.second.viableAsBinding();
479+
return literal.viableAsBinding();
461480
}))
462481
return false;
463482

@@ -494,19 +513,15 @@ class BindingSet {
494513
return hasViableBindings() || isDirectHole();
495514
}
496515

497-
ArrayRef<Constraint *> getConformanceRequirements() const {
498-
return Protocols;
499-
}
500-
501516
unsigned getNumViableLiteralBindings() const;
502517

503518
unsigned getNumViableDefaultableBindings() const {
504519
if (isDirectHole())
505520
return 1;
506521

507522
auto numDefaultable = llvm::count_if(
508-
Defaults, [](const std::pair<CanType, Constraint *> &entry) {
509-
return entry.second->getKind() == ConstraintKind::Defaultable;
523+
Defaults, [](Constraint *constraint) {
524+
return constraint->getKind() == ConstraintKind::Defaultable;
510525
});
511526

512527
// Short-circuit unviable checks if there are no defaultable bindings.
@@ -518,10 +533,12 @@ class BindingSet {
518533
auto unviable =
519534
llvm::count_if(Bindings, [&](const PotentialBinding &binding) {
520535
auto type = binding.BindingType->getCanonicalType();
521-
auto def = Defaults.find(type);
522-
return def != Defaults.end()
523-
? def->second->getKind() == ConstraintKind::Defaultable
524-
: false;
536+
for (auto *constraint : Defaults) {
537+
if (constraint->getSecondType()->isEqual(type)) {
538+
return constraint->getKind() == ConstraintKind::Defaultable;
539+
}
540+
}
541+
return false;
525542
});
526543

527544
assert(numDefaultable >= unviable);
@@ -572,6 +589,11 @@ class BindingSet {
572589
/// requirements down the subtype or equivalence chain.
573590
void inferTransitiveProtocolRequirements();
574591

592+
/// Try to coalesce integer and floating point literal protocols
593+
/// if they appear together because the only possible default type that
594+
/// could satisfy both requirements is `Double`.
595+
void coalesceIntegerAndFloatLiteralRequirements();
596+
575597
/// Check whether the given binding set covers any of the literal protocols
576598
/// associated with this type variable. The idea is that if a type variable
577599
/// has a binding like Int and also it has a conformance requirement to
@@ -607,8 +629,6 @@ class BindingSet {
607629
/// checking.
608630
void addBinding(PotentialBinding binding, bool isTransitive);
609631

610-
void addLiteralRequirement(Constraint *literal);
611-
612632
void addDefault(Constraint *constraint);
613633

614634
StringRef getLiteralBindingKind(LiteralBindingKind K) const {

include/swift/Sema/CSTrail.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,10 @@ GRAPH_NODE_CHANGE(AddedConstraint)
7676
GRAPH_NODE_CHANGE(RemovedConstraint)
7777
GRAPH_NODE_CHANGE(InferredBindings)
7878
GRAPH_NODE_CHANGE(RetractedBindings)
79+
GRAPH_NODE_CHANGE(RetractedLiteral)
7980
GRAPH_NODE_CHANGE(RetractedDelayedBy)
81+
GRAPH_NODE_CHANGE(RetractedProtocol)
82+
GRAPH_NODE_CHANGE(RetractedDefault)
8083

8184
BINDING_RELATION_CHANGE(RetractedAdjacentVar)
8285
BINDING_RELATION_CHANGE(RetractedSubtypeOf)

include/swift/Sema/ConstraintSystem.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6196,7 +6196,9 @@ class TypeVarBindingProducer : public BindingProducer<TypeVariableBinding> {
61966196
public:
61976197
using Element = TypeVariableBinding;
61986198

6199-
TypeVarBindingProducer(const BindingSet &bindings);
6199+
TypeVarBindingProducer(ConstraintSystem &cs,
6200+
TypeVariableType *typeVar,
6201+
const BindingSet &bindings);
62006202

62016203
/// Retrieve a set of bindings available in the current state.
62026204
ArrayRef<Binding> getCurrentBindings() const { return Bindings; }

0 commit comments

Comments
 (0)