Skip to content

Commit 9a0b774

Browse files
committed
Auto merge of rust-lang#97931 - xldenis:fix-if-let-source-scopes, r=nagisa
Fix `SourceScope` for `if let` bindings. Fixes rust-lang#97799. I'm not sure how to test this properly, is there any way to observe the difference in behavior apart from `ui` tests? I'm worried that they would be overlooked in the case of a regression.
2 parents 17c6bde + a434e4c commit 9a0b774

16 files changed

+330
-177
lines changed

compiler/rustc_mir_build/src/build/expr/into.rs

+22-2
Original file line numberDiff line numberDiff line change
@@ -63,15 +63,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
6363
(if_then_scope, then_source_info),
6464
LintLevel::Inherited,
6565
|this| {
66+
let source_info = if this.is_let(cond) {
67+
let variable_scope = this.new_source_scope(
68+
then_expr.span,
69+
LintLevel::Inherited,
70+
None,
71+
);
72+
this.source_scope = variable_scope;
73+
SourceInfo { span: then_expr.span, scope: variable_scope }
74+
} else {
75+
this.source_info(then_expr.span)
76+
};
6677
let (then_block, else_block) =
6778
this.in_if_then_scope(condition_scope, |this| {
6879
let then_blk = unpack!(this.then_else_break(
6980
block,
7081
&this.thir[cond],
7182
Some(condition_scope),
7283
condition_scope,
73-
then_expr.span,
84+
source_info
7485
));
86+
7587
this.expr_into_dest(destination, then_blk, then_expr)
7688
});
7789
then_block.and(else_block)
@@ -97,7 +109,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
97109
ExprKind::Let { expr, ref pat } => {
98110
let scope = this.local_scope();
99111
let (true_block, false_block) = this.in_if_then_scope(scope, |this| {
100-
this.lower_let_expr(block, &this.thir[expr], pat, scope, expr_span)
112+
this.lower_let_expr(block, &this.thir[expr], pat, scope, None, expr_span)
101113
});
102114

103115
this.cfg.push_assign_constant(
@@ -575,4 +587,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
575587

576588
block_and
577589
}
590+
591+
fn is_let(&self, expr: ExprId) -> bool {
592+
match self.thir[expr].kind {
593+
ExprKind::Let { .. } => true,
594+
ExprKind::Scope { value, .. } => self.is_let(value),
595+
_ => false,
596+
}
597+
}
578598
}

compiler/rustc_mir_build/src/build/matches/mod.rs

+29-10
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
4040
expr: &Expr<'tcx>,
4141
temp_scope_override: Option<region::Scope>,
4242
break_scope: region::Scope,
43-
variable_scope_span: Span,
43+
variable_source_info: SourceInfo,
4444
) -> BlockAnd<()> {
4545
let this = self;
4646
let expr_span = expr.span;
@@ -52,15 +52,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
5252
&this.thir[lhs],
5353
temp_scope_override,
5454
break_scope,
55-
variable_scope_span,
55+
variable_source_info,
5656
));
5757

5858
let rhs_then_block = unpack!(this.then_else_break(
5959
lhs_then_block,
6060
&this.thir[rhs],
6161
temp_scope_override,
6262
break_scope,
63-
variable_scope_span,
63+
variable_source_info,
6464
));
6565

