1
Fork 0

Make arena allocation for the THIR work

This commit is contained in:
LeSeulArtichaut 2021-03-05 21:56:02 +01:00
parent a9f4dfc8fa
commit c2c4322891
17 changed files with 530 additions and 387 deletions

View file

@ -12,7 +12,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut self, &mut self,
destination: Place<'tcx>, destination: Place<'tcx>,
block: BasicBlock, block: BasicBlock,
ast_block: &Block<'tcx>, ast_block: &Block<'_, 'tcx>,
source_info: SourceInfo, source_info: SourceInfo,
) -> BlockAnd<()> { ) -> BlockAnd<()> {
let Block { let Block {
@ -56,8 +56,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
destination: Place<'tcx>, destination: Place<'tcx>,
mut block: BasicBlock, mut block: BasicBlock,
span: Span, span: Span,
stmts: &[Stmt<'tcx>], stmts: &[Stmt<'_, 'tcx>],
expr: Option<&Expr<'tcx>>, expr: Option<&Expr<'_, 'tcx>>,
safety_mode: BlockSafety, safety_mode: BlockSafety,
) -> BlockAnd<()> { ) -> BlockAnd<()> {
let this = self; let this = self;

View file

@ -8,7 +8,7 @@ use rustc_middle::ty::CanonicalUserTypeAnnotation;
impl<'a, 'tcx> Builder<'a, 'tcx> { impl<'a, 'tcx> Builder<'a, 'tcx> {
/// Compile `expr`, yielding a compile-time constant. Assumes that /// Compile `expr`, yielding a compile-time constant. Assumes that
/// `expr` is a valid compile-time constant! /// `expr` is a valid compile-time constant!
crate fn as_constant(&mut self, expr: &Expr<'tcx>) -> Constant<'tcx> { crate fn as_constant(&mut self, expr: &Expr<'_, 'tcx>) -> Constant<'tcx> {
let this = self; let this = self;
let Expr { ty, temp_lifetime: _, span, kind } = expr; let Expr { ty, temp_lifetime: _, span, kind } = expr;
match kind { match kind {

View file

@ -17,7 +17,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
crate fn as_local_operand( crate fn as_local_operand(
&mut self, &mut self,
block: BasicBlock, block: BasicBlock,
expr: &Expr<'tcx>, expr: &Expr<'_, 'tcx>,
) -> BlockAnd<Operand<'tcx>> { ) -> BlockAnd<Operand<'tcx>> {
let local_scope = self.local_scope(); let local_scope = self.local_scope();
self.as_operand(block, Some(local_scope), expr) self.as_operand(block, Some(local_scope), expr)
@ -74,7 +74,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
crate fn as_local_call_operand( crate fn as_local_call_operand(
&mut self, &mut self,
block: BasicBlock, block: BasicBlock,
expr: &Expr<'tcx>, expr: &Expr<'_, 'tcx>,
) -> BlockAnd<Operand<'tcx>> { ) -> BlockAnd<Operand<'tcx>> {
let local_scope = self.local_scope(); let local_scope = self.local_scope();
self.as_call_operand(block, Some(local_scope), expr) self.as_call_operand(block, Some(local_scope), expr)
@ -93,7 +93,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut self, &mut self,
mut block: BasicBlock, mut block: BasicBlock,
scope: Option<region::Scope>, scope: Option<region::Scope>,
expr: &Expr<'tcx>, expr: &Expr<'_, 'tcx>,
) -> BlockAnd<Operand<'tcx>> { ) -> BlockAnd<Operand<'tcx>> {
debug!("as_operand(block={:?}, expr={:?})", block, expr); debug!("as_operand(block={:?}, expr={:?})", block, expr);
let this = self; let this = self;
@ -123,7 +123,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut self, &mut self,
mut block: BasicBlock, mut block: BasicBlock,
scope: Option<region::Scope>, scope: Option<region::Scope>,
expr: &Expr<'tcx>, expr: &Expr<'_, 'tcx>,
) -> BlockAnd<Operand<'tcx>> { ) -> BlockAnd<Operand<'tcx>> {
debug!("as_call_operand(block={:?}, expr={:?})", block, expr); debug!("as_call_operand(block={:?}, expr={:?})", block, expr);
let this = self; let this = self;

View file

@ -350,7 +350,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
crate fn as_place( crate fn as_place(
&mut self, &mut self,
mut block: BasicBlock, mut block: BasicBlock,
expr: &Expr<'tcx>, expr: &Expr<'_, 'tcx>,
) -> BlockAnd<Place<'tcx>> { ) -> BlockAnd<Place<'tcx>> {
let place_builder = unpack!(block = self.as_place_builder(block, expr)); let place_builder = unpack!(block = self.as_place_builder(block, expr));
block.and(place_builder.into_place(self.tcx, self.typeck_results)) block.and(place_builder.into_place(self.tcx, self.typeck_results))
@ -361,7 +361,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
crate fn as_place_builder( crate fn as_place_builder(
&mut self, &mut self,
block: BasicBlock, block: BasicBlock,
expr: &Expr<'tcx>, expr: &Expr<'_, 'tcx>,
) -> BlockAnd<PlaceBuilder<'tcx>> { ) -> BlockAnd<PlaceBuilder<'tcx>> {
self.expr_as_place(block, expr, Mutability::Mut, None) self.expr_as_place(block, expr, Mutability::Mut, None)
} }
@ -374,7 +374,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
crate fn as_read_only_place( crate fn as_read_only_place(
&mut self, &mut self,
mut block: BasicBlock, mut block: BasicBlock,
expr: &Expr<'tcx>, expr: &Expr<'_, 'tcx>,
) -> BlockAnd<Place<'tcx>> { ) -> BlockAnd<Place<'tcx>> {
let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr)); let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr));
block.and(place_builder.into_place(self.tcx, self.typeck_results)) block.and(place_builder.into_place(self.tcx, self.typeck_results))
@ -389,7 +389,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
fn as_read_only_place_builder( fn as_read_only_place_builder(
&mut self, &mut self,
block: BasicBlock, block: BasicBlock,
expr: &Expr<'tcx>, expr: &Expr<'_, 'tcx>,
) -> BlockAnd<PlaceBuilder<'tcx>> { ) -> BlockAnd<PlaceBuilder<'tcx>> {
self.expr_as_place(block, expr, Mutability::Not, None) self.expr_as_place(block, expr, Mutability::Not, None)
} }
@ -397,7 +397,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
fn expr_as_place( fn expr_as_place(
&mut self, &mut self,
mut block: BasicBlock, mut block: BasicBlock,
expr: &Expr<'tcx>, expr: &Expr<'_, 'tcx>,
mutability: Mutability, mutability: Mutability,
fake_borrow_temps: Option<&mut Vec<Local>>, fake_borrow_temps: Option<&mut Vec<Local>>,
) -> BlockAnd<PlaceBuilder<'tcx>> { ) -> BlockAnd<PlaceBuilder<'tcx>> {
@ -584,8 +584,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
fn lower_index_expression( fn lower_index_expression(
&mut self, &mut self,
mut block: BasicBlock, mut block: BasicBlock,
base: &Expr<'tcx>, base: &Expr<'_, 'tcx>,
index: &Expr<'tcx>, index: &Expr<'_, 'tcx>,
mutability: Mutability, mutability: Mutability,
fake_borrow_temps: Option<&mut Vec<Local>>, fake_borrow_temps: Option<&mut Vec<Local>>,
temp_lifetime: Option<region::Scope>, temp_lifetime: Option<region::Scope>,

View file

@ -22,7 +22,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
crate fn as_local_rvalue( crate fn as_local_rvalue(
&mut self, &mut self,
block: BasicBlock, block: BasicBlock,
expr: &Expr<'tcx>, expr: &Expr<'_, 'tcx>,
) -> BlockAnd<Rvalue<'tcx>> { ) -> BlockAnd<Rvalue<'tcx>> {
let local_scope = self.local_scope(); let local_scope = self.local_scope();
self.as_rvalue(block, Some(local_scope), expr) self.as_rvalue(block, Some(local_scope), expr)
@ -33,7 +33,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut self, &mut self,
mut block: BasicBlock, mut block: BasicBlock,
scope: Option<region::Scope>, scope: Option<region::Scope>,
expr: &Expr<'tcx>, expr: &Expr<'_, 'tcx>,
) -> BlockAnd<Rvalue<'tcx>> { ) -> BlockAnd<Rvalue<'tcx>> {
debug!("expr_as_rvalue(block={:?}, scope={:?}, expr={:?})", block, scope, expr); debug!("expr_as_rvalue(block={:?}, scope={:?}, expr={:?})", block, scope, expr);
@ -368,7 +368,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
upvar_ty: Ty<'tcx>, upvar_ty: Ty<'tcx>,
temp_lifetime: Option<region::Scope>, temp_lifetime: Option<region::Scope>,
mut block: BasicBlock, mut block: BasicBlock,
arg: &Expr<'tcx>, arg: &Expr<'_, 'tcx>,
) -> BlockAnd<Operand<'tcx>> { ) -> BlockAnd<Operand<'tcx>> {
let this = self; let this = self;

View file

@ -14,7 +14,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut self, &mut self,
block: BasicBlock, block: BasicBlock,
temp_lifetime: Option<region::Scope>, temp_lifetime: Option<region::Scope>,
expr: &Expr<'tcx>, expr: &Expr<'_, 'tcx>,
mutability: Mutability, mutability: Mutability,
) -> BlockAnd<Local> { ) -> BlockAnd<Local> {
// this is the only place in mir building that we need to truly need to worry about // this is the only place in mir building that we need to truly need to worry about
@ -27,7 +27,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut self, &mut self,
mut block: BasicBlock, mut block: BasicBlock,
temp_lifetime: Option<region::Scope>, temp_lifetime: Option<region::Scope>,
expr: &Expr<'tcx>, expr: &Expr<'_, 'tcx>,
mutability: Mutability, mutability: Mutability,
) -> BlockAnd<Local> { ) -> BlockAnd<Local> {
debug!( debug!(

View file

@ -31,7 +31,7 @@ crate enum RvalueFunc {
/// Determines the category for a given expression. Note that scope /// Determines the category for a given expression. Note that scope
/// and paren expressions have no category. /// and paren expressions have no category.
impl Category { impl Category {
crate fn of(ek: &ExprKind<'_>) -> Option<Category> { crate fn of(ek: &ExprKind<'_, '_>) -> Option<Category> {
match *ek { match *ek {
ExprKind::Scope { .. } => None, ExprKind::Scope { .. } => None,

View file

@ -18,7 +18,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut self, &mut self,
destination: Place<'tcx>, destination: Place<'tcx>,
mut block: BasicBlock, mut block: BasicBlock,
expr: &Expr<'tcx>, expr: &Expr<'_, 'tcx>,
) -> BlockAnd<()> { ) -> BlockAnd<()> {
debug!("expr_into_dest(destination={:?}, block={:?}, expr={:?})", destination, block, expr); debug!("expr_into_dest(destination={:?}, block={:?}, expr={:?})", destination, block, expr);

View file

@ -13,7 +13,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
crate fn stmt_expr( crate fn stmt_expr(
&mut self, &mut self,
mut block: BasicBlock, mut block: BasicBlock,
expr: &Expr<'tcx>, expr: &Expr<'_, 'tcx>,
statement_scope: Option<region::Scope>, statement_scope: Option<region::Scope>,
) -> BlockAnd<()> { ) -> BlockAnd<()> {
let this = self; let this = self;

View file

@ -89,8 +89,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
destination: Place<'tcx>, destination: Place<'tcx>,
span: Span, span: Span,
mut block: BasicBlock, mut block: BasicBlock,
scrutinee: &Expr<'tcx>, scrutinee: &Expr<'_, 'tcx>,
arms: &[Arm<'tcx>], arms: &[Arm<'_, 'tcx>],
) -> BlockAnd<()> { ) -> BlockAnd<()> {
let scrutinee_span = scrutinee.span; let scrutinee_span = scrutinee.span;
let scrutinee_place = let scrutinee_place =
@ -119,7 +119,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
fn lower_scrutinee( fn lower_scrutinee(
&mut self, &mut self,
mut block: BasicBlock, mut block: BasicBlock,
scrutinee: &Expr<'tcx>, scrutinee: &Expr<'_, 'tcx>,
scrutinee_span: Span, scrutinee_span: Span,
) -> BlockAnd<Place<'tcx>> { ) -> BlockAnd<Place<'tcx>> {
let scrutinee_place = unpack!(block = self.as_place(block, scrutinee)); let scrutinee_place = unpack!(block = self.as_place(block, scrutinee));
@ -149,8 +149,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
fn create_match_candidates<'pat>( fn create_match_candidates<'pat>(
&mut self, &mut self,
scrutinee: Place<'tcx>, scrutinee: Place<'tcx>,
arms: &'pat [Arm<'tcx>], arms: &'pat [Arm<'pat, 'tcx>],
) -> Vec<(&'pat Arm<'tcx>, Candidate<'pat, 'tcx>)> { ) -> Vec<(&'pat Arm<'pat, 'tcx>, Candidate<'pat, 'tcx>)> {
// Assemble a list of candidates: there is one candidate per pattern, // Assemble a list of candidates: there is one candidate per pattern,
// which means there may be more than one candidate *per arm*. // which means there may be more than one candidate *per arm*.
arms.iter() arms.iter()
@ -224,7 +224,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
destination: Place<'tcx>, destination: Place<'tcx>,
scrutinee_place: Place<'tcx>, scrutinee_place: Place<'tcx>,
scrutinee_span: Span, scrutinee_span: Span,
arm_candidates: Vec<(&'_ Arm<'tcx>, Candidate<'_, 'tcx>)>, arm_candidates: Vec<(&'_ Arm<'_, 'tcx>, Candidate<'_, 'tcx>)>,
outer_source_info: SourceInfo, outer_source_info: SourceInfo,
fake_borrow_temps: Vec<(Place<'tcx>, Local)>, fake_borrow_temps: Vec<(Place<'tcx>, Local)>,
) -> BlockAnd<()> { ) -> BlockAnd<()> {
@ -285,7 +285,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut self, &mut self,
outer_source_info: SourceInfo, outer_source_info: SourceInfo,
candidate: Candidate<'_, 'tcx>, candidate: Candidate<'_, 'tcx>,
guard: Option<&Guard<'tcx>>, guard: Option<&Guard<'_, 'tcx>>,
fake_borrow_temps: &Vec<(Place<'tcx>, Local)>, fake_borrow_temps: &Vec<(Place<'tcx>, Local)>,
scrutinee_span: Span, scrutinee_span: Span,
arm_span: Option<Span>, arm_span: Option<Span>,
@ -361,7 +361,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut self, &mut self,
mut block: BasicBlock, mut block: BasicBlock,
irrefutable_pat: Pat<'tcx>, irrefutable_pat: Pat<'tcx>,
initializer: &Expr<'tcx>, initializer: &Expr<'_, 'tcx>,
) -> BlockAnd<()> { ) -> BlockAnd<()> {
match *irrefutable_pat.kind { match *irrefutable_pat.kind {
// Optimize the case of `let x = ...` to write directly into `x` // Optimize the case of `let x = ...` to write directly into `x`
@ -1612,7 +1612,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
&mut self, &mut self,
candidate: Candidate<'pat, 'tcx>, candidate: Candidate<'pat, 'tcx>,
parent_bindings: &[(Vec<Binding<'tcx>>, Vec<Ascription<'tcx>>)], parent_bindings: &[(Vec<Binding<'tcx>>, Vec<Ascription<'tcx>>)],
guard: Option<&Guard<'tcx>>, guard: Option<&Guard<'_, 'tcx>>,
fake_borrows: &Vec<(Place<'tcx>, Local)>, fake_borrows: &Vec<(Place<'tcx>, Local)>,
scrutinee_span: Span, scrutinee_span: Span,
arm_span: Option<Span>, arm_span: Option<Span>,

View file

@ -1,7 +1,7 @@
use crate::build; use crate::build;
use crate::build::scope::DropKind; use crate::build::scope::DropKind;
use crate::thir::cx::Cx; use crate::thir::cx::build_thir;
use crate::thir::{BindingMode, Expr, LintLevel, Pat, PatKind}; use crate::thir::{Arena, BindingMode, Expr, LintLevel, Pat, PatKind};
use rustc_attr::{self as attr, UnwindAttr}; use rustc_attr::{self as attr, UnwindAttr};
use rustc_errors::ErrorReported; use rustc_errors::ErrorReported;
use rustc_hir as hir; use rustc_hir as hir;
@ -43,6 +43,7 @@ crate fn mir_built<'tcx>(
fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> { fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_> {
let id = tcx.hir().local_def_id_to_hir_id(def.did); let id = tcx.hir().local_def_id_to_hir_id(def.did);
let body_owner_kind = tcx.hir().body_owner_kind(id); let body_owner_kind = tcx.hir().body_owner_kind(id);
let typeck_results = tcx.typeck_opt_const_arg(def);
// Figure out what primary body this item has. // Figure out what primary body this item has.
let (body_id, return_ty_span, span_with_body) = match tcx.hir().get(id) { let (body_id, return_ty_span, span_with_body) = match tcx.hir().get(id) {
@ -87,15 +88,15 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
// If we don't have a specialized span for the body, just use the // If we don't have a specialized span for the body, just use the
// normal def span. // normal def span.
let span_with_body = span_with_body.unwrap_or_else(|| tcx.hir().span(id)); let span_with_body = span_with_body.unwrap_or_else(|| tcx.hir().span(id));
let arena = Arena::default();
tcx.infer_ctxt().enter(|infcx| { tcx.infer_ctxt().enter(|infcx| {
let mut cx = Cx::new(tcx, def); let body = if let Some(ErrorReported) = typeck_results.tainted_by_errors {
let body = if let Some(ErrorReported) = cx.typeck_results.tainted_by_errors {
build::construct_error(&infcx, def, id, body_id, body_owner_kind) build::construct_error(&infcx, def, id, body_id, body_owner_kind)
} else if body_owner_kind.is_fn_or_closure() { } else if body_owner_kind.is_fn_or_closure() {
// fetch the fully liberated fn signature (that is, all bound // fetch the fully liberated fn signature (that is, all bound
// types/lifetimes replaced) // types/lifetimes replaced)
let fn_sig = cx.typeck_results.liberated_fn_sigs()[id]; let fn_sig = typeck_results.liberated_fn_sigs()[id];
let fn_def_id = tcx.hir().local_def_id(id); let fn_def_id = tcx.hir().local_def_id(id);
let safety = match fn_sig.unsafety { let safety = match fn_sig.unsafety {
@ -104,7 +105,7 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
}; };
let body = tcx.hir().body(body_id); let body = tcx.hir().body(body_id);
let expr = cx.mirror_expr(&body.value); let thir = build_thir(tcx, def, &arena, &body.value);
let ty = tcx.type_of(fn_def_id); let ty = tcx.type_of(fn_def_id);
let mut abi = fn_sig.abi; let mut abi = fn_sig.abi;
let implicit_argument = match ty.kind() { let implicit_argument = match ty.kind() {
@ -189,7 +190,7 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
return_ty, return_ty,
return_ty_span, return_ty_span,
body, body,
expr, thir,
span_with_body, span_with_body,
); );
if yield_ty.is_some() { if yield_ty.is_some() {
@ -209,12 +210,12 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
// place to be the type of the constant because NLL typeck will // place to be the type of the constant because NLL typeck will
// equate them. // equate them.
let return_ty = cx.typeck_results.node_type(id); let return_ty = typeck_results.node_type(id);
let ast_expr = &tcx.hir().body(body_id).value; let ast_expr = &tcx.hir().body(body_id).value;
let expr = cx.mirror_expr(ast_expr); let thir = build_thir(tcx, def, &arena, ast_expr);
build::construct_const(&infcx, expr, def, id, return_ty, return_ty_span) build::construct_const(&infcx, thir, def, id, return_ty, return_ty_span)
}; };
lints::check(tcx, &body); lints::check(tcx, &body);
@ -601,7 +602,7 @@ fn construct_fn<'tcx, A>(
return_ty: Ty<'tcx>, return_ty: Ty<'tcx>,
return_ty_span: Span, return_ty_span: Span,
body: &'tcx hir::Body<'tcx>, body: &'tcx hir::Body<'tcx>,
expr: Expr<'tcx>, expr: &Expr<'_, 'tcx>,
span_with_body: Span, span_with_body: Span,
) -> Body<'tcx> ) -> Body<'tcx>
where where
@ -668,7 +669,7 @@ where
fn construct_const<'a, 'tcx>( fn construct_const<'a, 'tcx>(
infcx: &'a InferCtxt<'a, 'tcx>, infcx: &'a InferCtxt<'a, 'tcx>,
expr: Expr<'tcx>, expr: &Expr<'_, 'tcx>,
def: ty::WithOptConstParam<LocalDefId>, def: ty::WithOptConstParam<LocalDefId>,
hir_id: hir::HirId, hir_id: hir::HirId,
const_ty: Ty<'tcx>, const_ty: Ty<'tcx>,
@ -825,7 +826,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
fn_def_id: DefId, fn_def_id: DefId,
arguments: &[ArgInfo<'tcx>], arguments: &[ArgInfo<'tcx>],
argument_scope: region::Scope, argument_scope: region::Scope,
expr: &Expr<'tcx>, expr: &Expr<'_, 'tcx>,
) -> BlockAnd<()> { ) -> BlockAnd<()> {
// Allocate locals for the function arguments // Allocate locals for the function arguments
for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() { for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() {

View file

@ -574,7 +574,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
crate fn break_scope( crate fn break_scope(
&mut self, &mut self,
mut block: BasicBlock, mut block: BasicBlock,
value: Option<&Expr<'tcx>>, value: Option<&Expr<'_, 'tcx>>,
target: BreakableTarget, target: BreakableTarget,
source_info: SourceInfo, source_info: SourceInfo,
) -> BlockAnd<()> { ) -> BlockAnd<()> {
@ -918,7 +918,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
crate fn test_bool( crate fn test_bool(
&mut self, &mut self,
mut block: BasicBlock, mut block: BasicBlock,
condition: &Expr<'tcx>, condition: &Expr<'_, 'tcx>,
source_info: SourceInfo, source_info: SourceInfo,
) -> (BasicBlock, BasicBlock) { ) -> (BasicBlock, BasicBlock) {
let cond = unpack!(block = self.as_local_operand(block, condition)); let cond = unpack!(block = self.as_local_operand(block, condition));

View file

@ -0,0 +1,98 @@
use crate::thir::*;
macro_rules! declare_arena {
([], [$($a:tt $name:ident: $ty:ty,)*]) => {
#[derive(Default)]
pub struct Arena<'thir, 'tcx> {
pub dropless: rustc_arena::DroplessArena,
drop: rustc_arena::DropArena,
$($name: rustc_arena::arena_for_type!($a[$ty]),)*
}
pub trait ArenaAllocatable<'thir, 'tcx, T = Self>: Sized {
fn allocate_on(self, arena: &'thir Arena<'thir, 'tcx>) -> &'thir mut Self;
fn allocate_from_iter(
arena: &'thir Arena<'thir, 'tcx>,
iter: impl ::std::iter::IntoIterator<Item = Self>,
) -> &'thir mut [Self];
}
impl<'thir, 'tcx, T: Copy> ArenaAllocatable<'thir, 'tcx, ()> for T {
#[inline]
fn allocate_on(self, arena: &'thir Arena<'thir, 'tcx>) -> &'thir mut Self {
arena.dropless.alloc(self)
}
#[inline]
fn allocate_from_iter(
arena: &'thir Arena<'thir, 'tcx>,
iter: impl ::std::iter::IntoIterator<Item = Self>,
) -> &'thir mut [Self] {
arena.dropless.alloc_from_iter(iter)
}
}
$(
impl<'thir, 'tcx> ArenaAllocatable<'thir, 'tcx, $ty> for $ty {
#[inline]
fn allocate_on(self, arena: &'thir Arena<'thir, 'tcx>) -> &'thir mut Self {
if !::std::mem::needs_drop::<Self>() {
return arena.dropless.alloc(self);
}
match rustc_arena::which_arena_for_type!($a[&arena.$name]) {
::std::option::Option::<&rustc_arena::TypedArena<Self>>::Some(ty_arena) => {
ty_arena.alloc(self)
}
::std::option::Option::None => unsafe { arena.drop.alloc(self) },
}
}
#[inline]
fn allocate_from_iter(
arena: &'thir Arena<'thir, 'tcx>,
iter: impl ::std::iter::IntoIterator<Item = Self>,
) -> &'thir mut [Self] {
if !::std::mem::needs_drop::<Self>() {
return arena.dropless.alloc_from_iter(iter);
}
match rustc_arena::which_arena_for_type!($a[&arena.$name]) {
::std::option::Option::<&rustc_arena::TypedArena<Self>>::Some(ty_arena) => {
ty_arena.alloc_from_iter(iter)
}
::std::option::Option::None => unsafe { arena.drop.alloc_from_iter(iter) },
}
}
}
)*
impl<'thir, 'tcx> Arena<'thir, 'tcx> {
#[inline]
pub fn alloc<T: ArenaAllocatable<'thir, 'tcx, U>, U>(&'thir self, value: T) -> &'thir mut T {
value.allocate_on(self)
}
#[allow(dead_code)] // function is never used
#[inline]
pub fn alloc_slice<T: ::std::marker::Copy>(&'thir self, value: &[T]) -> &'thir mut [T] {
if value.is_empty() {
return &mut [];
}
self.dropless.alloc_slice(value)
}
pub fn alloc_from_iter<T: ArenaAllocatable<'thir, 'tcx, U>, U>(
&'thir self,
iter: impl ::std::iter::IntoIterator<Item = T>,
) -> &'thir mut [T] {
T::allocate_from_iter(self, iter)
}
}
}
}
declare_arena!([], [
[] arm: Arm<'thir, 'tcx>,
[] expr: Expr<'thir, 'tcx>,
[] field_expr: FieldExpr<'thir, 'tcx>,
[few] inline_asm_operand: InlineAsmOperand<'thir, 'tcx>,
[] stmt: Stmt<'thir, 'tcx>,
]);

View file

@ -7,8 +7,8 @@ use rustc_middle::ty;
use rustc_index::vec::Idx; use rustc_index::vec::Idx;
impl<'tcx> Cx<'tcx> { impl<'thir, 'tcx> Cx<'thir, 'tcx> {
crate fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> Block<'tcx> { crate fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> Block<'thir, 'tcx> {
// 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);
@ -23,7 +23,7 @@ impl<'tcx> Cx<'tcx> {
opt_destruction_scope, opt_destruction_scope,
span: block.span, span: block.span,
stmts, stmts,
expr: block.expr.as_ref().map(|expr| self.mirror_expr_boxed(expr)), expr: block.expr.as_ref().map(|expr| self.mirror_expr(expr)),
safety_mode: match block.rules { safety_mode: match block.rules {
hir::BlockCheckMode::DefaultBlock => BlockSafety::Safe, hir::BlockCheckMode::DefaultBlock => BlockSafety::Safe,
hir::BlockCheckMode::UnsafeBlock(..) => BlockSafety::ExplicitUnsafe(block.hir_id), hir::BlockCheckMode::UnsafeBlock(..) => BlockSafety::ExplicitUnsafe(block.hir_id),
@ -37,26 +37,21 @@ impl<'tcx> Cx<'tcx> {
&mut self, &mut self,
block_id: hir::ItemLocalId, block_id: hir::ItemLocalId,
stmts: &'tcx [hir::Stmt<'tcx>], stmts: &'tcx [hir::Stmt<'tcx>],
) -> Vec<Stmt<'tcx>> { ) -> &'thir [Stmt<'thir, 'tcx>] {
let mut result = vec![]; self.arena.alloc_from_iter(stmts.iter().enumerate().filter_map(|(index, stmt)| {
for (index, stmt) in stmts.iter().enumerate() {
let hir_id = stmt.hir_id; let hir_id = stmt.hir_id;
let opt_dxn_ext = self.region_scope_tree.opt_destruction_scope(hir_id.local_id); let opt_dxn_ext = self.region_scope_tree.opt_destruction_scope(hir_id.local_id);
match stmt.kind { match stmt.kind {
hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => { hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => Some(Stmt {
result.push(Stmt { kind: StmtKind::Expr {
kind: StmtKind::Expr { scope: region::Scope { id: hir_id.local_id, data: region::ScopeData::Node },
scope: region::Scope { expr: self.mirror_expr(expr),
id: hir_id.local_id, },
data: region::ScopeData::Node, opt_destruction_scope: opt_dxn_ext,
}, }),
expr: self.mirror_expr_boxed(expr),
},
opt_destruction_scope: opt_dxn_ext,
})
}
hir::StmtKind::Item(..) => { hir::StmtKind::Item(..) => {
// ignore for purposes of the MIR // ignore for purposes of the MIR
None
} }
hir::StmtKind::Local(ref local) => { hir::StmtKind::Local(ref local) => {
let remainder_scope = region::Scope { let remainder_scope = region::Scope {
@ -86,7 +81,7 @@ impl<'tcx> Cx<'tcx> {
} }
} }
result.push(Stmt { Some(Stmt {
kind: StmtKind::Let { kind: StmtKind::Let {
remainder_scope, remainder_scope,
init_scope: region::Scope { init_scope: region::Scope {
@ -94,14 +89,13 @@ impl<'tcx> Cx<'tcx> {
data: region::ScopeData::Node, data: region::ScopeData::Node,
}, },
pattern, pattern,
initializer: local.init.map(|init| self.mirror_expr_boxed(init)), initializer: local.init.map(|init| self.mirror_expr(init)),
lint_level: LintLevel::Explicit(local.hir_id), lint_level: LintLevel::Explicit(local.hir_id),
}, },
opt_destruction_scope: opt_dxn_ext, opt_destruction_scope: opt_dxn_ext,
}); })
} }
} }
} }))
result
} }
} }

View file

@ -15,8 +15,33 @@ use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
use rustc_middle::ty::{self, AdtKind, Ty}; use rustc_middle::ty::{self, AdtKind, Ty};
use rustc_span::Span; use rustc_span::Span;
impl<'tcx> Cx<'tcx> { use std::iter;
crate fn mirror_expr(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> {
impl<'thir, 'tcx> Cx<'thir, 'tcx> {
/// Mirrors and allocates a single [`hir::Expr`]. If you need to mirror a whole slice
/// of expressions, prefer using [`mirror_exprs`].
///
/// [`mirror_exprs`]: Self::mirror_exprs
crate fn mirror_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> &'thir Expr<'thir, 'tcx> {
self.arena.alloc(self.mirror_expr_inner(expr))
}
/// Mirrors and allocates a slice of [`hir::Expr`]s. They will be allocated as a
/// contiguous sequence in memory.
crate fn mirror_exprs(&mut self, exprs: &'tcx [hir::Expr<'tcx>]) -> &'thir [Expr<'thir, 'tcx>] {
self.arena.alloc_from_iter(exprs.iter().map(|expr| self.mirror_expr_inner(expr)))
}
/// Mirrors a [`hir::Expr`] without allocating it into the arena.
/// This is a separate, private function so that [`mirror_expr`] and [`mirror_exprs`] can
/// decide how to allocate this expression (alone or within a slice).
///
/// [`mirror_expr`]: Self::mirror_expr
/// [`mirror_exprs`]: Self::mirror_exprs
pub(super) fn mirror_expr_inner(
&mut self,
hir_expr: &'tcx hir::Expr<'tcx>,
) -> Expr<'thir, 'tcx> {
let temp_lifetime = self.region_scope_tree.temporary_scope(hir_expr.hir_id.local_id); let temp_lifetime = self.region_scope_tree.temporary_scope(hir_expr.hir_id.local_id);
let expr_scope = let expr_scope =
region::Scope { id: hir_expr.hir_id.local_id, data: region::ScopeData::Node }; region::Scope { id: hir_expr.hir_id.local_id, data: region::ScopeData::Node };
@ -38,7 +63,7 @@ impl<'tcx> Cx<'tcx> {
span: hir_expr.span, span: hir_expr.span,
kind: ExprKind::Scope { kind: ExprKind::Scope {
region_scope: expr_scope, region_scope: expr_scope,
value: Box::new(expr), value: self.arena.alloc(expr),
lint_level: LintLevel::Explicit(hir_expr.hir_id), lint_level: LintLevel::Explicit(hir_expr.hir_id),
}, },
}; };
@ -53,7 +78,7 @@ impl<'tcx> Cx<'tcx> {
span: hir_expr.span, span: hir_expr.span,
kind: ExprKind::Scope { kind: ExprKind::Scope {
region_scope, region_scope,
value: Box::new(expr), value: self.arena.alloc(expr),
lint_level: LintLevel::Inherited, lint_level: LintLevel::Inherited,
}, },
}; };
@ -63,20 +88,12 @@ impl<'tcx> Cx<'tcx> {
expr expr
} }
crate fn mirror_exprs(&mut self, exprs: &'tcx [hir::Expr<'tcx>]) -> Vec<Expr<'tcx>> {
exprs.iter().map(|expr| self.mirror_expr(expr)).collect()
}
crate fn mirror_expr_boxed(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Box<Expr<'tcx>> {
Box::new(self.mirror_expr(expr))
}
fn apply_adjustment( fn apply_adjustment(
&mut self, &mut self,
hir_expr: &'tcx hir::Expr<'tcx>, hir_expr: &'tcx hir::Expr<'tcx>,
mut expr: Expr<'tcx>, mut expr: Expr<'thir, 'tcx>,
adjustment: &Adjustment<'tcx>, adjustment: &Adjustment<'tcx>,
) -> Expr<'tcx> { ) -> Expr<'thir, 'tcx> {
let Expr { temp_lifetime, mut span, .. } = expr; let Expr { temp_lifetime, mut span, .. } = expr;
// Adjust the span from the block, to the last expression of the // Adjust the span from the block, to the last expression of the
@ -89,7 +106,7 @@ impl<'tcx> Cx<'tcx> {
// x // x
// // ^ 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<'thir, 'tcx>| {
if let ExprKind::Block { body } = &expr.kind { if let ExprKind::Block { body } = &expr.kind {
if let Some(ref last_expr) = body.expr { if let Some(ref last_expr) = body.expr {
span = last_expr.span; span = last_expr.span;
@ -101,13 +118,13 @@ impl<'tcx> Cx<'tcx> {
let kind = match adjustment.kind { let kind = match adjustment.kind {
Adjust::Pointer(PointerCast::Unsize) => { Adjust::Pointer(PointerCast::Unsize) => {
adjust_span(&mut expr); adjust_span(&mut expr);
ExprKind::Pointer { cast: PointerCast::Unsize, source: Box::new(expr) } ExprKind::Pointer { cast: PointerCast::Unsize, source: self.arena.alloc(expr) }
} }
Adjust::Pointer(cast) => ExprKind::Pointer { cast, source: Box::new(expr) }, Adjust::Pointer(cast) => ExprKind::Pointer { cast, source: self.arena.alloc(expr) },
Adjust::NeverToAny => ExprKind::NeverToAny { source: Box::new(expr) }, Adjust::NeverToAny => ExprKind::NeverToAny { source: self.arena.alloc(expr) },
Adjust::Deref(None) => { Adjust::Deref(None) => {
adjust_span(&mut expr); adjust_span(&mut expr);
ExprKind::Deref { arg: Box::new(expr) } ExprKind::Deref { arg: self.arena.alloc(expr) }
} }
Adjust::Deref(Some(deref)) => { Adjust::Deref(Some(deref)) => {
// We don't need to do call adjust_span here since // We don't need to do call adjust_span here since
@ -122,7 +139,7 @@ impl<'tcx> Cx<'tcx> {
span, span,
kind: ExprKind::Borrow { kind: ExprKind::Borrow {
borrow_kind: deref.mutbl.to_borrow_kind(), borrow_kind: deref.mutbl.to_borrow_kind(),
arg: Box::new(expr), arg: self.arena.alloc(expr),
}, },
}; };
@ -130,22 +147,22 @@ impl<'tcx> Cx<'tcx> {
hir_expr, hir_expr,
adjustment.target, adjustment.target,
Some(call), Some(call),
vec![expr], self.arena.alloc_from_iter(iter::once(expr)),
deref.span, deref.span,
) )
} }
Adjust::Borrow(AutoBorrow::Ref(_, m)) => { Adjust::Borrow(AutoBorrow::Ref(_, m)) => {
ExprKind::Borrow { borrow_kind: m.to_borrow_kind(), arg: Box::new(expr) } ExprKind::Borrow { borrow_kind: m.to_borrow_kind(), arg: self.arena.alloc(expr) }
} }
Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => { Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
ExprKind::AddressOf { mutability, arg: Box::new(expr) } ExprKind::AddressOf { mutability, arg: self.arena.alloc(expr) }
} }
}; };
Expr { temp_lifetime, ty: adjustment.target, span, kind } Expr { temp_lifetime, ty: adjustment.target, span, kind }
} }
fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> { fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'thir, 'tcx> {
let expr_ty = self.typeck_results().expr_ty(expr); let expr_ty = self.typeck_results().expr_ty(expr);
let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
@ -157,7 +174,7 @@ impl<'tcx> Cx<'tcx> {
let args = self.mirror_exprs(args); let args = self.mirror_exprs(args);
ExprKind::Call { ExprKind::Call {
ty: expr.ty, ty: expr.ty,
fun: Box::new(expr), fun: self.arena.alloc(expr),
args, args,
from_hir_call: true, from_hir_call: true,
fn_span, fn_span,
@ -185,8 +202,10 @@ impl<'tcx> Cx<'tcx> {
ExprKind::Call { ExprKind::Call {
ty: method.ty, ty: method.ty,
fun: Box::new(method), fun: self.arena.alloc(method),
args: vec![self.mirror_expr(fun), tupled_args], args: &*self
.arena
.alloc_from_iter(vec![self.mirror_expr_inner(fun), tupled_args]),
from_hir_call: true, from_hir_call: true,
fn_span: expr.span, fn_span: expr.span,
} }
@ -216,26 +235,22 @@ impl<'tcx> Cx<'tcx> {
}); });
debug!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty); debug!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty);
let field_refs = args let field_refs =
.iter() self.arena.alloc_from_iter(args.iter().enumerate().map(|(idx, e)| {
.enumerate() FieldExpr { name: Field::new(idx), expr: self.mirror_expr(e) }
.map(|(idx, e)| FieldExpr { }));
name: Field::new(idx),
expr: self.mirror_expr(e),
})
.collect();
ExprKind::Adt { ExprKind::Adt {
adt_def, adt_def,
substs, substs,
variant_index: index, variant_index: index,
fields: field_refs, fields: &*field_refs,
user_ty, user_ty,
base: None, base: None,
} }
} else { } else {
ExprKind::Call { ExprKind::Call {
ty: self.typeck_results().node_type(fun.hir_id), ty: self.typeck_results().node_type(fun.hir_id),
fun: self.mirror_expr_boxed(fun), fun: self.mirror_expr(fun),
args: self.mirror_exprs(args), args: self.mirror_exprs(args),
from_hir_call: true, from_hir_call: true,
fn_span: expr.span, fn_span: expr.span,
@ -244,32 +259,30 @@ impl<'tcx> Cx<'tcx> {
} }
} }
hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, ref arg) => ExprKind::Borrow { hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, ref arg) => {
borrow_kind: mutbl.to_borrow_kind(), ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg: self.mirror_expr(arg) }
arg: self.mirror_expr_boxed(arg), }
},
hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => { hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => {
ExprKind::AddressOf { mutability, arg: self.mirror_expr_boxed(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 { body: self.mirror_block(blk) },
hir::ExprKind::Assign(ref lhs, ref rhs, _) => ExprKind::Assign { hir::ExprKind::Assign(ref lhs, ref rhs, _) => {
lhs: self.mirror_expr_boxed(lhs), ExprKind::Assign { lhs: self.mirror_expr(lhs), rhs: self.mirror_expr(rhs) }
rhs: self.mirror_expr_boxed(rhs), }
},
hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => { hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => {
if self.typeck_results().is_method_call(expr) { if self.typeck_results().is_method_call(expr) {
let lhs = self.mirror_expr(lhs); let lhs = self.mirror_expr_inner(lhs);
let rhs = self.mirror_expr(rhs); let rhs = self.mirror_expr_inner(rhs);
self.overloaded_operator(expr, vec![lhs, rhs]) self.overloaded_operator(expr, &*self.arena.alloc_from_iter(vec![lhs, rhs]))
} else { } else {
ExprKind::AssignOp { ExprKind::AssignOp {
op: bin_op(op.node), op: bin_op(op.node),
lhs: self.mirror_expr_boxed(lhs), lhs: self.mirror_expr(lhs),
rhs: self.mirror_expr_boxed(rhs), rhs: self.mirror_expr(rhs),
} }
} }
} }
@ -282,29 +295,29 @@ impl<'tcx> Cx<'tcx> {
hir::ExprKind::Binary(op, ref lhs, ref rhs) => { hir::ExprKind::Binary(op, ref lhs, ref rhs) => {
if self.typeck_results().is_method_call(expr) { if self.typeck_results().is_method_call(expr) {
let lhs = self.mirror_expr(lhs); let lhs = self.mirror_expr_inner(lhs);
let rhs = self.mirror_expr(rhs); let rhs = self.mirror_expr_inner(rhs);
self.overloaded_operator(expr, vec![lhs, rhs]) self.overloaded_operator(expr, &*self.arena.alloc_from_iter(vec![lhs, rhs]))
} else { } else {
// FIXME overflow // FIXME overflow
match op.node { match op.node {
hir::BinOpKind::And => ExprKind::LogicalOp { hir::BinOpKind::And => ExprKind::LogicalOp {
op: LogicalOp::And, op: LogicalOp::And,
lhs: self.mirror_expr_boxed(lhs), lhs: self.mirror_expr(lhs),
rhs: self.mirror_expr_boxed(rhs), rhs: self.mirror_expr(rhs),
}, },
hir::BinOpKind::Or => ExprKind::LogicalOp { hir::BinOpKind::Or => ExprKind::LogicalOp {
op: LogicalOp::Or, op: LogicalOp::Or,
lhs: self.mirror_expr_boxed(lhs), lhs: self.mirror_expr(lhs),
rhs: self.mirror_expr_boxed(rhs), rhs: self.mirror_expr(rhs),
}, },
_ => { _ => {
let op = bin_op(op.node); let op = bin_op(op.node);
ExprKind::Binary { ExprKind::Binary {
op, op,
lhs: self.mirror_expr_boxed(lhs), lhs: self.mirror_expr(lhs),
rhs: self.mirror_expr_boxed(rhs), rhs: self.mirror_expr(rhs),
} }
} }
} }
@ -313,39 +326,48 @@ impl<'tcx> Cx<'tcx> {
hir::ExprKind::Index(ref lhs, ref index) => { hir::ExprKind::Index(ref lhs, ref index) => {
if self.typeck_results().is_method_call(expr) { if self.typeck_results().is_method_call(expr) {
let lhs = self.mirror_expr(lhs); let lhs = self.mirror_expr_inner(lhs);
let index = self.mirror_expr(index); let index = self.mirror_expr_inner(index);
self.overloaded_place(expr, expr_ty, None, vec![lhs, index], expr.span) self.overloaded_place(
expr,
expr_ty,
None,
&*self.arena.alloc_from_iter(vec![lhs, index]),
expr.span,
)
} else { } else {
ExprKind::Index { ExprKind::Index { lhs: self.mirror_expr(lhs), index: self.mirror_expr(index) }
lhs: self.mirror_expr_boxed(lhs),
index: self.mirror_expr_boxed(index),
}
} }
} }
hir::ExprKind::Unary(hir::UnOp::Deref, ref arg) => { hir::ExprKind::Unary(hir::UnOp::Deref, ref arg) => {
if self.typeck_results().is_method_call(expr) { if self.typeck_results().is_method_call(expr) {
let arg = self.mirror_expr(arg); let arg = self.mirror_expr_inner(arg);
self.overloaded_place(expr, expr_ty, None, vec![arg], expr.span) self.overloaded_place(
expr,
expr_ty,
None,
&*self.arena.alloc_from_iter(iter::once(arg)),
expr.span,
)
} else { } else {
ExprKind::Deref { arg: self.mirror_expr_boxed(arg) } ExprKind::Deref { arg: self.mirror_expr(arg) }
} }
} }
hir::ExprKind::Unary(hir::UnOp::Not, ref arg) => { hir::ExprKind::Unary(hir::UnOp::Not, ref arg) => {
if self.typeck_results().is_method_call(expr) { if self.typeck_results().is_method_call(expr) {
let arg = self.mirror_expr(arg); let arg = self.mirror_expr_inner(arg);
self.overloaded_operator(expr, vec![arg]) self.overloaded_operator(expr, &*self.arena.alloc_from_iter(iter::once(arg)))
} else { } else {
ExprKind::Unary { op: UnOp::Not, arg: self.mirror_expr_boxed(arg) } ExprKind::Unary { op: UnOp::Not, arg: self.mirror_expr(arg) }
} }
} }
hir::ExprKind::Unary(hir::UnOp::Neg, ref arg) => { hir::ExprKind::Unary(hir::UnOp::Neg, ref arg) => {
if self.typeck_results().is_method_call(expr) { if self.typeck_results().is_method_call(expr) {
let arg = self.mirror_expr(arg); let arg = self.mirror_expr_inner(arg);
self.overloaded_operator(expr, vec![arg]) self.overloaded_operator(expr, &*self.arena.alloc_from_iter(iter::once(arg)))
} else if let hir::ExprKind::Lit(ref lit) = arg.kind { } else if let hir::ExprKind::Lit(ref lit) = arg.kind {
ExprKind::Literal { ExprKind::Literal {
literal: self.const_eval_literal(&lit.node, expr_ty, lit.span, true), literal: self.const_eval_literal(&lit.node, expr_ty, lit.span, true),
@ -353,7 +375,7 @@ impl<'tcx> Cx<'tcx> {
const_id: None, const_id: None,
} }
} else { } else {
ExprKind::Unary { op: UnOp::Neg, arg: self.mirror_expr_boxed(arg) } ExprKind::Unary { op: UnOp::Neg, arg: self.mirror_expr(arg) }
} }
} }
@ -370,9 +392,12 @@ impl<'tcx> Cx<'tcx> {
user_ty, user_ty,
fields: self.field_refs(fields), fields: self.field_refs(fields),
base: base.as_ref().map(|base| FruInfo { base: base.as_ref().map(|base| FruInfo {
base: self.mirror_expr_boxed(base), base: self.mirror_expr(base),
field_types: self.typeck_results().fru_field_types()[expr.hir_id] field_types: self.arena.alloc_from_iter(
.clone(), self.typeck_results().fru_field_types()[expr.hir_id]
.iter()
.cloned(),
),
}), }),
} }
} }
@ -419,12 +444,12 @@ impl<'tcx> Cx<'tcx> {
} }
}; };
let upvars = self let upvars = self.arena.alloc_from_iter(
.typeck_results self.typeck_results
.closure_min_captures_flattened(def_id) .closure_min_captures_flattened(def_id)
.zip(substs.upvar_tys()) .zip(substs.upvar_tys())
.map(|(captured_place, ty)| self.capture_upvar(expr, captured_place, ty)) .map(|(captured_place, ty)| self.capture_upvar(expr, captured_place, ty)),
.collect(); );
ExprKind::Closure { closure_id: def_id, substs, upvars, movability } ExprKind::Closure { closure_id: def_id, substs, upvars, movability }
} }
@ -435,100 +460,95 @@ impl<'tcx> Cx<'tcx> {
hir::ExprKind::InlineAsm(ref asm) => ExprKind::InlineAsm { hir::ExprKind::InlineAsm(ref asm) => ExprKind::InlineAsm {
template: asm.template, template: asm.template,
operands: asm operands: self.arena.alloc_from_iter(asm.operands.iter().map(|(op, _op_sp)| {
.operands match *op {
.iter() hir::InlineAsmOperand::In { reg, ref expr } => {
.map(|(op, _op_sp)| { InlineAsmOperand::In { reg, expr: self.mirror_expr(expr) }
match *op { }
hir::InlineAsmOperand::In { reg, ref expr } => { hir::InlineAsmOperand::Out { reg, late, ref expr } => {
InlineAsmOperand::In { reg, expr: self.mirror_expr(expr) } InlineAsmOperand::Out {
reg,
late,
expr: expr.as_ref().map(|expr| self.mirror_expr(expr)),
} }
hir::InlineAsmOperand::Out { reg, late, ref expr } => { }
InlineAsmOperand::Out { hir::InlineAsmOperand::InOut { reg, late, ref expr } => {
reg, InlineAsmOperand::InOut { reg, late, expr: self.mirror_expr(expr) }
late, }
expr: expr.as_ref().map(|expr| self.mirror_expr(expr)), hir::InlineAsmOperand::SplitInOut {
reg,
late,
ref in_expr,
ref out_expr,
} => InlineAsmOperand::SplitInOut {
reg,
late,
in_expr: self.mirror_expr(in_expr),
out_expr: out_expr.as_ref().map(|expr| self.mirror_expr(expr)),
},
hir::InlineAsmOperand::Const { ref expr } => {
InlineAsmOperand::Const { expr: self.mirror_expr(expr) }
}
hir::InlineAsmOperand::Sym { ref expr } => {
let qpath = match expr.kind {
hir::ExprKind::Path(ref qpath) => qpath,
_ => span_bug!(
expr.span,
"asm `sym` operand should be a path, found {:?}",
expr.kind
),
};
let temp_lifetime =
self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
let res = self.typeck_results().qpath_res(qpath, expr.hir_id);
let ty;
match res {
Res::Def(DefKind::Fn, _) | Res::Def(DefKind::AssocFn, _) => {
ty = self.typeck_results().node_type(expr.hir_id);
let user_ty = self.user_substs_applied_to_res(expr.hir_id, res);
InlineAsmOperand::SymFn {
expr: self.arena.alloc(Expr {
ty,
temp_lifetime,
span: expr.span,
kind: ExprKind::Literal {
literal: ty::Const::zero_sized(self.tcx, ty),
user_ty,
const_id: None,
},
}),
}
} }
}
hir::InlineAsmOperand::InOut { reg, late, ref expr } => { Res::Def(DefKind::Static, def_id) => {
InlineAsmOperand::InOut { reg, late, expr: self.mirror_expr(expr) } InlineAsmOperand::SymStatic { def_id }
} }
hir::InlineAsmOperand::SplitInOut {
reg, _ => {
late, self.tcx.sess.span_err(
ref in_expr,
ref out_expr,
} => InlineAsmOperand::SplitInOut {
reg,
late,
in_expr: self.mirror_expr(in_expr),
out_expr: out_expr.as_ref().map(|expr| self.mirror_expr(expr)),
},
hir::InlineAsmOperand::Const { ref expr } => {
InlineAsmOperand::Const { expr: self.mirror_expr(expr) }
}
hir::InlineAsmOperand::Sym { ref expr } => {
let qpath = match expr.kind {
hir::ExprKind::Path(ref qpath) => qpath,
_ => span_bug!(
expr.span, expr.span,
"asm `sym` operand should be a path, found {:?}", "asm `sym` operand must point to a fn or static",
expr.kind );
),
}; // Not a real fn, but we're not reaching codegen anyways...
let temp_lifetime = ty = self.tcx.ty_error();
self.region_scope_tree.temporary_scope(expr.hir_id.local_id); InlineAsmOperand::SymFn {
let res = self.typeck_results().qpath_res(qpath, expr.hir_id); expr: self.arena.alloc(Expr {
let ty; ty,
match res { temp_lifetime,
Res::Def(DefKind::Fn, _) | Res::Def(DefKind::AssocFn, _) => { span: expr.span,
ty = self.typeck_results().node_type(expr.hir_id); kind: ExprKind::Literal {
let user_ty = literal: ty::Const::zero_sized(self.tcx, ty),
self.user_substs_applied_to_res(expr.hir_id, res); user_ty: None,
InlineAsmOperand::SymFn { const_id: None,
expr: Expr {
ty,
temp_lifetime,
span: expr.span,
kind: ExprKind::Literal {
literal: ty::Const::zero_sized(self.tcx, ty),
user_ty,
const_id: None,
},
}, },
} }),
}
Res::Def(DefKind::Static, def_id) => {
InlineAsmOperand::SymStatic { def_id }
}
_ => {
self.tcx.sess.span_err(
expr.span,
"asm `sym` operand must point to a fn or static",
);
// Not a real fn, but we're not reaching codegen anyways...
ty = self.tcx.ty_error();
InlineAsmOperand::SymFn {
expr: Expr {
ty,
temp_lifetime,
span: expr.span,
kind: ExprKind::Literal {
literal: ty::Const::zero_sized(self.tcx, ty),
user_ty: None,
const_id: None,
},
},
}
} }
} }
} }
} }
}) }
.collect(), })),
options: asm.options, options: asm.options,
line_spans: asm.line_spans, line_spans: asm.line_spans,
}, },
@ -550,15 +570,15 @@ impl<'tcx> Cx<'tcx> {
let count_def_id = self.tcx.hir().local_def_id(count.hir_id); let count_def_id = self.tcx.hir().local_def_id(count.hir_id);
let count = ty::Const::from_anon_const(self.tcx, count_def_id); let count = ty::Const::from_anon_const(self.tcx, count_def_id);
ExprKind::Repeat { value: self.mirror_expr_boxed(v), count } ExprKind::Repeat { value: self.mirror_expr(v), count }
} }
hir::ExprKind::Ret(ref v) => { hir::ExprKind::Ret(ref v) => {
ExprKind::Return { value: v.as_ref().map(|v| self.mirror_expr_boxed(v)) } ExprKind::Return { value: v.as_ref().map(|v| self.mirror_expr(v)) }
} }
hir::ExprKind::Break(dest, ref value) => match dest.target_id { hir::ExprKind::Break(dest, ref value) => match dest.target_id {
Ok(target_id) => ExprKind::Break { Ok(target_id) => ExprKind::Break {
label: region::Scope { id: target_id.local_id, data: region::ScopeData::Node }, label: region::Scope { id: target_id.local_id, data: region::ScopeData::Node },
value: value.as_ref().map(|value| self.mirror_expr_boxed(value)), value: value.as_ref().map(|value| self.mirror_expr(value)),
}, },
Err(err) => bug!("invalid loop id for break: {}", err), Err(err) => bug!("invalid loop id for break: {}", err),
}, },
@ -569,19 +589,19 @@ impl<'tcx> Cx<'tcx> {
Err(err) => bug!("invalid loop id for continue: {}", err), Err(err) => bug!("invalid loop id for continue: {}", err),
}, },
hir::ExprKind::If(cond, then, else_opt) => ExprKind::If { hir::ExprKind::If(cond, then, else_opt) => ExprKind::If {
cond: self.mirror_expr_boxed(cond), cond: self.mirror_expr(cond),
then: self.mirror_expr_boxed(then), then: self.mirror_expr(then),
else_opt: else_opt.map(|el| self.mirror_expr_boxed(el)), else_opt: else_opt.map(|el| self.mirror_expr(el)),
}, },
hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match { hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match {
scrutinee: self.mirror_expr_boxed(discr), scrutinee: self.mirror_expr(discr),
arms: arms.iter().map(|a| self.convert_arm(a)).collect(), arms: self.arena.alloc_from_iter(arms.iter().map(|a| self.convert_arm(a))),
}, },
hir::ExprKind::Loop(ref body, ..) => { hir::ExprKind::Loop(ref body, ..) => {
let block_ty = self.typeck_results().node_type(body.hir_id); let block_ty = self.typeck_results().node_type(body.hir_id);
let temp_lifetime = self.region_scope_tree.temporary_scope(body.hir_id.local_id); let temp_lifetime = self.region_scope_tree.temporary_scope(body.hir_id.local_id);
let block = self.mirror_block(body); let block = self.mirror_block(body);
let body = Box::new(Expr { let body = self.arena.alloc(Expr {
ty: block_ty, ty: block_ty,
temp_lifetime, temp_lifetime,
span: block.span, span: block.span,
@ -590,7 +610,7 @@ impl<'tcx> Cx<'tcx> {
ExprKind::Loop { body } ExprKind::Loop { body }
} }
hir::ExprKind::Field(ref source, ..) => ExprKind::Field { hir::ExprKind::Field(ref source, ..) => ExprKind::Field {
lhs: self.mirror_expr_boxed(source), lhs: self.mirror_expr(source),
name: Field::new(self.tcx.field_index(expr.hir_id, self.typeck_results)), name: Field::new(self.tcx.field_index(expr.hir_id, self.typeck_results)),
}, },
hir::ExprKind::Cast(ref source, ref cast_ty) => { hir::ExprKind::Cast(ref source, ref cast_ty) => {
@ -607,13 +627,13 @@ impl<'tcx> Cx<'tcx> {
// using a coercion (or is a no-op). // using a coercion (or is a no-op).
let cast = if self.typeck_results().is_coercion_cast(source.hir_id) { let cast = if self.typeck_results().is_coercion_cast(source.hir_id) {
// Convert the lexpr to a vexpr. // Convert the lexpr to a vexpr.
ExprKind::Use { source: self.mirror_expr_boxed(source) } ExprKind::Use { source: self.mirror_expr(source) }
} else if self.typeck_results().expr_ty(source).is_region_ptr() { } else if self.typeck_results().expr_ty(source).is_region_ptr() {
// Special cased so that we can type check that the element // Special cased so that we can type check that the element
// type of the source matches the pointed to type of the // type of the source matches the pointed to type of the
// destination. // destination.
ExprKind::Pointer { ExprKind::Pointer {
source: self.mirror_expr_boxed(source), source: self.mirror_expr(source),
cast: PointerCast::ArrayToPointer, cast: PointerCast::ArrayToPointer,
} }
} else { } else {
@ -651,11 +671,13 @@ impl<'tcx> Cx<'tcx> {
}; };
let source = if let Some((did, offset, var_ty)) = var { let source = if let Some((did, offset, var_ty)) = var {
let mk_const = |literal| Expr { let mk_const = |literal| {
temp_lifetime, self.arena.alloc(Expr {
ty: var_ty, temp_lifetime,
span: expr.span, ty: var_ty,
kind: ExprKind::Literal { literal, user_ty: None, const_id: None }, span: expr.span,
kind: ExprKind::Literal { literal, user_ty: None, const_id: None },
})
}; };
let offset = mk_const(ty::Const::from_bits( let offset = mk_const(ty::Const::from_bits(
self.tcx, self.tcx,
@ -675,12 +697,14 @@ impl<'tcx> Cx<'tcx> {
), ),
ty: var_ty, ty: var_ty,
})); }));
let bin = ExprKind::Binary { let bin =
op: BinOp::Add, ExprKind::Binary { op: BinOp::Add, lhs: lhs, rhs: offset };
lhs: Box::new(lhs), self.arena.alloc(Expr {
rhs: Box::new(offset), temp_lifetime,
}; ty: var_ty,
Expr { temp_lifetime, ty: var_ty, span: expr.span, kind: bin } span: expr.span,
kind: bin,
})
} }
None => offset, None => offset,
} }
@ -688,14 +712,18 @@ impl<'tcx> Cx<'tcx> {
self.mirror_expr(source) self.mirror_expr(source)
}; };
ExprKind::Cast { source: Box::new(source) } ExprKind::Cast { source: source }
}; };
if let Some(user_ty) = user_ty { if let Some(user_ty) = user_ty {
// NOTE: Creating a new Expr and wrapping a Cast inside of it may be // NOTE: Creating a new Expr and wrapping a Cast inside of it may be
// inefficient, revisit this when performance becomes an issue. // inefficient, revisit this when performance becomes an issue.
let cast_expr = let cast_expr = self.arena.alloc(Expr {
Box::new(Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind: cast }); temp_lifetime,
ty: expr_ty,
span: expr.span,
kind: cast,
});
debug!("make_mirror_unadjusted: (cast) user_ty={:?}", user_ty); debug!("make_mirror_unadjusted: (cast) user_ty={:?}", user_ty);
ExprKind::ValueTypeAscription { source: cast_expr, user_ty: Some(*user_ty) } ExprKind::ValueTypeAscription { source: cast_expr, user_ty: Some(*user_ty) }
@ -707,7 +735,7 @@ impl<'tcx> Cx<'tcx> {
let user_provided_types = self.typeck_results.user_provided_types(); let user_provided_types = self.typeck_results.user_provided_types();
let user_ty = user_provided_types.get(ty.hir_id).copied(); let user_ty = user_provided_types.get(ty.hir_id).copied();
debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty); debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty);
let mirrored = self.mirror_expr_boxed(source); let mirrored = self.mirror_expr(source);
if source.is_syntactic_place_expr() { if source.is_syntactic_place_expr() {
ExprKind::PlaceTypeAscription { source: mirrored, user_ty } ExprKind::PlaceTypeAscription { source: mirrored, user_ty }
} else { } else {
@ -715,17 +743,15 @@ impl<'tcx> Cx<'tcx> {
} }
} }
hir::ExprKind::DropTemps(ref source) => { hir::ExprKind::DropTemps(ref source) => {
ExprKind::Use { source: self.mirror_expr_boxed(source) } ExprKind::Use { source: self.mirror_expr(source) }
} }
hir::ExprKind::Box(ref value) => ExprKind::Box { value: self.mirror_expr_boxed(value) }, hir::ExprKind::Box(ref value) => ExprKind::Box { value: self.mirror_expr(value) },
hir::ExprKind::Array(ref fields) => ExprKind::Array { hir::ExprKind::Array(ref fields) => {
fields: fields.iter().map(|field| self.mirror_expr(field)).collect(), ExprKind::Array { fields: self.mirror_exprs(fields) }
}, }
hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { fields: self.mirror_exprs(fields) },
fields: fields.iter().map(|field| self.mirror_expr(field)).collect(),
},
hir::ExprKind::Yield(ref v, _) => ExprKind::Yield { value: self.mirror_expr_boxed(v) }, hir::ExprKind::Yield(ref v, _) => ExprKind::Yield { value: self.mirror_expr(v) },
hir::ExprKind::Err => unreachable!(), hir::ExprKind::Err => unreachable!(),
}; };
@ -772,7 +798,7 @@ impl<'tcx> Cx<'tcx> {
expr: &hir::Expr<'_>, expr: &hir::Expr<'_>,
span: Span, span: Span,
overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>, overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
) -> Expr<'tcx> { ) -> Expr<'thir, 'tcx> {
let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
let (def_id, substs, user_ty) = match overloaded_callee { let (def_id, substs, user_ty) = match overloaded_callee {
Some((def_id, substs)) => (def_id, substs, None), Some((def_id, substs)) => (def_id, substs, None),
@ -799,13 +825,13 @@ impl<'tcx> Cx<'tcx> {
} }
} }
fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> Arm<'tcx> { fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> Arm<'thir, 'tcx> {
Arm { Arm {
pattern: self.pattern_from_hir(&arm.pat), pattern: self.pattern_from_hir(&arm.pat),
guard: arm.guard.as_ref().map(|g| match g { guard: arm.guard.as_ref().map(|g| match g {
hir::Guard::If(ref e) => Guard::If(self.mirror_expr_boxed(e)), hir::Guard::If(ref e) => Guard::If(self.mirror_expr(e)),
hir::Guard::IfLet(ref pat, ref e) => { hir::Guard::IfLet(ref pat, ref e) => {
Guard::IfLet(self.pattern_from_hir(pat), self.mirror_expr_boxed(e)) Guard::IfLet(self.pattern_from_hir(pat), self.mirror_expr(e))
} }
}), }),
body: self.mirror_expr(arm.body), body: self.mirror_expr(arm.body),
@ -815,7 +841,11 @@ impl<'tcx> Cx<'tcx> {
} }
} }
fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKind<'tcx> { fn convert_path_expr(
&mut self,
expr: &'tcx hir::Expr<'tcx>,
res: Res,
) -> ExprKind<'thir, 'tcx> {
let substs = self.typeck_results().node_substs(expr.hir_id); let substs = self.typeck_results().node_substs(expr.hir_id);
match res { match res {
// A regular function, constructor function or a constant. // A regular function, constructor function or a constant.
@ -883,7 +913,7 @@ impl<'tcx> Cx<'tcx> {
variant_index: adt_def.variant_index_with_ctor_id(def_id), variant_index: adt_def.variant_index_with_ctor_id(def_id),
substs, substs,
user_ty: user_provided_type, user_ty: user_provided_type,
fields: vec![], fields: self.arena.alloc_from_iter(iter::empty()),
base: None, base: None,
}, },
_ => bug!("unexpected ty: {:?}", ty), _ => bug!("unexpected ty: {:?}", ty),
@ -904,7 +934,9 @@ impl<'tcx> Cx<'tcx> {
def_id: id, def_id: id,
} }
}; };
ExprKind::Deref { arg: Box::new(Expr { ty, temp_lifetime, span: expr.span, kind }) } ExprKind::Deref {
arg: self.arena.alloc(Expr { ty, temp_lifetime, span: expr.span, kind }),
}
} }
Res::Local(var_hir_id) => self.convert_var(var_hir_id), Res::Local(var_hir_id) => self.convert_var(var_hir_id),
@ -913,7 +945,7 @@ impl<'tcx> Cx<'tcx> {
} }
} }
fn convert_var(&mut self, var_hir_id: hir::HirId) -> ExprKind<'tcx> { fn convert_var(&mut self, var_hir_id: hir::HirId) -> ExprKind<'thir, 'tcx> {
// We want upvars here not captures. // We want upvars here not captures.
// Captures will be handled in MIR. // Captures will be handled in MIR.
let is_upvar = self let is_upvar = self
@ -936,9 +968,9 @@ impl<'tcx> Cx<'tcx> {
fn overloaded_operator( fn overloaded_operator(
&mut self, &mut self,
expr: &'tcx hir::Expr<'tcx>, expr: &'tcx hir::Expr<'tcx>,
args: Vec<Expr<'tcx>>, args: &'thir [Expr<'thir, 'tcx>],
) -> ExprKind<'tcx> { ) -> ExprKind<'thir, 'tcx> {
let fun = Box::new(self.method_callee(expr, expr.span, None)); let fun = self.arena.alloc(self.method_callee(expr, expr.span, None));
ExprKind::Call { ty: fun.ty, fun, args, from_hir_call: false, fn_span: expr.span } ExprKind::Call { ty: fun.ty, fun, args, from_hir_call: false, fn_span: expr.span }
} }
@ -947,9 +979,9 @@ impl<'tcx> Cx<'tcx> {
expr: &'tcx hir::Expr<'tcx>, expr: &'tcx hir::Expr<'tcx>,
place_ty: Ty<'tcx>, place_ty: Ty<'tcx>,
overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>, overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
args: Vec<Expr<'tcx>>, args: &'thir [Expr<'thir, 'tcx>],
span: Span, span: Span,
) -> ExprKind<'tcx> { ) -> ExprKind<'thir, 'tcx> {
// For an overloaded *x or x[y] expression of type T, the method // For an overloaded *x or x[y] expression of type T, the method
// call returns an &T and we must add the deref so that the types // call returns an &T and we must add the deref so that the types
// line up (this is because `*x` and `x[y]` represent places): // line up (this is because `*x` and `x[y]` represent places):
@ -966,8 +998,8 @@ impl<'tcx> Cx<'tcx> {
// construct the complete expression `foo()` for the overloaded call, // construct the complete expression `foo()` for the overloaded call,
// which will yield the &T type // which will yield the &T type
let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id);
let fun = Box::new(self.method_callee(expr, span, overloaded_callee)); let fun = self.arena.alloc(self.method_callee(expr, span, overloaded_callee));
let ref_expr = Box::new(Expr { let ref_expr = self.arena.alloc(Expr {
temp_lifetime, temp_lifetime,
ty: ref_ty, ty: ref_ty,
span, span,
@ -983,7 +1015,7 @@ impl<'tcx> Cx<'tcx> {
closure_expr: &'tcx hir::Expr<'tcx>, closure_expr: &'tcx hir::Expr<'tcx>,
captured_place: &'tcx ty::CapturedPlace<'tcx>, captured_place: &'tcx ty::CapturedPlace<'tcx>,
upvar_ty: Ty<'tcx>, upvar_ty: Ty<'tcx>,
) -> Expr<'tcx> { ) -> Expr<'thir, 'tcx> {
let upvar_capture = captured_place.info.capture_kind; let upvar_capture = captured_place.info.capture_kind;
let temp_lifetime = self.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id); let temp_lifetime = self.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id);
let var_ty = captured_place.place.base_ty; let var_ty = captured_place.place.base_ty;
@ -1007,12 +1039,14 @@ impl<'tcx> Cx<'tcx> {
for proj in captured_place.place.projections.iter() { for proj in captured_place.place.projections.iter() {
let kind = match proj.kind { let kind = match proj.kind {
HirProjectionKind::Deref => ExprKind::Deref { arg: Box::new(captured_place_expr) }, HirProjectionKind::Deref => {
ExprKind::Deref { arg: self.arena.alloc(captured_place_expr) }
}
HirProjectionKind::Field(field, ..) => { HirProjectionKind::Field(field, ..) => {
// Variant index will always be 0, because for multi-variant // Variant index will always be 0, because for multi-variant
// enums, we capture the enum entirely. // enums, we capture the enum entirely.
ExprKind::Field { ExprKind::Field {
lhs: Box::new(captured_place_expr), lhs: self.arena.alloc(captured_place_expr),
name: Field::new(field as usize), name: Field::new(field as usize),
} }
} }
@ -1038,21 +1072,21 @@ impl<'tcx> Cx<'tcx> {
temp_lifetime, temp_lifetime,
ty: upvar_ty, ty: upvar_ty,
span: closure_expr.span, span: closure_expr.span,
kind: ExprKind::Borrow { borrow_kind, arg: Box::new(captured_place_expr) }, kind: ExprKind::Borrow {
borrow_kind,
arg: self.arena.alloc(captured_place_expr),
},
} }
} }
} }
} }
/// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExpr. /// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExpr.
fn field_refs(&mut self, fields: &'tcx [hir::Field<'tcx>]) -> Vec<FieldExpr<'tcx>> { fn field_refs(&mut self, fields: &'tcx [hir::Field<'tcx>]) -> &'thir [FieldExpr<'thir, 'tcx>] {
fields self.arena.alloc_from_iter(fields.iter().map(|field| FieldExpr {
.iter() name: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)),
.map(|field| FieldExpr { expr: self.mirror_expr(field.expr),
name: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)), }))
expr: self.mirror_expr(field.expr),
})
.collect()
} }
} }

View file

@ -2,6 +2,7 @@
//! structures into the THIR. The `builder` is generally ignorant of the tcx, //! structures into the THIR. The `builder` is generally ignorant of the tcx,
//! etc., and instead goes through the `Cx` for most of its work. //! etc., and instead goes through the `Cx` for most of its work.
use crate::thir::arena::Arena;
use crate::thir::util::UserAnnotatedTyHelpers; use crate::thir::util::UserAnnotatedTyHelpers;
use crate::thir::*; use crate::thir::*;
@ -13,9 +14,18 @@ use rustc_middle::middle::region;
use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput};
use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::ty::{self, Ty, TyCtxt};
#[derive(Clone)] crate fn build_thir<'thir, 'tcx>(
crate struct Cx<'tcx> {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
owner_def: ty::WithOptConstParam<LocalDefId>,
arena: &'thir Arena<'thir, 'tcx>,
expr: &'tcx hir::Expr<'tcx>,
) -> &'thir Expr<'thir, 'tcx> {
Cx::new(tcx, owner_def, &arena).mirror_expr(expr)
}
struct Cx<'thir, 'tcx> {
tcx: TyCtxt<'tcx>,
arena: &'thir Arena<'thir, 'tcx>,
crate param_env: ty::ParamEnv<'tcx>, crate param_env: ty::ParamEnv<'tcx>,
@ -26,20 +36,23 @@ crate struct Cx<'tcx> {
body_owner: DefId, body_owner: DefId,
} }
impl<'tcx> Cx<'tcx> { impl<'thir, 'tcx> Cx<'thir, 'tcx> {
crate fn new(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>) -> Cx<'tcx> { fn new(
tcx: TyCtxt<'tcx>,
def: ty::WithOptConstParam<LocalDefId>,
arena: &'thir Arena<'thir, 'tcx>,
) -> Cx<'thir, 'tcx> {
let typeck_results = tcx.typeck_opt_const_arg(def); let typeck_results = tcx.typeck_opt_const_arg(def);
Cx { Cx {
tcx, tcx,
arena,
param_env: tcx.param_env(def.did), param_env: tcx.param_env(def.did),
region_scope_tree: tcx.region_scope_tree(def.did), region_scope_tree: tcx.region_scope_tree(def.did),
typeck_results, typeck_results,
body_owner: def.did.to_def_id(), body_owner: def.did.to_def_id(),
} }
} }
}
impl<'tcx> Cx<'tcx> {
crate fn const_eval_literal( crate fn const_eval_literal(
&mut self, &mut self,
lit: &'tcx ast::LitKind, lit: &'tcx ast::LitKind,
@ -74,7 +87,7 @@ impl<'tcx> Cx<'tcx> {
} }
} }
impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'tcx> { impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'_, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx self.tcx
} }

View file

@ -24,6 +24,9 @@ crate mod pattern;
crate use self::pattern::PatTyProj; crate use self::pattern::PatTyProj;
crate use self::pattern::{BindingMode, FieldPat, Pat, PatKind, PatRange}; crate use self::pattern::{BindingMode, FieldPat, Pat, PatKind, PatRange};
mod arena;
crate use arena::Arena;
mod util; mod util;
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
@ -33,13 +36,13 @@ crate enum LintLevel {
} }
#[derive(Debug)] #[derive(Debug)]
crate struct Block<'tcx> { crate struct Block<'thir, 'tcx> {
crate targeted_by_break: bool, crate targeted_by_break: bool,
crate region_scope: region::Scope, crate region_scope: region::Scope,
crate opt_destruction_scope: Option<region::Scope>, crate opt_destruction_scope: Option<region::Scope>,
crate span: Span, crate span: Span,
crate stmts: Vec<Stmt<'tcx>>, crate stmts: &'thir [Stmt<'thir, 'tcx>],
crate expr: Option<Box<Expr<'tcx>>>, crate expr: Option<&'thir Expr<'thir, 'tcx>>,
crate safety_mode: BlockSafety, crate safety_mode: BlockSafety,
} }
@ -52,19 +55,19 @@ crate enum BlockSafety {
} }
#[derive(Debug)] #[derive(Debug)]
crate struct Stmt<'tcx> { crate struct Stmt<'thir, 'tcx> {
crate kind: StmtKind<'tcx>, crate kind: StmtKind<'thir, 'tcx>,
crate opt_destruction_scope: Option<region::Scope>, crate opt_destruction_scope: Option<region::Scope>,
} }
#[derive(Debug)] #[derive(Debug)]
crate enum StmtKind<'tcx> { crate enum StmtKind<'thir, 'tcx> {
Expr { Expr {
/// scope for this statement; may be used as lifetime of temporaries /// scope for this statement; may be used as lifetime of temporaries
scope: region::Scope, scope: region::Scope,
/// expression being evaluated in this statement /// expression being evaluated in this statement
expr: Box<Expr<'tcx>>, expr: &'thir Expr<'thir, 'tcx>,
}, },
Let { Let {
@ -82,7 +85,7 @@ crate enum StmtKind<'tcx> {
pattern: Pat<'tcx>, pattern: Pat<'tcx>,
/// let pat: ty = <INIT> ... /// let pat: ty = <INIT> ...
initializer: Option<Box<Expr<'tcx>>>, initializer: Option<&'thir Expr<'thir, 'tcx>>,
/// the lint level for this let-statement /// the lint level for this let-statement
lint_level: LintLevel, lint_level: LintLevel,
@ -91,12 +94,12 @@ crate enum StmtKind<'tcx> {
// `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger.
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
rustc_data_structures::static_assert_size!(Expr<'_>, 160); rustc_data_structures::static_assert_size!(Expr<'_, '_>, 144);
/// The Thir trait implementor lowers their expressions (`&'tcx H::Expr`) /// The Thir trait implementor lowers their expressions (`&'tcx H::Expr`)
/// into instances of this `Expr` enum. This lowering can be done /// into instances of this `Expr` enum. This lowering can be done
/// basically as lazily or as eagerly as desired: every recursive /// basically as lazily or as eagerly as desired: every recursive
/// reference to an expression in this enum is an `Box<Expr<'tcx>>`, which /// reference to an expression in this enum is an `&'thir Expr<'thir, 'tcx>`, which
/// may in turn be another instance of this enum (boxed), or else an /// may in turn be another instance of this enum (boxed), or else an
/// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very /// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very
/// short-lived. They are created by `Thir::to_expr`, analyzed and /// short-lived. They are created by `Thir::to_expr`, analyzed and
@ -108,7 +111,7 @@ rustc_data_structures::static_assert_size!(Expr<'_>, 160);
/// example, method calls and overloaded operators are absent: they are /// example, method calls and overloaded operators are absent: they are
/// expected to be converted into `Expr::Call` instances. /// expected to be converted into `Expr::Call` instances.
#[derive(Debug)] #[derive(Debug)]
crate struct Expr<'tcx> { crate struct Expr<'thir, 'tcx> {
/// type of this expression /// type of this expression
crate ty: Ty<'tcx>, crate ty: Ty<'tcx>,
@ -120,28 +123,28 @@ crate struct Expr<'tcx> {
crate span: Span, crate span: Span,
/// kind of expression /// kind of expression
crate kind: ExprKind<'tcx>, crate kind: ExprKind<'thir, 'tcx>,
} }
#[derive(Debug)] #[derive(Debug)]
crate enum ExprKind<'tcx> { crate enum ExprKind<'thir, 'tcx> {
Scope { Scope {
region_scope: region::Scope, region_scope: region::Scope,
lint_level: LintLevel, lint_level: LintLevel,
value: Box<Expr<'tcx>>, value: &'thir Expr<'thir, 'tcx>,
}, },
Box { Box {
value: Box<Expr<'tcx>>, value: &'thir Expr<'thir, 'tcx>,
}, },
If { If {
cond: Box<Expr<'tcx>>, cond: &'thir Expr<'thir, 'tcx>,
then: Box<Expr<'tcx>>, then: &'thir Expr<'thir, 'tcx>,
else_opt: Option<Box<Expr<'tcx>>>, else_opt: Option<&'thir Expr<'thir, 'tcx>>,
}, },
Call { Call {
ty: Ty<'tcx>, ty: Ty<'tcx>,
fun: Box<Expr<'tcx>>, fun: &'thir Expr<'thir, 'tcx>,
args: Vec<Expr<'tcx>>, args: &'thir [Expr<'thir, 'tcx>],
/// Whether this is from a call in HIR, rather than from an overloaded /// Whether this is from a call in HIR, rather than from an overloaded
/// operator. `true` for overloaded function call. /// operator. `true` for overloaded function call.
from_hir_call: bool, from_hir_call: bool,
@ -150,62 +153,62 @@ crate enum ExprKind<'tcx> {
fn_span: Span, fn_span: Span,
}, },
Deref { Deref {
arg: Box<Expr<'tcx>>, arg: &'thir Expr<'thir, 'tcx>,
}, // NOT overloaded! }, // NOT overloaded!
Binary { Binary {
op: BinOp, op: BinOp,
lhs: Box<Expr<'tcx>>, lhs: &'thir Expr<'thir, 'tcx>,
rhs: Box<Expr<'tcx>>, rhs: &'thir Expr<'thir, 'tcx>,
}, // NOT overloaded! }, // NOT overloaded!
LogicalOp { LogicalOp {
op: LogicalOp, op: LogicalOp,
lhs: Box<Expr<'tcx>>, lhs: &'thir Expr<'thir, 'tcx>,
rhs: Box<Expr<'tcx>>, rhs: &'thir Expr<'thir, 'tcx>,
}, // NOT overloaded! }, // NOT overloaded!
// LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands. // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands.
Unary { Unary {
op: UnOp, op: UnOp,
arg: Box<Expr<'tcx>>, arg: &'thir Expr<'thir, 'tcx>,
}, // NOT overloaded! }, // NOT overloaded!
Cast { Cast {
source: Box<Expr<'tcx>>, source: &'thir Expr<'thir, 'tcx>,
}, },
Use { Use {
source: Box<Expr<'tcx>>, source: &'thir Expr<'thir, 'tcx>,
}, // Use a lexpr to get a vexpr. }, // Use a lexpr to get a vexpr.
NeverToAny { NeverToAny {
source: Box<Expr<'tcx>>, source: &'thir Expr<'thir, 'tcx>,
}, },
Pointer { Pointer {
cast: PointerCast, cast: PointerCast,
source: Box<Expr<'tcx>>, source: &'thir Expr<'thir, 'tcx>,
}, },
Loop { Loop {
body: Box<Expr<'tcx>>, body: &'thir Expr<'thir, 'tcx>,
}, },
Match { Match {
scrutinee: Box<Expr<'tcx>>, scrutinee: &'thir Expr<'thir, 'tcx>,
arms: Vec<Arm<'tcx>>, arms: &'thir [Arm<'thir, 'tcx>],
}, },
Block { Block {
body: Block<'tcx>, body: Block<'thir, 'tcx>,
}, },
Assign { Assign {
lhs: Box<Expr<'tcx>>, lhs: &'thir Expr<'thir, 'tcx>,
rhs: Box<Expr<'tcx>>, rhs: &'thir Expr<'thir, 'tcx>,
}, },
AssignOp { AssignOp {
op: BinOp, op: BinOp,
lhs: Box<Expr<'tcx>>, lhs: &'thir Expr<'thir, 'tcx>,
rhs: Box<Expr<'tcx>>, rhs: &'thir Expr<'thir, 'tcx>,
}, },
Field { Field {
lhs: Box<Expr<'tcx>>, lhs: &'thir Expr<'thir, 'tcx>,
name: Field, name: Field,
}, },
Index { Index {
lhs: Box<Expr<'tcx>>, lhs: &'thir Expr<'thir, 'tcx>,
index: Box<Expr<'tcx>>, index: &'thir Expr<'thir, 'tcx>,
}, },
VarRef { VarRef {
id: hir::HirId, id: hir::HirId,
@ -220,35 +223,35 @@ crate enum ExprKind<'tcx> {
}, },
Borrow { Borrow {
borrow_kind: BorrowKind, borrow_kind: BorrowKind,
arg: Box<Expr<'tcx>>, arg: &'thir Expr<'thir, 'tcx>,
}, },
/// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`. /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`.
AddressOf { AddressOf {
mutability: hir::Mutability, mutability: hir::Mutability,
arg: Box<Expr<'tcx>>, arg: &'thir Expr<'thir, 'tcx>,
}, },
Break { Break {
label: region::Scope, label: region::Scope,
value: Option<Box<Expr<'tcx>>>, value: Option<&'thir Expr<'thir, 'tcx>>,
}, },
Continue { Continue {
label: region::Scope, label: region::Scope,
}, },
Return { Return {
value: Option<Box<Expr<'tcx>>>, value: Option<&'thir Expr<'thir, 'tcx>>,
}, },
ConstBlock { ConstBlock {
value: &'tcx Const<'tcx>, value: &'tcx Const<'tcx>,
}, },
Repeat { Repeat {
value: Box<Expr<'tcx>>, value: &'thir Expr<'thir, 'tcx>,
count: &'tcx Const<'tcx>, count: &'tcx Const<'tcx>,
}, },
Array { Array {
fields: Vec<Expr<'tcx>>, fields: &'thir [Expr<'thir, 'tcx>],
}, },
Tuple { Tuple {
fields: Vec<Expr<'tcx>>, fields: &'thir [Expr<'thir, 'tcx>],
}, },
Adt { Adt {
adt_def: &'tcx AdtDef, adt_def: &'tcx AdtDef,
@ -259,23 +262,23 @@ crate enum ExprKind<'tcx> {
/// Bar::<T> { ... }`. /// Bar::<T> { ... }`.
user_ty: Option<Canonical<'tcx, UserType<'tcx>>>, user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
fields: Vec<FieldExpr<'tcx>>, fields: &'thir [FieldExpr<'thir, 'tcx>],
base: Option<FruInfo<'tcx>>, base: Option<FruInfo<'thir, 'tcx>>,
}, },
PlaceTypeAscription { PlaceTypeAscription {
source: Box<Expr<'tcx>>, source: &'thir Expr<'thir, 'tcx>,
/// Type that the user gave to this expression /// Type that the user gave to this expression
user_ty: Option<Canonical<'tcx, UserType<'tcx>>>, user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
}, },
ValueTypeAscription { ValueTypeAscription {
source: Box<Expr<'tcx>>, source: &'thir Expr<'thir, 'tcx>,
/// Type that the user gave to this expression /// Type that the user gave to this expression
user_ty: Option<Canonical<'tcx, UserType<'tcx>>>, user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
}, },
Closure { Closure {
closure_id: DefId, closure_id: DefId,
substs: UpvarSubsts<'tcx>, substs: UpvarSubsts<'tcx>,
upvars: Vec<Expr<'tcx>>, upvars: &'thir [Expr<'thir, 'tcx>],
movability: Option<hir::Movability>, movability: Option<hir::Movability>,
}, },
Literal { Literal {
@ -296,7 +299,7 @@ crate enum ExprKind<'tcx> {
}, },
InlineAsm { InlineAsm {
template: &'tcx [InlineAsmTemplatePiece], template: &'tcx [InlineAsmTemplatePiece],
operands: Vec<InlineAsmOperand<'tcx>>, operands: &'thir [InlineAsmOperand<'thir, 'tcx>],
options: InlineAsmOptions, options: InlineAsmOptions,
line_spans: &'tcx [Span], line_spans: &'tcx [Span],
}, },
@ -304,40 +307,40 @@ crate enum ExprKind<'tcx> {
ThreadLocalRef(DefId), ThreadLocalRef(DefId),
LlvmInlineAsm { LlvmInlineAsm {
asm: &'tcx hir::LlvmInlineAsmInner, asm: &'tcx hir::LlvmInlineAsmInner,
outputs: Vec<Expr<'tcx>>, outputs: &'thir [Expr<'thir, 'tcx>],
inputs: Vec<Expr<'tcx>>, inputs: &'thir [Expr<'thir, 'tcx>],
}, },
Yield { Yield {
value: Box<Expr<'tcx>>, value: &'thir Expr<'thir, 'tcx>,
}, },
} }
#[derive(Debug)] #[derive(Debug)]
crate struct FieldExpr<'tcx> { crate struct FieldExpr<'thir, 'tcx> {
crate name: Field, crate name: Field,
crate expr: Expr<'tcx>, crate expr: &'thir Expr<'thir, 'tcx>,
} }
#[derive(Debug)] #[derive(Debug)]
crate struct FruInfo<'tcx> { crate struct FruInfo<'thir, 'tcx> {
crate base: Box<Expr<'tcx>>, crate base: &'thir Expr<'thir, 'tcx>,
crate field_types: Vec<Ty<'tcx>>, crate field_types: &'thir [Ty<'tcx>],
} }
#[derive(Debug)] #[derive(Debug)]
crate struct Arm<'tcx> { crate struct Arm<'thir, 'tcx> {
crate pattern: Pat<'tcx>, crate pattern: Pat<'tcx>,
crate guard: Option<Guard<'tcx>>, crate guard: Option<Guard<'thir, 'tcx>>,
crate body: Expr<'tcx>, crate body: &'thir Expr<'thir, 'tcx>,
crate lint_level: LintLevel, crate lint_level: LintLevel,
crate scope: region::Scope, crate scope: region::Scope,
crate span: Span, crate span: Span,
} }
#[derive(Debug)] #[derive(Debug)]
crate enum Guard<'tcx> { crate enum Guard<'thir, 'tcx> {
If(Box<Expr<'tcx>>), If(&'thir Expr<'thir, 'tcx>),
IfLet(Pat<'tcx>, Box<Expr<'tcx>>), IfLet(Pat<'tcx>, &'thir Expr<'thir, 'tcx>),
} }
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
@ -347,32 +350,32 @@ crate enum LogicalOp {
} }
#[derive(Debug)] #[derive(Debug)]
crate enum InlineAsmOperand<'tcx> { crate enum InlineAsmOperand<'thir, 'tcx> {
In { In {
reg: InlineAsmRegOrRegClass, reg: InlineAsmRegOrRegClass,
expr: Expr<'tcx>, expr: &'thir Expr<'thir, 'tcx>,
}, },
Out { Out {
reg: InlineAsmRegOrRegClass, reg: InlineAsmRegOrRegClass,
late: bool, late: bool,
expr: Option<Expr<'tcx>>, expr: Option<&'thir Expr<'thir, 'tcx>>,
}, },
InOut { InOut {
reg: InlineAsmRegOrRegClass, reg: InlineAsmRegOrRegClass,
late: bool, late: bool,
expr: Expr<'tcx>, expr: &'thir Expr<'thir, 'tcx>,
}, },
SplitInOut { SplitInOut {
reg: InlineAsmRegOrRegClass, reg: InlineAsmRegOrRegClass,
late: bool, late: bool,
in_expr: Expr<'tcx>, in_expr: &'thir Expr<'thir, 'tcx>,
out_expr: Option<Expr<'tcx>>, out_expr: Option<&'thir Expr<'thir, 'tcx>>,
}, },
Const { Const {
expr: Expr<'tcx>, expr: &'thir Expr<'thir, 'tcx>,
}, },
SymFn { SymFn {
expr: Expr<'tcx>, expr: &'thir Expr<'thir, 'tcx>,
}, },
SymStatic { SymStatic {
def_id: DefId, def_id: DefId,