Repository navigation
fix: hold aliases and string lists to their rules, quote messages - #740
Merged
Merged
Conversation
- #398: a new walk check rejects an alias that two type-registry Namings both claim. It is reported at the later alias, as ir/naming-alias-shared, and is scoped to TypeCommon.Name: an alias is a schema-resolution name and a source that writes one scopes it to its own record, so a document-wide compare would false-positive on two models stating the same short alias. - #399: the per-list alias switch becomes appendListViolations, and a TypeCommon or Service Namespace is held to its blank and repeat rules, reported as ir/namespace-blank and ir/namespace-duplicate. The verdicts for Tags, Scopes, content types, Server Enum, versions and FieldPath are recorded in the helper's doc comment rather than implemented. - #400 (message half): every document-derived fragment in a Violation.Message is quoted with strconv.Quote, so no message carries raw bytes. Violation.Path is out of scope. Closes #398, #399 Refs #400
Resolve the conflicts with main, keeping the generalized list rules and main's condensed wording, and bring the doc comments this branch adds under the 100-word cap main now enforces. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01GCzyGPq9DQ7RLfagZm2JB5
Plans and agent working notes are not part of the repository; what a reviewer needs is in the PR body, the commits and the linked issues. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The naming tests build documents without idSpaces, which main's id-spaces-absent rule now reports; they run through verifyDeclared, and namespaceDoc declares its spaces.
The one textual conflict is irverify.go's imports, where main's sort by slices and cmp meets this branch's strconv. Main also moved the tests' source reads onto type-checked declarations, so the namespace-owner test reads the TypeKind constants through irDecls rather than the parsed-source helper it was written against.
An alias that another property of the same model answers to, by its wire name or by an alias of its own, leaves a reader resolving that field with two candidates. A source can write one, since Avro accepts any string as an alias, so it is a problem in the spec rather than a compiler bug: pass/validate reports it as pass/ambiguous-alias, beside the duplicate wire names that same scope already holds. The registry-wide alias check in irverify is removed. Nothing in the IR decides a collision between types: a relative Avro alias is qualified by its own type's namespace, so one string on two types can be two names, and one document can hold independent schemas that each declare the same type and alias. ir-design §3.2 records both halves, and a pin test keeps irverify out of them.
Every []string field the ir package declares now has a decision in stringLists, keyed Type.Field as idPositions keys ID positions, and TestStringLists_AreAllClassified fails when a field is added without one. A path (TypeCommon.Namespace, Service.Namespace, GraphQLBinding.FieldPath) holds no blank segment, reported as ir/path-segment-blank. A repeated segment is legal, since com.acme.acme has three levels, so the namespace repeat rule is removed. A lifecycle set (Visibility.Only and an operation's ParameterVisibility and ReturnTypeVisibility) holds no blank entry and no repeat, reported as ir/set-entry-blank and ir/set-entry-duplicate. ir.Lifecycle aliases string, which is why a text search for []string fields never listed these three. Tags, scopes, media types, encodings and server variable values are the source's own entries, which only the source format can judge; #738 holds OpenAPI's tags and scopes. Version labels answer to Document.Versions as a whole, which #860 tracks.
Violation.Message now states its contract: text taken from the document is strconv.Quote'd, so a message is valid UTF-8 whatever the document holds. The member-id scope message was the one site still interpolating raw bytes. TestVerify_MessagesQuoteWhatTheDocumentSpells reaches every message that interpolates document text and pins its exact spelling, with an ill-formed byte in the quoted text wherever the check still reaches it. Unquoting any site reddens its own case; before it, most sites could lose their quote with every test green. Violation.Path is #739.
Main added the cycle check, whose export beside ValueCarriers met this branch's HeldLists in export_test.go; both are kept.
The cyclic-structure message interpolates the path a reference was entered at, and that path spells map keys from the document. Its case builds the cycle under a type ID holding an ill-formed byte, so the table reaches every message that quotes document text.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Three gaps in what checks an IR document's names and string lists, each settled where the rule belongs.
An alias another entity also answers to (#398). A property alias that a sibling property of the same model answers to, by its wire name or by an alias of its own, leaves a reader resolving that field with two candidates. A source can write one: Avro accepts any string as an alias, and no lowering can drop either claim without choosing between them. So this is a problem in the spec, not a compiler bug.
pass/validatenow reports it aspass/ambiguous-alias, besidepass/duplicate-wire-name, which already holds that scope.Across the type registry nothing reports a collision, because nothing in the IR can decide one:
A collision between named types is the compiler's to report, within the schema it parsed. ir-design §3.2 records both halves.
TestVerify_AliasClaimedByAnotherEntityIsCleanpins thatirverifystays out of them, and it still catches a per-listseenmap hoisted across Namings.Every
[]stringfield gets a decision (#399).irverifykeeps astringListstable keyedType.Field, the shapeidPositionsalready uses for ID positions.TestStringLists_AreAllClassifiedfails when the ir package declares a[]stringfield the table does not classify, or when the table names one that is gone. Two rules come out of it:TypeCommon.Namespace,Service.NamespaceandGraphQLBinding.FieldPathnever hold a blank segment (ir/path-segment-blank). A segment may repeat:com.acme.acmehas three levels, and every namespace grammar allows that.Visibility.Only,Operation.ParameterVisibilityandOperation.ReturnTypeVisibilityhold no blank entry and no repeat (ir/set-entry-blank,ir/set-entry-duplicate).ir.Lifecycleis an alias ofstring, so a text search for[]stringmisses these three. The type-checked test is what found them.The rest carry no list rule:
Document.Versionsas a whole, which irverify: version labels are not held to Document.Versions #860 tracks.Messages quote document text (#400). Every
Violation.Messagethat interpolates text from the document passes it throughstrconv.Quote, so a message is valid UTF-8 whatever the document holds.Violation.Messagenow states that contract. The member-ID scope message was the one site still spelling raw bytes.TestVerify_MessagesQuoteWhatTheDocumentSpellspins the exact message at every quoting site, with an ill-formed byte in the quoted text wherever the check still reaches it.Violation.Pathis the other half of #400, and #739 holds it.Alternatives considered
irverify.irverifyreports compiler bugs only. A collision a source wrote is carried by a correct compiler, as two fields with one wire name are, soirverifywould report a defect the compiler did not make. At registry scope it would also fire on both legal shapes above.com.acme.acme, which is three levels deep.Limitations
isBlankName, so irverify: the blank-alias rule misreads Unicode's default-ignorable set #832 (its misreading of Unicode's default-ignorable set) applies to path segments and set entries too.pass/ambiguous-aliascompares a model's own properties, the scopepass/duplicate-wire-nameholds. Inherited properties and other property lists, such as headers and resource identifiers, are not compared, matching that rule.checkStringListsis one more reflective walk, as everyirverifycheck is. Againstmain,Verifytook 6–9% longer on the three largest reference specs (github.json at 11,968 types: 2.59 s → 2.82 s).Validatewas unchanged within noise. ir: build WalkValues paths only when a visitor reads them #813 tracks walk cost in general.Test plan
go test ./ir/irverify ./pass ./internal/archtest -count=1strconv.Quotesite inir/irverify, unquoted one at a time, reddens a test. Each of the following, planted one at a time, reddens a named test:stringlists: the blank rule, the repeat rule (off, and on for paths), the ill-formed skip, the path/set selection, the first-index bookkeeping, three of the classifications, an unlisted field let through rather than held as a path, and a held list without a test fixture or with a fixture expecting the other rule;validatecheck: the wire-name pre-claim, the first-claimant guard, the own-name skip, the empty-alias skip, the reported node, and the per-model scope;seenmap hoisted across Namings.testdata), compiled throughmainand this branch, give identicalirverifyviolations,validatediagnostics and error diagnostics on every spec.make gate, with the pinned golangci-lint v2.14.0, on the branch beforemain's cycle check (fix(ir): report a document that contains itself #737) was merged in. After that merge: build, vet, lint and the affected packages' tests. CI runs the full gate on the head.Closes #398
Closes #399
Closes #400