The liveness walker drops 15 expression forms through a catch-all
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 14
- Forks
- 2
- Avg merge
- 12h 42m
- Merged PRs (30d)
- 61
Description
GlobalAstEnv::extract_uses_expr (src/hir/env.rs) walks 22 of the 38 Expr variants and ends in
_ => {}. Anything it does not name contributes no uses, silently.
That map is compute_block_liveness, which feeds two consumers:
borrow_cx::is_variable_used_after, the NLL predicate the dead-borrow sweep runs on. A borrow
whose only use sits in a dropped form is swept as dead, so a conflict that should be reported is
not. A missed diagnostic.- the capacity check's model of when a placed tile dies. A tile whose only reader sits in a dropped
form is taken as dead where it was made, so it does not count against anything placed after it.
An unsound admission.
How it surfaced
spawn on was one of the dropped forms, and it is the worst one to miss: a region is where a placed
tensor can legally be read -- the host cannot see device memory, so a read from outside is the
visibility error (E6003) and a read from inside is the ordinary way to use one.
let sx = transfer(x, Memory::W); // 3 MiB
let sy = transfer(y, Memory::W); // 3 MiB
spawn on(Topology::Dev) {
use_both(sx, sy); // the reads
}
Against a 4 MiB space this compiled clean and reported total_bytes: 3145728, tiles: 1. The lowering
holds both to the function's return:
%20 = call @vx_plugin_alloc_and_transfer(...)
%33 = call @vx_plugin_alloc_and_transfer(...)
call @vx_plugin_free(%20, ...)
call @vx_plugin_free(%33, ...)
llvm.return
so the admitted program runs with 6 MiB resident in a space declared to hold 4.
Fixed for SpawnOn, Print, Println, Match and Range, with a regression test at
tests/frontend/fail/spawn_region_reads_keep_tiles_live.vx.
Still dropped
IndirectCall, ComptimeBlock, EnumVariant, VecMacro, MacroCall, InlineMlir, Grad, Jvp,
Vjp, TransferPredicate, and the leaf forms that genuinely have no sub-expressions (Number,
StringLiteral, MemorySpace, Topology, SizeOf).
Each non-leaf one is the same bug waiting: a read the analysis cannot see. The autodiff forms are
worth checking first, since grad(f, x) reads x and the result of a Grad is exactly the kind of
value that gets placed.
The shape of it
A catch-all in a use-extractor fails silently and in the unsafe direction: an unwalked form means
fewer uses, which means values look deader than they are. Both consumers then err toward permitting
something. An exhaustive match would have made each new Expr variant a compile error at this site
instead, which is the behaviour worth having here -- the cost of forgetting one is a missed
diagnostic or an unsound admission, not a lint.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
In src/hir/env.rs, inspect GlobalAstEnv::extract_uses_expr and the Expr variants still omitted from its walk; begin by tracing compute_block_liveness to its two consumers. Extend coverage for the remaining non-leaf forms, make omission visible through exhaustive matching, and run tests/frontend/fail/spawn_region_reads_keep_tiles_live.vx plus relevant frontend tests to confirm reads keep values live.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- compilers, testing-qa
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 68/100