@@ -4145,7 +4145,25 @@ GenericSignatureBuilder::getConformanceAccessPath(Type type,
41454145 return found->second ;
41464146 }
41474147
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+ };
41494167
41504168 // If this is the first time we're asked to look up a conformance access path,
41514169 // visit all of the root conformance requirements in our generic signature and
@@ -4163,19 +4181,12 @@ GenericSignatureBuilder::getConformanceAccessPath(Type type,
41634181 ArrayRef<ConformanceAccessPath::Entry> path (root);
41644182 ConformanceAccessPath result (Context.AllocateCopy (path));
41654183
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);
41754185 }
41764186 }
41774187
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.
41794190 while (true ) {
41804191 auto found = Impl->ConformanceAccessPaths .find (
41814192 std::make_pair (canType, protocol));
@@ -4185,11 +4196,13 @@ GenericSignatureBuilder::getConformanceAccessPath(Type type,
41854196
41864197 assert (Impl->CurrentConformanceAccessPaths .size () > 0 );
41874198
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);
41904204
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) {
41934206 const auto &lastElt = pair.second .back ();
41944207 auto *lastProto = lastElt.second ;
41954208
@@ -4213,12 +4226,12 @@ GenericSignatureBuilder::getConformanceAccessPath(Type type,
42134226 if (!nextCanType->isTypeParameter ())
42144227 continue ;
42154228
4216- // Check if we already have a conformance access path for this anchor.
4217- auto key = std::make_pair (nextCanType, nextProto);
4218-
42194229 // 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)))
42224235 continue ;
42234236
42244237 if (entries.empty ()) {
@@ -4233,18 +4246,9 @@ GenericSignatureBuilder::getConformanceAccessPath(Type type,
42334246 ConformanceAccessPath result = Context.AllocateCopy (entries);
42344247 entries.pop_back ();
42354248
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);
42444250 }
42454251 }
4246-
4247- std::swap (morePaths, Impl->CurrentConformanceAccessPaths );
42484252 }
42494253}
42504254
0 commit comments