Skip to content

Commit e7e1a52

Browse files
committed
Refactor code so that block_context observations has nicely named (and documented) methods.
1 parent 556f583 commit e7e1a52

File tree

3 files changed

+58
-26
lines changed

3 files changed

+58
-26
lines changed

src/librustc_mir/build/block.rs

+1-11
Original file line numberDiff line numberDiff line change
@@ -177,17 +177,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
177177
let destination_ty = destination.ty(&this.local_decls, tcx).to_ty(tcx);
178178
if let Some(expr) = expr {
179179
let tail_result_is_ignored = destination_ty.is_unit() ||
180-
match this.block_context.last() {
181-
// no context: conservatively assume result is read
182-
None => false,
183-
184-
// sub-expression: block result feeds into some computation
185-
Some(BlockFrame::SubExpr) => false,
186-
187-
// otherwise: use accumualated is_ignored state.
188-
Some(BlockFrame::TailExpr { tail_result_is_ignored: ignored }) |
189-
Some(BlockFrame::Statement { ignores_expr_result: ignored }) => *ignored,
190-
};
180+
this.block_context.currently_ignores_tail_results();
191181
this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored });
192182

193183
unpack!(block = this.into(destination, block, expr));

src/librustc_mir/build/expr/as_temp.rs

+3-13
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
//! See docs in build/expr/mod.rs
1212
13-
use build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
13+
use build::{BlockAnd, BlockAndExtension, Builder};
1414
use hair::*;
1515
use rustc::middle::region;
1616
use rustc::mir::*;
@@ -68,19 +68,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
6868
debug!("creating temp {:?} with block_context: {:?}", local_decl, this.block_context);
6969
// Find out whether this temp is being created within the
7070
// tail expression of a block whose result is ignored.
71-
for bf in this.block_context.iter().rev() {
72-
match bf {
73-
BlockFrame::SubExpr => continue,
74-
BlockFrame::Statement { .. } => break,
75-
&BlockFrame::TailExpr { tail_result_is_ignored } => {
76-
local_decl = local_decl.block_tail(BlockTailInfo {
77-
tail_result_is_ignored
78-
});
79-
break;
80-
}
81-
}
71+
if let Some(tail_info) = this.block_context.currently_in_block_tail() {
72+
local_decl = local_decl.block_tail(tail_info);
8273
}
83-
8474
this.local_decls.push(local_decl)
8575
};
8676
if !expr_ty.is_never() {

src/librustc_mir/build/mod.rs

+54-2
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,9 @@ impl BlockFrame {
336336
}
337337
}
338338

339+
#[derive(Debug)]
340+
struct BlockContext(Vec<BlockFrame>);
341+
339342
struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
340343
hir: Cx<'a, 'gcx, 'tcx>,
341344
cfg: CFG<'tcx>,
@@ -359,7 +362,7 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
359362
/// start just throwing new entries onto that vector in order to
360363
/// distinguish the context of EXPR1 from the context of EXPR2 in
361364
/// `{ STMTS; EXPR1 } + EXPR2`
362-
block_context: Vec<BlockFrame>,
365+
block_context: BlockContext,
363366

364367
/// The current unsafe block in scope, even if it is hidden by
365368
/// a PushUnsafeBlock
@@ -409,6 +412,55 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
409412
}
410413
}
411414

415+
impl BlockContext {
416+
fn new() -> Self { BlockContext(vec![]) }
417+
fn push(&mut self, bf: BlockFrame) { self.0.push(bf); }
418+
fn pop(&mut self) -> Option<BlockFrame> { self.0.pop() }
419+
420+
/// Traverses the frames on the BlockContext, searching for either
421+
/// the first block-tail expression frame with no intervening
422+
/// statement frame.
423+
///
424+
/// Notably, this skips over `SubExpr` frames; this method is
425+
/// meant to be used in the context of understanding the
426+
/// relationship of a temp (created within some complicated
427+
/// expression) with its containing expression, and whether the
428+
/// value of that *containing expression* (not the temp!) is
429+
/// ignored.
430+
fn currently_in_block_tail(&self) -> Option<BlockTailInfo> {
431+
for bf in self.0.iter().rev() {
432+
match bf {
433+
BlockFrame::SubExpr => continue,
434+
BlockFrame::Statement { .. } => break,
435+
&BlockFrame::TailExpr { tail_result_is_ignored } =>
436+
return Some(BlockTailInfo { tail_result_is_ignored })
437+
}
438+
}
439+
440+
return None;
441+
}
442+
443+
/// Looks at the topmost frame on the BlockContext and reports
444+
/// whether its one that would discard a block tail result.
445+
///
446+
/// Unlike `currently_within_ignored_tail_expression`, this does
447+
/// *not* skip over `SubExpr` frames: here, we want to know
448+
/// whether the block result itself is discarded.
449+
fn currently_ignores_tail_results(&self) -> bool {
450+
match self.0.last() {
451+
// no context: conservatively assume result is read
452+
None => false,
453+
454+
// sub-expression: block result feeds into some computation
455+
Some(BlockFrame::SubExpr) => false,
456+
457+
// otherwise: use accumulated is_ignored state.
458+
Some(BlockFrame::TailExpr { tail_result_is_ignored: ignored }) |
459+
Some(BlockFrame::Statement { ignores_expr_result: ignored }) => *ignored,
460+
}
461+
}
462+
}
463+
412464
#[derive(Debug)]
413465
enum LocalsForNode {
414466
/// In the usual case, a node-id for an identifier maps to at most
@@ -764,7 +816,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
764816
fn_span: span,
765817
arg_count,
766818
scopes: vec![],
767-
block_context: vec![],
819+
block_context: BlockContext::new(),
768820
source_scopes: IndexVec::new(),
769821
source_scope: OUTERMOST_SOURCE_SCOPE,
770822
source_scope_local_data: IndexVec::new(),

0 commit comments

Comments
 (0)