6666
rhs_then_block.unit()
@@ -73,13 +73,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
7373
&this.thir[value],
7474
temp_scope_override,
7575
break_scope,
76-
variable_scope_span,
76+
variable_source_info,
7777
)
7878
})
7979
}
80-
ExprKind::Let { expr, ref pat } => {
81-
this.lower_let_expr(block, &this.thir[expr], pat, break_scope, variable_scope_span)
82-
}
80+
ExprKind::Let { expr, ref pat } => this.lower_let_expr(
81+
block,
82+
&this.thir[expr],
83+
pat,
84+
break_scope,
85+
Some(variable_source_info.scope),
86+
variable_source_info.span,
87+
),
8388
_ => {
8489
let temp_scope = temp_scope_override.unwrap_or_else(|| this.local_scope());
8590
let mutability = Mutability::Mut;
@@ -1772,6 +1777,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17721777
expr: &Expr<'tcx>,
17731778
pat: &Pat<'tcx>,
17741779
else_target: region::Scope,
1780+
source_scope: Option<SourceScope>,
17751781
span: Span,
17761782
) -> BlockAnd<()> {
17771783
let expr_span = expr.span;
@@ -1797,7 +1803,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
17971803
let otherwise_post_guard_block = otherwise_candidate.pre_binding_block.unwrap();
17981804
self.break_for_else(otherwise_post_guard_block, else_target, self.source_info(expr_span));
17991805

1800-
self.declare_bindings(None, pat.span.to(span), pat, ArmHasGuard(false), opt_expr_place);
1806+
self.declare_bindings(
1807+
source_scope,
1808+
pat.span.to(span),
1809+
pat,
1810+
ArmHasGuard(false),
1811+
opt_expr_place,
1812+
);
1813+
18011814
let post_guard_block = self.bind_pattern(
18021815
self.source_info(pat.span),
18031816
guard_candidate,
@@ -1969,12 +1982,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
19691982
Guard::If(e) => {
19701983
let e = &this.thir[e];
19711984
guard_span = e.span;
1972-
this.then_else_break(block, e, None, match_scope, arm_span)
1985+
this.then_else_break(
1986+
block,
1987+
e,
1988+
None,
1989+
match_scope,
1990+
this.source_info(arm_span),
1991+
)
19731992
}
19741993
Guard::IfLet(ref pat, scrutinee) => {
19751994
let s = &this.thir[scrutinee];
19761995
guard_span = s.span;
1977-
this.lower_let_expr(block, s, pat, match_scope, arm_span)
1996+
this.lower_let_expr(block, s, pat, match_scope, None, arm_span)
19781997
}
19791998
});
19801999

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
// compile-flags:-g
2+
3+
// === GDB TESTS ==================================================================================
4+
5+
// gdb-command:run
6+
// gdb-command:info locals
7+
// gdb-check:a = 123
8+
9+
// gdb-command:continue
10+
// gdb-command:info locals
11+
// gdb-check:x = 42
12+
// gdb-check:a = 123
13+
14+
// gdb-command:continue
15+
// gdb-command:info locals
16+
// gdb-check:y = true
17+
// gdb-check:b = 456
18+
// gdb-check:x = 42
19+
// gdb-check:a = 123
20+
21+
// gdb-command:continue
22+
// gdb-command:info locals
23+
// gdb-check:z = 10
24+
// gdb-check:c = 789
25+
// gdb-check:y = true
26+
// gdb-check:b = 456
27+
// gdb-check:x = 42
28+
// gdb-check:a = 123
29+
30+
// === LLDB TESTS =================================================================================
31+
32+
// lldb-command:run
33+
// lldb-command:frame variable
34+
// lldb-check:(int) a = 123
35+
36+
// lldb-command:continue
37+
// lldb-command:frame variable
38+
// lldb-check:(int) a = 123 (int) x = 42
39+
40+
// lldb-command:continue
41+
// lldb-command:frame variable
42+
// lldb-check:(int) a = 123 (int) x = 42 (int) b = 456 (bool) y = true
43+
44+
// lldb-command:continue
45+
// lldb-command:frame variable
46+
// lldb-check:(int) a = 123 (int) x = 42 (int) b = 456 (bool) y = true (int) c = 789 (int) z = 10
47+
48+
// === CDB TESTS ==================================================================================
49+
50+
// cdb-command: g
51+
// cdb-command: dv
52+
// cdb-check:[...]a = 0n123
53+
54+
// cdb-command: g
55+
// cdb-command: dv
56+
// cdb-check:[...]a = 0n123
57+
// cdb-check:[...]x = 0n42
58+
59+
// cdb-command: g
60+
// cdb-command: dv
61+
// cdb-check:[...]y = true
62+
// cdb-check:[...]b = 0n456
63+
// cdb-check:[...]a = 0n123
64+
// cdb-check:[...]x = 0n42
65+
66+
// cdb-command: g
67+
// cdb-command: dv
68+
// cdb-check:[...]z = 0n10
69+
// cdb-check:[...]c = 0n789
70+
// cdb-check:[...]y = true
71+
// cdb-check:[...]b = 0n456
72+
// cdb-check:[...]a = 0n123
73+
// cdb-check:[...]x = 0n42
74+
75+
fn main() {
76+
let a = id(123);
77+
78+
zzz(); // #break
79+
80+
if let Some(x) = id(Some(42)) {
81+
zzz(); // #break
82+
83+
let b = id(456);
84+
85+
if let Ok(y) = id::<Result<bool, ()>>(Ok(true)) {
86+
zzz(); // #break
87+
88+
let c = id(789);
89+
90+
if let (z, 42) = id((10, 42)) {
91+
zzz(); // #break
92+
}
93+
}
94+
}
95+
}
96+
97+
#[inline(never)]
98+
fn id<T>(value: T) -> T { value }
99+
100+
fn zzz() { }

