Closed
Description
Reduced from a debuginfo test failing with an implementation of #31005:
fn main() {
match Ok::<(), ()>(()) {
Ok(a) => zzz(),
Err(a) => zzz()
}
}
fn zzz() {}
fn main() -> () {
let var0: (); // a in Scope(3) at test2.rs:3:12: 3:13
let var1: (); // a in Scope(3) at test2.rs:4:13: 4:14
let mut tmp0: std::result::Result<(), ()>;
let mut tmp1: ();
bb0: {
tmp1 = (); // Scope(5) at test2.rs:2:24: 2:26
tmp0 = std::prelude::v1::Ok<(), ()>(tmp1,); // Scope(4) at test2.rs:2:11: 2:27
switch(tmp0) -> [Ok: bb4, Err: bb5]; // Scope(3) at test2.rs:3:9: 3:14
}
bb1: {
return; // Scope(0) at test2.rs:1:1: 6:2
}
bb2: {
return = zzz() -> bb1; // Scope(7) at test2.rs:3:18: 3:23
}
bb3: {
return = zzz() -> bb1; // Scope(10) at test2.rs:4:19: 4:24
}
bb4: {
var0 = ((tmp0 as Ok).0: ()); // Scope(3) at test2.rs:3:12: 3:13
goto -> bb2; // Scope(3) at test2.rs:3:9: 3:14
}
bb5: {
var1 = ((tmp0 as Err).0: ()); // Scope(3) at test2.rs:4:13: 4:14
goto -> bb3; // Scope(3) at test2.rs:4:9: 4:15
}
Scope(0) {
Scope(1) {
Parent: Scope(0)
Scope(2) {
Parent: Scope(1)
Scope(3) {
Parent: Scope(2)
Scope(4) {
Parent: Scope(3)
Scope(5) {
Parent: Scope(4)
Scope(6) {
Parent: Scope(3)
Scope(7) {
Parent: Scope(6)
Scope(8) {
Parent: Scope(7)
Scope(9) {
Parent: Scope(3)
Scope(10) {
Parent: Scope(9)
Scope(11) {
Parent: Scope(10)
}
You can see that both a
bindings and their assignments share the scope of the match, Scope(3)
.
This appears to be intentional in the implementation of pattern-matching:
// Before we do anything, create uninitialized variables with
// suitable extent for all of the bindings in this match. It's
// easiest to do this up front because some of these arms may
// be unreachable or reachable multiple times.
let var_scope_id = self.innermost_scope_id();
for arm in &arms {
self.declare_bindings(var_scope_id, &arm.patterns[0]);
}
However, this breaks debugging (as both variables appear declared at the same time) and potentially MIR-based region/borrow checking, in the future.