Conversation
A related: entry naming an imported module's surface (related: alias/Surface(expr)) drew a false allium.reference.unknownName because collect_referenced_trigger_names never offered surfaces. Offer each surface block's name, exactly as config and deferred roots already are; collect_declared_names is untouched so unqualified resolution and the ambiguous-import machinery are unaffected. Membership stays a name-existence check, not a kind check: any qualified reference to a declared surface name now resolves, related: or not. One consequence is disclosed and pinned: a default literal typed to an imported surface loses its only diagnostic and gets no field validation, since surfaces carry no field schema (deferred-root-typed defaults already behave this way).
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.
Fixes #98.
Bug
A surface's
related:clause is the documented construct for linking to another surface, and qualified names are the documented cross-module reference form — butrelated: merge/MergeWizard(expr)warnsallium.reference.unknownName("which imported module 'merge' does not define") while the module visibly declaressurface MergeWizard. The offered-names set (collect_referenced_trigger_names) holds declared types, referenced triggers,configand deferred roots (#89/#91) — never surfaces. The checker demonstrably knows the construct: the same link written unqualified drawsallium.surface.relatedUndefinedlocally.Fix
Offer each surface block's name, exactly as #91 added config and deferred roots to this same function.
collect_declared_namesis untouched, so unqualified resolution and the ambiguous-import machinery are unaffected; the blast radius is qualified-reference membership only.Disclosed side effects (membership is a name-existence check, not a kind check): any qualified reference to a declared surface name stops warning — including positions where a surface makes no sense, e.g. a
when:subscription, and adefaultliteral typed to an imported surface (default merge/MergeWizard fallback = { ... }), which loses its only flag with nothing replacing it, since surfaces have no field schema for the imported-default validation to check. Both are consistent with entity/config/deferred names already being offered, and both are pinned by deliberate tests so a future kind-aware refinement flips them consciously.Tests
+6 integration tests in
cross_module_lifecycle.rs(qualified related link resolves with zerounknownName/relatedUndefined; merged single-file oracle accepts the link; a link to an undeclared surface still warns; an unqualified link stays local; both disclosed side effects pinned) and +1 unit test on the offering set. Behaviour spec updated (four new rules + the offered-set prose); CHANGELOG entry under Unreleased. Full workspace suite green (668 tests); clippy warning multiset identical to main; the repo's owndocs/project/specsdiagnostics byte-identical before/after.Real-world impact
In a spec family of any size, the surface worth linking to often lives in another module: a worklist that hands each row off to a wizard another spec owns, a summary view linking to a detail view. That hand-off is exactly what
related: alias/Wizard(expr)expresses — and today it cannot be written without a warning that fails the gate. The available options are mutingallium.reference.unknownNameline by line (with a comment explaining the checker rather than the domain) or dropping the link and losing the navigation contract from the spec.Supporting evidence from a private ~190-spec corpus we maintain: one such cross-module hand-off (a worklist surface offering an account-merge wizard owned by another module) carries exactly that suppression today, and a full-corpus diagnostic diff with this fix shows precisely that one warning disappearing and nothing else changing. This change only removes warnings; it cannot turn a previously green gate red.
Note: this PR and the dotted-member-access one both touch
analysis.rs, the check behaviour spec, and the CHANGELOG - whichever merges second needs a trivial union rebase; happy to rebase promptly.