Skip to content

Incorrect "this value is reassigned later and never used" note for unused_assignment warning in diverging else block. #156416

@zachs18

Description

@zachs18

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

Metadata

Metadata

Assignees

Labels

A-diagnosticsArea: Messages for errors, warnings, and lintsL-unused_assignmentsLint: unused_assignmentsP-highHigh priorityT-compilerRelevant to the compiler team, which will review and decide on the PR/issue.regression-from-stable-to-betaPerformance or correctness regression from stable to beta.

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions