Skip to content

winmd-inspect: disambiguate colliding names with fabricated namespaces - #351

Open
compnerd wants to merge 1 commit into
compnerd/render-closure-4-nestingfrom
compnerd/render-closure-5-collision
Open

winmd-inspect: disambiguate colliding names with fabricated namespaces#351
compnerd wants to merge 1 commit into
compnerd/render-closure-4-nestingfrom
compnerd/render-closure-5-collision

Conversation

@compnerd

Copy link
Copy Markdown
Owner

Disambiguate the names two reached declarations would otherwise share, so every signature spelling resolves to the declaration it names and the generated source compiles. Builds on the nesting slice, adding the collision tally, the fabricated namespace containers, and the frontier logic.

The projection is one flat top-level Swift scope, so a name is ambiguous when two or more of the top-level declarations the closure emits bear it of any kind — a second value type, an interface or delegate, or a runtime class. Because only a value type can be wrapped, an ambiguous value type is spelled and emitted fully namespace-qualified under fabricated namespace enum containers (A.Point/B.Point), while the same-named protocol stays bare. Ambiguity is counted over the projected (arity-stripped) name the emission carries and only over the reached declarations, so an unreachable same-named type never forces a wrap; the qualification keys off the value type's raw namespace.name identity (so a same-named generic protocol does not borrow it) and confirms the reference resolves locally (so an external same-named type spells bare). The decode spelling, the emit nesting, and the collision tally derive from one source on Storage, so they cannot drift.

The per-scope validation reconciles every declaration scope — the top-level roots and each container's direct children — so members bear distinct labels: a residual clash faults rather than emitting uncompilable output. Two same-named top-level protocols fault ambiguous; a fabricated namespace container shadowing an emitted type, or a generic interface/delegate's synthesized internal protocol <name>ABI colliding with a co-emitted type, or a fabricated container shadowing a signature-referenced frontier type the closure spells but does not emit, faults collision. A frontier — a name the closure spells but does not emit — is derived once from the emitted-set complement rather than enumerated per reason: the walk records every spelled reference (a signature-named type or an interface's named base) as its emitted top-level spelling paired with the TypeDef Id it resolves to, and a reference is a frontier exactly when that Id (its outermost encloser's, so a nested A.Inner turns on its root A, not on Inner) is absent from the emitted set. One rule then covers every way a name goes unemitted — a runtime class, a GUID-less shape, a known-bridged or layout-rejected value type, a metadata-nested protocol, a value type under a non-container, and an external reference (including an
external base the bases view names though the local-only requires walk does not). The one frontier set serves both seams: the fabricated-namespace shadow check faults on a label it bears, and the reached-only ambiguity tally treats it as a distinct top-level bearer — a reached A.Point beside a frontier B.Point (external, layout-rejected, known-bridged to the same target, or an inherited base) wraps and qualifies to A.Point rather than spelling a bare Point that captures the frontier's reference. Deriving from the complement, not a name subtraction, keeps a top-level frontier A reserved even when an unrelated nested Foo.A is emitted, and reading the known bridge name as the spelling lets a value type of that target name contend. A post-walk reachability prune keeps only the declarations reachable from the seeds through emittable nodes, dropping the orphans a discarded frontier would otherwise leave behind, and the emit renders each kept body once the reached-only qualification sets are fixed, so a body is spelled with the same set that folds it into the tree.

