A scalar that hoists its own node because of format loses any value constraints declared beside
it, with no diagnostic.
components:
schemas:
Encoded: {type: string, format: byte, minLength: 5, maxLength: 9}
Custom: {type: string, format: iban, minLength: 5}
Both lower to a Scalar carrying the encoding and constraints: null. The same keywords on a
schema that does not hoist — {type: string, minLength: 5} — are kept.
Why
hoistByteScalar and hoistFormatScalar build their ir.Scalar from the common annotations, the
base primitive and the encoding, and never read schemaConstraints. Because they intern at the
positions own pointer, the shared path that would otherwise attach constraints sees the node as
already owned and returns before running.
Scope
Distinct from the contentEncoding/contentMediaType case, which had the identical shape and was
fixed by threading the schema into the hoister so it can set Constraints. The same one-line
change applies here; it was deliberately left out of that fix to keep it to the regression it was
closing rather than widening into behaviour that predates it.
Goldens will move: the corpus does exercise format: byte, so closing this changes emitted IR for
encoding-byte and any spec pairing an unknown format with a bound.
Method
Compiled through openapi.New().Compile(...) and inspected the emitted Scalar; contrasted
against the non-hoisting spelling and against the fixed content-vocabulary path.
A scalar that hoists its own node because of
formatloses any value constraints declared besideit, with no diagnostic.
Both lower to a
Scalarcarrying the encoding andconstraints: null. The same keywords on aschema that does not hoist —
{type: string, minLength: 5}— are kept.Why
hoistByteScalarandhoistFormatScalarbuild theirir.Scalarfrom the common annotations, thebase primitive and the encoding, and never read
schemaConstraints. Because they intern at thepositions own pointer, the shared path that would otherwise attach constraints sees the node as
already owned and returns before running.
Scope
Distinct from the
contentEncoding/contentMediaTypecase, which had the identical shape and wasfixed by threading the schema into the hoister so it can set
Constraints. The same one-linechange applies here; it was deliberately left out of that fix to keep it to the regression it was
closing rather than widening into behaviour that predates it.
Goldens will move: the corpus does exercise
format: byte, so closing this changes emitted IR forencoding-byteand any spec pairing an unknownformatwith a bound.Method
Compiled through
openapi.New().Compile(...)and inspected the emittedScalar; contrastedagainst the non-hoisting spelling and against the fixed content-vocabulary path.