Skip to content

Eagerly construct bodies of THIR #82495

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 7 commits into from
Mar 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 23 additions & 30 deletions compiler/rustc_mir_build/src/build/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ use crate::build::matches::ArmHasGuard;
use crate::build::ForGuard::OutsideGuard;
use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
use crate::thir::*;
use rustc_hir as hir;
use rustc_middle::mir::*;
use rustc_session::lint::builtin::UNSAFE_OP_IN_UNSAFE_FN;
use rustc_session::lint::Level;
Expand All @@ -13,7 +12,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut self,
destination: Place<'tcx>,
block: BasicBlock,
ast_block: &'tcx hir::Block<'tcx>,
ast_block: &Block<'_, 'tcx>,
source_info: SourceInfo,
) -> BlockAnd<()> {
let Block {
Expand All @@ -24,7 +23,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
expr,
targeted_by_break,
safety_mode,
} = self.hir.mirror(ast_block);
} = *ast_block;
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| {
if targeted_by_break {
Expand All @@ -50,8 +49,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
destination: Place<'tcx>,
mut block: BasicBlock,
span: Span,
stmts: Vec<StmtRef<'tcx>>,
expr: Option<ExprRef<'tcx>>,
stmts: &[Stmt<'_, 'tcx>],
expr: Option<&Expr<'_, 'tcx>>,
safety_mode: BlockSafety,
) -> BlockAnd<()> {
let this = self;
Expand Down Expand Up @@ -79,18 +78,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
this.update_source_scope_for_safety_mode(span, safety_mode);

let source_info = this.source_info(span);
for stmt in stmts {
let Stmt { kind, opt_destruction_scope } = this.hir.mirror(stmt);
for Stmt { kind, opt_destruction_scope } in stmts {
match kind {
StmtKind::Expr { scope, expr } => {
&StmtKind::Expr { scope, expr } => {
this.block_context.push(BlockFrame::Statement { ignores_expr_result: true });
unpack!(
block = this.in_opt_scope(
opt_destruction_scope.map(|de| (de, source_info)),
|this| {
let si = (scope, source_info);
this.in_scope(si, LintLevel::Inherited, |this| {
let expr = this.hir.mirror(expr);
this.stmt_expr(block, expr, Some(scope))
})
}
Expand All @@ -102,45 +99,44 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
this.block_context.push(BlockFrame::Statement { ignores_expr_result });

// Enter the remainder scope, i.e., the bindings' destruction scope.
this.push_scope((remainder_scope, source_info));
this.push_scope((*remainder_scope, source_info));
let_scope_stack.push(remainder_scope);

// Declare the bindings, which may create a source scope.
let remainder_span =
remainder_scope.span(this.hir.tcx(), &this.hir.region_scope_tree);
let remainder_span = remainder_scope.span(this.tcx, this.region_scope_tree);

let visibility_scope =
Some(this.new_source_scope(remainder_span, LintLevel::Inherited, None));

// Evaluate the initializer, if present.
if let Some(init) = initializer {
let initializer_span = init.span();
let initializer_span = init.span;

unpack!(
block = this.in_opt_scope(
opt_destruction_scope.map(|de| (de, source_info)),
|this| {
let scope = (init_scope, source_info);
this.in_scope(scope, lint_level, |this| {
let scope = (*init_scope, source_info);
this.in_scope(scope, *lint_level, |this| {
this.declare_bindings(
visibility_scope,
remainder_span,
&pattern,
pattern,
ArmHasGuard(false),
Some((None, initializer_span)),
);
this.expr_into_pattern(block, pattern, init)
this.expr_into_pattern(block, pattern.clone(), init)
})
}
)
);
} else {
let scope = (init_scope, source_info);
unpack!(this.in_scope(scope, lint_level, |this| {
let scope = (*init_scope, source_info);
unpack!(this.in_scope(scope, *lint_level, |this| {
this.declare_bindings(
visibility_scope,
remainder_span,
&pattern,
pattern,
ArmHasGuard(false),
None,
);
Expand Down Expand Up @@ -171,18 +167,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {

// Then, the block may have an optional trailing expression which is a “return” value
// of the block, which is stored into `destination`.
let tcx = this.hir.tcx();
let tcx = this.tcx;
let destination_ty = destination.ty(&this.local_decls, tcx).ty;
if let Some(expr) = expr {
let tail_result_is_ignored =
destination_ty.is_unit() || this.block_context.currently_ignores_tail_results();
let span = match expr {
ExprRef::Thir(expr) => expr.span,
ExprRef::Mirror(ref expr) => expr.span,
};
this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored, span });
this.block_context
.push(BlockFrame::TailExpr { tail_result_is_ignored, span: expr.span });

unpack!(block = this.into(destination, block, expr));
unpack!(block = this.expr_into_dest(destination, block, expr));
let popped = this.block_context.pop();

assert!(popped.map_or(false, |bf| bf.is_tail_expr()));
Expand All @@ -194,13 +187,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
if destination_ty.is_unit() {
// We only want to assign an implicit `()` as the return value of the block if the
// block does not diverge. (Otherwise, we may try to assign a unit to a `!`-type.)
this.cfg.push_assign_unit(block, source_info, destination, this.hir.tcx());
this.cfg.push_assign_unit(block, source_info, destination, this.tcx);
}
}
// Finally, we pop all the let scopes before exiting out from the scope of block
// itself.
for scope in let_scope_stack.into_iter().rev() {
unpack!(block = this.pop_scope((scope, source_info), block));
unpack!(block = this.pop_scope((*scope, source_info), block));
}
// Restore the original source scope.
this.source_scope = outer_source_scope;
Expand All @@ -220,7 +213,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Safety::Safe => {}
// no longer treat `unsafe fn`s as `unsafe` contexts (see RFC #2585)
Safety::FnUnsafe
if self.hir.tcx().lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, hir_id).0
if self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, hir_id).0
!= Level::Allow => {}
_ => return,
}
Expand Down
16 changes: 5 additions & 11 deletions compiler/rustc_mir_build/src/build/expr/as_constant.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,9 @@ use rustc_middle::ty::CanonicalUserTypeAnnotation;
impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Compile `expr`, yielding a compile-time constant. Assumes that
/// `expr` is a valid compile-time constant!
crate fn as_constant<M>(&mut self, expr: M) -> Constant<'tcx>
where
M: Mirror<'tcx, Output = Expr<'tcx>>,
{
let expr = self.hir.mirror(expr);
self.expr_as_constant(expr)
}

fn expr_as_constant(&mut self, expr: Expr<'tcx>) -> Constant<'tcx> {
crate fn as_constant(&mut self, expr: &Expr<'_, 'tcx>) -> Constant<'tcx> {
let this = self;
let Expr { ty, temp_lifetime: _, span, kind } = expr;
let Expr { ty, temp_lifetime: _, span, ref kind } = *expr;
match kind {
ExprKind::Scope { region_scope: _, lint_level: _, value } => this.as_constant(value),
ExprKind::Literal { literal, user_ty, const_id: _ } => {
Expand All @@ -33,7 +25,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
Constant { span, user_ty, literal }
}
ExprKind::StaticRef { literal, .. } => Constant { span, user_ty: None, literal },
ExprKind::ConstBlock { value } => Constant { span, user_ty: None, literal: value },
ExprKind::ConstBlock { value } => {
Constant { span: span, user_ty: None, literal: value }
}
_ => span_bug!(span, "expression is not a valid constant {:?}", kind),
}
}
Expand Down
69 changes: 20 additions & 49 deletions compiler/rustc_mir_build/src/build/expr/as_operand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// after the current enclosing `ExprKind::Scope` has ended, so
/// please do *not* return it from functions to avoid bad
/// miscompiles.
crate fn as_local_operand<M>(&mut self, block: BasicBlock, expr: M) -> BlockAnd<Operand<'tcx>>
where
M: Mirror<'tcx, Output = Expr<'tcx>>,
{
crate fn as_local_operand(
&mut self,
block: BasicBlock,
expr: &Expr<'_, 'tcx>,
) -> BlockAnd<Operand<'tcx>> {
let local_scope = self.local_scope();
self.as_operand(block, Some(local_scope), expr)
}
Expand Down Expand Up @@ -70,14 +71,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// value to the stack.
///
/// See #68034 for more details.
crate fn as_local_call_operand<M>(
crate fn as_local_call_operand(
&mut self,
block: BasicBlock,
expr: M,
) -> BlockAnd<Operand<'tcx>>
where
M: Mirror<'tcx, Output = Expr<'tcx>>,
{
expr: &Expr<'_, 'tcx>,
) -> BlockAnd<Operand<'tcx>> {
let local_scope = self.local_scope();
self.as_call_operand(block, Some(local_scope), expr)
}
Expand All @@ -88,41 +86,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
/// this time.
///
/// The operand is known to be live until the end of `scope`.
crate fn as_operand<M>(
&mut self,
block: BasicBlock,
scope: Option<region::Scope>,
expr: M,
) -> BlockAnd<Operand<'tcx>>
where
M: Mirror<'tcx, Output = Expr<'tcx>>,
{
let expr = self.hir.mirror(expr);
self.expr_as_operand(block, scope, expr)
}

///
/// Like `as_local_call_operand`, except that the argument will
/// not be valid once `scope` ends.
fn as_call_operand<M>(
&mut self,
block: BasicBlock,
scope: Option<region::Scope>,
expr: M,
) -> BlockAnd<Operand<'tcx>>
where
M: Mirror<'tcx, Output = Expr<'tcx>>,
{
let expr = self.hir.mirror(expr);
self.expr_as_call_operand(block, scope, expr)
}

fn expr_as_operand(
crate fn as_operand(
&mut self,
mut block: BasicBlock,
scope: Option<region::Scope>,
expr: Expr<'tcx>,
expr: &Expr<'_, 'tcx>,
) -> BlockAnd<Operand<'tcx>> {
debug!("expr_as_operand(block={:?}, expr={:?})", block, expr);
debug!("as_operand(block={:?}, expr={:?})", block, expr);
let this = self;

if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
Expand All @@ -133,7 +106,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}

let category = Category::of(&expr.kind).unwrap();
debug!("expr_as_operand: category={:?} for={:?}", category, expr.kind);
debug!("as_operand: category={:?} for={:?}", category, expr.kind);
match category {
Category::Constant => {
let constant = this.as_constant(expr);
Expand All @@ -146,13 +119,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}

fn expr_as_call_operand(
crate fn as_call_operand(
&mut self,
mut block: BasicBlock,
scope: Option<region::Scope>,
expr: Expr<'tcx>,
expr: &Expr<'_, 'tcx>,
) -> BlockAnd<Operand<'tcx>> {
debug!("expr_as_call_operand(block={:?}, expr={:?})", block, expr);
debug!("as_call_operand(block={:?}, expr={:?})", block, expr);
let this = self;

if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
Expand All @@ -163,22 +136,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
});
}

let tcx = this.hir.tcx();
let tcx = this.tcx;

if tcx.features().unsized_fn_params {
let ty = expr.ty;
let span = expr.span;
let param_env = this.hir.param_env;
let param_env = this.param_env;

if !ty.is_sized(tcx.at(span), param_env) {
// !sized means !copy, so this is an unsized move
assert!(!ty.is_copy_modulo_regions(tcx.at(span), param_env));

// As described above, detect the case where we are passing a value of unsized
// type, and that value is coming from the deref of a box.
if let ExprKind::Deref { ref arg } = expr.kind {
let arg = this.hir.mirror(arg.clone());

if let ExprKind::Deref { arg } = expr.kind {
// Generate let tmp0 = arg0
let operand = unpack!(block = this.as_temp(block, scope, arg, Mutability::Mut));

Expand All @@ -193,6 +164,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
}

this.expr_as_operand(block, scope, expr)
this.as_operand(block, scope, expr)
}
}
Loading