Opaque result type archetypes can involve type variables, which
then get introduced into GenericSignatureBuilders and the
generated GenericSignatures. Allocate them in the proper arena
So we don’t end up with use-after-free errors.
Fixes rdar://problem/50309503.
It's a recursive helper that only captures one argument other than
'this'. Pay the cost of putting a declaration in a commonly-included
header to simplify the code.
No intended functionality change.
Introduced during the bring-up of the generics system in July, 2012,
Substitution (and SubstitutionList) has been completely superseded by
SubstitutionMap. R.I.P.
Convert NameAliasType’s internal representation from tail-allocating an
array of Substitutions (to be treated as a SubstitutionList) to store a
single SubstitutionMap. Serialize using that SubstitutionMap.
Collapse the out-of-line array of replacement types and the DenseMap used
for conformances into a single field that references out-of-line,
tail-allocated storage for all of the contents of a SubstitutionMap.
The conformances are now represented as a flat array whose indices
line up with the indices of the conformance requirements in the
underlying generic signtature.
Reference this storage via a single shared_ptr, so that copies of
SubstitutionMaps are cheap but we aren't (yet) uniqueing them or
storing them within the ASTContext.
This new format more efficiently represents existing information, while
more accurately encoding important information about nested generic
contexts with same-type and layout constraints that need to be evaluated
at runtime. It's also designed with an eye to forward- and
backward-compatible expansion for ABI stability with future Swift
versions.
Queries against the generic signature might use types that are
ill-formed for that generic signature, e.g., because they refer to
associated types of unrelated protocols. Detect such conditions to
maintain GSB invariants that all potential archetypes in a well-formed
generic signature are well-formed.
Fixes the crash in SR-6797 / rdar://problem/36673825.
conformsToProtocol() is the main way in which we check whether a given type
conforms to a given protocol. Extend it to check conditional requirements by
default, so that an unmodified caller will get the "does not conform" result
(with diagnostics when a location is present) rather than simply ignoring
the conditional requirements.
Some callers take responsibility for conditional requirements, e.g., to
push them into the constraint system. Allow those callers to opt out of
this checking, and do so wherever appropriate.
Fixes rdar://problem/35518088, where we were ignoring the conditional
requirements needed to verify that Equatable synthesis could be performed.
Introduce GenericSignature::requirementsNotSatisfiedBy(otherSig) to
compute the set of requirements in a generic signature that aren't satisfied
by some other generic signature. This is used both for conditional
conformances (the conditional requirements) and for name mangling of
constrained extensions/protocol conformances.
This allows determining which requirements make a conformance conditional; as
in, which requirements aren't known as part of the type itself.
Additionally, use this to assert that a few builtin protocols aren't
conditionally-conformed-to, something we won't support for now.
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.
When asking a substitution map for a conformance, it's okay if the
conformance isn't there---just detect this case and return None.
Also, collapse a redundant testcase Huon noted.
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.
Introduce an API that determines the "conformance access path" that
one would follow to find the conformance of a given type parameter
(e.g., T.Iterator.Element) to a given protocol (e.g., Equatable). A
conformance access path starts at one of the explicit requirements
of that generic signature and then proceeds through zero or more
protocol-supplied requirements. For example, given this function:
func f<C: Collection>(_: C) { }
The conformance access path for "C.Iterator: IteratorProtocol" is
(C, Collection) -> (Self, Sequence) -> (Self.Iterator, IteratorProtocol)
because one starts with the explicit requirement "C: Collection", goes
to the inherited protocol requirement (the "Self" in Collection
conforms to Sequence) and then a requirement on the associated type
(Self.Iterator in Sequence conforms to IteratorProtocol).
This is all scaffolding now; it's intended to be used by IRGen (to
find the witness tables it needs) and SubstitutionMap (to dig out
conformances during substitution).
This was a remnant of the old generics implementation, where
all nested types were expanded into an AllArchetypes list.
For quite some time, this method no longer returned *all*
dependent types, only those with generic requirements on
them, and all if its remaining uses were a bit convoluted.
- In the generic specialization code, we used this to mangle
substitutions for generic parameters that are not subject
to a concrete same-type constraint.
A new GenericSignature::getSubstitutableParams()
function handles this use-case instead. It is similar
to getGenericParams(), but only returns generic parameters
which require substitution.
In the future, SubstitutionLists will only store replacement
types for these generic parameters, instead of the list of
types that we used to produce from getAllDependentTypes().
- In specialization mangling and speculative devirtualization,
we relied on SubstitutionLists having the same size and
order as getAllDependentTypes(). It's better to turn the
SubstitutionList into a SubstitutionMap instead, and do lookups
into the map.
- In the SIL parser, we were making a pass over the generic
requirements before looking at getAllDependentTypes();
enumeratePairedRequirements() gives the correct information
upfront.
- In SIL box serialization, we don't serialize the size of the
substitution list, since it's available from the generic
signature. Add a GenericSignature::getSubstitutionListSize()
method, but that will go away soon once SubstitionList
serialization only serializes replacement types for generic
parameters.
- A few remaining uses now call enumeratePairedRequirements()
directly.
Make the addSubstitution() and addConformance() methods private,
and declare GenericEnvironment and GenericSignature as friends of
SubstitutionMap.
At some point in the future, we can switch to a more efficient
representation of SubstitutionMap, where instead of storing
multiple hashtables, we store arrays; the keys are pre-determined.
These are no longer necessary now that we have combineSubstitutionMaps(),
and will not make sense once we switch to a more compact representation
for SubstitutionMap.
SubstitutionList is going to be a more compact representation of
a SubstitutionMap, suitable for inline allocation inside another
object.
For now, it's just a typedef for ArrayRef<Substitution>.
First, add some new utility methods to create SubstitutionMaps:
- GenericSignature::getSubstitutionMap() -- provides a new
way to directly build a SubstitutionMap. It takes a
TypeSubstitutionFn and LookupConformanceFn. This is
equivalent to first calling getSubstitutions() with the two
functions to create an ArrayRef<Substitution>, followed by
the old form of getSubstitutionMap() on the result.
- TypeBase::getContextSubstitutionMap() -- replacement for
getContextSubstitutions(), returning a SubstitutionMap.
- TypeBase::getMemberSubstitutionMap() -- replacement for
getMemberSubstitutions(), returning a SubstitutionMap.
With these in place, almost all existing uses of subst() taking
a ModuleDecl can now use the new form taking a SubstitutionMap
instead. The few remaining cases are explicitly written to use a
TypeSubstitutionFn and LookupConformanceFn.
When enumerating requirements, always use the archetype anchors to
express requirements. Unlike "representatives", which are simply there
to maintain the union-find data structure used to track equivalence
classes of potential archetypes, archetype anchors are the
ABI-stable canonical types within a fully-formed generic signature.
The test case churn comes from two places. First, while
representatives are *often* the same as the archetype anchors, they
aren't *always* the same. Where they differ, we'll see a change in
both the printed generic signature and, therefore, it's
mangling.
Additionally, requirement inference now takes much greater
care to make sure that the first types in the requirement follow
archetype anchor ordering, so actual conformance requirements occur in
the requirement list at the archetype anchor---not at the first type
that is equivalent to the anchor---which permits the simplification in
IRGen's emission of polymorphic arguments.
This commit introduces new kind of requirements: layout requirements.
This kind of requirements allows to expose that a type should satisfy certain layout properties, e.g. it should be a trivial type, have a given size and alignment, etc.
Use a syntax that declares the layout's generic parameters and fields,
followed by the generic arguments to apply to the layout:
{ var Int, let String } // A concrete box layout with a mutable Int
// and immutable String field
<T, U> { var T, let U } <Int, String> // A generic box layout,
// applied to Int and String
// arguments
The "core" data structure used to record the substitutions to be
performed is a TypeSubstitutionMap, which is a DenseMap. This is a
fairly heavyweight, static data structure for something where
* We occasionally want a more dynamic, lazily-populated data structure, and
* We can usually provide more efficient storage than a DenseMap.
So, introduce a Type::subst() variant that takes a TypeSubstitutionFn,
which is just a function that maps a SubstitutableType * to a Type (or
nothing). Use this as the core variant of subst(). with an adapter for
existing TypeSubstitutionMaps. Over time, TypeSubstitutionMap should
go away.
This eliminates the really gross registration of archetype builders
within the ASTContext, and is another little step toward lazily
constructing archetypes.
Introduce a new operation on generic signatures,
enumeratePairedRequirements(), which invokes a callback with each
(dependent type, set-of-conformance-requirements) pair that needs to
be recorded within substitutions. Switch the last two remaining
consumers of witness markers (GenericSignature::getAllDependentTypes()
and GenericSignature::getSubstitutions()) over to this new entrypoint.
This gives us a concept we can eventually use to cache the lowered physical layout of fragile structs and classes, and more immediately, concretize the layout of closure boxes in a way that lets us represent the capture of generic environments and multiple captured values without compromising the "nominal" nature of box layouts. To start exercising the basic implementation, change the representation of SILBoxType to be in terms of a SILLayout, though avoid any immediate functionality change by preserving the single-boxed-type interface for now.