Skip to content

Commit 066d44b

Browse files
committed
refactor the targeted_by_break field
In master, this field was an arbitrary node-id (in fact, an id for something that doesn't even exist in the HIR -- the `catch` node). Breaks targeting this block used that id. In the newer system, this field is a boolean, and any breaks targeted this block will use the id of the block.
1 parent 6a47fa1 commit 066d44b

File tree

9 files changed

+72
-60
lines changed

9 files changed

+72
-60
lines changed

src/librustc/cfg/construct.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,11 +74,11 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
7474

7575
impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
7676
fn block(&mut self, blk: &hir::Block, pred: CFGIndex) -> CFGIndex {
77-
if let Some(break_to_expr_id) = blk.break_to_expr_id {
77+
if blk.targeted_by_break {
7878
let expr_exit = self.add_ast_node(blk.id, &[]);
7979

8080
self.breakable_block_scopes.push(BlockScope {
81-
block_expr_id: break_to_expr_id,
81+
block_expr_id: blk.id,
8282
break_index: expr_exit,
8383
});
8484

src/librustc/hir/lowering.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,7 +1156,7 @@ impl<'a> LoweringContext<'a> {
11561156
bounds.iter().map(|bound| self.lower_ty_param_bound(bound)).collect()
11571157
}
11581158

1159-
fn lower_block(&mut self, b: &Block, break_to: Option<NodeId>) -> P<hir::Block> {
1159+
fn lower_block(&mut self, b: &Block, targeted_by_break: bool) -> P<hir::Block> {
11601160
let mut expr = None;
11611161

11621162
let mut stmts = vec![];
@@ -1179,7 +1179,7 @@ impl<'a> LoweringContext<'a> {
11791179
expr: expr,
11801180
rules: self.lower_block_check_mode(&b.rules),
11811181
span: b.span,
1182-
break_to_expr_id: break_to,
1182+
targeted_by_break: targeted_by_break,
11831183
})
11841184
}
11851185

@@ -1274,7 +1274,7 @@ impl<'a> LoweringContext<'a> {
12741274
}
12751275
ItemKind::Fn(ref decl, unsafety, constness, abi, ref generics, ref body) => {
12761276
self.with_new_scopes(|this| {
1277-
let body = this.lower_block(body, None);
1277+
let body = this.lower_block(body, false);
12781278
let body = this.expr_block(body, ThinVec::new());
12791279
let body_id = this.record_body(body, Some(decl));
12801280
hir::ItemFn(this.lower_fn_decl(decl),
@@ -1368,7 +1368,7 @@ impl<'a> LoweringContext<'a> {
13681368
hir::TraitMethod::Required(names))
13691369
}
13701370
TraitItemKind::Method(ref sig, Some(ref body)) => {
1371-
let body = this.lower_block(body, None);
1371+
let body = this.lower_block(body, false);
13721372
let expr = this.expr_block(body, ThinVec::new());
13731373
let body_id = this.record_body(expr, Some(&sig.decl));
13741374
hir::TraitItemKind::Method(this.lower_method_sig(sig),
@@ -1424,7 +1424,7 @@ impl<'a> LoweringContext<'a> {
14241424
hir::ImplItemKind::Const(this.lower_ty(ty), body_id)
14251425
}
14261426
ImplItemKind::Method(ref sig, ref body) => {
1427-
let body = this.lower_block(body, None);
1427+
let body = this.lower_block(body, false);
14281428
let expr = this.expr_block(body, ThinVec::new());
14291429
let body_id = this.record_body(expr, Some(&sig.decl));
14301430
hir::ImplItemKind::Method(this.lower_method_sig(sig), body_id)
@@ -1848,15 +1848,15 @@ impl<'a> LoweringContext<'a> {
18481848
id: id,
18491849
rules: hir::DefaultBlock,
18501850
span: span,
1851-
break_to_expr_id: None,
1851+
targeted_by_break: false,
18521852
});
18531853
P(self.expr_block(blk, ThinVec::new()))
18541854
}
18551855
_ => P(self.lower_expr(els)),
18561856
}
18571857
});
18581858

1859-
let then_blk = self.lower_block(blk, None);
1859+
let then_blk = self.lower_block(blk, false);
18601860
let then_expr = self.expr_block(then_blk, ThinVec::new());
18611861

18621862
hir::ExprIf(P(self.lower_expr(cond)), P(then_expr), else_opt)
@@ -1865,18 +1865,18 @@ impl<'a> LoweringContext<'a> {
18651865
self.with_loop_scope(e.id, |this|
18661866
hir::ExprWhile(
18671867
this.with_loop_condition_scope(|this| P(this.lower_expr(cond))),
1868-
this.lower_block(body, None),
1868+
this.lower_block(body, false),
18691869
this.lower_opt_sp_ident(opt_ident)))
18701870
}
18711871
ExprKind::Loop(ref body, opt_ident) => {
18721872
self.with_loop_scope(e.id, |this|
1873-
hir::ExprLoop(this.lower_block(body, None),
1873+
hir::ExprLoop(this.lower_block(body, false),
18741874
this.lower_opt_sp_ident(opt_ident),
18751875
hir::LoopSource::Loop))
18761876
}
18771877
ExprKind::Catch(ref body) => {
1878-
self.with_catch_scope(e.id, |this|
1879-
hir::ExprBlock(this.lower_block(body, Some(e.id))))
1878+
self.with_catch_scope(body.id, |this|
1879+
hir::ExprBlock(this.lower_block(body, true)))
18801880
}
18811881
ExprKind::Match(ref expr, ref arms) => {
18821882
hir::ExprMatch(P(self.lower_expr(expr)),
@@ -1894,7 +1894,7 @@ impl<'a> LoweringContext<'a> {
18941894
})
18951895
})
18961896
}
1897-
ExprKind::Block(ref blk) => hir::ExprBlock(self.lower_block(blk, None)),
1897+
ExprKind::Block(ref blk) => hir::ExprBlock(self.lower_block(blk, false)),
18981898
ExprKind::Assign(ref el, ref er) => {
18991899
hir::ExprAssign(P(self.lower_expr(el)), P(self.lower_expr(er)))
19001900
}
@@ -2040,7 +2040,7 @@ impl<'a> LoweringContext<'a> {
20402040

20412041
// `<pat> => <body>`
20422042
{
2043-
let body = self.lower_block(body, None);
2043+
let body = self.lower_block(body, false);
20442044
let body_expr = P(self.expr_block(body, ThinVec::new()));
20452045
let pat = self.lower_pat(pat);
20462046
arms.push(self.arm(hir_vec![pat], body_expr));
@@ -2112,7 +2112,7 @@ impl<'a> LoweringContext<'a> {
21122112
let (guard, body) = if let ExprKind::If(ref cond,
21132113
ref then,
21142114
_) = else_expr.node {
2115-
let then = self.lower_block(then, None);
2115+
let then = self.lower_block(then, false);
21162116
(Some(cond),
21172117
self.expr_block(then, ThinVec::new()))
21182118
} else {
@@ -2162,7 +2162,7 @@ impl<'a> LoweringContext<'a> {
21622162
// Note that the block AND the condition are evaluated in the loop scope.
21632163
// This is done to allow `break` from inside the condition of the loop.
21642164
let (body, break_expr, sub_expr) = self.with_loop_scope(e.id, |this| (
2165-
this.lower_block(body, None),
2165+
this.lower_block(body, false),
21662166
this.expr_break(e.span, ThinVec::new()),
21672167
this.with_loop_condition_scope(|this| P(this.lower_expr(sub_expr))),
21682168
));
@@ -2223,7 +2223,7 @@ impl<'a> LoweringContext<'a> {
22232223
// `::std::option::Option::Some(<pat>) => <body>`
22242224
let pat_arm = {
22252225
let body_block = self.with_loop_scope(e.id,
2226-
|this| this.lower_block(body, None));
2226+
|this| this.lower_block(body, false));
22272227
let body_expr = P(self.expr_block(body_block, ThinVec::new()));
22282228
let pat = self.lower_pat(pat);
22292229
let some_pat = self.pat_some(e.span, pat);
@@ -2655,7 +2655,7 @@ impl<'a> LoweringContext<'a> {
26552655
id: self.next_id(),
26562656
rules: hir::DefaultBlock,
26572657
span: span,
2658-
break_to_expr_id: None,
2658+
targeted_by_break: false,
26592659
}
26602660
}
26612661

@@ -2763,7 +2763,7 @@ impl<'a> LoweringContext<'a> {
27632763
id: id,
27642764
stmts: stmts,
27652765
expr: Some(expr),
2766-
break_to_expr_id: None,
2766+
targeted_by_break: false,
27672767
});
27682768
self.expr_block(block, attrs)
27692769
}

src/librustc/hir/mod.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -549,9 +549,11 @@ pub struct Block {
549549
/// Distinguishes between `unsafe { ... }` and `{ ... }`
550550
pub rules: BlockCheckMode,
551551
pub span: Span,
552-
/// The id of the expression that `break` breaks to if the block can be broken out of.
553-
/// Currently only `Some(_)` for `catch {}` blocks
554-
pub break_to_expr_id: Option<NodeId>,
552+
/// If true, then there may exist `break 'a` values that aim to
553+
/// break out of this block early. As of this writing, this is not
554+
/// currently permitted in Rust itself, but it is generated as
555+
/// part of `catch` statements.
556+
pub targeted_by_break: bool,
555557
}
556558

557559
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash)]

src/librustc/middle/liveness.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -821,8 +821,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
821821

822822
fn propagate_through_block(&mut self, blk: &hir::Block, succ: LiveNode)
823823
-> LiveNode {
824-
if let Some(break_to_expr_id) = blk.break_to_expr_id {
825-
self.breakable_block_ln.insert(break_to_expr_id, succ);
824+
if blk.targeted_by_break {
825+
self.breakable_block_ln.insert(blk.id, succ);
826826
}
827827
let succ = self.propagate_through_opt_expr(blk.expr.as_ref().map(|e| &**e), succ);
828828
blk.stmts.iter().rev().fold(succ, |succ, stmt| {

src/librustc_mir/build/block.rs

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,42 @@ use build::{BlockAnd, BlockAndExtension, Builder};
1212
use hair::*;
1313
use rustc::mir::*;
1414
use rustc::hir;
15+
use syntax_pos::Span;
1516

1617
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
1718
pub fn ast_block(&mut self,
1819
destination: &Lvalue<'tcx>,
19-
mut block: BasicBlock,
20-
ast_block: &'tcx hir::Block)
20+
block: BasicBlock,
21+
ast_block: &'tcx hir::Block,
22+
source_info: SourceInfo)
2123
-> BlockAnd<()> {
22-
let Block { extent, span, stmts, expr } = self.hir.mirror(ast_block);
24+
let Block { extent, span, stmts, expr, targeted_by_break } = self.hir.mirror(ast_block);
2325
self.in_scope(extent, block, move |this| {
26+
if targeted_by_break {
27+
// This is a `break`-able block (currently only `catch { ... }`)
28+
let exit_block = this.cfg.start_new_block();
29+
let block_exit = this.in_breakable_scope(None, exit_block,
30+
destination.clone(), |this| {
31+
this.ast_block_stmts(destination, block, span, stmts, expr)
32+
});
33+
this.cfg.terminate(unpack!(block_exit), source_info,
34+
TerminatorKind::Goto { target: exit_block });
35+
exit_block.unit()
36+
} else {
37+
this.ast_block_stmts(destination, block, span, stmts, expr)
38+
}
39+
})
40+
}
41+
42+
fn ast_block_stmts(&mut self,
43+
destination: &Lvalue<'tcx>,
44+
mut block: BasicBlock,
45+
span: Span,
46+
stmts: Vec<StmtRef<'tcx>>,
47+
expr: Option<ExprRef<'tcx>>)
48+
-> BlockAnd<()> {
49+
let this = self;
50+
2451
// This convoluted structure is to avoid using recursion as we walk down a list
2552
// of statements. Basically, the structure we get back is something like:
2653
//
@@ -96,6 +123,5 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
96123
// Restore the original visibility scope.
97124
this.visibility_scope = outer_visibility_scope;
98125
block.unit()
99-
})
100126
}
101127
}

src/librustc_mir/build/expr/into.rs

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
4040
this.in_scope(extent, block, |this| this.into(destination, block, value))
4141
}
4242
ExprKind::Block { body: ast_block } => {
43-
if let Some(_) = ast_block.break_to_expr_id {
44-
// This is a `break`-able block (currently only `catch { ... }`)
45-
let exit_block = this.cfg.start_new_block();
46-
let block_exit = this.in_breakable_scope(None, exit_block,
47-
destination.clone(), |this| {
48-
this.ast_block(destination, block, ast_block)
49-
});
50-
this.cfg.terminate(unpack!(block_exit), source_info,
51-
TerminatorKind::Goto { target: exit_block });
52-
exit_block.unit()
53-
} else {
54-
this.ast_block(destination, block, ast_block)
55-
}
43+
this.ast_block(destination, block, ast_block, source_info)
5644
}
5745
ExprKind::Match { discriminant, arms } => {
5846
this.match_expr(destination, expr_span, block, discriminant, arms)

src/librustc_mir/hair/cx/block.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block {
2323
// in order to get the lexical scoping correctly.
2424
let stmts = mirror_stmts(cx, self.id, &*self.stmts);
2525
Block {
26+
targeted_by_break: self.targeted_by_break,
2627
extent: cx.tcx.region_maps.node_extent(self.id),
2728
span: self.span,
2829
stmts: stmts,

src/librustc_mir/hair/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ pub use rustc_const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPatt
3131

3232
#[derive(Clone, Debug)]
3333
pub struct Block<'tcx> {
34+
pub targeted_by_break: bool,
3435
pub extent: CodeExtent,
3536
pub span: Span,
3637
pub stmts: Vec<StmtRef<'tcx>>,

src/librustc_typeck/check/mod.rs

Lines changed: 12 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -416,15 +416,11 @@ pub struct EnclosingBreakables<'gcx, 'tcx> {
416416
}
417417

418418
impl<'gcx, 'tcx> EnclosingBreakables<'gcx, 'tcx> {
419-
fn find_breakable(&mut self, target: hir::ScopeTarget)
420-
-> Option<&mut BreakableCtxt<'gcx, 'tcx>>
421-
{
422-
let opt_index = target.opt_id().and_then(|id| self.by_id.get(&id).cloned());
423-
if let Some(ix) = opt_index {
424-
Some(&mut self.stack[ix])
425-
} else {
426-
None
427-
}
419+
fn find_breakable(&mut self, target_id: ast::NodeId) -> &mut BreakableCtxt<'gcx, 'tcx> {
420+
let ix = *self.by_id.get(&target_id).unwrap_or_else(|| {
421+
bug!("could not find enclosing breakable with id {}", target_id);
422+
});
423+
&mut self.stack[ix]
428424
}
429425
}
430426

@@ -3472,12 +3468,12 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
34723468
tcx.mk_nil()
34733469
}
34743470
hir::ExprBreak(destination, ref expr_opt) => {
3471+
if let Some(target_id) = destination.target_id.opt_id() {
34753472
let coerce_to = {
34763473
let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
3477-
enclosing_breakables
3478-
.find_breakable(destination.target_id).map(|ctxt| ctxt.coerce_to)
3474+
enclosing_breakables.find_breakable(target_id).coerce_to
34793475
};
3480-
if let Some(coerce_to) = coerce_to {
3476+
34813477
let e_ty;
34823478
let cause;
34833479
if let Some(ref e) = *expr_opt {
@@ -3492,7 +3488,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
34923488
}
34933489

34943490
let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
3495-
let ctxt = enclosing_breakables.find_breakable(destination.target_id).unwrap();
3491+
let ctxt = enclosing_breakables.find_breakable(target_id);
34963492

34973493
let result = if let Some(ref e) = *expr_opt {
34983494
// Special-case the first element, as it has no "previous expressions".
@@ -4024,7 +4020,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
40244020
replace(&mut *fcx_ps, unsafety_state)
40254021
};
40264022

4027-
let mut ty = if let Some(break_to_expr_id) = blk.break_to_expr_id {
4023+
let mut ty = if blk.targeted_by_break {
40284024
let unified = self.next_ty_var(TypeVariableOrigin::TypeInference(blk.span));
40294025
let coerce_to = expected.only_has_type(self).unwrap_or(unified);
40304026
let ctxt = BreakableCtxt {
@@ -4034,15 +4030,13 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
40344030
may_break: false,
40354031
};
40364032

4037-
let (mut ctxt, (e_ty, cause)) = self.with_breakable_ctxt(break_to_expr_id, ctxt, || {
4033+
let (mut ctxt, (e_ty, cause)) = self.with_breakable_ctxt(blk.id, ctxt, || {
40384034
for s in &blk.stmts {
40394035
self.check_stmt(s);
40404036
}
40414037
let coerce_to = {
40424038
let mut enclosing_breakables = self.enclosing_breakables.borrow_mut();
4043-
enclosing_breakables.find_breakable(
4044-
hir::ScopeTarget::Block(break_to_expr_id)
4045-
).unwrap().coerce_to
4039+
enclosing_breakables.find_breakable(blk.id).coerce_to
40464040
};
40474041
let e_ty;
40484042
let cause;

0 commit comments

Comments
 (0)