You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
winmd-inspect: nest metadata-nested value types into Swift nesting
Fold the flat closure emission into real Swift nesting, so a metadata-nested
value type emits as a nested type under its container chain and every signature
that names it resolves to that declaration. Disambiguating the names two reached
declarations would otherwise share is the next slice.
A metadata-nested value type emits as a real nested Swift type under its
enclosing-`TypeDef` container chain (`Outer.Inner`), and every signature that
names it spells the same dot-path, so the declaration and its uses agree and two
same-named nested types under different enclosers stay distinct. The walk emits
the enclosing value type too — even when only `Outer.Inner` is named and nothing
references `Outer` directly — so the container `Inner` nests inside actually
exists; a value type nests only when every enclosing level is an emitted
value-type container (`struct`/`enum`), else it is a dropped frontier the
consumer defines (an enclosing `protocol` cannot nest a value type, an excluded
runtime `class` is not emitted). An interface or delegate is a Swift `protocol`,
which cannot nest, so a metadata-nested one is a dropped frontier and only a
top-level one is a legal root. The flat emission folds into a containment forest
whose roots render in the walk's post-order, so a dependency precedes the type
naming it and a top-level type keeps its position.
A custom struct/enum template may open with a header comment and append a
brace-delimited footer around its main declaration; the child block is spliced
before the *main declaration's* closing brace — matched by a brace-depth count
over the body's *code* (braces inside a `//` or `/* */` comment or a single- or
triple-quoted string literal are skipped, the block-comment and multiline-string
states held across lines), from the first code `{` — not the last brace-only
line, so the child nests inside the container rather than above the declaration
(a header comment's or a multiline literal's braces) or into the footer (the
last brace).
A nested type's enclosing dot-path strips the CLR arity suffix from every
component, not only the leaf, and the strip lives at the single escape seam,
before each component is keyword-escaped, so a storage spelling and a
directly-resolved one escape identically and a generic instantiation's base
(`` `protocol`<…> ``) composes without a second strip that would cut the escape
backtick. But a *generic* encloser has no valid unqualified spelling — a member
of `Outer`1` is `Outer<T>.Inner`, needing the enclosing specialization the
projection does not yet emit, which the arity-stripped `Outer.Inner` misbinds
if the consumer supplies the generic `Outer` — so a reference into a type nested
under a generic encloser is dropped as an unsupported frontier rather than
spelled uncompilable, resolved (like a `TypeSpec` or a null index) to nothing.
An interface whose base is a metadata-nested interface names that base through
the same enclosing dot-path (`Outer.IChild`) its own nested declaration and a
signature naming it both wear, so the refinement resolves rather than reading
the bare `TypeName`, which binds no visible declaration. The selected base is
resolved to its local definition through the same `requires` scope-chain walk
the closure uses, so a base named directly through an `Interface_TypeDef` and
one named through an `Interface_TypeRef` — whose nested references the walk
follows to the local nested definition — alike carry the enclosing path; the
`.render *` batch resolves a `TypeRef` base by the same recursion. Each path
component is keyword-escaped separately. A top-level or external base resolves
to no enclosing path and spells bare, as does a base a `-I` override names that
matches no local definition.
Integration tests cover two same-named nested value types each nested under its
encloser, an enclosing value type reached only through a nested member, a child
nested inside its container despite a header comment's braces, a trailing
footer, and a multiline string literal's braces, a reference into a type nested
under a generic encloser dropped as an unsupported frontier, a generic
instantiation whose
already-stripped keyword base keeps its escape, and a top-level interface whose
base is a nested interface — named through an `Interface_TypeDef`, and (resolved
by the scope-chain walk) through an `Interface_TypeRef` — spelled through its
enclosing path.
0 commit comments