Skip to content

Commit 10160cb

Browse files
authored
Merge pull request swiftlang#35353 from xedin/refactor-binding-storage
[ConstraintSystem] Refactor storage of potential bindings
2 parents edcefe3 + 7617b74 commit 10160cb

File tree

4 files changed

+164
-95
lines changed

4 files changed

+164
-95
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 72 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -4638,13 +4638,13 @@ class ConstraintSystem {
46384638

46394639
PotentialBinding(Type type, AllowedBindingKind kind,
46404640
PointerUnion<Constraint *, ConstraintLocator *> source)
4641-
: BindingType(type->getWithoutParens()), Kind(kind),
4642-
BindingSource(source) {}
4641+
: BindingType(type), Kind(kind), BindingSource(source) {}
46434642

46444643
public:
46454644
PotentialBinding(Type type, AllowedBindingKind kind, Constraint *source)
4646-
: BindingType(type->getWithoutParens()), Kind(kind),
4647-
BindingSource(source) {}
4645+
: PotentialBinding(
4646+
type->getWithoutParens(), kind,
4647+
PointerUnion<Constraint *, ConstraintLocator *>(source)) {}
46484648

46494649
bool isDefaultableBinding() const {
46504650
if (auto *constraint = BindingSource.dyn_cast<Constraint *>())
@@ -4695,6 +4695,11 @@ class ConstraintSystem {
46954695
AllowedBindingKind::Exact,
46964696
/*source=*/locator};
46974697
}
4698+
4699+
static PotentialBinding forPlaceholder(Type placeholderTy) {
4700+
return {placeholderTy, AllowedBindingKind::Exact,
4701+
PointerUnion<Constraint *, ConstraintLocator *>()};
4702+
}
46984703
};
46994704