src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff

+12-10
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,28 @@
1010
scope 1 {
1111
debug x => _1; // in scope 1 at $DIR/discriminant.rs:11:9: 11:10
1212
}
13+
scope 2 {
14+
}
1315

1416
bb0: {
1517
StorageLive(_1); // scope 0 at $DIR/discriminant.rs:11:9: 11:10
1618
StorageLive(_2); // scope 0 at $DIR/discriminant.rs:11:13: 11:64
17-
StorageLive(_3); // scope 0 at $DIR/discriminant.rs:11:34: 11:44
18-
Deinit(_3); // scope 0 at $DIR/discriminant.rs:11:34: 11:44
19-
((_3 as Some).0: bool) = const true; // scope 0 at $DIR/discriminant.rs:11:34: 11:44
20-
discriminant(_3) = 1; // scope 0 at $DIR/discriminant.rs:11:34: 11:44
21-
- _4 = discriminant(_3); // scope 0 at $DIR/discriminant.rs:11:21: 11:31
22-
- switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
23-
+ _4 = const 1_isize; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
24-
+ switchInt(const 1_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
19+
StorageLive(_3); // scope 2 at $DIR/discriminant.rs:11:34: 11:44
20+
Deinit(_3); // scope 2 at $DIR/discriminant.rs:11:34: 11:44
21+
((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:11:34: 11:44
22+
discriminant(_3) = 1; // scope 2 at $DIR/discriminant.rs:11:34: 11:44
23+
- _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:11:21: 11:31
24+
- switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:11:21: 11:31
25+
+ _4 = const 1_isize; // scope 2 at $DIR/discriminant.rs:11:21: 11:31
26+
+ switchInt(const 1_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:11:21: 11:31
2527
}
2628

2729
bb1: {
28-
switchInt(((_3 as Some).0: bool)) -> [false: bb3, otherwise: bb2]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
30+
switchInt(((_3 as Some).0: bool)) -> [false: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:11:21: 11:31
2931
}
3032

3133
bb2: {
32-
_2 = const 42_i32; // scope 0 at $DIR/discriminant.rs:11:47: 11:49
34+
_2 = const 42_i32; // scope 2 at $DIR/discriminant.rs:11:47: 11:49
3335
goto -> bb4; // scope 0 at $DIR/discriminant.rs:11:13: 11:64
3436
}
3537

src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff

+12-10
Original file line numberDiff line numberDiff line change
@@ -10,26 +10,28 @@
1010
scope 1 {
1111
debug x => _1; // in scope 1 at $DIR/discriminant.rs:11:9: 11:10
1212
}
13+
scope 2 {
14+
}
1315

1416
bb0: {
1517
StorageLive(_1); // scope 0 at $DIR/discriminant.rs:11:9: 11:10
1618
StorageLive(_2); // scope 0 at $DIR/discriminant.rs:11:13: 11:64
17-
StorageLive(_3); // scope 0 at $DIR/discriminant.rs:11:34: 11:44
18-
Deinit(_3); // scope 0 at $DIR/discriminant.rs:11:34: 11:44
19-
((_3 as Some).0: bool) = const true; // scope 0 at $DIR/discriminant.rs:11:34: 11:44
20-
discriminant(_3) = 1; // scope 0 at $DIR/discriminant.rs:11:34: 11:44
21-
- _4 = discriminant(_3); // scope 0 at $DIR/discriminant.rs:11:21: 11:31
22-
- switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
23-
+ _4 = const 1_isize; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
24-
+ switchInt(const 1_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
19+
StorageLive(_3); // scope 2 at $DIR/discriminant.rs:11:34: 11:44
20+
Deinit(_3); // scope 2 at $DIR/discriminant.rs:11:34: 11:44
21+
((_3 as Some).0: bool) = const true; // scope 2 at $DIR/discriminant.rs:11:34: 11:44
22+
discriminant(_3) = 1; // scope 2 at $DIR/discriminant.rs:11:34: 11:44
23+
- _4 = discriminant(_3); // scope 2 at $DIR/discriminant.rs:11:21: 11:31
24+
- switchInt(move _4) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:11:21: 11:31
25+
+ _4 = const 1_isize; // scope 2 at $DIR/discriminant.rs:11:21: 11:31
26+
+ switchInt(const 1_isize) -> [1_isize: bb1, otherwise: bb3]; // scope 2 at $DIR/discriminant.rs:11:21: 11:31
2527
}
2628

2729
bb1: {
28-
switchInt(((_3 as Some).0: bool)) -> [false: bb3, otherwise: bb2]; // scope 0 at $DIR/discriminant.rs:11:21: 11:31
30+
switchInt(((_3 as Some).0: bool)) -> [false: bb3, otherwise: bb2]; // scope 2 at $DIR/discriminant.rs:11:21: 11:31
2931
}
3032

3133
bb2: {
32-
_2 = const 42_i32; // scope 0 at $DIR/discriminant.rs:11:47: 11:49
34+
_2 = const 42_i32; // scope 2 at $DIR/discriminant.rs:11:47: 11:49
3335
goto -> bb4; // scope 0 at $DIR/discriminant.rs:11:13: 11:64
3436
}
3537

src/test/mir-opt/early_otherwise_branch_soundness.no_downcast.EarlyOtherwiseBranch.diff

+10-8
Original file line numberDiff line numberDiff line change
@@ -7,22 +7,24 @@
77
let mut _2: isize; // in scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:20: 13:30
88
let mut _3: isize; // in scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31
99
let mut _4: &E; // in scope 0 at $DIR/early_otherwise_branch_soundness.rs:12:16: 12:17
10+
scope 1 {
11+
}
1012

1113
bb0: {
12-
_3 = discriminant((*_1)); // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31
13-
switchInt(move _3) -> [1_isize: bb1, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31
14+
_3 = discriminant((*_1)); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31
15+
switchInt(move _3) -> [1_isize: bb1, otherwise: bb3]; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31
1416
}
1517

1618
bb1: {
17-
StorageLive(_4); // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31
18-
_4 = move (((*_1) as Some).0: &E); // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31
19-
_2 = discriminant((*_4)); // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31
20-
StorageDead(_4); // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31
21-
switchInt(move _2) -> [1_isize: bb2, otherwise: bb3]; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31
19+
StorageLive(_4); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31
20+
_4 = move (((*_1) as Some).0: &E); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31
21+
_2 = discriminant((*_4)); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31
22+
StorageDead(_4); // scope 1 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31
23+
switchInt(move _2) -> [1_isize: bb2, otherwise: bb3]; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:13:12: 13:31
2224
}
2325

2426
bb2: {
25-
_0 = const 1_u32; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:38: 13:39
27+
_0 = const 1_u32; // scope 1 at $DIR/early_otherwise_branch_soundness.rs:13:38: 13:39
2628
goto -> bb4; // scope 0 at $DIR/early_otherwise_branch_soundness.rs:13:5: 13:52
2729
}
2830

0 commit comments

Comments
 (0)