Skip to content

Commit aaf84ac

Browse files
committed
RequirementMachine: Implement RequirementMachine::initWithProtocolSignatureRequirements()
1 parent f3bcc52 commit aaf84ac

File tree

4 files changed

+98
-5
lines changed

4 files changed

+98
-5
lines changed

lib/AST/RequirementMachine/RequirementLowering.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1089,6 +1089,51 @@ void RuleBuilder::initWithWrittenRequirements(
10891089
addRequirement(req, /*proto=*/nullptr);
10901090
}
10911091

1092+
/// For building a rewrite system for a protocol connected component from
1093+
/// a previously-built requirement signature.
1094+
///
1095+
/// Will trigger requirement signature computation if we haven't built
1096+
/// requirement signatures for this connected component yet, in which case we
1097+
/// will recursively end up building another rewrite system for this component
1098+
/// using initWithProtocolWrittenRequirements().
1099+
void RuleBuilder::initWithProtocolSignatureRequirements(
1100+
ArrayRef<const ProtocolDecl *> protos) {
1101+
assert(!Initialized);
1102+
Initialized = 1;
1103+
1104+
// Add all protocols to the referenced set, so that subsequent calls
1105+
// to addReferencedProtocol() with one of these protocols don't add
1106+
// them to the import list.
1107+
for (auto *proto : protos) {
1108+
ReferencedProtocols.insert(proto);
1109+
}
1110+
1111+
for (auto *proto : protos) {
1112+
if (Dump) {
1113+
llvm::dbgs() << "protocol " << proto->getName() << " {\n";
1114+
}
1115+
1116+
addPermanentProtocolRules(proto);
1117+
1118+
auto reqs = proto->getRequirementSignature();
1119+
for (auto req : reqs.getRequirements())
1120+
addRequirement(req.getCanonical(), proto, /*requirementID=*/None);
1121+
for (auto alias : reqs.getTypeAliases())
1122+
addTypeAlias(alias, proto);
1123+
1124+
for (auto *otherProto : proto->getProtocolDependencies())
1125+
addReferencedProtocol(otherProto);
1126+
1127+
if (Dump) {
1128+
llvm::dbgs() << "}\n";
1129+
}
1130+
}
1131+
1132+
// Collect all protocols transitively referenced from this connected component
1133+
// of the protocol dependency graph.
1134+
collectRulesFromReferencedProtocols();
1135+
}
1136+
10921137
/// For building a rewrite system for a protocol connected component from
10931138
/// user-written requirements. Used when actually building requirement
10941139
/// signatures.
@@ -1097,6 +1142,9 @@ void RuleBuilder::initWithProtocolWrittenRequirements(
10971142
assert(!Initialized);
10981143
Initialized = 1;
10991144

1145+
// Add all protocols to the referenced set, so that subsequent calls
1146+
// to addReferencedProtocol() with one of these protocols don't add
1147+
// them to the import list.
11001148
for (auto *proto : protos) {
11011149
ReferencedProtocols.insert(proto);
11021150
}

lib/AST/RequirementMachine/RequirementLowering.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ struct RuleBuilder {
125125

126126
void initWithGenericSignatureRequirements(ArrayRef<Requirement> requirements);
127127
void initWithWrittenRequirements(ArrayRef<StructuralRequirement> requirements);
128+
void initWithProtocolSignatureRequirements(ArrayRef<const ProtocolDecl *> proto);
128129
void initWithProtocolWrittenRequirements(ArrayRef<const ProtocolDecl *> proto);
129130
void addReferencedProtocol(const ProtocolDecl *proto);
130131
void collectRulesFromReferencedProtocols();

lib/AST/RequirementMachine/RequirementMachine.cpp

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,46 @@ void RequirementMachine::checkCompletionResult(CompletionResult result) const {
6363
}
6464
}
6565

66+
/// Build a requirement machine for the previously-computed requirement
67+
/// signatures connected component of protocols.
68+
///
69+
/// This must only be called exactly once, before any other operations are
70+
/// performed on this requirement machine.
71+
///
72+
/// Used by RewriteContext::getRequirementMachine(const ProtocolDecl *).
73+
///
74+
/// Returns failure if completion fails within the configured number of steps.
75+
std::pair<CompletionResult, unsigned>
76+
RequirementMachine::initWithProtocolSignatureRequirements(
77+
ArrayRef<const ProtocolDecl *> protos) {
78+
FrontendStatsTracer tracer(Stats, "build-rewrite-system");
79+
80+
if (Dump) {
81+
llvm::dbgs() << "Adding protocols";
82+
for (auto *proto : protos) {
83+
llvm::dbgs() << " " << proto->getName();
84+
}
85+
llvm::dbgs() << " {\n";
86+
}
87+
88+
RuleBuilder builder(Context, System.getReferencedProtocols());
89+
builder.initWithProtocolSignatureRequirements(protos);
90+
91+
// Add the initial set of rewrite rules to the rewrite system.
92+
System.initialize(/*recordLoops=*/true, protos,
93+
std::move(builder.WrittenRequirements),
94+
std::move(builder.PermanentRules),
95+
std::move(builder.RequirementRules));
96+
97+
auto result = computeCompletion(RewriteSystem::DisallowInvalidRequirements);
98+
99+
if (Dump) {
100+
llvm::dbgs() << "}\n";
101+
}
102+
103+
return result;
104+
}
105+
66106
/// Build a requirement machine for the requirements of a generic signature.
67107
///
68108
/// In this mode, minimization is not going to be performed, so rewrite loops
@@ -109,12 +149,12 @@ RequirementMachine::initWithGenericSignature(CanGenericSignature sig) {
109149
return result;
110150
}
111151

112-
/// Build a requirement machine for the structural requirements of a set
113-
/// of protocols, which are understood to form a strongly-connected component
114-
/// (SCC) of the protocol dependency graph.
152+
/// Build a requirement machine for the user-written requirements of connected
153+
/// component of protocols.
115154
///
116-
/// In this mode, minimization will be performed, so rewrite loops are recorded
117-
/// during completion.
155+
/// This is used when actually building the requirement signatures of these
156+
/// protocols. In this mode, minimization will be performed, so rewrite loops
157+
/// are recorded during completion.
118158
///
119159
/// This must only be called exactly once, before any other operations are
120160
/// performed on this requirement machine.

lib/AST/RequirementMachine/RequirementMachine.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ class RequirementMachine final {
9090

9191
void checkCompletionResult(CompletionResult result) const;
9292

93+
std::pair<CompletionResult, unsigned>
94+
initWithProtocolSignatureRequirements(
95+
ArrayRef<const ProtocolDecl *> protos);
96+
9397
std::pair<CompletionResult, unsigned>
9498
initWithGenericSignature(CanGenericSignature sig);
9599

0 commit comments

Comments
 (0)