Skip to content

Commit 5c5d2ea

Browse files
authored
Merge pull request #41945 from slavapestov/rqm-split-concrete-equiv-class-improvements
RequirementMachine: Improve the 'split concrete equivalence classes' hack a bit
2 parents 4625f4a + 441fa16 commit 5c5d2ea

15 files changed

+444
-232
lines changed

include/swift/Basic/LangOptions.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -520,6 +520,10 @@ namespace swift {
520520
/// algorithm.
521521
unsigned RequirementMachineMaxConcreteNesting = 30;
522522

523+
/// Maximum number of attempts to make when splitting concrete equivalence
524+
/// classes.
525+
unsigned RequirementMachineMaxSplitConcreteEquivClassAttempts = 2;
526+
523527
/// Enable the new experimental protocol requirement signature minimization
524528
/// algorithm.
525529
RequirementMachineMode RequirementMachineProtocolSignatures =

include/swift/Option/FrontendOptions.td

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,12 @@ def requirement_machine_max_concrete_nesting : Joined<["-"], "requirement-machin
355355
Flags<[FrontendOption, HelpHidden, DoesNotAffectIncrementalBuild]>,
356356
HelpText<"Set the maximum concrete type nesting depth before giving up">;
357357

358+
def requirement_machine_max_split_concrete_equiv_class_attempts : Joined<["-"], "requirement-machine-max-split-concrete-equiv-class-attempts=">,
359+
Flags<[FrontendOption, HelpHidden, DoesNotAffectIncrementalBuild]>,
360+
HelpText<"Set the maximum concrete number of attempts at splitting "
361+
"concrete equivalence classes before giving up. There should "
362+
"never be a reason to change this">;
363+
358364
def disable_requirement_machine_concrete_contraction : Flag<["-"], "disable-requirement-machine-concrete-contraction">,
359365
HelpText<"Disable preprocessing pass to eliminate conformance requirements "
360366
"on generic parameters which are made concrete">;

lib/AST/RequirementMachine/GenericSignatureQueries.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -156,9 +156,14 @@ getSuperclassBound(Type depType,
156156
return props->getSuperclassBound(genericParams, term, Map);
157157
}
158158

159-
bool RequirementMachine::isConcreteType(Type depType) const {
159+
/// Unlike the other queries, we have occasion to call this on a requirement
160+
/// machine for a protocol connected component as well as a top-level
161+
/// generic signature, so plumb through the protocol to use for the root
162+
/// `Self` generic parameter here.
163+
bool RequirementMachine::isConcreteType(Type depType,
164+
const ProtocolDecl *proto) const {
160165
auto term = Context.getMutableTermForType(depType->getCanonicalType(),
161-
/*proto=*/nullptr);
166+
proto);
162167
System.simplify(term);
163168
verify(term);
164169

@@ -169,11 +174,16 @@ bool RequirementMachine::isConcreteType(Type depType) const {
169174
return props->isConcreteType();
170175
}
171176

177+
/// Unlike the other queries, we have occasion to call this on a requirement
178+
/// machine for a protocol connected component as well as a top-level
179+
/// generic signature, so plumb through the protocol to use for the root
180+
/// `Self` generic parameter here.
172181
Type RequirementMachine::
173182
getConcreteType(Type depType,
174-
TypeArrayView<GenericTypeParamType> genericParams) const {
183+
TypeArrayView<GenericTypeParamType> genericParams,
184+
const ProtocolDecl *proto) const {
175185
auto term = Context.getMutableTermForType(depType->getCanonicalType(),
176-
/*proto=*/nullptr);
186+
proto);
177187
System.simplify(term);
178188
verify(term);
179189

@@ -683,9 +693,11 @@ void RequirementMachine::verify(const MutableTerm &term) const {
683693
if (term.begin()->getKind() == Symbol::Kind::GenericParam) {
684694
auto *genericParam = term.begin()->getGenericParam();
685695
TypeArrayView<GenericTypeParamType> genericParams = getGenericParams();
686-
auto found = std::find(genericParams.begin(),
687-
genericParams.end(),
688-
genericParam);
696+
auto found = std::find_if(genericParams.begin(),
697+
genericParams.end(),
698+
[&](GenericTypeParamType *otherType) {
699+
return genericParam->isEqual(otherType);
700+
});
689701
if (found == genericParams.end()) {
690702
llvm::errs() << "Bad generic parameter in " << term << "\n";
691703
dump(llvm::errs());

lib/AST/RequirementMachine/RequirementMachine.cpp

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,22 +167,28 @@ RequirementMachine::initWithGenericSignature(CanGenericSignature sig) {
167167
/// Returns failure if completion fails within the configured number of steps.
168168
std::pair<CompletionResult, unsigned>
169169
RequirementMachine::initWithProtocolWrittenRequirements(
170-
ArrayRef<const ProtocolDecl *> protos) {
170+
ArrayRef<const ProtocolDecl *> component,
171+
const llvm::DenseMap<const ProtocolDecl *,
172+
SmallVector<StructuralRequirement, 4>> protos) {
171173
FrontendStatsTracer tracer(Stats, "build-rewrite-system");
172174

175+
// For RequirementMachine::verify() when called by generic signature queries;
176+
// We have a single valid generic parameter at depth 0, index 0.
177+
Params.push_back(component[0]->getSelfInterfaceType()->getCanonicalType());
178+
173179
if (Dump) {
174180
llvm::dbgs() << "Adding protocols";
175-
for (auto *proto : protos) {
181+
for (auto *proto : component) {
176182
llvm::dbgs() << " " << proto->getName();
177183
}
178184
llvm::dbgs() << " {\n";
179185
}
180186

181187
RuleBuilder builder(Context, System.getReferencedProtocols());
182-
builder.initWithProtocolWrittenRequirements(protos);
188+
builder.initWithProtocolWrittenRequirements(component, protos);
183189

184190
// Add the initial set of rewrite rules to the rewrite system.
185-
System.initialize(/*recordLoops=*/true, protos,
191+
System.initialize(/*recordLoops=*/true, component,
186192
std::move(builder.WrittenRequirements),
187193
std::move(builder.ImportedRules),
188194
std::move(builder.PermanentRules),

lib/AST/RequirementMachine/RequirementMachine.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ class RequirementMachine final {
9999

100100
std::pair<CompletionResult, unsigned>
101101
initWithProtocolWrittenRequirements(
102-
ArrayRef<const ProtocolDecl *> protos);
102+
ArrayRef<const ProtocolDecl *> component,
103+
const llvm::DenseMap<const ProtocolDecl *,
104+
SmallVector<StructuralRequirement, 4>> protos);
103105

104106
std::pair<CompletionResult, unsigned>
105107
initWithWrittenRequirements(
@@ -140,9 +142,11 @@ class RequirementMachine final {
140142
GenericSignature::RequiredProtocols getRequiredProtocols(Type depType) const;
141143
Type getSuperclassBound(Type depType,
142144
TypeArrayView<GenericTypeParamType> genericParams) const;
143-
bool isConcreteType(Type depType) const;
145+
bool isConcreteType(Type depType,
146+
const ProtocolDecl *proto=nullptr) const;
144147
Type getConcreteType(Type depType,
145-
TypeArrayView<GenericTypeParamType> genericParams) const;
148+
TypeArrayView<GenericTypeParamType> genericParams,
149+
const ProtocolDecl *proto=nullptr) const;
146150
bool areSameTypeParameterInContext(Type depType1, Type depType2) const;
147151
bool isCanonicalTypeInContext(Type type) const;
148152
Type getCanonicalTypeInContext(Type type,

0 commit comments

Comments
 (0)