47004705
struct LiteralRequirement {
@@ -4751,7 +4756,7 @@ class ConstraintSystem {
47514756
TypeVariableType *TypeVar;
47524757

47534758
/// The set of potential bindings.
4754-
SmallVector<PotentialBinding, 4> Bindings;
4759+
llvm::SmallSetVector<PotentialBinding, 4> Bindings;
47554760

47564761
/// The set of protocol requirements placed on this type variable.
47574762
llvm::SmallVector<Constraint *, 4> Protocols;
@@ -4981,13 +4986,21 @@ class ConstraintSystem {
49814986
/// \param canBeNil The flag that determines whether given type
49824987
/// variable requires all of its bindings to be optional.
49834988
///
4984-
/// \returns true if binding covers given literal protocol.
4985-
bool isLiteralCoveredBy(const LiteralRequirement &literal,
4986-
PotentialBinding &binding, bool canBeNil) const;
4989+
/// \returns a pair of bool and a type:
4990+
/// - bool, true if binding covers given literal protocol;
4991+
/// - type, non-null if binding type has to be adjusted
4992+
/// to cover given literal protocol;
4993+
std::pair<bool, Type> isLiteralCoveredBy(const LiteralRequirement &literal,
4994+
const PotentialBinding &binding,
4995+
bool canBeNil) const;
49874996

49884997
/// Add a potential binding to the list of bindings,
49894998
/// coalescing supertype bounds when we are able to compute the meet.
4990-
void addPotentialBinding(PotentialBinding binding,
4999+
///
5000+
/// \returns true if this binding has been added to the set,
5001+
/// false otherwise (e.g. because binding with this type is
5002+
/// already in the set).
5003+
bool addPotentialBinding(PotentialBinding binding,
49915004
bool allowJoinMeet = true);
49925005

49935006
/// Check if this binding is viable for inclusion in the set.
@@ -5024,13 +5037,9 @@ class ConstraintSystem {
50245037
///
50255038
/// Which gives us a new (superclass A) binding for T2 as well as T1.
50265039
///
5027-
/// \param cs The constraint system this type variable is associated with.
5028-
///
50295040
/// \param inferredBindings The set of all bindings inferred for type
50305041
/// variables in the workset.
50315042
void inferTransitiveBindings(
5032-
ConstraintSystem &cs,
5033-
llvm::SmallPtrSetImpl<CanType> &existingTypes,
50345043
const llvm::SmallDenseMap<TypeVariableType *,
50355044
ConstraintSystem::PotentialBindings>
50365045
&inferredBindings);
@@ -5039,20 +5048,16 @@ class ConstraintSystem {
50395048
/// between two type variables and attempt to propagate protocol
50405049
/// requirements down the subtype or equivalence chain.
50415050
void inferTransitiveProtocolRequirements(
5042-
const ConstraintSystem &cs,
50435051
llvm::SmallDenseMap<TypeVariableType *,
50445052
ConstraintSystem::PotentialBindings>
50455053
&inferredBindings);
50465054

50475055
public:
5048-
bool infer(ConstraintSystem &cs,
5049-
llvm::SmallPtrSetImpl<CanType> &exactTypes,
5050-
Constraint *constraint);
5056+
bool infer(Constraint *constraint);
50515057

50525058
/// Finalize binding computation for this type variable by
50535059
/// inferring bindings from context e.g. transitive bindings.
5054-
void finalize(ConstraintSystem &cs,
5055-
llvm::SmallDenseMap<TypeVariableType *,
5060+
void finalize(llvm::SmallDenseMap<TypeVariableType *,
50565061
ConstraintSystem::PotentialBindings>
50575062
&inferredBindings);
50585063

@@ -6233,6 +6238,54 @@ struct DenseMapInfo<swift::constraints::SolutionApplicationTargetsKey> {
62336238
}
62346239
};
62356240

6241+
template <>
6242+
struct DenseMapInfo<swift::constraints::ConstraintSystem::PotentialBinding> {
6243+
using Binding = swift::constraints::ConstraintSystem::PotentialBinding;
6244+
6245+
static Binding getEmptyKey() {
6246+
return placeholderKey(llvm::DenseMapInfo<swift::TypeBase *>::getEmptyKey());
6247+
}
6248+
6249+
static Binding getTombstoneKey() {
6250+
return placeholderKey(
6251+
llvm::DenseMapInfo<swift::TypeBase *>::getTombstoneKey());
6252+
}
6253+
6254+
static unsigned getHashValue(const Binding &Val) {
6255+
return DenseMapInfo<swift::Type>::getHashValue(
6256+
Val.BindingType->getCanonicalType());
6257+
}
6258+
6259+
static bool isEqual(const Binding &LHS, const Binding &RHS) {
6260+
auto lhsTy = LHS.BindingType.getPointer();
6261+
auto rhsTy = RHS.BindingType.getPointer();
6262+
6263+
// Fast path: pointer equality.
6264+
if (DenseMapInfo<swift::TypeBase *>::isEqual(lhsTy, rhsTy))
6265+
return true;
6266+
6267+
// If either side is empty or tombstone, let's use pointer equality.
6268+
{
6269+
auto emptyTy = llvm::DenseMapInfo<swift::TypeBase *>::getEmptyKey();
6270+
auto tombstoneTy =
6271+
llvm::DenseMapInfo<swift::TypeBase *>::getTombstoneKey();
6272+
6273+
if (lhsTy == emptyTy || lhsTy == tombstoneTy)
6274+
return lhsTy == rhsTy;
6275+
6276+
if (rhsTy == emptyTy || rhsTy == tombstoneTy)
6277+
return lhsTy == rhsTy;
6278+
}
6279+
6280+
// Otherwise let's drop the sugar and check.
6281+
return LHS.BindingType->isEqual(RHS.BindingType);
6282+
}
6283+
6284+
private:
6285+
static Binding placeholderKey(swift::Type type) {
6286+
return Binding::forPlaceholder(type);
6287+
}
6288+
};
62366289
}
62376290

62386291
#endif // LLVM_SWIFT_SEMA_CONSTRAINT_SYSTEM_H

0 commit comments

Comments
 (0)