This is a more correct fix for the issue that inspired PR #62854.
In particular, this does not change the numbering of generic
argument levels, and so does not break generic type parameter
lookups.
Added a new test case to verify that nested types that mix
generics and non-generics in different ways consistently identify
the correct generic argument labels.
A "generic" case is any case whose payload type depends
on generic type parameters for the enum or any enclosing type.
Some examples:
```
struct S<T> {
enum E {
case a // Non-generic case
case b(Int) // Non-generic case
case c(T) // Generic case
case d([U]) // Generic case
case e([Int]) // Non-generic case
}
}
```
This is important for correctly distinguishing MPE versus
SPE layouts. A case is considered "empty" only if it
is either a non-payload case (`case a`) or if the payload
is zero-sized and non-generic. Generic cases are always
treated as non-zero-sized for purposes of determining
the layout strategy.
Correctly testing this is tricky, since some of the
layout strategies differ only in whether they export
extra tag values as XIs. The easiest way to verify is
to check whether wrapping the result in an `Optional<>`
adds another byte to the overall size.
This exercises a number of cases that the previous logic got
wrong, including cases where MPEs are laid out like SPEs,
and cases where we use the SPE or MPE layout strategies for enums
that have no non-empty payloads. (These cases are superficially
similar but differ in how they handle XIs.)
These new tests allowed me to correct a number logical flaws
about how layouts are selected. In particular, cases with
generic payloads are always considered to be non-empty for
purposes of selecting a layout strategy. Only cases that
are statically known to be empty are considered empty for
layout purposes.
We clear the NodeFactory to prevent unbounded buildup of allocated memory, but this is done too eagerly. In particular, normalizeReflectionName can end up clearing the factory while the calling code is still using nodes that were allocated from it.
To keep peak memory usage low while avoiding this problem, we introduce a checkpoint mechanism in NodeFactory. A checkpoint can be pushed and then subsequently popped. When a checkpoint is popped, only the nodes allocated since the checkpoint was pushed are invalidated and the memory reclaimed. This allows us to quickly clear short-lived nodes like those created in normalizeReflectionName, while preserving longer-lived nodes used in code calling it. Uses of clearNodeFactory are replaced with this checkpoint mechanism.
rdar://106547092
Allocate an empty BuiltinTypeInfo. The code previously allocated a TypeInfo but set its kind to Builtin, which led to calling code doing an incorrect cast and reading an invalid value for the Name field.
rdar://106563125
TypeInfoProvider's address was used as part of the key to cache type
infos. This can cause the unnecessary recomputation of type infos, as
different instances of TypeInfoProviders may provide the exact same type
infos. Allow TypeInfoProviders to provide an id which can be used for
caching purposes.
rdar://80001304
that contain zero-sized payloads, which should resolve a number of issues with
RemoteMirror incorrectly reflecting enum cases and/or measuring the layout of
structures containing enums.
Background: Enum cases that have zero-sized payloads are handled
differently from other payload-bearing cases.
1. For layout purposes, they're treated as
non-payload cases. This can cause an MPE to
actually get represented in memory as a single-payload
or non-payload enum.
2. However, zero-sized payloads are still considered for
extra inhabitant calculations. Since they have no
extra inhabitants, this tends to cause such enums to
also not expose extra inhabitants to containing enums.
This commit makes several change to how RemoteMirror determines
enum layout:
* The various "*EnumTypeInfo" classes now represent
layout mechanisms -- as described in (1) above,
this can differ from the source code concept.
* An Enum "kind" is separately computed to reflect the
source code concept; this ensures that the dumped
type information reflects the source code.
* For single-payload and no-payload _layouts_,
the extra inhabitant calculation has been adjusted
to ensure that zero-sized payloads are correctly
considered.
Resolves: rdar://92945673
Fix computation of generic params per level when a generic type is
nested in a non-generic one. For example, for the following code:
```
class A {
class B<T, U> {
}
}
```
Fix the array of generic params per level from [2] to [0, 2].
rdar://103457629