Skip to content

symbol_index: resolve fully-qualified constructor calls to the direct_call_shape wall - #8591

Merged
briansrls merged 1 commit into
mainfrom
fix/qualified-constructor-symbol-index
Aug 19, 2026
Merged

briansrls merged 1 commit into
mainfrom
fix/qualified-constructor-symbol-index

Conversation

@gunbai-bot

@gunbai-bot gunbai-bot Bot commented Aug 19, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Population-A follow-up to #8579's refusal census, opened separately per operator direction (not bundled into #8579).

qualified_direct_call (the ExprMethodCall inline gate in infer_expr_body) and func_sig_from_global_bare → borrowed_census_decl both resolve a fully-qualified constructor call like gunbc.WitnessBin.Run(...) via symbol_index_lookup on the 3-segment dotted name built from field_access_spine(recv) + method name. symbol_index_insert_unique_disj_variant_aliases only ever inserted the 2-segment module_path.variant_name shortcut, and only when that variant name was corpus-wide unique — so a fully-qualified constructor call site never found a symbol-index entry, qualified_direct_call fell through, and the call landed on the generic method-call bridge instead of the direct_call_shape_diags wall it should have reached.

The fix adds an unconditional insertion of module_path.TypeName.variant_name ahead of the existing uniqueness-gated 2-segment aliases. It needs no corpus-wide uniqueness check: a variant name is unique within its own Disj, and a TypeName is unique within its own module, so the 3-segment key can never collide by construction.

Applied to both the .dag authority (src/v1/04_infer.dag) and its frozen Rust mirror (src/v1/stage0/src/v1_compiler_infer.rs), since the required-regen fold treats drift between the two as a refusal. The mirror hunk (115 lines) is hand-written, not emitter-produced -- a real regen was infeasible in this session (local release build OOM-killed under the shared memory slice; a remote-built binary is linux/amd64 and can't execute in this arm64 container). Its correspondence to what the emitter would produce from the .dag edit is therefore unverified, not stale by intent. It should be regenerated and diffed against this hand-written version the first time a working regen path is available, per the drift-hiding lesson from #8488/#8513.

Scope

This closes population A only — qualified-module-path constructor calls whose receiver spine root is not a shadowed local (spine_root_is_shadowed false). Population B (~800 refusals, ordinary local-receiver method calls where the spine root is shadowed) is untouched: spine_root_is_shadowed short-circuits before any lookup is attempted, and closing it needs a per-method parameter-contract authority that doesn't exist yet. That population is being reported to the operator separately, not fixed here.

Receipt

  • BEFORE: 2810 refusals (CI run 32304792971, --required-floor, main).
  • AFTER: to be reported once this branch's witnesses.yml --required-floor step executes — local execution is currently blocked (a local release build of claim_executor was OOM-killed under the shared session memory slice; a remote-built binary is linux/amd64 and cannot execute in this arm64 session container), so CI's run is both the correctness verification (green-by-execution) and the source of the AFTER count.

— sent from stern-tern-636

… form for Disj variants

qualified_direct_call (ExprMethodCall) and func_sig_from_global_bare both resolve a
callee like gunbc.WitnessBin.Run(...) via symbol_index_lookup on the 3-segment dotted
name built from the receiver spine plus method name. symbol_index_insert_unique_disj_variant_aliases
only ever inserted the 2-segment module_path.variant_name shortcut, and only when that
variant name was corpus-wide unique -- so a fully-qualified constructor call never found
an entry, fell through qualified_direct_call, and landed on the generic method-call
bridge instead of the direct_call_shape_diags wall.

The fix adds an unconditional insertion of module_path.TypeName.variant_name ahead of
the existing uniqueness-gated 2-segment aliases: it needs no uniqueness check because a
variant name is unique within its own Disj and a TypeName is unique within its own
module, so the 3-segment key can never collide. This is scoped to constructor calls
whose receiver spine root is not a shadowed local (population A per the #8579 census);
ordinary local-receiver method calls are unaffected.
@briansrls
briansrls merged commit b19d231 into main Aug 19, 2026
1 check passed
@briansrls
briansrls deleted the fix/qualified-constructor-symbol-index branch August 19, 2026 23:12
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.

1 participant