Skip to content

t27b: a module constant nothing analyzed reaches is lazy like an unreached body; a local of an undeclared type keeps its refusal (Closes #10899, #10903, #11053) - #11046

Merged
gHashTag merged 4 commits into
masterfrom
t27b/lazy-consts-10899
Oct 19, 2026

Conversation

@gHashTag

@gHashTag gHashTag commented Oct 19, 2026 •

Copy link
Copy Markdown
Owner

Closes #10899
Closes #10903
Closes #11053

Part of epic #10879 (t27b for t27o). Three commits and a ledger commit, built on #10999.

What

Zig resolves a module-level constant only when something analyzed names it. A constant nothing analyzed reaches (pub const ALLOWED : [][]const u8 = ["gfternary"];, pub const REGION_BRAM : MemRegion = MemRegion_new(..);) compiles even though Zig would refuse it the moment a test read it. t27b resolved every constant eagerly and refused those two as ConstDecl(slice) and ConstDecl. This PR withdraws that refusal the way #10999 withdraws the refusals of an unreached fn body.

The rule, in .t27

  • specs/tri/t27b/ast_shape.t27, analyzed (+ reach_named, new mentioned_in): the reach now covers constants. Roots are tests, invariants and declarations that are neither a fn nor a const; a fn or a const is reached when a root or a reached fn or const names it. A hardware-only constant is never reached (a guard; without it ddr3_head_bandwidth, ddr3_ternary_matvec and eth_top_ax7203 went from pass to blocked). The is_hw_const exemption and the unreferenced_tuple_const glue are deleted, subsumed by the reach.
  • specs/tri/t27b/lazy_sig_plan.t27, const_plan(construct, detail, spelled): for a constant nothing reaches, the refusals are judged by body_plan, except that an annotation Zig cannot read in the file and a constant with no value keep the refusal. They come back through withdrawn_come_back when AstGen refuses the file anyway.
  • Glue: eager_const (cli/t27b/src/lower/unanalyzed.rs), called by the eager constant loop in lower.rs.
  • The hole of t27b: do not lower bodies no test reaches -- Sema-level refusals in an unreached fn are withdrawn from one plan (Closes #10897) #10999, issue [bug] t27b: a local of an undeclared type in an unreached fn passes, Zig refuses it (hole in the #10897 body rule) #11053: body_plan now keeps type (undeclared), so fn f() { var x : Missing = 0; } in an unreached fn is refused by t27b as t27c refuses it (BLOCKED). A mutant of the lazy_signature fixture in tail.rs covers it.
  • Fixture specs/tri/t27b/conformance/lazy_const.t27 (type LazyRegion, a name unique in specs/), Rust test a_constant_zig_never_resolves with the negative controls.

Measured (t27b built from this branch, --jobs 1; master build before)

Front end Pass before Pass after Unsupported before -> after
Rust (492) 421 434 63 -> 50
Zig (724) 710 710 5 -> 5
Total (1,216) 1,131 1,144 68 -> 55

13 specs gained, none lost, no per-test verdict changed. --reference t27c over the 13: t27c compiles and passes every one, 0 disagreements. specs/lsp/schema.t27 (newly passes) and gen_w683.t27 (newly decided, 2 failing tests, the same two t27c fails): 0 disagreements. Repository corpus (2,438 specs), master build against the build before the #11053 fix: 4 files differ (the schema and gen_w683 flips, the new fixture, ast_shape's own test count); everything touched by the deletions is identical per test.

Negative controls (against t27c test-report): a test naming the slice, directly or through a fn: t27c BLOCKED, t27b ConstDecl(slice); a test naming a call-initialised struct: t27c passes, t27b ConstDecl (the counted remainder); a type, a fn or a name declared nowhere: t27c BLOCKED, t27b refuses.

Gates

  • Hand lines in cli/t27b: +27 -28, net -1; the own-language budget compiled from the merge base returns rc=0.
  • cargo test --release -p t27b: all test binaries pass. dupe_scan: the merge base's 15 findings, no new one (run at the first commit). check_devhome_paths and tri types ratchet: clean.
  • Ledger: specs/lsp/schema.t27 is pass now (the ratchet read UNEXPECTED PASS for it), cap 128 -> 127, recounted from the current file. The 13 UNLISTED rows, including lazy_const.t27, are the steward's; the STALE train_hslm is master's.

Not run

The repository-corpus comparison on the final head (it ran on the build before the #11053 fix); dupe_scan, devhome and types ratchet were last run before the final two commits and are covered by CI.

🤖 Generated with Claude Code

@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-19 12:53:15 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 47
PRs with All Checks Green 3
READY 2
FAILING 47
PENDING 0
NO CHECKS YET 0

These columns do not partition: 2 + 47 + 0 + 0 = 49, and there are 50 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=57b91bb96334 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@gHashTag
gHashTag force-pushed the t27b/lazy-consts-10899 branch from adf58d0 to 0de485b Compare October 19, 2026 13:36
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-19 13:37:02 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 48
PRs with All Checks Green 2
READY 2
FAILING 48
PENDING 0
NO CHECKS YET 0

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=57b91bb96334 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-19 14:55:59 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 47
PRs with All Checks Green 3
READY 2
FAILING 47
PENDING 0
NO CHECKS YET 0

These columns do not partition: 2 + 47 + 0 + 0 = 49, and there are 50 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=57b91bb96334 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-19 15:30:51 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 47
PRs with All Checks Green 3
READY 2
FAILING 47
PENDING 0
NO CHECKS YET 0

These columns do not partition: 2 + 47 + 0 + 0 = 49, and there are 50 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=57b91bb96334 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

claude and others added 4 commits October 19, 2026 22:58
…ached body -- ConstDecl and ConstDecl(slice) refusals are withdrawn (Closes #10899, Closes #10903)

WIP checkpoint. ast_shape.t27 analyzed marks the constants a root or a reached fn or constant mentions
(constants are no longer roots); lazy_sig_plan.t27 const_plan decides which refusals of an unreached
constant are Sema's (the body rule, but an annotation Zig cannot read keeps the refusal); the glue
eager_const withdraws them into the same held list restore_held returns when AstGen refuses the file.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…e subsumed by the constant reach -- hand lines net 0 (Closes #10899, Closes #10903)

unreferenced_tuple_const skipped an untyped list constant nothing names, and the hw set skipped the
constants only the hardware reads. The reach of ast_shape.t27 analyzed now says which constants an
analyzed root can name, and eager_const withdraws the Sema-level refusals of the rest, so both are
gone. The hw rule moves into the reach: a hardware-only constant is never reached, whoever names it,
exactly as before (without that guard ddr3_head_bandwidth, ddr3_ternary_matvec and eth_top_ax7203
turned from pass to FnDecl(reference not yet implemented)). The repository corpus (2,438 specs) has
identical per-test verdicts with the base binary except the three files that newly decide:
lsp/schema.t27 (blocked -> pass), port/scripts/gen_w683.t27 (blocked -> two failing tests t27c also
fails), and the new lazy_const fixture. The Rust test and the glue are written in fewer lines.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
… test reaches (Closes #11053)

AstGen resolves every name in a body, reached or not, so fn f() { var x : Missing = 0; } is "use of
undeclared identifier 'Missing'" whether or not a test calls f (t27c test-report: BLOCKED). Since #10999
body_plan withdrew its refusal (type (undeclared)) as a Sema-level one and t27b passed the spec. body_plan
now keeps it, which also keeps it for a constant (const_plan). Negative control: the plan spec's test,
and a mutant of conformance/lazy_signature.t27 in cli/t27b/tests/tail.rs (refused by t27b, BLOCKED by
t27c). The hand lines stay net <= 0: a comment line of arraylit.rs about the removed tuple-const skip goes.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
The constant rule of this PR lets specs/lsp/schema.t27 pass under t27b (the
ratchet read UNEXPECTED PASS for it, "ledger blocked (type mismatch), now
pass"). The row and the cap are recounted from the current file: 127 not-pass
rows, cap 127. Same shape as #10862 and #10999.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
@gHashTag
gHashTag force-pushed the t27b/lazy-consts-10899 branch from 0fe198d to 45d89cf Compare October 19, 2026 16:00
@gHashTag gHashTag changed the title t27b: a module constant nothing analyzed reaches is lazy like an unreached body (Closes #10899, Closes #10903) t27b: a module constant nothing analyzed reaches is lazy like an unreached body; a local of an undeclared type keeps its refusal (Closes #10899, #10903, #11053) Oct 19, 2026
@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-10-19 16:03:49 UTC

Summary

Status Count
Total Open PRs 50
PRs with Failing Checks 40
PRs with All Checks Green 10
READY 2
FAILING 40
PENDING 0
NO CHECKS YET 0

These columns do not partition: 2 + 40 + 0 + 0 = 42, and there are 50 open PRs. A PR is being counted twice or not at all.

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=57b91bb96334 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants