Sema: Avoid copying BindingSets

They're stored inside the ConstraintGraphNode now, so returning a
`const BindingSet *` from within determineBestBindings() should
be safe.
This commit is contained in:
Slava Pestov
2025-12-10 17:19:54 -05:00
parent da8b721654
commit ba7df4013e
9 changed files with 22 additions and 21 deletions

View File

@@ -385,6 +385,10 @@ public:
BindingSet(ConstraintSystem &CS, TypeVariableType *TypeVar,
const PotentialBindings &info);
BindingSet(BindingSet &&other) = default;
BindingSet(const BindingSet &other) = delete;
ConstraintSystem &getConstraintSystem() const { return CS; }
TypeVariableType *getTypeVariable() const { return TypeVar; }

View File

@@ -5270,7 +5270,7 @@ public:
/// Determine whether given type variable with its set of bindings is viable
/// to be attempted on the next step of the solver.
std::optional<BindingSet> determineBestBindings(
const BindingSet *determineBestBindings(
llvm::function_ref<void(const BindingSet &)> onCandidate);
/// Get bindings for the given type variable based on current
@@ -6200,7 +6200,7 @@ class TypeVarBindingProducer : public BindingProducer<TypeVariableBinding> {
public:
using Element = TypeVariableBinding;
TypeVarBindingProducer(BindingSet &bindings);
TypeVarBindingProducer(const BindingSet &bindings);
/// Retrieve a set of bindings available in the current state.
ArrayRef<Binding> getCurrentBindings() const { return Bindings; }

View File

@@ -1180,7 +1180,7 @@ bool BindingSet::operator<(const BindingSet &other) {
return isPotentiallyIncomplete() < other.isPotentiallyIncomplete();
}
std::optional<BindingSet> ConstraintSystem::determineBestBindings(
const BindingSet *ConstraintSystem::determineBestBindings(
llvm::function_ref<void(const BindingSet &)> onCandidate) {
// Look for potential type variable bindings.
BindingSet *bestBindings = nullptr;
@@ -1238,10 +1238,7 @@ std::optional<BindingSet> ConstraintSystem::determineBestBindings(
bestBindings = &bindings;
}
if (!bestBindings)
return std::nullopt;
return std::optional(*bestBindings);
return bestBindings;
}
/// Find the set of type variables that are inferable from the given type.

View File

@@ -263,7 +263,7 @@ StepResult ComponentStep::take(bool prevFailed) {
SmallString<64> potentialBindings;
llvm::raw_svector_ostream bos(potentialBindings);
auto bestBindings = CS.determineBestBindings([&](const BindingSet &bindings) {
const auto *bestBindings = CS.determineBestBindings([&](const BindingSet &bindings) {
if (CS.isDebugMode() && bindings.hasViableBindings()) {
bos.indent(CS.solverState->getCurrentIndent() + 2);
bos << "(";

View File

@@ -540,7 +540,7 @@ class TypeVariableStep final : public BindingStep<TypeVarBindingProducer> {
bool SawFirstLiteralConstraint = false;
public:
TypeVariableStep(BindingContainer &bindings,
TypeVariableStep(const BindingContainer &bindings,
SmallVectorImpl<Solution> &solutions)
: BindingStep(bindings.getConstraintSystem(), {bindings}, solutions),
TypeVar(bindings.getTypeVariable()) {}

View File

@@ -5309,7 +5309,7 @@ ConstraintSystem::inferKeyPathLiteralCapability(KeyPathExpr *keyPath) {
return success(mutability, isSendable);
}
TypeVarBindingProducer::TypeVarBindingProducer(BindingSet &bindings)
TypeVarBindingProducer::TypeVarBindingProducer(const BindingSet &bindings)
: BindingProducer(bindings.getConstraintSystem(),
bindings.getTypeVariable()->getImpl().getLocator()),
TypeVar(bindings.getTypeVariable()), CanBeNil(bindings.canBeNil()) {

View File

@@ -196,7 +196,7 @@ TEST_F(SemaTest, TestTransitiveProtocolInference) {
cs.getConstraintLocator({}, LocatorPathElt::ContextualType(
CTP_Initialization)));
auto bindings = inferBindings(cs, typeVar);
auto &bindings = inferBindings(cs, typeVar);
ASSERT_TRUE(bindings.getConformanceRequirements().empty());
ASSERT_TRUE(bool(bindings.TransitiveProtocols));
verifyProtocolInferenceResults(*bindings.TransitiveProtocols,
@@ -218,7 +218,7 @@ TEST_F(SemaTest, TestTransitiveProtocolInference) {
cs.addConstraint(ConstraintKind::Conversion, typeVar, GPT1,
cs.getConstraintLocator({}));
auto bindings = inferBindings(cs, typeVar);
auto &bindings = inferBindings(cs, typeVar);
ASSERT_TRUE(bindings.getConformanceRequirements().empty());
ASSERT_TRUE(bool(bindings.TransitiveProtocols));
verifyProtocolInferenceResults(*bindings.TransitiveProtocols,
@@ -281,10 +281,10 @@ TEST_F(SemaTest, TestComplexTransitiveProtocolInference) {
cs.addConstraint(ConstraintKind::Equal, typeVar1, typeVar5, nilLocator);
cs.addConstraint(ConstraintKind::Conversion, typeVar5, typeVar6, nilLocator);
auto bindingsForT1 = inferBindings(cs, typeVar1);
auto bindingsForT2 = inferBindings(cs, typeVar2);
auto bindingsForT3 = inferBindings(cs, typeVar3);
auto bindingsForT5 = inferBindings(cs, typeVar5);
auto &bindingsForT1 = inferBindings(cs, typeVar1);
auto &bindingsForT2 = inferBindings(cs, typeVar2);
auto &bindingsForT3 = inferBindings(cs, typeVar3);
auto &bindingsForT5 = inferBindings(cs, typeVar5);
ASSERT_TRUE(bool(bindingsForT1.TransitiveProtocols));
verifyProtocolInferenceResults(*bindingsForT1.TransitiveProtocols,
@@ -335,7 +335,7 @@ TEST_F(SemaTest, TestTransitiveProtocolInferenceThroughEquivalenceChains) {
cs.addConstraint(ConstraintKind::ConformsTo, typeVar2, protocolTy0, nilLocator);
cs.addConstraint(ConstraintKind::ConformsTo, typeVar3, protocolTy1, nilLocator);
auto bindings = inferBindings(cs, typeVar0);
auto &bindings = inferBindings(cs, typeVar0);
ASSERT_TRUE(bool(bindings.TransitiveProtocols));
verifyProtocolInferenceResults(*bindings.TransitiveProtocols,

View File

@@ -124,8 +124,8 @@ ProtocolType *SemaTest::createProtocol(llvm::StringRef protocolName,
return ProtocolType::get(PD, parent, Context);
}
BindingSet SemaTest::inferBindings(ConstraintSystem &cs,
TypeVariableType *typeVar) {
const BindingSet &SemaTest::inferBindings(ConstraintSystem &cs,
TypeVariableType *typeVar) {
for (auto *typeVar : cs.getTypeVariables()) {
auto &node = cs.getConstraintGraph()[typeVar];
node.resetBindingSet();

View File

@@ -80,8 +80,8 @@ protected:
ProtocolType *createProtocol(llvm::StringRef protocolName,
Type parent = Type());
static BindingSet inferBindings(ConstraintSystem &cs,
TypeVariableType *typeVar);
static const BindingSet &inferBindings(ConstraintSystem &cs,
TypeVariableType *typeVar);
};
} // end namespace unittest