Integration tests cover two same-named value types each wrapped in its namespace enum, a value type colliding with a same-named protocol, arity and same-namespace-arity collisions, a generic type's ABI name colliding with a metadata type, a fabricated container shadowing an emitted type (at the root and a level down) and a frontier type (top-level, nested — whose enclosing root it shadows —, an external interface base, and an external base a fabricated enum A must not un-frontier merely because an unrelated nested Foo.A is emitted), a reached value type wrapping against a frontier of the same name (an external
referent, a layout-rejected value type, an external base, and a known bridge target each), and an unreachable same-named type leaving a reached one bare.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ca46124ecd

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/winmd-inspect/Shell.swift Outdated
Comment thread Sources/winmd-inspect/Shell.swift Outdated
@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from ca46124 to 20aed49 Compare August 27, 2026 19:56

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 20aed49ef5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/winmd-inspect/Shell.swift
@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from 20aed49 to 5e22166 Compare August 27, 2026 23:54

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 5e22166e40

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/winmd-inspect/Shell.swift Outdated
@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from 5e22166 to 6ad027f Compare August 28, 2026 00:50

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6ad027fe48

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/winmd-inspect/Shell.swift Outdated
Comment thread Sources/winmd-inspect/Shell.swift Outdated
@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from 6ad027f to 480b0e3 Compare August 28, 2026 05:28

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 480b0e3bec

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/WinMD/Storage.swift
Comment thread Sources/winmd-inspect/Shell.swift Outdated
@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from 480b0e3 to c6e410c Compare August 28, 2026 05:40

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c6e410c7d3

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/winmd-inspect/Shell.swift Outdated
@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch 2 times, most recently from 1f99012 to 285009e Compare August 28, 2026 06:48

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 285009ea57

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/winmd-inspect/Shell.swift Outdated
@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from 285009e to 4ca5e73 Compare August 28, 2026 16:36

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4ca5e73c94

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/WinMDSynthesis/Resolver.swift Outdated
Comment thread Sources/winmd-inspect/Shell.swift Outdated
@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from 4ca5e73 to c535488 Compare August 28, 2026 20:27

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c535488547

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/winmd-inspect/Shell.swift Outdated
Comment thread Sources/winmd-inspect/Shell.swift Outdated
@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from c535488 to 9dd1364 Compare August 28, 2026 21:01

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9dd1364b40

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/winmd-inspect/Shell.swift Outdated
@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from 9dd1364 to 561a427 Compare August 29, 2026 21:53
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 29, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-01T20:01:30.930996Z d85afcf New commits
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 561a427072

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/winmd-inspect/Shell.swift
Comment thread Sources/winmd-inspect/Shell.swift Outdated
@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from 561a427 to fe9943e Compare August 29, 2026 22:12

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: fe9943e45a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/winmd-inspect/Shell.swift Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d7b3b7e6d6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/winmd-inspect/Shell.swift
Comment thread Sources/winmd-inspect/Shell.swift
@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from d7b3b7e to 9c163ef Compare August 31, 2026 21:21

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9c163ef328

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread Sources/winmd-inspect/Shell.swift
@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from 9c163ef to 768b2f5 Compare August 31, 2026 21:46

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 768b2f51cb

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +831 to +833
try emitted.contains(emission.id)
&& emission.name == language.escape(language.root)
&& session.storage.nesting(of: emission.id).isEmpty

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Require the fallback-root match to be an interface

When a rootless interface reaches a top-level value type named IUnknown through one of its signatures, this predicate sets rooted even though the emission is a struct or enum. The synthesized protocol IRoot: IUnknown is then excluded from the frontier set, so the value type remains bare and the inheritance resolves to a non-protocol type, producing invalid Swift. Restrict this exemption to an emitted interface that can actually serve as the fallback protocol.

Useful? React with 👍 / 👎.

Comment on lines +1241 to +1245
let folded = fold(kids.sorted { earliest($0) < earliest($1) })
let container = Shell.inject(folded.block,
into: "public enum \(label(node)) {\n}",
container: label(node))
return (folded.header, container, folded.footer)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Wrap every conditional branch declaring the primary type

When a custom template declares the same ambiguous value type in multiple conditional-compilation clauses, such as #if A; struct Point {}; #else; struct Point {}; #endif, partition selects only the first declaration and leaves the other clause in folded.footer. This namespace branch consequently wraps only the first Point; when the alternate clause is active, signatures still spell A.Point but the output declares only a bare Point. Preserve the conditional structure while applying the fabricated namespace to every branch that declares the primary type.

Useful? React with 👍 / 👎.

@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from 768b2f5 to f93536b Compare August 31, 2026 21:57

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f93536bf72

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +835 to +838
for reference in spelled
where emitted.contains(reference.owner)
&& (reference.id == nil || !emitted.contains(reference.id!))
&& !(reference.fallback && rooted) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reserve fixed template type names before fabricating namespaces

