-
-
Notifications
You must be signed in to change notification settings - Fork 14.7k
Description
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)]