@@ -4145,7 +4145,25 @@ GenericSignatureBuilder::getConformanceAccessPath(Type type,
4145
4145
return found->second ;
4146
4146
}
4147
4147
4148
- FrontendStatsTracer (Context.Stats , " get-conformance-access-path" );
4148
+ auto *Stats = Context.Stats ;
4149
+
4150
+ FrontendStatsTracer (Stats, " get-conformance-access-path" );
4151
+
4152
+ auto recordPath = [&](CanType type, ProtocolDecl *proto,
4153
+ ConformanceAccessPath path) {
4154
+ // Add the path to the buffer.
4155
+ Impl->CurrentConformanceAccessPaths .emplace_back (type, path);
4156
+
4157
+ // Add the path to the map.
4158
+ auto key = std::make_pair (type, proto);
4159
+ auto inserted = Impl->ConformanceAccessPaths .insert (
4160
+ std::make_pair (key, path));
4161
+ assert (inserted.second );
4162
+ (void ) inserted;
4163
+
4164
+ if (Stats)
4165
+ ++Stats->getFrontendCounters ().NumConformanceAccessPathsRecorded ;
4166
+ };
4149
4167
4150
4168
// If this is the first time we're asked to look up a conformance access path,
4151
4169
// visit all of the root conformance requirements in our generic signature and
@@ -4163,19 +4181,12 @@ GenericSignatureBuilder::getConformanceAccessPath(Type type,
4163
4181
ArrayRef<ConformanceAccessPath::Entry> path (root);
4164
4182
ConformanceAccessPath result (Context.AllocateCopy (path));
4165
4183
4166
- // Add the path to the buffer.
4167
- Impl->CurrentConformanceAccessPaths .emplace_back (rootType, result);
4168
-
4169
- // Add the path to the map.
4170
- auto key = std::make_pair (rootType, rootProto);
4171
- auto inserted = Impl->ConformanceAccessPaths .insert (
4172
- std::make_pair (key, result));
4173
- assert (inserted.second );
4174
- (void ) inserted;
4184
+ recordPath (rootType, rootProto, result);
4175
4185
}
4176
4186
}
4177
4187
4178
- // We keep going until we find the path we are looking for.
4188
+ // We enumerate conformance access paths in lexshort order until we find the
4189
+ // path whose corresponding type canonicalizes to the one we are looking for.
4179
4190
while (true ) {
4180
4191
auto found = Impl->ConformanceAccessPaths .find (
4181
4192
std::make_pair (canType, protocol));
@@ -4185,11 +4196,13 @@ GenericSignatureBuilder::getConformanceAccessPath(Type type,
4185
4196
4186
4197
assert (Impl->CurrentConformanceAccessPaths .size () > 0 );
4187
4198
4188
- // Refill the buffer.
4189
- std::vector<std::pair<CanType, ConformanceAccessPath>> morePaths;
4199
+ // The buffer consists of all conformance access paths of length N.
4200
+ // Swap it out with an empty buffer, and fill it with all paths of
4201
+ // length N+1.
4202
+ std::vector<std::pair<CanType, ConformanceAccessPath>> oldPaths;
4203
+ std::swap (Impl->CurrentConformanceAccessPaths , oldPaths);
4190
4204
4191
- // From each path in the buffer, compute all paths of length plus one.
4192
- for (const auto &pair : Impl->CurrentConformanceAccessPaths ) {
4205
+ for (const auto &pair : oldPaths) {
4193
4206
const auto &lastElt = pair.second .back ();
4194
4207
auto *lastProto = lastElt.second ;
4195
4208
@@ -4213,12 +4226,12 @@ GenericSignatureBuilder::getConformanceAccessPath(Type type,
4213
4226
if (!nextCanType->isTypeParameter ())
4214
4227
continue ;
4215
4228
4216
- // Check if we already have a conformance access path for this anchor.
4217
- auto key = std::make_pair (nextCanType, nextProto);
4218
-
4219
4229
// If we've already seen a path for this conformance, skip it and
4220
- // don't add it to the buffer.
4221
- if (Impl->ConformanceAccessPaths .count (key))
4230
+ // don't add it to the buffer. Note that because we iterate over
4231
+ // conformance access paths in lexshort order, the existing
4232
+ // conformance access path is shorter than the one we found just now.
4233
+ if (Impl->ConformanceAccessPaths .count (
4234
+ std::make_pair (nextCanType, nextProto)))
4222
4235
continue ;
4223
4236
4224
4237
if (entries.empty ()) {
@@ -4233,18 +4246,9 @@ GenericSignatureBuilder::getConformanceAccessPath(Type type,
4233
4246
ConformanceAccessPath result = Context.AllocateCopy (entries);
4234
4247
entries.pop_back ();
4235
4248
4236
- // Add the path to the buffer.
4237
- morePaths.emplace_back (nextCanType, result);
4238
-
4239
- // Add the path to the map.
4240
- auto inserted = Impl->ConformanceAccessPaths .insert (
4241
- std::make_pair (key, result));
4242
- assert (inserted.second );
4243
- (void ) inserted;
4249
+ recordPath (nextCanType, nextProto, result);
4244
4250
}
4245
4251
}
4246
-
4247
- std::swap (morePaths, Impl->CurrentConformanceAccessPaths );
4248
4252
}
4249
4253
}
4250
4254
0 commit comments