Offer config blocks and deferred declarations to importers - #91
Merged
Conversation
The offered-names set a qualified reference alias/Name is validated against held declared types and referenced triggers only. A module's config block and its deferred declarations were absent, so two documented reference forms drew false allium.reference.unknownName warnings: - alias/config.param — the language reference's 'Config parameter references' section documents exactly this form, and checker rule 46 requires it to resolve; even the documented config-default position warned. - alias/DeferredName — a deferred declaration the module visibly carries. The diagnostic also claimed the module 'does not define' a config block it plainly defines. collect_referenced_trigger_names now offers 'config' when the module declares a config block, and each deferred declaration's root name (deferred Foo and deferred Foo.bar both offer Foo). A deferred declared against another module's alias (deferred other/Foo) stays a foreign reference, not a local offering. Field-level validation of config references (rules 46/47: does page_size exist, do the types match) remains open — this fix stops the false positive on the block reference itself. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…fered deferred other/Foreign records that 'other' owns the construct; the declaring module must offer neither the name nor the alias. The behaviour was already implemented (extract_leading_ident returns None for qualified paths) but had no test holding it in place. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…mports # Conflicts: # crates/allium-parser/src/analysis.rs # crates/allium/tests/cross_module_lifecycle.rs
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 #89.
Bug
The offered-names set that a qualified reference
alias/Nameis validated against (collect_referenced_trigger_names) held declared type names and referenced triggers only. Two reference forms drew falseallium.reference.unknownNamewarnings (exit 1) although the aliased module visibly carries the construct:1.
alias/config.param— contradicting the language reference. The reference's "Config parameter references" section documents exactly this form:and checker rule 46 requires it to resolve ("A qualified config reference in a default expression must resolve to a declared parameter in an imported module's config block"). On main, even that documented config-default position warns — and the message claims the module "does not define" a
configblock it plainly defines.2.
alias/DeferredName— adeferreddeclaration the module carries. Natural cross-module form: a module declaringdeferred UnhandledExceptionis exactly the module another spec wants to name inrequires: mobile_auth/UnhandledException(request).Repro (fails on main, passes here — transcribed into
cross_module_lifecycle.rs): provider with a config block +deferred ExternalHelper; consumer referencingp/config.page_size(both in a config default and in a rule) andp/ExternalHelper→ 3 false warnings on main, 0 here.Fix
collect_referenced_trigger_namesadditionally offers:config, when the module declares a config block;deferred Fooanddeferred Foo.barboth offerFoo). A deferred declared against another module's alias (deferred other/Foo) names a construct that module owns and is deliberately not offered —extract_leading_identreturnsNonefor qualified paths.Not in scope (follow-up)
Field-level validation of config references (rules 46/47: does
page_sizeexist in the imported block, do the types match). Today the QRef foralias/config.page_sizecarries only the nameconfig, so a field typo produces the byte-identical diagnostic to a valid reference. This fix stops the false positive on the block reference; field resolution needs the qref collector to carry the member chain.Tests
deferred other/Foreignoffers neither the name nor the alias)p/NoSuchDeferredstill warns;p/configagainst a module with no config block still warns)Real-world impact
On a ~180-spec production corpus, the v3.5.0 → v3.5.3 upgrade produced 8 false
unknownNamewarnings of these two shapes (5 config, 3 deferred), each now carrying a suppression directive plus an explanatory comment. With this fix those suppressions become unnecessary.Note: this PR and the config/deferred one both append tests to
cross_module_lifecycle.rsand theanalysis.rstest module — whichever merges second needs a trivial union rebase; happy to rebase promptly.