The refactoring that moved the substitution of the outer environment
into an opaque type archeptype into the generic environment eliminated
the need for the bound signature entirely, so remove it.
When forming the generic signature of a generic environment for opaque
types, substitute for the outer generic parameters based on the provided
substitution map. We weren't able to do this before because the
substitution cannot be performed when there are interface types or
type variables involved. However, the lazy construction of this
generic signature and use of other queries on opaque type archetypes
ensures that we don't form new generic signatures until we have
concrete types to work with.
This enables same-type constraints amongst different opaque result types
and their associated types.
Teach `GenericEnvironment` how to lazily create opaque type archetypes,
performing the contextual substitutions as required but without
building the "bound" generic signature until required. To get here,
augment `GenericEnvironment` with knowledge of the purpose of the
environment, whether it is for normal cases (any signature), an opened
existential type, or an opaque type. For opaque types, store the
opaque type declaration and substitution map, which we also use to
uniquely find the generic environment. Among other things, this
ensures that different opaque type archetypes within the same opaque
type declaration are properly sharing a generic environment, which
wasn't happening before.
This still doesn't handle the case where a non-concrete anchor has a
concrete parent; that requires switching the archetype representation
to be "flat".
Fixes <rdar://problem/84734584>.
Start treating the null {Can}GenericSignature as a regular signature
with no requirements and no parameters. This not only makes for a much
safer abstraction, but allows us to simplify a lot of the clients of
GenericSignature that would previously have to check for null before
using the abstraction.
Instead of using the recursiveConcreteType and recursiveSuperclass bits in
EquivalenceClass, store an ErrorType to the cached value before we begin
archetype construction. If a recursive call attempts to get the archetype
for the same type re-entrantly, we will return an ErrorType.
Instead of using the recursiveConcreteType and recursiveSuperclass bits in
EquivalenceClass, store an ErrorType to the cached value before we begin
archetype construction. If a recursive call attempts to get the archetype
for the same type re-entrantly, we will return an ErrorType.
Structurally prevent a number of common anti-patterns involving generic
signatures by separating the interface into GenericSignature and the
implementation into GenericSignatureBase. In particular, this allows
the comparison operators to be deleted which forces callers to
canonicalize the signature or ask to compare pointers explicitly.
We've fixed a number of bugs recently where callers did not expect
to get a null Type out of subst(). This occurs particularly often
in SourceKit, where the input AST is often invalid and the types
resulting from substitution are mostly used for display.
Let's fix all these potential problems in one fell swoop by changing
subst() to always return a Type, possibly one containing ErrorTypes.
Only a couple of places depended on the old behavior, and they were
easy enough to change from checking for a null Type to checking if
the result responds with true to hasError().
Also while we're at it, simplify a few call sites of subst().
Replace two prominent uses of SubstitutionList, in ConcreteDeclRef and
Witness, with SubstitutionMap. Deal with the myriad places where we
now have substitution maps and need substitution lists (or vice versa)
caused by this change.
Overall, removes ~50 explicit uses of SubstitutionList (of ~400).
Replace manual substitution mapping by using the existing ProtocolConformanceRef::getAssociatedConformance helper to look up the Equatable conformance from Hashable. Replace use of manual Substitution construction with SubstitutionMaps.
The key path pattern needs to include a reference to the external descriptor, along with hooks for lowering its type arguments and indices, if any. The runtime will need to instantiate and interpolate the external component when the key path object is instantiated.
While we're here, let's also reserve some more component header bytes for future expansion, since this is an ABI we're going to be living with for a while.
This will allow key paths to resiliently reference public properties from other binaries by referencing a descriptor vended by the originating binary. NFC yet, this just provides printing/parsing/verification of the new component.
Except GenericEnvironment.h, because you can't meaningfully use a
GenericEnvironment without its signature. Lots less depends on
GenericSignature.h now. NFC
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()`.
SubstitutionMap::lookupConformance() would map archetypes out
of context to compute a conformance path. Do the same thing
in SubstitutionMap::lookupSubstitution().
The DenseMap of replacement types in a SubstitutionMap now
always has GenericTypeParamTypes as keys.
This simplifies some code and brings us one step closer to
a more efficient representation of SubstitutionMaps.
The core substitution routine for the archetypes-to-interface types
substitution was attempting to provide mappings for nested archetypes,
when in fact these archetypes would (1) always be resolvable via their
parent, and (2) could in fact cause infinite recursion, as with the
new test case. Fixes SR-4617 / rdar://problem/31673819.
Rather than detecting recursion and bailing early, delay requirements
that would form recursive types. Note that we aren't actually
processing them later.
When looking for a conformance for an archetype, map it out of context
to compute the conformance access path, then do the actual lookups
based on mapping the starting type back into the context. Eliminate
the parent map and "walk the conformances" functionality.
Substitution maps are effectively tied to a particular generic
signature or environment; keep track of that signature/environment so
that we can (eventually) use it to find conformances.