Skip to content

Commit b8ec4c4

Browse files
committed
Auto merge of #62233 - matthewjasper:exit-arm-scopes, r=pnkfelix
Exit arm scopes Due to a bug in the HIR CFG construction, borrows for arm scopes were incorrectly leaking into other arms. This PR also includes some drive-by improvements to `-Zunpretty=hir,identified` that would have been helpful while investigating this. Closes #62107
2 parents 5d8ffb5 + de5c6ec commit b8ec4c4

File tree

6 files changed

+43
-17
lines changed

6 files changed

+43
-17
lines changed

src/librustc/cfg/construct.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
371371
let expr_exit = self.add_ast_node(id, &[]);
372372

373373
// Keep track of the previous guard expressions
374-
let mut prev_guards = Vec::new();
374+
let mut prev_guard = None;
375+
let match_scope = region::Scope { id, data: region::ScopeData::Node };
375376

376377
for arm in arms {
377378
// Add an exit node for when we've visited all the
@@ -389,23 +390,23 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
389390
let guard_start = self.add_dummy_node(&[pat_exit]);
390391
// Visit the guard expression
391392
let guard_exit = match guard {
392-
hir::Guard::If(ref e) => self.expr(e, guard_start),
393+
hir::Guard::If(ref e) => (&**e, self.expr(e, guard_start)),
393394
};
394395
// #47295: We used to have very special case code
395396
// here for when a pair of arms are both formed
396397
// solely from constants, and if so, not add these
397398
// edges. But this was not actually sound without
398399
// other constraints that we stopped enforcing at
399400
// some point.
400-
while let Some(prev) = prev_guards.pop() {
401-
self.add_contained_edge(prev, guard_start);
401+
if let Some((prev_guard, prev_index)) = prev_guard.take() {
402+
self.add_exiting_edge(prev_guard, prev_index, match_scope, guard_start);
402403
}
403404

404405
// Push the guard onto the list of previous guards
405-
prev_guards.push(guard_exit);
406+
prev_guard = Some(guard_exit);
406407

407408
// Update the exit node for the pattern
408-
pat_exit = guard_exit;
409+
pat_exit = guard_exit.1;
409410
}
410411

411412
// Add an edge from the exit of this pattern to the

src/librustc/hir/print.rs

+3
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ pub enum AnnNode<'a> {
2727
SubItem(hir::HirId),
2828
Expr(&'a hir::Expr),
2929
Pat(&'a hir::Pat),
30+
Arm(&'a hir::Arm),
3031
}
3132

3233
pub enum Nested {
@@ -1821,6 +1822,7 @@ impl<'a> State<'a> {
18211822
self.s.space();
18221823
}
18231824
self.cbox(indent_unit);
1825+
self.ann.pre(self, AnnNode::Arm(arm));
18241826
self.ibox(0);
18251827
self.print_outer_attributes(&arm.attrs);
18261828
let mut first = true;
@@ -1865,6 +1867,7 @@ impl<'a> State<'a> {
18651867
self.s.word(",");
18661868
}
18671869
}
1870+
self.ann.post(self, AnnNode::Arm(arm));
18681871
self.end() // close enclosing cbox
18691872
}
18701873

src/librustc_borrowck/dataflow.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,8 @@ impl<'tcx, O: DataFlowOperator> pprust::PpAnn for DataFlowContext<'tcx, O> {
109109
pprust::AnnNode::Block(blk) => blk.hir_id.local_id,
110110
pprust::AnnNode::Item(_) |
111111
pprust::AnnNode::SubItem(_) => return,
112-
pprust::AnnNode::Pat(pat) => pat.hir_id.local_id
112+
pprust::AnnNode::Pat(pat) => pat.hir_id.local_id,
113+
pprust::AnnNode::Arm(arm) => arm.hir_id.local_id,
113114
};
114115

115116
if !self.has_bitset_for_local_id(id) {

src/librustc_driver/pretty.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -387,28 +387,28 @@ impl<'hir> pprust_hir::PpAnn for IdentifiedAnnotation<'hir> {
387387
pprust_hir::AnnNode::Name(_) => {},
388388
pprust_hir::AnnNode::Item(item) => {
389389
s.s.space();
390-
s.synth_comment(format!("hir_id: {} hir local_id: {}",
391-
item.hir_id, item.hir_id.local_id.as_u32()))
390+
s.synth_comment(format!("hir_id: {}", item.hir_id));
392391
}
393392
pprust_hir::AnnNode::SubItem(id) => {
394393
s.s.space();
395-
s.synth_comment(id.to_string())
394+
s.synth_comment(id.to_string());
396395
}
397396
pprust_hir::AnnNode::Block(blk) => {
398397
s.s.space();
399-
s.synth_comment(format!("block hir_id: {} hir local_id: {}",
400-
blk.hir_id, blk.hir_id.local_id.as_u32()))
398+
s.synth_comment(format!("block hir_id: {}", blk.hir_id));
401399
}
402400
pprust_hir::AnnNode::Expr(expr) => {
403401
s.s.space();
404-
s.synth_comment(format!("expr hir_id: {} hir local_id: {}",
405-
expr.hir_id, expr.hir_id.local_id.as_u32()));
406-
s.pclose()
402+
s.synth_comment(format!("expr hir_id: {}", expr.hir_id));
403+
s.pclose();
407404
}
408405
pprust_hir::AnnNode::Pat(pat) => {
409406
s.s.space();
410-
s.synth_comment(format!("pat hir_id: {} hir local_id: {}",
411-
pat.hir_id, pat.hir_id.local_id.as_u32()))
407+
s.synth_comment(format!("pat hir_id: {}", pat.hir_id));
408+
}
409+
pprust_hir::AnnNode::Arm(arm) => {
410+
s.s.space();
411+
s.synth_comment(format!("arm hir_id: {}", arm.hir_id));
412412
}
413413
}
414414
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
fn main() {
2+
let e: i32;
3+
match e {
4+
//~^ ERROR use of possibly uninitialized variable
5+
ref u if true => {}
6+
ref v if true => {
7+
let tx = 0;
8+
&tx;
9+
}
10+
_ => (),
11+
}
12+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
error[E0381]: use of possibly uninitialized variable: `e`
2+
--> $DIR/issue-62107-match-arm-scopes.rs:3:11
3+
|
4+
LL | match e {
5+
| ^ use of possibly uninitialized `e`
6+
7+
error: aborting due to previous error
8+
9+
For more information about this error, try `rustc --explain E0381`.

0 commit comments

Comments
 (0)