Related to #147485
Description
rustc panics with called Option::unwrap() on a None value in SimplifyLocals::run_pass → LocalUpdater::super_basic_block_data when compiling a crate where main calls two functions from different logical origins: one involving an enum whose variants are annotated with #[rustc_dummy] and a String parameter (introducing drop glue), and one involving a reference reborrow. The crash only manifests under -C opt-level=3 -C codegen-units=16 -g -C debug-assertions=yes.
Reproducer
#![allow(non_camel_case_types)]
#![feature(rustc_attrs)]
enum crew_of_enterprise_d {
#[rustc_dummy] worf,
}
fn boldly_go(_crew_member: crew_of_enterprise_d, _where: String) {}
fn main_d1342639() {
boldly_go(crew_of_enterprise_d::worf, "x".to_string());
}
fn foo(x: &isize) {
let a = 1;
let mut z = x;
z = &a;
}
fn main_c31c2192() {
foo(&1);
}
fn main() {
main_d1342639();
main_c31c2192();
}
Command
rustc -C opt-level=3 -C codegen-units=16 -g -C debug-assertions=yes reproduce.rs
Expected behavior
The program compiles successfully. None of the code is invalid Rust; #[rustc_dummy] is an internal attribute but should not cause a compiler panic.
Actual behavior
thread 'rustc' panicked at compiler/rustc_mir_transform/src/simplify.rs:677:27:
called `Option::unwrap()` on a `None` value
error: the compiler unexpectedly panicked. This is a bug
query stack during panic:
#0 [optimized_mir] optimizing MIR for `main`
#1 [items_of_instance] collecting items used by `main`
... and 1 other queries...
Root cause analysis
The call chain is:
run_optimization_passes
→ SimplifyLocals::run_pass (simplify.rs:455)
→ LocalUpdater::visit_body_preserves_cfg
→ LocalUpdater::super_basic_block_data (simplify.rs:677) ← panic
SimplifyLocals builds a remapping table of live locals and then LocalUpdater walks the MIR rewriting all local references through that table. The unwrap() at line 677 fires when a local is referenced in the MIR body but has no entry in the remapping — meaning SimplifyLocals incorrectly classified it as removable while it was still live. The combination of #[rustc_dummy] on enum variants (which affects attribute processing during MIR construction), String drop glue (which introduces additional MIR locals for the destructor), and a reference reborrow in the same main under debuginfo (-g, which adds StorageLive/StorageDead scope locals) with -C codegen-units=16 appears to confuse the liveness analysis, causing a local to be placed in the remove set while still being referenced.
Environment
- Compiler:
rustc 1.95.0-nightly
- Commit:
9b1f8ff42d110b0ca138116745be921df5dc97e7
- Host:
x86_64-unknown-linux-gnu
- Required flags:
-C opt-level=3 -C codegen-units=16 -g -C debug-assertions=yes
- Requires:
#![feature(rustc_attrs)]
Related to #147485
Description
rustcpanics withcalled Option::unwrap() on a None valueinSimplifyLocals::run_pass→LocalUpdater::super_basic_block_datawhen compiling a crate wheremaincalls two functions from different logical origins: one involving an enum whose variants are annotated with#[rustc_dummy]and aStringparameter (introducing drop glue), and one involving a reference reborrow. The crash only manifests under-C opt-level=3 -C codegen-units=16 -g -C debug-assertions=yes.Reproducer
Command
Expected behavior
The program compiles successfully. None of the code is invalid Rust;
#[rustc_dummy]is an internal attribute but should not cause a compiler panic.Actual behavior
Root cause analysis
The call chain is:
SimplifyLocalsbuilds a remapping table of live locals and thenLocalUpdaterwalks the MIR rewriting all local references through that table. Theunwrap()at line 677 fires when a local is referenced in the MIR body but has no entry in the remapping — meaningSimplifyLocalsincorrectly classified it as removable while it was still live. The combination of#[rustc_dummy]on enum variants (which affects attribute processing during MIR construction),Stringdrop glue (which introduces additional MIR locals for the destructor), and a reference reborrow in the samemainunder debuginfo (-g, which addsStorageLive/StorageDeadscope locals) with-C codegen-units=16appears to confuse the liveness analysis, causing a local to be placed in the remove set while still being referenced.Environment
rustc 1.95.0-nightly9b1f8ff42d110b0ca138116745be921df5dc97e7x86_64-unknown-linux-gnu-C opt-level=3 -C codegen-units=16 -g -C debug-assertions=yes#![feature(rustc_attrs)]