We're now getting the right set of potential archetypes, so this hack is
just extraneous work. Reduces the number of lookups into the
equivalence class nested type cache by ~24%, but only improves
type-checking performance of the standard library by ~3%.
We want to delay the realization of potential archetypes as late as
possible; for layout constraints, push realization of potential archetypes
down past the point where we know whether we’re learning anything new
about the equivalence class.
No functionality change, yet.
Any potential archetype with the lowest depth in the equivalence class
will do when we're resolving for equivalence classes, so keep the
lowest-depth potential archetype handy.
Teach GenericSignatureBuilder::resolveEquivalenceClass() to perform
resolution of a type into a dependent type and its equivalence class
without realizing that potential archetype. Improves type-checking
time for the standard library by ~6%.
We want to be able to resolve a type to a particular known equivalence class
without realizing the corresponding potential archetype. Represent this in
ResolveResult, even though we're not using this state yet.
When we're only resolving the equivalence class in which a dependent type
occurs, always use the archetype anchor for the equivalence class to
find the equivalence class of the next nested type. This means that,
for example, determining the equivalence class of
C.SubSequence.SubSequence.SubSequence.SubSequence for a Collection C
will only resolve potential archetypes up to
C.SubSequence.SubSequence.
Not much benefit from this because the GenericSignatureBuilder itself
isn't using resolveEquivalenceClass() when expanding requirements.
Prior to the removal of the “lookup conformance function”, whenever
the type checker created a GenericSignatureBuilder, its lookup conformance
function would mark any referenced conformance as “used”. Do so now via
a LazyResolver callback, which fixes a regression in multi-file type
checking scenarios.
Now that the GenericSignatureBuilder is no longer sensitive to the input
module, stop uniquing the canonical GSBs based on that module. The main
win here is when deserializing a generic environment: we would end up
creating a canonical GSB in the module we deserialized and another
canonical GSB in the module in which it is used.
Implement a module-agnostic conformance lookup operation within the GSB
itself, so it does not need to be supplied by the code constructing the
generic signature builder. This makes the generic signature builder
(closer to) being module-agnostic.
Now that we only record potential archetypes involving the "anchor"
archetypes, there is no need to collapse structurally-equivalent potential
archetypes. Delete some temporary code.
When we have an equivalence class that contains two unrelated
associated types with the same name, infer a same-type constraint
between those two associated types. This is a more principled way to
introduce these constraints that we had before, fixing a
recently-introduced regression.
Since overriding associated types aren't recorded as potential archetypes,
there is no point in introducing inferred same-type constraints involving
them.
Use the "override" information in associated type declarations to provide
AST-level access to the associated type "anchor", i.e., the canonical
associated type that will be used in generic signatures, mangling,
etc.
In the Generic Signature Builder, only build potential archetypes for
associated types that are anchors, which reduces the number of
potential archetypes we build when type-checking the standard library
by 14% and type-checking time for the standard library by 16%.
There's a minor regression here in some generic signatures that were
accidentally getting (correct) same-type constraints. There were
existing bugs in this area already (Huon found some of them), while
will be addressed as a follow-up.
Fies SR-5726, where we were failing to type-check due to missed
associated type constraints.
If the class itself is generic and we're looking up a nested type
from a conformance, we would pass an interface type to
mapTypeOutOfContext() and crash.
Once we compute a generic signature from a generic signature builder,
all queries involving that generic signature will go through a separate
(canonicalized) builder, and the original builder can no longer be used.
The canonicalization process then creates a new, effectively identical
generic signature builder. How silly.
Once we’ve computed the signature of a generic signature builder, “register”
it with the ASTContext, allowing us to move the existing generic signature
builder into place as the canonical generic signature builder. The builder
requires minimal patching but is otherwise fully usable.
Thanks to Slava Pestov for the idea!
This is somewhat of a pyrrhic victory, because it was just a shell over
resolvePotentialArchetype() anyway, but we now have fewer entry points that
produce potential archetypes.
Use resolveEquivalenceClass() instead, which will be more lightweight in the
future. This is effectively NFC because we were already alway working on
the representatives of the equivalence classes in this code.
We shouldn’t need a potential archetype to map an interface type to a
contextual type. Port `getTypeInContext()` over to `EquivalenceClass`,
largely unchanged, so we don’t directly form archetypes.
Kills a few more uses of `GenericSignatureBuilder::resolveArchetype()`.
The anchor of an equivalence class canonically represents that equivalence
class. Add API for computing the anchor directly, and switch a few more
clients off of `resolveArchetype()`.
Funnel all places where we create a generic signature builder to compute
the generic signature through a single entry point in the GSB
(`computeGenericSignature()`), and make `finalize` and `getGenericSignature`
private so no new uses crop up.
Tighten up the signature of `computeGenericSignature()` so it only works on
GSB rvalues, and ensure that all clients consider the GSB dead after that
point by clearing out the internal representation of the GSB.