Summary
#353 closed the order-dependent hint at the four inline structural positions —
items, additionalProperties, a patternProperties entry, a prefixItems slot —
by having the pointer walk (structuralPointerHint) replay what the structural
lowering composes. That derivation is confined to /components/schemas/…, and the
remainder is this issue.
Under /paths the enclosing hint comes from an operationId, a response, or a
media-type key, none of which the pointer records. With no reference to it, the
position is named by the structural lowering:
t/anon/paths/~1x/get/responses/200/content/application~1json/schema/items
hint=response_item
Add a component pointing at that same pointer, and the node is named items
instead — the last segment of the pointer, which is all the walk has there.
It is not an order dependence
Worth stating precisely, because #353 was. Components lower before paths, so a
reference from components always interns the node first, in either spelling of
the document. Both orders produce items, and the document stays deterministic.
What is left is that a node's name depends on whether some unrelated schema
elsewhere points at it. A/items in components is A_item whether or not anything
references it; the same position under /paths is response_item or items
depending on that. It is a weaker defect than #353's and a real one: the name an
emitter renders should be a property of the declaration, not of the document's
reference graph.
What closing it would take
- Make the reference side never name the node. A node's hint would come only
from the lowering that reaches it through its enclosing declaration; a lowering
arriving through an outside $ref would intern the node but not claim its name,
and the declaration would set it on arrival. That matches the IR's own principle —
a name comes from a declaration, not from a reference to it — but it means the
type registry has to distinguish an authoritative namer from a provisional one,
which is new machinery in compilers/compile rather than a change to one hint
function.
- Decide the weaker spelling names the node at these positions everywhere.
Cheaper, and worse: the enclosing context is most of what makes an anonymous
node's hint usable to an emitter.
Direction 1 looks right and is the larger change. It would also subsume
branchPointerHint and structuralPointerHint, which exist only to make two namers
agree — with direction 1 there is one namer, and the agreement is structural rather
than maintained.
Where it is pinned
TestInlinePosition_UnderPathsTakesTheWeakerName
(compilers/openapi/internal/schema/schema_test.go) pins all three values — the
unreferenced response_item and the referenced items in both declaration orders —
and names this issue.
Note that orderInvariantIR() no longer excludes ir.Naming.Hint at all: #353 made
the field comparable, and this remainder is not an order dependence, so nothing here
needs hiding from that comparison.
Summary
#353 closed the order-dependent hint at the four inline structural positions —
items,additionalProperties, apatternPropertiesentry, aprefixItemsslot —by having the pointer walk (
structuralPointerHint) replay what the structurallowering composes. That derivation is confined to
/components/schemas/…, and theremainder is this issue.
Under
/pathsthe enclosing hint comes from an operationId, a response, or amedia-type key, none of which the pointer records. With no reference to it, the
position is named by the structural lowering:
Add a component pointing at that same pointer, and the node is named
itemsinstead — the last segment of the pointer, which is all the walk has there.
It is not an order dependence
Worth stating precisely, because #353 was. Components lower before paths, so a
reference from
componentsalways interns the node first, in either spelling ofthe document. Both orders produce
items, and the document stays deterministic.What is left is that a node's name depends on whether some unrelated schema
elsewhere points at it.
A/itemsin components isA_itemwhether or not anythingreferences it; the same position under
/pathsisresponse_itemoritemsdepending on that. It is a weaker defect than #353's and a real one: the name an
emitter renders should be a property of the declaration, not of the document's
reference graph.
What closing it would take
from the lowering that reaches it through its enclosing declaration; a lowering
arriving through an outside
$refwould intern the node but not claim its name,and the declaration would set it on arrival. That matches the IR's own principle —
a name comes from a declaration, not from a reference to it — but it means the
type registry has to distinguish an authoritative namer from a provisional one,
which is new machinery in
compilers/compilerather than a change to one hintfunction.
Cheaper, and worse: the enclosing context is most of what makes an anonymous
node's hint usable to an emitter.
Direction 1 looks right and is the larger change. It would also subsume
branchPointerHintandstructuralPointerHint, which exist only to make two namersagree — with direction 1 there is one namer, and the agreement is structural rather
than maintained.
Where it is pinned
TestInlinePosition_UnderPathsTakesTheWeakerName(
compilers/openapi/internal/schema/schema_test.go) pins all three values — theunreferenced
response_itemand the referenceditemsin both declaration orders —and names this issue.
Note that
orderInvariantIR()no longer excludesir.Naming.Hintat all: #353 madethe field comparable, and this remainder is not an order dependence, so nothing here
needs hiding from that comparison.