When an ambiguous value type is under a namespace whose leading segment matches a type name emitted directly by the bundled template, this loop cannot detect the shadow because spelled contains only metadata references and bases. For example, two reached Point types can fabricate public enum OptionSet, after which the bundled flags projection nested inside it declares struct Point: OptionSet; Swift resolves OptionSet to the enclosing enum rather than the standard-library protocol, producing invalid source. Primitive spellings such as CInt have the same problem and can silently bind fields to the fabricated enum, so fixed dialect/template type references must also be reserved against namespace containers.

Useful? React with 👍 / 👎.

@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from f93536b to 141c8cb Compare August 31, 2026 22:08

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 141c8cba72

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 360 to +362
for modifier in mods {
try record(modifier.type, into: &table, with: storage)
try record(modifier.type, into: &table, spelling: &spellings,
with: storage, qualifying: qualifying)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Revisit references first cached as modifiers

When the same TypeDefOrRef token first appears as a custom modifier and later as an indirect reference to a value type beneath a generic encloser, this call records it with the default embedded: true. The later pointer/byref occurrence then returns early from record because the token is already cached, so decoding emits an invalid spelling such as UnsafeMutablePointer<Outer.Inner> instead of the intended opaque pointer. Fresh evidence beyond the earlier indirect-reference report is this modifier-first cache path; pass the occurrence context here or allow the later ordinary occurrence to revise the cached resolution.

Useful? React with 👍 / 👎.

@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from 141c8cb to 61afc02 Compare August 31, 2026 22:26

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 61afc024d7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1994 to +1995
let label = String((bridge ?? reference.identity.name)
.prefix { $0 != "." && $0 != "`" })

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Track the projected Guid spelling

When a signature references System.Guid, decoding emits IID or CLSID rather than Guid (with the parameter name selecting CLSID). This fallback nevertheless records Guid as the frontier label, so a reached value type such as A.CLSID is not treated as contended and remains a bare struct CLSID; the generated parameter then binds to that struct instead of the imported CLSID. Record the same IID/CLSID spelling used by decoding for each occurrence.

Useful? React with 👍 / 👎.

@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from 61afc02 to 5485bf0 Compare August 31, 2026 22:52
@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from 5485bf0 to 35e3968 Compare September 1, 2026 15:34

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 35e3968cb5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +1996 to +2000
let leaf = reference.identity.name.split(separator: ".").last
.map(String.init) ?? reference.identity.name
let identity = Identity(namespace: reference.identity.namespace,
name: leaf)
let bridge = dialect.known[identity]

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reserve the bridged encloser name for nested references

When a custom language maps an enclosing type (for example, wellknown Outer OuterBridge) and a signature names Outer.Inner, TypeDefOrRef.spelling emits OuterBridge.Inner via its encloser-bridge lookup. This frontier scan only tests the leaf Inner and then falls back to Outer, so a reached value type such as A.OuterBridge remains bare and captures the generated reference instead of being wrapped; mirror the decoder's encloser-bridge lookup when deriving the frontier label.

Useful? React with 👍 / 👎.

@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from 35e3968 to cf2c451 Compare September 1, 2026 15:46

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cf2c451bb2

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +403 to +405
} else {
generic = try storage.enclosedByGeneric(tuple)
value = try storage.kind(tuple).value

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve external generic-nested value kinds

When a by-value signature names an external value type nested under a generic encloser (for example, External.Outer1.Innerencoded asVALUETYPE), there is no local definition, so this branch classifies the TypeRefrow itself; since aTypeRefhas neitherFlagsnorExtends, kind(tuple)always reports.class. The subsequent generic guard therefore discards the reference, and decoding silently substitutes the dialect's opaque pointer instead of dropping the containing declaration, changing its ABI layout. Preserve the NamedKind.valuecarried bySignatureType.named` for unresolved external references rather than inferring their kind from the reference row.

Useful? React with 👍 / 👎.

@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from cf2c451 to ef315ea Compare September 1, 2026 17:46

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ef315ea1e0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines 1023 to 1024
if emission.kind == "struct" || emission.kind == "enum" {
container.insert(emission.id)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate the rendered declaration before making it a container

When a custom template renders an enclosing metadata struct/enum as another accepted type declaration, such as typealias Outer = CInt or protocol Outer, declared remains true and this metadata-kind check still marks it as a nestable container. If the closure also reaches Outer.Inner, rendered tries to inject Inner into that alias/protocol; the alias fallback leaves Inner at file scope, while a protocol cannot contain the synthesized stored type, so signatures spelling Outer.Inner do not resolve. Fresh evidence beyond the earlier emittedness reports is that container eligibility is derived from emission.kind rather than the actual declaration kind found in the rendered body; require a rendered member-bearing struct/enum before nesting children.

Useful? React with 👍 / 👎.

Disambiguate the names two reached declarations would otherwise share, so every
signature spelling resolves to the declaration it names and the generated source
compiles. Builds on the nesting slice; the frontier reservation the shadow check
and contention need is the following slice.

The projection is one flat top-level Swift scope, so a name is ambiguous when two
or more of the emitted top-level declarations bear it, of any kind. Only a value
type can be wrapped, so an ambiguous value type is emitted fully
namespace-qualified under fabricated namespace `enum` containers
(`A.Point`/`B.Point`) while the same-named `protocol` stays bare. A closure
integration test pins this cross-kind case end to end — a reached struct
`A.Point` beside an interface, then a delegate, `B.Point` — so the value type
wraps under `enum A` while the emitted non-value declaration stays a bare
top-level `Point`, no redeclaration. Ambiguity is
counted over the projected (arity-stripped) name and only over the reached
declarations, so an unreachable same-named type never forces a wrap; the
qualification keys off the value type's raw `namespace.name` identity and confirms
the reference resolves locally. One `Storage.spelling(resolved:qualifying:)` rule
drives the decode spelling, the emit nesting, and — through a `spelling(of id:)`
overload — the inheritance clause, so a nested base under a wrapped encloser reads
`A.Outer.IChild` exactly as a signature naming it decodes, and the three seams
cannot drift. Nesting folds only a type's *primary* declaration into its
container: a custom template may frame the type with a file-scope `import`
header or an `extension` footer, which Swift permits only at file scope, so
`Surface.partition` — locating the primary declaration off the syntax tree —
splits them off the rendered body and they bubble up, through every enclosing
container, to the roots. This is symmetric across a real `.type` container and a
fabricated `.space` namespace: `nest` renders a node as a (header, declaration,
footer) triple, folds each member's declaration in, and accumulates its members'
hoisted headers and footers to pass further up. A hoisted auxiliary lands in the
root file scope, so the per-scope collision check attributes it there rather than
its container — and every nested type's auxiliaries hoist, however deep it sits,
so two descendants of different wrapped containers each hoisting a same-named
`struct Helper` are a file-scope redeclaration a per-container check would miss.

Emittedness — which reached types the closure actually declares — is read from
the rendered body off the syntax tree (`Surface.declarations`): the top-level
`struct`/`class`/`enum`/`protocol`/`actor` and `typealias` names, so per-type
boilerplate, a documented-but-omitted ABI helper, a value declaration of the
type's name, a nested member, or a declaration inside a comment does not count. Every *other* top-level name a body declares — not just the primary and
the specially recognised generic `<name>ABI` helper, but any auxiliary a custom
template emits (a `struct A` beside a `protocol IRoot`) — is recorded as a scope
occupant, so the per-scope collision check faults a fabricated namespace `enum A`
or another declaration that redeclares it. The collision tally and the emit both
key off this emitted set, computed once after a reachability prune, so a body is
spelled with the same set that folds it into the tree. The emitted set is
re-pruned against the *bodied* declarations before it drives the tally: the first
prune propagates a node's references on its metadata kind, but a custom template
may omit an intermediate declaration (render nothing for a reached `struct
Point`), so a type reached only through that omitted node — a `Widget` a `Point`
field names — is an orphan the emitted source never references, dropped rather
than left to render unattached and fault an unrelated collision. A by-value type nested
beneath a generic encloser — named directly or through a `TypeRef`, its kind read
off the resolved definition — is dropped rather than misrendered as an
ABI-changing opaque pointer; but only a genuinely *by-value* occurrence poisons
its owner — a reference solely behind a pointer, byref, or array embeds no layout
and renders as an opaque pointer, so it drops nothing — and its referent is left
unrecorded, so the decode spells that opaque pointer rather than an uncompilable
`UnsafeMutablePointer<Outer.Inner>` naming a type the closure never emits.

The collision fixtures assemble their metadata through `WinMDFixture`, an in-target
`#~` assembler that interns the heaps and computes the table ranges, with a fluent
`WinMDBuilder` facade that assigns rids, links member lists, encodes signatures,
and resolves references — so a scenario reads in a dozen declarative lines instead
of a hundred of hand-encoded bytes.

This slice also reserves the frontier names a signature spells but the closure
does not emit, so a reached value type sharing a name with one contends —
wrapping and spelling namespace-qualified rather than bare and capturing the
frontier's reference. The frontier set is derived once from the emitted-set
complement: the walk records every spelled reference — a signature-named type or
an interface's named base — as its emitted top-level spelling paired with the
`TypeDef` Id it resolves to (its outermost encloser's, so a nested `A.Inner`
turns on its root `A`), and a reference is a frontier exactly when that Id is
absent from the emitted set. `Storage.collisions(contended:)` bumps a reached
value type whose projected name a frontier bears to ambiguous — so an emitted
signature naming both a local `A.Point` and an external `Point` wraps `A.Point`
rather than leaving both positions bound to the generated bare `Point`. Whether a
fabricated namespace would then *shadow* one of those bare references is the
following slice; this slice reserves and contends.

The reservation reads the metadata resolution, not the rendered text. The decode
records every signature reference of every emitted owner in `spelled` — its
owner, the local `Id` it resolves to (or nil for an external), and its category
— so a reference is a frontier exactly when that referent is unemitted. The
template spells names; it does not choose which references the surface bears, so
the closure keys renderedness off that graph rather than re-scanning the
rendered body for each label. A reached value type still contends with a
frontier of its projected name, and a literal identifier a template writes that
no signature references is absent from `spelled` and reserves nothing.

The synthesized fallback root (`IUnknown`) is not a frontier only when a
*top-level* local interface of that name is emitted: the bare `protocol IRoot:
IUnknown` resolves at file scope, so a metadata-nested `Outer.IUnknown` does not
satisfy the exemption, and with several local `IUnknown`s the reached one is
chosen. The exemption is keyed on a fallback flag, not the spelling, so an
explicit external `IUnknown` parameter or base stays a frontier.

A `known`-bridged reference reserves the frontier under its bridge leaf name,
keyed on the identity's leaf component as the decode spells it: a nested
`Outer.Inner` bridged `wellknown Inner …` reserves `InnerBridge`, not the
enclosing root `Outer`. Keying the bridge on the qualified `Outer.Inner` missed
it and reserved `Outer`, so a reached `A.InnerBridge` of the bridge name stayed
uncontended and captured the frontier bare rather than wrapping under `enum A`.

The base render tolerates a `Queries/bases.sql` override predating the `ref`/`def`
provenance columns. The bundled render reads those columns to resolve a local
base's Id, so a copied override carrying the former `(base, spec)` view shape
faults on the missing column; `heritage` catches that `SQLError.column` and
re-runs a legacy shape that resolves each base to a local interface by name —
the best-effort resolution the provenance replaced — so an emitted local base
keeps its Id (not mistaken for a frontier) and the older override renders
rather than failing, the extension-point tolerance `fields`/`requires` get.
@compnerd
compnerd force-pushed the compnerd/render-closure-5-collision branch from ef315ea to d85afcf Compare September 1, 2026 19:56

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d85afcff00

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +2003 to +2004
let root: Int? = if let id = rows.first?[0].integer {
try session.storage.nesting(of: id).first?.id ?? id

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep bridged nested references on the frontier

When a wellknown Inner InnerBridge reference names Outer.Inner and Outer is independently emitted, pairing the bridged label with the outermost encloser's ID makes the frontier pass treat InnerBridge as emitted. The nested Inner declaration is actually suppressed by the bridge, so a reached value type such as A.InnerBridge remains bare and captures the signature intended for the imported bridge. Even with the new leaf-based bridge lookup, bridged references should not use the encloser's emittedness when constructing Spelled.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant