Summary
annotation.RawFromNode keeps a !!timestamp or !!binary scalar as the text the
source wrote, but still refuses one whose text does not satisfy the tag it declares:
x-when: !!timestamp notadate # dropped, warning "extension could not be serialized"
x-blob: !!binary "###" # dropped, same warning
The whole extension is discarded and the caller gets a warning diagnostic
(ExtensionsFrom, annotation.go).
That refusal is inherited rather than chosen. It exists because the conversion used
to decode these scalars to produce its output, so a decode failure had nowhere to
go. Nothing consumes the decoded value any more — the decode survives only as a tag
check — so the refusal is now the one thing standing between a construct the source
wrote and the IR.
Why it may be wrong
RawFromNode's documented rule is that it refuses what JSON cannot name: a
non-string mapping key, a key written twice, .nan/.inf. Both scalars above are
perfectly nameable in JSON — they are strings. They are refused for failing YAML
type resolution, which is a different rule, and one the sibling arm already declines
to apply: a tag yaml.v3 resolves no type for (!acme/thing) keeps its text rather
than being dropped, on the stated grounds that refusing would lose an extension value
the source did write.
Against that: dropping with a warning is louder than preserving silently, and a
!!binary "###" is a genuinely malformed construct that an author probably wants to
hear about. The IR has no channel for "kept, but suspect" — RawFromNode returns
(value, error) and the error path is what produces the diagnostic — so keeping the
text and keeping the warning is not currently expressible without threading a
diagnostic through the walk.
Decision needed
Which of "refuse and warn" or "preserve as text" is right for a scalar whose tag
promises a type its text does not hold, and whether the IR wants a way to say both.
Whatever is chosen, RawFromNode's doc comment states the current rule and must move
with it.
Context
Split out of #242, which settled what these scalars preserve and deliberately left
what they accept unchanged so the two questions could be answered separately. The
!!timestamp / !!binary arm of scalar in
compilers/openapi/internal/annotation/rawjson.go points here.
Summary
annotation.RawFromNodekeeps a!!timestampor!!binaryscalar as the text thesource wrote, but still refuses one whose text does not satisfy the tag it declares:
The whole extension is discarded and the caller gets a warning diagnostic
(
ExtensionsFrom,annotation.go).That refusal is inherited rather than chosen. It exists because the conversion used
to decode these scalars to produce its output, so a decode failure had nowhere to
go. Nothing consumes the decoded value any more — the decode survives only as a tag
check — so the refusal is now the one thing standing between a construct the source
wrote and the IR.
Why it may be wrong
RawFromNode's documented rule is that it refuses what JSON cannot name: anon-string mapping key, a key written twice,
.nan/.inf. Both scalars above areperfectly nameable in JSON — they are strings. They are refused for failing YAML
type resolution, which is a different rule, and one the sibling arm already declines
to apply: a tag yaml.v3 resolves no type for (
!acme/thing) keeps its text ratherthan being dropped, on the stated grounds that refusing would lose an extension value
the source did write.
Against that: dropping with a warning is louder than preserving silently, and a
!!binary "###"is a genuinely malformed construct that an author probably wants tohear about. The IR has no channel for "kept, but suspect" —
RawFromNodereturns(value, error)and the error path is what produces the diagnostic — so keeping thetext and keeping the warning is not currently expressible without threading a
diagnostic through the walk.
Decision needed
Which of "refuse and warn" or "preserve as text" is right for a scalar whose tag
promises a type its text does not hold, and whether the IR wants a way to say both.
Whatever is chosen,
RawFromNode's doc comment states the current rule and must movewith it.
Context
Split out of #242, which settled what these scalars preserve and deliberately left
what they accept unchanged so the two questions could be answered separately. The
!!timestamp/!!binaryarm ofscalarincompilers/openapi/internal/annotation/rawjson.gopoints here.