Code
fn main() {
let x;
if true {
x = 42;
} else {
x = 35;
panic!();
}
println!("{x}");
}
Current output
warning: value assigned to `x` is never read
--> src/main.rs:6:9
|
4 | x = 42;
| ------ `x` is overwritten here before the previous value is read
5 | } else {
6 | x = 35;
| ^^^^^^ this value is reassigned later and never used
|
= note: `#[warn(unused_assignments)]` (part of `#[warn(unused)]`) on by default
warning: `bisect-diag` (bin "bisect-diag") generated 1 warning
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.08s
Desired output
warning: value assigned to `x` is never read
--> src/main.rs:6:9
|
6 | x = 35;
| ^^^^^^
|
= help: maybe it is overwritten before being read?
= note: `#[warn(unused_assignments)]` (part of `#[warn(unused)]`) on by default
warning: `bisect-diag` (bin "bisect-diag") generated 1 warning
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.07s
Rationale and extra context
This regressed in #154456 cc @chenyukang
The "desired output" is the output on stable 1.95.0 (and before #154456). The "current output" is the output on beta and nightly (and after #154456). I'm not sure if the "desired output" is the best it could be, but it seems better than the current output seeming to imply that both branches of an if happen.
Other cases
Note that the code with the true and false branches swapped does not have the same issue (i.e. the current output on beta and nightly is the same as the stable output for the following code).
swap if and else blocks
// This code does *not* have the same issue
fn main() {
let x;
if true {
x = 42;
panic!();
} else {
x = 35;
}
println!("{x}");
}
$ cargo +nightly b
Compiling bisect-diag v0.1.0 (/tmp/bisect-diag)
warning: value assigned to `x` is never read
--> src/main.rs:4:9
|
4 | x = 42;
| ^^^^^^
|
= help: maybe it is overwritten before being read?
= note: `#[warn(unused_assignments)]` (part of `#[warn(unused)]`) on by default
warning: `bisect-diag` (bin "bisect-diag") generated 1 warning
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.06s
This does happen for match blocks, but in reverse order, i.e. only if the diverging block is first
fn main() {
let x;
match true {
false => {
x = 35;
panic!();
}
true => x = 42,
}
println!("{x}");
}
$ cargo +nightly b
warning: value assigned to `x` is never read
--> src/main.rs:5:13
|
5 | x = 35;
| ^^^^^^ this value is reassigned later and never used
...
8 | true => x = 42,
| ------ `x` is overwritten here before the previous value is read
|
= note: `#[warn(unused_assignments)]` (part of `#[warn(unused)]`) on by default
warning: `bisect-diag` (bin "bisect-diag") generated 1 warning
Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.00s
Rust Version
$ rustc +nightly --version --verbose
rustc 1.97.0-nightly (82bee9650 2026-05-09)
binary: rustc
commit-hash: 82bee965077a631d6fbdee4014f2ec535535aaa3
commit-date: 2026-05-09
host: x86_64-unknown-linux-gnu
release: 1.97.0-nightly
LLVM version: 22.1.4
Anything else?
searched nightlies: from nightly-2026-02-27 to nightly-2026-05-10
regressed nightly: nightly-2026-04-02
searched commit range: 48cc71e...7e46c5f
regressed commit: 12ab1cf
bisected with cargo-bisect-rustc v0.6.11
Host triple: x86_64-unknown-linux-gnu
Reproduce with:
cargo bisect-rustc --start=1.95.0 --preserve --prompt
@rustbot label +regression-from-stable-to-beta +L-unused_assignments
Code
Current output
Desired output
Rationale and extra context
This regressed in #154456 cc @chenyukang
The "desired output" is the output on stable 1.95.0 (and before #154456). The "current output" is the output on beta and nightly (and after #154456). I'm not sure if the "desired output" is the best it could be, but it seems better than the current output seeming to imply that both branches of an
ifhappen.Other cases
Note that the code with the true and false branches swapped does not have the same issue (i.e. the current output on beta and nightly is the same as the stable output for the following code).
swap if and else blocks
This does happen for
matchblocks, but in reverse order, i.e. only if the diverging block is firstRust Version
Anything else?
searched nightlies: from nightly-2026-02-27 to nightly-2026-05-10
regressed nightly: nightly-2026-04-02
searched commit range: 48cc71e...7e46c5f
regressed commit: 12ab1cf
bisected with cargo-bisect-rustc v0.6.11
Host triple: x86_64-unknown-linux-gnu
Reproduce with:
@rustbot label +regression-from-stable-to-beta +L-unused_assignments