Store blocks in Thir
.
Like expressions, statements, and match arms. This shrinks `thir::Stmt` and is a precursor to further shrinking `thir::Expr`.
This commit is contained in:
parent
e7c25c3a97
commit
2df805fc7a
11 changed files with 66 additions and 47 deletions
|
@ -75,6 +75,7 @@ macro_rules! thir_with_elements {
|
||||||
|
|
||||||
thir_with_elements! {
|
thir_with_elements! {
|
||||||
arms: ArmId => Arm<'tcx> => "a{}",
|
arms: ArmId => Arm<'tcx> => "a{}",
|
||||||
|
blocks: BlockId => Block => "b{}",
|
||||||
exprs: ExprId => Expr<'tcx> => "e{}",
|
exprs: ExprId => Expr<'tcx> => "e{}",
|
||||||
stmts: StmtId => Stmt<'tcx> => "s{}",
|
stmts: StmtId => Stmt<'tcx> => "s{}",
|
||||||
}
|
}
|
||||||
|
@ -168,7 +169,7 @@ pub enum StmtKind<'tcx> {
|
||||||
initializer: Option<ExprId>,
|
initializer: Option<ExprId>,
|
||||||
|
|
||||||
/// `let pat: ty = <INIT> else { <ELSE> }
|
/// `let pat: ty = <INIT> else { <ELSE> }
|
||||||
else_block: Option<Block>,
|
else_block: Option<BlockId>,
|
||||||
|
|
||||||
/// The lint level for this `let` statement.
|
/// The lint level for this `let` statement.
|
||||||
lint_level: LintLevel,
|
lint_level: LintLevel,
|
||||||
|
@ -292,7 +293,7 @@ pub enum ExprKind<'tcx> {
|
||||||
},
|
},
|
||||||
/// A block.
|
/// A block.
|
||||||
Block {
|
Block {
|
||||||
body: Block,
|
block: BlockId,
|
||||||
},
|
},
|
||||||
/// An assignment: `lhs = rhs`.
|
/// An assignment: `lhs = rhs`.
|
||||||
Assign {
|
Assign {
|
||||||
|
@ -802,5 +803,5 @@ mod size_asserts {
|
||||||
static_assert_size!(Block, 56);
|
static_assert_size!(Block, 56);
|
||||||
static_assert_size!(Expr<'_>, 88);
|
static_assert_size!(Expr<'_>, 88);
|
||||||
static_assert_size!(Pat<'_>, 24);
|
static_assert_size!(Pat<'_>, 24);
|
||||||
static_assert_size!(Stmt<'_>, 120);
|
static_assert_size!(Stmt<'_>, 72);
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ pub fn walk_expr<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, expr: &Exp
|
||||||
visitor.visit_arm(&visitor.thir()[arm]);
|
visitor.visit_arm(&visitor.thir()[arm]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Block { ref body } => visitor.visit_block(body),
|
Block { block } => visitor.visit_block(&visitor.thir()[block]),
|
||||||
Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => {
|
Assign { lhs, rhs } | AssignOp { lhs, rhs, op: _ } => {
|
||||||
visitor.visit_expr(&visitor.thir()[lhs]);
|
visitor.visit_expr(&visitor.thir()[lhs]);
|
||||||
visitor.visit_expr(&visitor.thir()[rhs]);
|
visitor.visit_expr(&visitor.thir()[rhs]);
|
||||||
|
@ -174,7 +174,7 @@ pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stm
|
||||||
}
|
}
|
||||||
visitor.visit_pat(pattern);
|
visitor.visit_pat(pattern);
|
||||||
if let Some(block) = else_block {
|
if let Some(block) = else_block {
|
||||||
visitor.visit_block(block)
|
visitor.visit_block(&visitor.thir()[*block])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
destination: Place<'tcx>,
|
destination: Place<'tcx>,
|
||||||
block: BasicBlock,
|
block: BasicBlock,
|
||||||
ast_block: &Block,
|
ast_block: BlockId,
|
||||||
source_info: SourceInfo,
|
source_info: SourceInfo,
|
||||||
) -> BlockAnd<()> {
|
) -> BlockAnd<()> {
|
||||||
let Block {
|
let Block {
|
||||||
|
@ -21,7 +21,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
expr,
|
expr,
|
||||||
targeted_by_break,
|
targeted_by_break,
|
||||||
safety_mode,
|
safety_mode,
|
||||||
} = *ast_block;
|
} = self.thir[ast_block];
|
||||||
let expr = expr.map(|expr| &self.thir[expr]);
|
let expr = expr.map(|expr| &self.thir[expr]);
|
||||||
self.in_opt_scope(opt_destruction_scope.map(|de| (de, source_info)), move |this| {
|
self.in_opt_scope(opt_destruction_scope.map(|de| (de, source_info)), move |this| {
|
||||||
this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| {
|
this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| {
|
||||||
|
@ -130,7 +130,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
block,
|
block,
|
||||||
init,
|
init,
|
||||||
initializer_span,
|
initializer_span,
|
||||||
else_block,
|
*else_block,
|
||||||
visibility_scope,
|
visibility_scope,
|
||||||
*remainder_scope,
|
*remainder_scope,
|
||||||
remainder_span,
|
remainder_span,
|
||||||
|
|
|
@ -83,8 +83,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// Don't bother with StorageLive and Dead for these temporaries,
|
// Don't bother with StorageLive and Dead for these temporaries,
|
||||||
// they are never assigned.
|
// they are never assigned.
|
||||||
ExprKind::Break { .. } | ExprKind::Continue { .. } | ExprKind::Return { .. } => (),
|
ExprKind::Break { .. } | ExprKind::Continue { .. } | ExprKind::Return { .. } => (),
|
||||||
ExprKind::Block { body: Block { expr: None, targeted_by_break: false, .. } }
|
ExprKind::Block { block }
|
||||||
if expr_ty.is_never() => {}
|
if let Block { expr: None, targeted_by_break: false, .. } = this.thir[block]
|
||||||
|
&& expr_ty.is_never() => {}
|
||||||
_ => {
|
_ => {
|
||||||
this.cfg
|
this.cfg
|
||||||
.push(block, Statement { source_info, kind: StatementKind::StorageLive(temp) });
|
.push(block, Statement { source_info, kind: StatementKind::StorageLive(temp) });
|
||||||
|
|
|
@ -46,7 +46,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ExprKind::Block { body: ref ast_block } => {
|
ExprKind::Block { block: ast_block } => {
|
||||||
this.ast_block(destination, block, ast_block, source_info)
|
this.ast_block(destination, block, ast_block, source_info)
|
||||||
}
|
}
|
||||||
ExprKind::Match { scrutinee, ref arms } => {
|
ExprKind::Match { scrutinee, ref arms } => {
|
||||||
|
|
|
@ -116,14 +116,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// it is usually better to focus on `the_value` rather
|
// it is usually better to focus on `the_value` rather
|
||||||
// than the entirety of block(s) surrounding it.
|
// than the entirety of block(s) surrounding it.
|
||||||
let adjusted_span = (|| {
|
let adjusted_span = (|| {
|
||||||
if let ExprKind::Block { body } = &expr.kind && let Some(tail_ex) = body.expr {
|
if let ExprKind::Block { block } = expr.kind
|
||||||
|
&& let Some(tail_ex) = this.thir[block].expr
|
||||||
|
{
|
||||||
let mut expr = &this.thir[tail_ex];
|
let mut expr = &this.thir[tail_ex];
|
||||||
while let ExprKind::Block {
|
loop {
|
||||||
body: Block { expr: Some(nested_expr), .. },
|
match expr.kind {
|
||||||
}
|
ExprKind::Block { block }
|
||||||
| ExprKind::Scope { value: nested_expr, .. } = expr.kind
|
if let Some(nested_expr) = this.thir[block].expr =>
|
||||||
{
|
{
|
||||||
expr = &this.thir[nested_expr];
|
expr = &this.thir[nested_expr];
|
||||||
|
}
|
||||||
|
ExprKind::Scope { value: nested_expr, .. } => {
|
||||||
|
expr = &this.thir[nested_expr];
|
||||||
|
}
|
||||||
|
_ => break,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.block_context.push(BlockFrame::TailExpr {
|
this.block_context.push(BlockFrame::TailExpr {
|
||||||
tail_result_is_ignored: true,
|
tail_result_is_ignored: true,
|
||||||
|
|
|
@ -2280,15 +2280,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
mut block: BasicBlock,
|
mut block: BasicBlock,
|
||||||
init: &Expr<'tcx>,
|
init: &Expr<'tcx>,
|
||||||
initializer_span: Span,
|
initializer_span: Span,
|
||||||
else_block: &Block,
|
else_block: BlockId,
|
||||||
visibility_scope: Option<SourceScope>,
|
visibility_scope: Option<SourceScope>,
|
||||||
remainder_scope: region::Scope,
|
remainder_scope: region::Scope,
|
||||||
remainder_span: Span,
|
remainder_span: Span,
|
||||||
pattern: &Pat<'tcx>,
|
pattern: &Pat<'tcx>,
|
||||||
) -> BlockAnd<()> {
|
) -> BlockAnd<()> {
|
||||||
|
let else_block_span = self.thir[else_block].span;
|
||||||
let (matching, failure) = self.in_if_then_scope(remainder_scope, |this| {
|
let (matching, failure) = self.in_if_then_scope(remainder_scope, |this| {
|
||||||
let scrutinee = unpack!(block = this.lower_scrutinee(block, init, initializer_span));
|
let scrutinee = unpack!(block = this.lower_scrutinee(block, init, initializer_span));
|
||||||
let pat = Pat { ty: init.ty, span: else_block.span, kind: Box::new(PatKind::Wild) };
|
let pat = Pat { ty: init.ty, span: else_block_span, kind: Box::new(PatKind::Wild) };
|
||||||
let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false);
|
let mut wildcard = Candidate::new(scrutinee.clone(), &pat, false);
|
||||||
this.declare_bindings(
|
this.declare_bindings(
|
||||||
visibility_scope,
|
visibility_scope,
|
||||||
|
@ -2318,7 +2319,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
// This block is for the failure case
|
// This block is for the failure case
|
||||||
let failure = this.bind_pattern(
|
let failure = this.bind_pattern(
|
||||||
this.source_info(else_block.span),
|
this.source_info(else_block_span),
|
||||||
wildcard,
|
wildcard,
|
||||||
None,
|
None,
|
||||||
&fake_borrow_temps,
|
&fake_borrow_temps,
|
||||||
|
@ -2334,19 +2335,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// This place is not really used because this destination place
|
// This place is not really used because this destination place
|
||||||
// should never be used to take values at the end of the failure
|
// should never be used to take values at the end of the failure
|
||||||
// block.
|
// block.
|
||||||
let dummy_place = self.temp(self.tcx.types.never, else_block.span);
|
let dummy_place = self.temp(self.tcx.types.never, else_block_span);
|
||||||
let failure_block;
|
let failure_block;
|
||||||
unpack!(
|
unpack!(
|
||||||
failure_block = self.ast_block(
|
failure_block = self.ast_block(
|
||||||
dummy_place,
|
dummy_place,
|
||||||
failure,
|
failure,
|
||||||
else_block,
|
else_block,
|
||||||
self.source_info(else_block.span),
|
self.source_info(else_block_span),
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
self.cfg.terminate(
|
self.cfg.terminate(
|
||||||
failure_block,
|
failure_block,
|
||||||
self.source_info(else_block.span),
|
self.source_info(else_block_span),
|
||||||
TerminatorKind::Unreachable,
|
TerminatorKind::Unreachable,
|
||||||
);
|
);
|
||||||
matching.unit()
|
matching.unit()
|
||||||
|
|
|
@ -9,13 +9,13 @@ use rustc_index::vec::Idx;
|
||||||
use rustc_middle::ty::CanonicalUserTypeAnnotation;
|
use rustc_middle::ty::CanonicalUserTypeAnnotation;
|
||||||
|
|
||||||
impl<'tcx> Cx<'tcx> {
|
impl<'tcx> Cx<'tcx> {
|
||||||
pub(crate) fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> Block {
|
pub(crate) fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> BlockId {
|
||||||
// We have to eagerly lower the "spine" of the statements
|
// We have to eagerly lower the "spine" of the statements
|
||||||
// in order to get the lexical scoping correctly.
|
// in order to get the lexical scoping correctly.
|
||||||
let stmts = self.mirror_stmts(block.hir_id.local_id, block.stmts);
|
let stmts = self.mirror_stmts(block.hir_id.local_id, block.stmts);
|
||||||
let opt_destruction_scope =
|
let opt_destruction_scope =
|
||||||
self.region_scope_tree.opt_destruction_scope(block.hir_id.local_id);
|
self.region_scope_tree.opt_destruction_scope(block.hir_id.local_id);
|
||||||
Block {
|
let block = Block {
|
||||||
targeted_by_break: block.targeted_by_break,
|
targeted_by_break: block.targeted_by_break,
|
||||||
region_scope: region::Scope {
|
region_scope: region::Scope {
|
||||||
id: block.hir_id.local_id,
|
id: block.hir_id.local_id,
|
||||||
|
@ -34,7 +34,9 @@ impl<'tcx> Cx<'tcx> {
|
||||||
BlockSafety::ExplicitUnsafe(block.hir_id)
|
BlockSafety::ExplicitUnsafe(block.hir_id)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
|
|
||||||
|
self.thir.blocks.push(block)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mirror_stmts(
|
fn mirror_stmts(
|
||||||
|
|
|
@ -108,8 +108,8 @@ impl<'tcx> Cx<'tcx> {
|
||||||
// // ^ error message points at this expression.
|
// // ^ error message points at this expression.
|
||||||
// }
|
// }
|
||||||
let mut adjust_span = |expr: &mut Expr<'tcx>| {
|
let mut adjust_span = |expr: &mut Expr<'tcx>| {
|
||||||
if let ExprKind::Block { body } = &expr.kind {
|
if let ExprKind::Block { block } = expr.kind {
|
||||||
if let Some(last_expr) = body.expr {
|
if let Some(last_expr) = self.thir[block].expr {
|
||||||
span = self.thir[last_expr].span;
|
span = self.thir[last_expr].span;
|
||||||
expr.span = span;
|
expr.span = span;
|
||||||
}
|
}
|
||||||
|
@ -369,7 +369,7 @@ impl<'tcx> Cx<'tcx> {
|
||||||
ExprKind::AddressOf { mutability, arg: self.mirror_expr(arg) }
|
ExprKind::AddressOf { mutability, arg: self.mirror_expr(arg) }
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: self.mirror_block(blk) },
|
hir::ExprKind::Block(ref blk, _) => ExprKind::Block { block: self.mirror_block(blk) },
|
||||||
|
|
||||||
hir::ExprKind::Assign(ref lhs, ref rhs, _) => {
|
hir::ExprKind::Assign(ref lhs, ref rhs, _) => {
|
||||||
ExprKind::Assign { lhs: self.mirror_expr(lhs), rhs: self.mirror_expr(rhs) }
|
ExprKind::Assign { lhs: self.mirror_expr(lhs), rhs: self.mirror_expr(rhs) }
|
||||||
|
@ -680,8 +680,8 @@ impl<'tcx> Cx<'tcx> {
|
||||||
let body = self.thir.exprs.push(Expr {
|
let body = self.thir.exprs.push(Expr {
|
||||||
ty: block_ty,
|
ty: block_ty,
|
||||||
temp_lifetime,
|
temp_lifetime,
|
||||||
span: block.span,
|
span: self.thir[block].span,
|
||||||
kind: ExprKind::Block { body: block },
|
kind: ExprKind::Block { block },
|
||||||
});
|
});
|
||||||
ExprKind::Loop { body }
|
ExprKind::Loop { body }
|
||||||
}
|
}
|
||||||
|
|
|
@ -311,8 +311,15 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||||
// bar::<{ N + 1 }>();
|
// bar::<{ N + 1 }>();
|
||||||
// }
|
// }
|
||||||
// ```
|
// ```
|
||||||
ExprKind::Block { body: thir::Block { stmts: box [], expr: Some(e), .. } } => {
|
ExprKind::Block { block } => {
|
||||||
self.recurse_build(*e)?
|
if let thir::Block { stmts: box [], expr: Some(e), .. } = &self.body.blocks[*block] {
|
||||||
|
self.recurse_build(*e)?
|
||||||
|
} else {
|
||||||
|
self.maybe_supported_error(
|
||||||
|
node.span,
|
||||||
|
"blocks are not supported in generic constant",
|
||||||
|
)?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// `ExprKind::Use` happens when a `hir::ExprKind::Cast` is a
|
// `ExprKind::Use` happens when a `hir::ExprKind::Cast` is a
|
||||||
// "coercion cast" i.e. using a coercion or is a no-op.
|
// "coercion cast" i.e. using a coercion or is a no-op.
|
||||||
|
@ -349,10 +356,6 @@ impl<'a, 'tcx> AbstractConstBuilder<'a, 'tcx> {
|
||||||
node.span,
|
node.span,
|
||||||
"array construction is not supported in generic constants",
|
"array construction is not supported in generic constants",
|
||||||
)?,
|
)?,
|
||||||
ExprKind::Block { .. } => self.maybe_supported_error(
|
|
||||||
node.span,
|
|
||||||
"blocks are not supported in generic constant",
|
|
||||||
)?,
|
|
||||||
ExprKind::NeverToAny { .. } => self.maybe_supported_error(
|
ExprKind::NeverToAny { .. } => self.maybe_supported_error(
|
||||||
node.span,
|
node.span,
|
||||||
"converting nevers to any is not supported in generic constant",
|
"converting nevers to any is not supported in generic constant",
|
||||||
|
|
|
@ -1,6 +1,17 @@
|
||||||
DefId(0:3 ~ thir_tree[8f1d]::main):
|
DefId(0:3 ~ thir_tree[8f1d]::main):
|
||||||
Thir {
|
Thir {
|
||||||
arms: [],
|
arms: [],
|
||||||
|
blocks: [
|
||||||
|
Block {
|
||||||
|
targeted_by_break: false,
|
||||||
|
region_scope: Node(1),
|
||||||
|
opt_destruction_scope: None,
|
||||||
|
span: $DIR/thir-tree.rs:4:15: 4:17 (#0),
|
||||||
|
stmts: [],
|
||||||
|
expr: None,
|
||||||
|
safety_mode: Safe,
|
||||||
|
},
|
||||||
|
],
|
||||||
exprs: [
|
exprs: [
|
||||||
Expr {
|
Expr {
|
||||||
ty: (),
|
ty: (),
|
||||||
|
@ -9,15 +20,7 @@ Thir {
|
||||||
),
|
),
|
||||||
span: $DIR/thir-tree.rs:4:15: 4:17 (#0),
|
span: $DIR/thir-tree.rs:4:15: 4:17 (#0),
|
||||||
kind: Block {
|
kind: Block {
|
||||||
body: Block {
|
block: b0,
|
||||||
targeted_by_break: false,
|
|
||||||
region_scope: Node(1),
|
|
||||||
opt_destruction_scope: None,
|
|
||||||
span: $DIR/thir-tree.rs:4:15: 4:17 (#0),
|
|
||||||
stmts: [],
|
|
||||||
expr: None,
|
|
||||||
safety_mode: Safe,
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Expr {
|
Expr {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue