Skip to content

Accept qualified contract names in fulfils/demands clauses (#21)#33

Merged
yavorpanayotov merged 1 commit into
mainfrom
fix/qualified-contract-names
Jun 11, 2026
Merged

Accept qualified contract names in fulfils/demands clauses (#21)#33
yavorpanayotov merged 1 commit into
mainfrom
fix/qualified-contract-names

Conversation

@yavorpanayotov

Copy link
Copy Markdown
Collaborator

Closes #21.

Problem

parse_contracts_clause parsed a single bare ident for the contract name, so fulfils base/MyContract failed with expected block item ..., found '/' — while base/Caller parses fine in facing position, and the language reference (§ contract imports) says:

Contracts are importable across modules via use, following the same coordinate system as entity imports.

So cross-spec contract sharing (one abstract contract, multiple fulfils providers) was impossible without redeclaring the contract per spec — copies that drift silently, as the issue notes.

Fix

  • Parser: the contracts clause now accepts alias/Name after demands/fulfils. Unlike expression position there is no division to disambiguate from, so a / here can only introduce a qualified name and is consumed unconditionally. A missing name after / gets a targeted error (expected contract name after '/').
  • AST: ContractBinding gains qualifier: Option<String>, mirroring QualifiedName.
  • Analysis: qualified entries are collected by collect_qualified_references, so the imported contract counts as referenced in its defining module (cross-module unused tracking); they no longer insert their bare name into the local referenced-idents set, where a qualified ref could mask an unused same-named local Value/Enum.
  • WASM/TS: WasmContractBinding gains the qualifier: string | null field. Since the TS extension/LSP parse through this same WASM parser, the fix also removes the allium.parse.error the extension surfaced on these files (post-TypeScript analyzer discards WASM parse diagnostics #25).
  • Spec: structural-validator rule 36 updated to document the optionally-qualified form.

Verification

The issue's exact two-file reproducer now checks clean: exit 0, no parse error, and MyContract is not flagged unused in base.allium.

Tests: 3 new parser unit tests (qualified fulfils, qualified+local mix, missing-name error), 1 CLI integration test with the issue's reproducer, 1 TS test that the qualified form parses with zero diagnostics. Full matrix green: Rust workspace (345 parser + 24 CLI integration + the rest), TS 314 extension + 8 LSP, npm run lint clean.

🤖 Generated with Claude Code

parse_contracts_clause parsed a single bare ident for the contract name,
so `fulfils base/MyContract` failed with "expected block item ..., found
'/'" — while the language reference says contracts are importable across
modules via `use`, following the same coordinate system as entity
imports, and `base/Caller` already parses in facing position.

The contracts clause now accepts `alias/Name`, stored as a new
`qualifier: Option<String>` on ContractBinding (mirroring QualifiedName).
Unlike expression position there is no division to disambiguate from, so
the `/` is consumed unconditionally.

Analysis keeps in step: qualified entries are collected as cross-module
qualified references (so the imported contract counts as used in its
defining module), and no longer pollute the local referenced-idents set,
where they could mask an unused same-named local Value or Enum.

The WASM/TS mirror type WasmContractBinding gains the qualifier field.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@yavorpanayotov yavorpanayotov merged commit 9cd9463 into main Jun 11, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Parser rejects qualified contract names in fulfils / demands clauses (cross-spec contract imports broken)

1 participant