Store THIR in IndexVec
s instead of an Arena
This commit is contained in:
parent
e78bccfbc0
commit
dc3eabd487
18 changed files with 686 additions and 633 deletions
|
@ -9,14 +9,12 @@ use rustc_hir_pretty as pprust_hir;
|
||||||
use rustc_middle::hir::map as hir_map;
|
use rustc_middle::hir::map as hir_map;
|
||||||
use rustc_middle::ty::{self, TyCtxt};
|
use rustc_middle::ty::{self, TyCtxt};
|
||||||
use rustc_mir::util::{write_mir_graphviz, write_mir_pretty};
|
use rustc_mir::util::{write_mir_graphviz, write_mir_pretty};
|
||||||
use rustc_mir_build::thir;
|
|
||||||
use rustc_session::config::{Input, PpAstTreeMode, PpHirMode, PpMode, PpSourceMode};
|
use rustc_session::config::{Input, PpAstTreeMode, PpHirMode, PpMode, PpSourceMode};
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::symbol::Ident;
|
use rustc_span::symbol::Ident;
|
||||||
use rustc_span::FileName;
|
use rustc_span::FileName;
|
||||||
|
|
||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::fmt::Write;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
pub use self::PpMode::*;
|
pub use self::PpMode::*;
|
||||||
|
@ -491,18 +489,8 @@ fn print_with_analysis(
|
||||||
}
|
}
|
||||||
|
|
||||||
ThirTree => {
|
ThirTree => {
|
||||||
let mut out = String::new();
|
// FIXME(rust-lang/project-thir-unsafeck#8)
|
||||||
abort_on_err(rustc_typeck::check_crate(tcx), tcx.sess);
|
todo!()
|
||||||
debug!("pretty printing THIR tree");
|
|
||||||
for did in tcx.body_owners() {
|
|
||||||
let hir = tcx.hir();
|
|
||||||
let body = hir.body(hir.body_owned_by(hir.local_def_id_to_hir_id(did)));
|
|
||||||
let arena = thir::Arena::default();
|
|
||||||
let thir =
|
|
||||||
thir::build_thir(tcx, ty::WithOptConstParam::unknown(did), &arena, &body.value);
|
|
||||||
let _ = writeln!(out, "{:?}:\n{:#?}\n", did, thir);
|
|
||||||
}
|
|
||||||
out
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
|
|
|
@ -12,18 +12,19 @@ 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,
|
||||||
source_info: SourceInfo,
|
source_info: SourceInfo,
|
||||||
) -> BlockAnd<()> {
|
) -> BlockAnd<()> {
|
||||||
let Block {
|
let Block {
|
||||||
region_scope,
|
region_scope,
|
||||||
opt_destruction_scope,
|
opt_destruction_scope,
|
||||||
span,
|
span,
|
||||||
stmts,
|
ref stmts,
|
||||||
expr,
|
expr,
|
||||||
targeted_by_break,
|
targeted_by_break,
|
||||||
safety_mode,
|
safety_mode,
|
||||||
} = *ast_block;
|
} = *ast_block;
|
||||||
|
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| {
|
||||||
if targeted_by_break {
|
if targeted_by_break {
|
||||||
|
@ -32,13 +33,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
destination,
|
destination,
|
||||||
block,
|
block,
|
||||||
span,
|
span,
|
||||||
stmts,
|
&stmts,
|
||||||
expr,
|
expr,
|
||||||
safety_mode,
|
safety_mode,
|
||||||
))
|
))
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
this.ast_block_stmts(destination, block, span, stmts, expr, safety_mode)
|
this.ast_block_stmts(destination, block, span, &stmts, expr, safety_mode)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
@ -49,8 +50,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: &[StmtId],
|
||||||
expr: Option<&Expr<'_, 'tcx>>,
|
expr: Option<&Expr<'tcx>>,
|
||||||
safety_mode: BlockSafety,
|
safety_mode: BlockSafety,
|
||||||
) -> BlockAnd<()> {
|
) -> BlockAnd<()> {
|
||||||
let this = self;
|
let this = self;
|
||||||
|
@ -78,23 +79,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
this.update_source_scope_for_safety_mode(span, safety_mode);
|
this.update_source_scope_for_safety_mode(span, safety_mode);
|
||||||
|
|
||||||
let source_info = this.source_info(span);
|
let source_info = this.source_info(span);
|
||||||
for Stmt { kind, opt_destruction_scope } in stmts {
|
for stmt in stmts {
|
||||||
|
let Stmt { ref kind, opt_destruction_scope } = this.thir[*stmt];
|
||||||
match kind {
|
match kind {
|
||||||
&StmtKind::Expr { scope, expr } => {
|
StmtKind::Expr { scope, expr } => {
|
||||||
this.block_context.push(BlockFrame::Statement { ignores_expr_result: true });
|
this.block_context.push(BlockFrame::Statement { ignores_expr_result: true });
|
||||||
unpack!(
|
unpack!(
|
||||||
block = this.in_opt_scope(
|
block = this.in_opt_scope(
|
||||||
opt_destruction_scope.map(|de| (de, source_info)),
|
opt_destruction_scope.map(|de| (de, source_info)),
|
||||||
|this| {
|
|this| {
|
||||||
let si = (scope, source_info);
|
let si = (*scope, source_info);
|
||||||
this.in_scope(si, LintLevel::Inherited, |this| {
|
this.in_scope(si, LintLevel::Inherited, |this| {
|
||||||
this.stmt_expr(block, expr, Some(scope))
|
this.stmt_expr(block, &this.thir[*expr], Some(*scope))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
StmtKind::Let { remainder_scope, init_scope, pattern, initializer, lint_level } => {
|
StmtKind::Let {
|
||||||
|
remainder_scope,
|
||||||
|
init_scope,
|
||||||
|
ref pattern,
|
||||||
|
initializer,
|
||||||
|
lint_level,
|
||||||
|
} => {
|
||||||
let ignores_expr_result = matches!(*pattern.kind, PatKind::Wild);
|
let ignores_expr_result = matches!(*pattern.kind, PatKind::Wild);
|
||||||
this.block_context.push(BlockFrame::Statement { ignores_expr_result });
|
this.block_context.push(BlockFrame::Statement { ignores_expr_result });
|
||||||
|
|
||||||
|
@ -110,6 +118,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
|
|
||||||
// Evaluate the initializer, if present.
|
// Evaluate the initializer, if present.
|
||||||
if let Some(init) = initializer {
|
if let Some(init) = initializer {
|
||||||
|
let init = &this.thir[*init];
|
||||||
let initializer_span = init.span;
|
let initializer_span = init.span;
|
||||||
|
|
||||||
unpack!(
|
unpack!(
|
||||||
|
@ -145,7 +154,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
|
|
||||||
debug!("ast_block_stmts: pattern={:?}", pattern);
|
debug!("ast_block_stmts: pattern={:?}", pattern);
|
||||||
this.visit_primary_bindings(
|
this.visit_primary_bindings(
|
||||||
&pattern,
|
pattern,
|
||||||
UserTypeProjections::none(),
|
UserTypeProjections::none(),
|
||||||
&mut |this, _, _, _, node, span, _, _| {
|
&mut |this, _, _, _, node, span, _, _| {
|
||||||
this.storage_live_binding(block, node, span, OutsideGuard, true);
|
this.storage_live_binding(block, node, span, OutsideGuard, true);
|
||||||
|
|
|
@ -8,11 +8,13 @@ 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, ref kind } = *expr;
|
let Expr { ty, temp_lifetime: _, span, ref kind } = *expr;
|
||||||
match *kind {
|
match *kind {
|
||||||
ExprKind::Scope { region_scope: _, lint_level: _, value } => this.as_constant(value),
|
ExprKind::Scope { region_scope: _, lint_level: _, value } => {
|
||||||
|
this.as_constant(&this.thir[value])
|
||||||
|
}
|
||||||
ExprKind::Literal { literal, user_ty, const_id: _ } => {
|
ExprKind::Literal { literal, user_ty, const_id: _ } => {
|
||||||
let user_ty = user_ty.map(|user_ty| {
|
let user_ty = user_ty.map(|user_ty| {
|
||||||
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
|
this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation {
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -101,8 +101,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
|
if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
|
||||||
let source_info = this.source_info(expr.span);
|
let source_info = this.source_info(expr.span);
|
||||||
let region_scope = (region_scope, source_info);
|
let region_scope = (region_scope, source_info);
|
||||||
return this
|
return this.in_scope(region_scope, lint_level, |this| {
|
||||||
.in_scope(region_scope, lint_level, |this| this.as_operand(block, scope, value));
|
this.as_operand(block, scope, &this.thir[value])
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let category = Category::of(&expr.kind).unwrap();
|
let category = Category::of(&expr.kind).unwrap();
|
||||||
|
@ -123,7 +124,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;
|
||||||
|
@ -132,7 +133,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
let source_info = this.source_info(expr.span);
|
let source_info = this.source_info(expr.span);
|
||||||
let region_scope = (region_scope, source_info);
|
let region_scope = (region_scope, source_info);
|
||||||
return this.in_scope(region_scope, lint_level, |this| {
|
return this.in_scope(region_scope, lint_level, |this| {
|
||||||
this.as_call_operand(block, scope, value)
|
this.as_call_operand(block, scope, &this.thir[value])
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +152,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// type, and that value is coming from the deref of a box.
|
// type, and that value is coming from the deref of a box.
|
||||||
if let ExprKind::Deref { arg } = expr.kind {
|
if let ExprKind::Deref { arg } = expr.kind {
|
||||||
// Generate let tmp0 = arg0
|
// Generate let tmp0 = arg0
|
||||||
let operand = unpack!(block = this.as_temp(block, scope, arg, Mutability::Mut));
|
let operand = unpack!(
|
||||||
|
block = this.as_temp(block, scope, &this.thir[arg], Mutability::Mut)
|
||||||
|
);
|
||||||
|
|
||||||
// Return the operand *tmp0 to be used as the call argument
|
// Return the operand *tmp0 to be used as the call argument
|
||||||
let place = Place {
|
let place = Place {
|
||||||
|
|
|
@ -381,7 +381,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))
|
||||||
|
@ -392,7 +392,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)
|
||||||
}
|
}
|
||||||
|
@ -405,7 +405,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))
|
||||||
|
@ -420,7 +420,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)
|
||||||
}
|
}
|
||||||
|
@ -428,7 +428,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>> {
|
||||||
|
@ -440,23 +440,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
ExprKind::Scope { region_scope, lint_level, value } => {
|
ExprKind::Scope { region_scope, lint_level, value } => {
|
||||||
this.in_scope((region_scope, source_info), lint_level, |this| {
|
this.in_scope((region_scope, source_info), lint_level, |this| {
|
||||||
this.expr_as_place(block, value, mutability, fake_borrow_temps)
|
this.expr_as_place(block, &this.thir[value], mutability, fake_borrow_temps)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ExprKind::Field { lhs, name } => {
|
ExprKind::Field { lhs, name } => {
|
||||||
let place_builder =
|
let place_builder = unpack!(
|
||||||
unpack!(block = this.expr_as_place(block, lhs, mutability, fake_borrow_temps,));
|
block =
|
||||||
|
this.expr_as_place(block, &this.thir[lhs], mutability, fake_borrow_temps,)
|
||||||
|
);
|
||||||
block.and(place_builder.field(name, expr.ty))
|
block.and(place_builder.field(name, expr.ty))
|
||||||
}
|
}
|
||||||
ExprKind::Deref { arg } => {
|
ExprKind::Deref { arg } => {
|
||||||
let place_builder =
|
let place_builder = unpack!(
|
||||||
unpack!(block = this.expr_as_place(block, arg, mutability, fake_borrow_temps,));
|
block =
|
||||||
|
this.expr_as_place(block, &this.thir[arg], mutability, fake_borrow_temps,)
|
||||||
|
);
|
||||||
block.and(place_builder.deref())
|
block.and(place_builder.deref())
|
||||||
}
|
}
|
||||||
ExprKind::Index { lhs, index } => this.lower_index_expression(
|
ExprKind::Index { lhs, index } => this.lower_index_expression(
|
||||||
block,
|
block,
|
||||||
lhs,
|
&this.thir[lhs],
|
||||||
index,
|
&this.thir[index],
|
||||||
mutability,
|
mutability,
|
||||||
fake_borrow_temps,
|
fake_borrow_temps,
|
||||||
expr.temp_lifetime,
|
expr.temp_lifetime,
|
||||||
|
@ -481,7 +485,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
|
|
||||||
ExprKind::PlaceTypeAscription { source, user_ty } => {
|
ExprKind::PlaceTypeAscription { source, user_ty } => {
|
||||||
let place_builder = unpack!(
|
let place_builder = unpack!(
|
||||||
block = this.expr_as_place(block, source, mutability, fake_borrow_temps,)
|
block = this.expr_as_place(
|
||||||
|
block,
|
||||||
|
&this.thir[source],
|
||||||
|
mutability,
|
||||||
|
fake_borrow_temps,
|
||||||
|
)
|
||||||
);
|
);
|
||||||
if let Some(user_ty) = user_ty {
|
if let Some(user_ty) = user_ty {
|
||||||
let annotation_index =
|
let annotation_index =
|
||||||
|
@ -509,6 +518,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
block.and(place_builder)
|
block.and(place_builder)
|
||||||
}
|
}
|
||||||
ExprKind::ValueTypeAscription { source, user_ty } => {
|
ExprKind::ValueTypeAscription { source, user_ty } => {
|
||||||
|
let source = &this.thir[source];
|
||||||
let temp =
|
let temp =
|
||||||
unpack!(block = this.as_temp(block, source.temp_lifetime, source, mutability));
|
unpack!(block = this.as_temp(block, source.temp_lifetime, source, mutability));
|
||||||
if let Some(user_ty) = user_ty {
|
if let Some(user_ty) = user_ty {
|
||||||
|
@ -613,8 +623,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>,
|
||||||
|
|
|
@ -23,7 +23,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)
|
||||||
|
@ -34,7 +34,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);
|
||||||
|
|
||||||
|
@ -46,19 +46,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
ExprKind::ThreadLocalRef(did) => block.and(Rvalue::ThreadLocalRef(did)),
|
ExprKind::ThreadLocalRef(did) => block.and(Rvalue::ThreadLocalRef(did)),
|
||||||
ExprKind::Scope { region_scope, lint_level, value } => {
|
ExprKind::Scope { region_scope, lint_level, value } => {
|
||||||
let region_scope = (region_scope, source_info);
|
let region_scope = (region_scope, source_info);
|
||||||
this.in_scope(region_scope, lint_level, |this| this.as_rvalue(block, scope, value))
|
this.in_scope(region_scope, lint_level, |this| {
|
||||||
|
this.as_rvalue(block, scope, &this.thir[value])
|
||||||
|
})
|
||||||
}
|
}
|
||||||
ExprKind::Repeat { value, count } => {
|
ExprKind::Repeat { value, count } => {
|
||||||
let value_operand = unpack!(block = this.as_operand(block, scope, value));
|
let value_operand =
|
||||||
|
unpack!(block = this.as_operand(block, scope, &this.thir[value]));
|
||||||
block.and(Rvalue::Repeat(value_operand, count))
|
block.and(Rvalue::Repeat(value_operand, count))
|
||||||
}
|
}
|
||||||
ExprKind::Binary { op, lhs, rhs } => {
|
ExprKind::Binary { op, lhs, rhs } => {
|
||||||
let lhs = unpack!(block = this.as_operand(block, scope, lhs));
|
let lhs = unpack!(block = this.as_operand(block, scope, &this.thir[lhs]));
|
||||||
let rhs = unpack!(block = this.as_operand(block, scope, rhs));
|
let rhs = unpack!(block = this.as_operand(block, scope, &this.thir[rhs]));
|
||||||
this.build_binary_op(block, op, expr_span, expr.ty, lhs, rhs)
|
this.build_binary_op(block, op, expr_span, expr.ty, lhs, rhs)
|
||||||
}
|
}
|
||||||
ExprKind::Unary { op, arg } => {
|
ExprKind::Unary { op, arg } => {
|
||||||
let arg = unpack!(block = this.as_operand(block, scope, arg));
|
let arg = unpack!(block = this.as_operand(block, scope, &this.thir[arg]));
|
||||||
// Check for -MIN on signed integers
|
// Check for -MIN on signed integers
|
||||||
if this.check_overflow && op == UnOp::Neg && expr.ty.is_signed() {
|
if this.check_overflow && op == UnOp::Neg && expr.ty.is_signed() {
|
||||||
let bool_ty = this.tcx.types.bool;
|
let bool_ty = this.tcx.types.bool;
|
||||||
|
@ -84,6 +87,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
block.and(Rvalue::UnaryOp(op, arg))
|
block.and(Rvalue::UnaryOp(op, arg))
|
||||||
}
|
}
|
||||||
ExprKind::Box { value } => {
|
ExprKind::Box { value } => {
|
||||||
|
let value = &this.thir[value];
|
||||||
// The `Box<T>` temporary created here is not a part of the HIR,
|
// The `Box<T>` temporary created here is not a part of the HIR,
|
||||||
// and therefore is not considered during generator auto-trait
|
// and therefore is not considered during generator auto-trait
|
||||||
// determination. See the comment about `box` at `yield_in_scope`.
|
// determination. See the comment about `box` at `yield_in_scope`.
|
||||||
|
@ -112,14 +116,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
block.and(Rvalue::Use(Operand::Move(Place::from(result))))
|
block.and(Rvalue::Use(Operand::Move(Place::from(result))))
|
||||||
}
|
}
|
||||||
ExprKind::Cast { source } => {
|
ExprKind::Cast { source } => {
|
||||||
let source = unpack!(block = this.as_operand(block, scope, source));
|
let source = unpack!(block = this.as_operand(block, scope, &this.thir[source]));
|
||||||
block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty))
|
block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty))
|
||||||
}
|
}
|
||||||
ExprKind::Pointer { cast, source } => {
|
ExprKind::Pointer { cast, source } => {
|
||||||
let source = unpack!(block = this.as_operand(block, scope, source));
|
let source = unpack!(block = this.as_operand(block, scope, &this.thir[source]));
|
||||||
block.and(Rvalue::Cast(CastKind::Pointer(cast), source, expr.ty))
|
block.and(Rvalue::Cast(CastKind::Pointer(cast), source, expr.ty))
|
||||||
}
|
}
|
||||||
ExprKind::Array { fields } => {
|
ExprKind::Array { ref fields } => {
|
||||||
// (*) We would (maybe) be closer to codegen if we
|
// (*) We would (maybe) be closer to codegen if we
|
||||||
// handled this and other aggregate cases via
|
// handled this and other aggregate cases via
|
||||||
// `into()`, not `as_rvalue` -- in that case, instead
|
// `into()`, not `as_rvalue` -- in that case, instead
|
||||||
|
@ -150,22 +154,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
let el_ty = expr.ty.sequence_element_type(this.tcx);
|
let el_ty = expr.ty.sequence_element_type(this.tcx);
|
||||||
let fields: Vec<_> = fields
|
let fields: Vec<_> = fields
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|f| unpack!(block = this.as_operand(block, scope, f)))
|
.copied()
|
||||||
|
.map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f])))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
block.and(Rvalue::Aggregate(box AggregateKind::Array(el_ty), fields))
|
block.and(Rvalue::Aggregate(box AggregateKind::Array(el_ty), fields))
|
||||||
}
|
}
|
||||||
ExprKind::Tuple { fields } => {
|
ExprKind::Tuple { ref fields } => {
|
||||||
// see (*) above
|
// see (*) above
|
||||||
// first process the set of fields
|
// first process the set of fields
|
||||||
let fields: Vec<_> = fields
|
let fields: Vec<_> = fields
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|f| unpack!(block = this.as_operand(block, scope, f)))
|
.copied()
|
||||||
|
.map(|f| unpack!(block = this.as_operand(block, scope, &this.thir[f])))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
block.and(Rvalue::Aggregate(box AggregateKind::Tuple, fields))
|
block.and(Rvalue::Aggregate(box AggregateKind::Tuple, fields))
|
||||||
}
|
}
|
||||||
ExprKind::Closure { closure_id, substs, upvars, movability, ref fake_reads } => {
|
ExprKind::Closure { closure_id, substs, ref upvars, movability, ref fake_reads } => {
|
||||||
// Convert the closure fake reads, if any, from `ExprRef` to mir `Place`
|
// Convert the closure fake reads, if any, from `ExprRef` to mir `Place`
|
||||||
// and push the fake reads.
|
// and push the fake reads.
|
||||||
// This must come before creating the operands. This is required in case
|
// This must come before creating the operands. This is required in case
|
||||||
|
@ -180,7 +186,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// };
|
// };
|
||||||
// ```
|
// ```
|
||||||
for (thir_place, cause, hir_id) in fake_reads.into_iter() {
|
for (thir_place, cause, hir_id) in fake_reads.into_iter() {
|
||||||
let place_builder = unpack!(block = this.as_place_builder(block, thir_place));
|
let place_builder =
|
||||||
|
unpack!(block = this.as_place_builder(block, &this.thir[*thir_place]));
|
||||||
|
|
||||||
if let Ok(place_builder_resolved) =
|
if let Ok(place_builder_resolved) =
|
||||||
place_builder.try_upvars_resolved(this.tcx, this.typeck_results)
|
place_builder.try_upvars_resolved(this.tcx, this.typeck_results)
|
||||||
|
@ -199,7 +206,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// see (*) above
|
// see (*) above
|
||||||
let operands: Vec<_> = upvars
|
let operands: Vec<_> = upvars
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
.copied()
|
||||||
.map(|upvar| {
|
.map(|upvar| {
|
||||||
|
let upvar = &this.thir[upvar];
|
||||||
match Category::of(&upvar.kind) {
|
match Category::of(&upvar.kind) {
|
||||||
// Use as_place to avoid creating a temporary when
|
// Use as_place to avoid creating a temporary when
|
||||||
// moving a variable into a closure, so that
|
// moving a variable into a closure, so that
|
||||||
|
@ -225,7 +234,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
arg,
|
arg,
|
||||||
} => unpack!(
|
} => unpack!(
|
||||||
block = this.limit_capture_mutability(
|
block = this.limit_capture_mutability(
|
||||||
upvar.span, upvar.ty, scope, block, arg,
|
upvar.span,
|
||||||
|
upvar.ty,
|
||||||
|
scope,
|
||||||
|
block,
|
||||||
|
&this.thir[arg],
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
_ => unpack!(block = this.as_operand(block, scope, upvar)),
|
_ => unpack!(block = this.as_operand(block, scope, upvar)),
|
||||||
|
@ -398,7 +411,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;
|
||||||
|
|
||||||
|
|
|
@ -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!(
|
||||||
|
@ -40,7 +40,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
let source_info = this.source_info(expr_span);
|
let source_info = this.source_info(expr_span);
|
||||||
if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
|
if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind {
|
||||||
return this.in_scope((region_scope, source_info), lint_level, |this| {
|
return this.in_scope((region_scope, source_info), lint_level, |this| {
|
||||||
this.as_temp(block, temp_lifetime, value, mutability)
|
this.as_temp(block, temp_lifetime, &this.thir[value], mutability)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,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);
|
||||||
|
|
||||||
|
@ -42,19 +42,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
let region_scope = (region_scope, source_info);
|
let region_scope = (region_scope, source_info);
|
||||||
ensure_sufficient_stack(|| {
|
ensure_sufficient_stack(|| {
|
||||||
this.in_scope(region_scope, lint_level, |this| {
|
this.in_scope(region_scope, lint_level, |this| {
|
||||||
this.expr_into_dest(destination, block, value)
|
this.expr_into_dest(destination, block, &this.thir[value])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ExprKind::Block { body: ref ast_block } => {
|
ExprKind::Block { body: ref ast_block } => {
|
||||||
this.ast_block(destination, block, ast_block, source_info)
|
this.ast_block(destination, block, ast_block, source_info)
|
||||||
}
|
}
|
||||||
ExprKind::Match { scrutinee, arms } => {
|
ExprKind::Match { scrutinee, ref arms } => {
|
||||||
this.match_expr(destination, expr_span, block, scrutinee, arms)
|
this.match_expr(destination, expr_span, block, &this.thir[scrutinee], arms)
|
||||||
}
|
}
|
||||||
ExprKind::If { cond, then, else_opt } => {
|
ExprKind::If { cond, then, else_opt } => {
|
||||||
let place = unpack!(
|
let place = unpack!(
|
||||||
block = this.as_temp(block, Some(this.local_scope()), cond, Mutability::Mut)
|
block = this.as_temp(
|
||||||
|
block,
|
||||||
|
Some(this.local_scope()),
|
||||||
|
&this.thir[cond],
|
||||||
|
Mutability::Mut
|
||||||
|
)
|
||||||
);
|
);
|
||||||
let operand = Operand::Move(Place::from(place));
|
let operand = Operand::Move(Place::from(place));
|
||||||
|
|
||||||
|
@ -63,9 +68,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
let term = TerminatorKind::if_(this.tcx, operand, then_block, else_block);
|
let term = TerminatorKind::if_(this.tcx, operand, then_block, else_block);
|
||||||
this.cfg.terminate(block, source_info, term);
|
this.cfg.terminate(block, source_info, term);
|
||||||
|
|
||||||
unpack!(then_block = this.expr_into_dest(destination, then_block, then));
|
unpack!(
|
||||||
|
then_block = this.expr_into_dest(destination, then_block, &this.thir[then])
|
||||||
|
);
|
||||||
else_block = if let Some(else_opt) = else_opt {
|
else_block = if let Some(else_opt) = else_opt {
|
||||||
unpack!(this.expr_into_dest(destination, else_block, else_opt))
|
unpack!(this.expr_into_dest(destination, else_block, &this.thir[else_opt]))
|
||||||
} else {
|
} else {
|
||||||
// Body of the `if` expression without an `else` clause must return `()`, thus
|
// Body of the `if` expression without an `else` clause must return `()`, thus
|
||||||
// we implicitly generate a `else {}` if it is not specified.
|
// we implicitly generate a `else {}` if it is not specified.
|
||||||
|
@ -89,6 +96,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
join_block.unit()
|
join_block.unit()
|
||||||
}
|
}
|
||||||
ExprKind::NeverToAny { source } => {
|
ExprKind::NeverToAny { source } => {
|
||||||
|
let source = &this.thir[source];
|
||||||
let is_call =
|
let is_call =
|
||||||
matches!(source.kind, ExprKind::Call { .. } | ExprKind::InlineAsm { .. });
|
matches!(source.kind, ExprKind::Call { .. } | ExprKind::InlineAsm { .. });
|
||||||
|
|
||||||
|
@ -127,7 +135,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
this.cfg.start_new_block(),
|
this.cfg.start_new_block(),
|
||||||
);
|
);
|
||||||
|
|
||||||
let lhs = unpack!(block = this.as_local_operand(block, lhs));
|
let lhs = unpack!(block = this.as_local_operand(block, &this.thir[lhs]));
|
||||||
let blocks = match op {
|
let blocks = match op {
|
||||||
LogicalOp::And => (else_block, shortcircuit_block),
|
LogicalOp::And => (else_block, shortcircuit_block),
|
||||||
LogicalOp::Or => (shortcircuit_block, else_block),
|
LogicalOp::Or => (shortcircuit_block, else_block),
|
||||||
|
@ -150,7 +158,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
this.cfg.goto(shortcircuit_block, source_info, join_block);
|
this.cfg.goto(shortcircuit_block, source_info, join_block);
|
||||||
|
|
||||||
let rhs = unpack!(else_block = this.as_local_operand(else_block, rhs));
|
let rhs = unpack!(else_block = this.as_local_operand(else_block, &this.thir[rhs]));
|
||||||
this.cfg.push_assign(else_block, source_info, destination, Rvalue::Use(rhs));
|
this.cfg.push_assign(else_block, source_info, destination, Rvalue::Use(rhs));
|
||||||
this.cfg.goto(else_block, source_info, join_block);
|
this.cfg.goto(else_block, source_info, join_block);
|
||||||
|
|
||||||
|
@ -186,18 +194,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// introduce a unit temporary as the destination for the loop body.
|
// introduce a unit temporary as the destination for the loop body.
|
||||||
let tmp = this.get_unit_temp();
|
let tmp = this.get_unit_temp();
|
||||||
// Execute the body, branching back to the test.
|
// Execute the body, branching back to the test.
|
||||||
let body_block_end = unpack!(this.expr_into_dest(tmp, body_block, body));
|
let body_block_end =
|
||||||
|
unpack!(this.expr_into_dest(tmp, body_block, &this.thir[body]));
|
||||||
this.cfg.goto(body_block_end, source_info, loop_block);
|
this.cfg.goto(body_block_end, source_info, loop_block);
|
||||||
|
|
||||||
// Loops are only exited by `break` expressions.
|
// Loops are only exited by `break` expressions.
|
||||||
None
|
None
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ExprKind::Call { ty: _, fun, args, from_hir_call, fn_span } => {
|
ExprKind::Call { ty: _, fun, ref args, from_hir_call, fn_span } => {
|
||||||
let fun = unpack!(block = this.as_local_operand(block, fun));
|
let fun = unpack!(block = this.as_local_operand(block, &this.thir[fun]));
|
||||||
let args: Vec<_> = args
|
let args: Vec<_> = args
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|arg| unpack!(block = this.as_local_call_operand(block, arg)))
|
.copied()
|
||||||
|
.map(|arg| unpack!(block = this.as_local_call_operand(block, &this.thir[arg])))
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let success = this.cfg.start_new_block();
|
let success = this.cfg.start_new_block();
|
||||||
|
@ -228,8 +238,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
this.diverge_from(block);
|
this.diverge_from(block);
|
||||||
success.unit()
|
success.unit()
|
||||||
}
|
}
|
||||||
ExprKind::Use { source } => this.expr_into_dest(destination, block, source),
|
ExprKind::Use { source } => this.expr_into_dest(destination, block, &this.thir[source]),
|
||||||
ExprKind::Borrow { arg, borrow_kind } => {
|
ExprKind::Borrow { arg, borrow_kind } => {
|
||||||
|
let arg = &this.thir[arg];
|
||||||
// We don't do this in `as_rvalue` because we use `as_place`
|
// We don't do this in `as_rvalue` because we use `as_place`
|
||||||
// for borrow expressions, so we cannot create an `RValue` that
|
// for borrow expressions, so we cannot create an `RValue` that
|
||||||
// remains valid across user code. `as_rvalue` is usually called
|
// remains valid across user code. `as_rvalue` is usually called
|
||||||
|
@ -244,6 +255,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
block.unit()
|
block.unit()
|
||||||
}
|
}
|
||||||
ExprKind::AddressOf { mutability, arg } => {
|
ExprKind::AddressOf { mutability, arg } => {
|
||||||
|
let arg = &this.thir[arg];
|
||||||
let place = match mutability {
|
let place = match mutability {
|
||||||
hir::Mutability::Not => this.as_read_only_place(block, arg),
|
hir::Mutability::Not => this.as_read_only_place(block, arg),
|
||||||
hir::Mutability::Mut => this.as_place(block, arg),
|
hir::Mutability::Mut => this.as_place(block, arg),
|
||||||
|
@ -252,7 +264,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
this.cfg.push_assign(block, source_info, destination, address_of);
|
this.cfg.push_assign(block, source_info, destination, address_of);
|
||||||
block.unit()
|
block.unit()
|
||||||
}
|
}
|
||||||
ExprKind::Adt { adt_def, variant_index, substs, user_ty, fields, ref base } => {
|
ExprKind::Adt { adt_def, variant_index, substs, user_ty, ref fields, ref base } => {
|
||||||
// See the notes for `ExprKind::Array` in `as_rvalue` and for
|
// See the notes for `ExprKind::Array` in `as_rvalue` and for
|
||||||
// `ExprKind::Borrow` above.
|
// `ExprKind::Borrow` above.
|
||||||
let is_union = adt_def.is_union();
|
let is_union = adt_def.is_union();
|
||||||
|
@ -264,19 +276,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// (evaluating them in order given by user)
|
// (evaluating them in order given by user)
|
||||||
let fields_map: FxHashMap<_, _> = fields
|
let fields_map: FxHashMap<_, _> = fields
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|f| (f.name, unpack!(block = this.as_operand(block, Some(scope), f.expr))))
|
.map(|f| {
|
||||||
|
(
|
||||||
|
f.name,
|
||||||
|
unpack!(
|
||||||
|
block = this.as_operand(block, Some(scope), &this.thir[f.expr])
|
||||||
|
),
|
||||||
|
)
|
||||||
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let field_names: Vec<_> =
|
let field_names: Vec<_> =
|
||||||
(0..adt_def.variants[variant_index].fields.len()).map(Field::new).collect();
|
(0..adt_def.variants[variant_index].fields.len()).map(Field::new).collect();
|
||||||
|
|
||||||
let fields: Vec<_> = if let Some(FruInfo { base, field_types }) = base {
|
let fields: Vec<_> = if let Some(FruInfo { base, field_types }) = base {
|
||||||
let place_builder = unpack!(block = this.as_place_builder(block, base));
|
let place_builder =
|
||||||
|
unpack!(block = this.as_place_builder(block, &this.thir[*base]));
|
||||||
|
|
||||||
// MIR does not natively support FRU, so for each
|
// MIR does not natively support FRU, so for each
|
||||||
// base-supplied field, generate an operand that
|
// base-supplied field, generate an operand that
|
||||||
// reads it from the base.
|
// reads it from the base.
|
||||||
iter::zip(field_names, *field_types)
|
iter::zip(field_names, &**field_types)
|
||||||
.map(|(n, ty)| match fields_map.get(&n) {
|
.map(|(n, ty)| match fields_map.get(&n) {
|
||||||
Some(v) => v.clone(),
|
Some(v) => v.clone(),
|
||||||
None => {
|
None => {
|
||||||
|
@ -316,7 +336,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
);
|
);
|
||||||
block.unit()
|
block.unit()
|
||||||
}
|
}
|
||||||
ExprKind::InlineAsm { template, operands, options, line_spans } => {
|
ExprKind::InlineAsm { template, ref operands, options, line_spans } => {
|
||||||
use crate::thir;
|
use crate::thir;
|
||||||
use rustc_middle::mir;
|
use rustc_middle::mir;
|
||||||
let operands = operands
|
let operands = operands
|
||||||
|
@ -324,19 +344,19 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
.map(|op| match *op {
|
.map(|op| match *op {
|
||||||
thir::InlineAsmOperand::In { reg, expr } => mir::InlineAsmOperand::In {
|
thir::InlineAsmOperand::In { reg, expr } => mir::InlineAsmOperand::In {
|
||||||
reg,
|
reg,
|
||||||
value: unpack!(block = this.as_local_operand(block, expr)),
|
value: unpack!(block = this.as_local_operand(block, &this.thir[expr])),
|
||||||
},
|
},
|
||||||
thir::InlineAsmOperand::Out { reg, late, expr } => {
|
thir::InlineAsmOperand::Out { reg, late, expr } => {
|
||||||
mir::InlineAsmOperand::Out {
|
mir::InlineAsmOperand::Out {
|
||||||
reg,
|
reg,
|
||||||
late,
|
late,
|
||||||
place: expr
|
place: expr.map(|expr| {
|
||||||
.as_ref()
|
unpack!(block = this.as_place(block, &this.thir[expr]))
|
||||||
.map(|expr| unpack!(block = this.as_place(block, expr))),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
thir::InlineAsmOperand::InOut { reg, late, expr } => {
|
thir::InlineAsmOperand::InOut { reg, late, expr } => {
|
||||||
let place = unpack!(block = this.as_place(block, expr));
|
let place = unpack!(block = this.as_place(block, &this.thir[expr]));
|
||||||
mir::InlineAsmOperand::InOut {
|
mir::InlineAsmOperand::InOut {
|
||||||
reg,
|
reg,
|
||||||
late,
|
late,
|
||||||
|
@ -349,9 +369,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
mir::InlineAsmOperand::InOut {
|
mir::InlineAsmOperand::InOut {
|
||||||
reg,
|
reg,
|
||||||
late,
|
late,
|
||||||
in_value: unpack!(block = this.as_local_operand(block, in_expr)),
|
in_value: unpack!(
|
||||||
out_place: out_expr.as_ref().map(|out_expr| {
|
block = this.as_local_operand(block, &this.thir[in_expr])
|
||||||
unpack!(block = this.as_place(block, out_expr))
|
),
|
||||||
|
out_place: out_expr.map(|out_expr| {
|
||||||
|
unpack!(block = this.as_place(block, &this.thir[out_expr]))
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -360,9 +382,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
value: box Constant { span, user_ty: None, literal: value.into() },
|
value: box Constant { span, user_ty: None, literal: value.into() },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
thir::InlineAsmOperand::SymFn { expr } => {
|
thir::InlineAsmOperand::SymFn { expr } => mir::InlineAsmOperand::SymFn {
|
||||||
mir::InlineAsmOperand::SymFn { value: box this.as_constant(expr) }
|
value: box this.as_constant(&this.thir[expr]),
|
||||||
}
|
},
|
||||||
thir::InlineAsmOperand::SymStatic { def_id } => {
|
thir::InlineAsmOperand::SymStatic { def_id } => {
|
||||||
mir::InlineAsmOperand::SymStatic { def_id }
|
mir::InlineAsmOperand::SymStatic { def_id }
|
||||||
}
|
}
|
||||||
|
@ -434,7 +456,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
|
|
||||||
ExprKind::Yield { value } => {
|
ExprKind::Yield { value } => {
|
||||||
let scope = this.local_scope();
|
let scope = this.local_scope();
|
||||||
let value = unpack!(block = this.as_operand(block, Some(scope), value));
|
let value = unpack!(block = this.as_operand(block, Some(scope), &this.thir[value]));
|
||||||
let resume = this.cfg.start_new_block();
|
let resume = this.cfg.start_new_block();
|
||||||
this.cfg.terminate(
|
this.cfg.terminate(
|
||||||
block,
|
block,
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -24,10 +24,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
match expr.kind {
|
match expr.kind {
|
||||||
ExprKind::Scope { region_scope, lint_level, value } => {
|
ExprKind::Scope { region_scope, lint_level, value } => {
|
||||||
this.in_scope((region_scope, source_info), lint_level, |this| {
|
this.in_scope((region_scope, source_info), lint_level, |this| {
|
||||||
this.stmt_expr(block, value, statement_scope)
|
this.stmt_expr(block, &this.thir[value], statement_scope)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ExprKind::Assign { lhs, rhs } => {
|
ExprKind::Assign { lhs, rhs } => {
|
||||||
|
let lhs = &this.thir[lhs];
|
||||||
|
let rhs = &this.thir[rhs];
|
||||||
let lhs_span = lhs.span;
|
let lhs_span = lhs.span;
|
||||||
|
|
||||||
// Note: we evaluate assignments right-to-left. This
|
// Note: we evaluate assignments right-to-left. This
|
||||||
|
@ -61,6 +63,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// only affects weird things like `x += {x += 1; x}`
|
// only affects weird things like `x += {x += 1; x}`
|
||||||
// -- is that equal to `x + (x + 1)` or `2*(x+1)`?
|
// -- is that equal to `x + (x + 1)` or `2*(x+1)`?
|
||||||
|
|
||||||
|
let lhs = &this.thir[lhs];
|
||||||
|
let rhs = &this.thir[rhs];
|
||||||
let lhs_ty = lhs.ty;
|
let lhs_ty = lhs.ty;
|
||||||
|
|
||||||
debug!("stmt_expr AssignOp block_context.push(SubExpr) : {:?}", expr);
|
debug!("stmt_expr AssignOp block_context.push(SubExpr) : {:?}", expr);
|
||||||
|
@ -87,24 +91,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
ExprKind::Break { label, value } => this.break_scope(
|
ExprKind::Break { label, value } => this.break_scope(
|
||||||
block,
|
block,
|
||||||
value.as_deref(),
|
value.map(|value| &this.thir[value]),
|
||||||
BreakableTarget::Break(label),
|
BreakableTarget::Break(label),
|
||||||
source_info,
|
source_info,
|
||||||
),
|
),
|
||||||
ExprKind::Return { value } => {
|
ExprKind::Return { value } => this.break_scope(
|
||||||
this.break_scope(block, value.as_deref(), BreakableTarget::Return, source_info)
|
block,
|
||||||
}
|
value.map(|value| &this.thir[value]),
|
||||||
ExprKind::LlvmInlineAsm { asm, outputs, inputs } => {
|
BreakableTarget::Return,
|
||||||
|
source_info,
|
||||||
|
),
|
||||||
|
ExprKind::LlvmInlineAsm { asm, ref outputs, ref inputs } => {
|
||||||
debug!("stmt_expr LlvmInlineAsm block_context.push(SubExpr) : {:?}", expr);
|
debug!("stmt_expr LlvmInlineAsm block_context.push(SubExpr) : {:?}", expr);
|
||||||
this.block_context.push(BlockFrame::SubExpr);
|
this.block_context.push(BlockFrame::SubExpr);
|
||||||
let outputs = outputs
|
let outputs = outputs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|output| unpack!(block = this.as_place(block, &output)))
|
.copied()
|
||||||
|
.map(|output| unpack!(block = this.as_place(block, &this.thir[output])))
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
.into_boxed_slice();
|
.into_boxed_slice();
|
||||||
let inputs = inputs
|
let inputs = inputs
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
.copied()
|
||||||
.map(|input| {
|
.map(|input| {
|
||||||
|
let input = &this.thir[input];
|
||||||
(input.span, unpack!(block = this.as_local_operand(block, &input)))
|
(input.span, unpack!(block = this.as_local_operand(block, &input)))
|
||||||
})
|
})
|
||||||
.collect::<Vec<_>>()
|
.collect::<Vec<_>>()
|
||||||
|
@ -139,14 +149,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
// 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 {
|
if let ExprKind::Block { body } = &expr.kind {
|
||||||
if let Some(tail_expr) = &body.expr {
|
if let Some(tail_expr) = body.expr {
|
||||||
let mut expr = &*tail_expr;
|
let mut expr = &this.thir[tail_expr];
|
||||||
while let ExprKind::Block {
|
while let ExprKind::Block {
|
||||||
body: Block { expr: Some(nested_expr), .. },
|
body: Block { expr: Some(nested_expr), .. },
|
||||||
}
|
}
|
||||||
| ExprKind::Scope { value: nested_expr, .. } = &expr.kind
|
| ExprKind::Scope { value: nested_expr, .. } = expr.kind
|
||||||
{
|
{
|
||||||
expr = nested_expr;
|
expr = &this.thir[nested_expr];
|
||||||
}
|
}
|
||||||
this.block_context.push(BlockFrame::TailExpr {
|
this.block_context.push(BlockFrame::TailExpr {
|
||||||
tail_result_is_ignored: true,
|
tail_result_is_ignored: true,
|
||||||
|
|
|
@ -90,8 +90,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: &[ArmId],
|
||||||
) -> BlockAnd<()> {
|
) -> BlockAnd<()> {
|
||||||
let scrutinee_span = scrutinee.span;
|
let scrutinee_span = scrutinee.span;
|
||||||
let scrutinee_place =
|
let scrutinee_place =
|
||||||
|
@ -99,7 +99,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
|
|
||||||
let mut arm_candidates = self.create_match_candidates(scrutinee_place.clone(), &arms);
|
let mut arm_candidates = self.create_match_candidates(scrutinee_place.clone(), &arms);
|
||||||
|
|
||||||
let match_has_guard = arms.iter().any(|arm| arm.guard.is_some());
|
let match_has_guard = arms.iter().copied().any(|arm| self.thir[arm].guard.is_some());
|
||||||
let mut candidates =
|
let mut candidates =
|
||||||
arm_candidates.iter_mut().map(|(_, candidate)| candidate).collect::<Vec<_>>();
|
arm_candidates.iter_mut().map(|(_, candidate)| candidate).collect::<Vec<_>>();
|
||||||
|
|
||||||
|
@ -120,7 +120,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<PlaceBuilder<'tcx>> {
|
) -> BlockAnd<PlaceBuilder<'tcx>> {
|
||||||
let scrutinee_place_builder = unpack!(block = self.as_place_builder(block, scrutinee));
|
let scrutinee_place_builder = unpack!(block = self.as_place_builder(block, scrutinee));
|
||||||
|
@ -156,12 +156,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
fn create_match_candidates<'pat>(
|
fn create_match_candidates<'pat>(
|
||||||
&mut self,
|
&mut self,
|
||||||
scrutinee: PlaceBuilder<'tcx>,
|
scrutinee: PlaceBuilder<'tcx>,
|
||||||
arms: &'pat [Arm<'pat, 'tcx>],
|
arms: &'pat [ArmId],
|
||||||
) -> Vec<(&'pat Arm<'pat, 'tcx>, Candidate<'pat, 'tcx>)> {
|
) -> Vec<(&'pat Arm<'tcx>, Candidate<'pat, 'tcx>)>
|
||||||
|
where
|
||||||
|
'a: 'pat,
|
||||||
|
{
|
||||||
// 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()
|
||||||
|
.copied()
|
||||||
.map(|arm| {
|
.map(|arm| {
|
||||||
|
let arm = &self.thir[arm];
|
||||||
let arm_has_guard = arm.guard.is_some();
|
let arm_has_guard = arm.guard.is_some();
|
||||||
let arm_candidate = Candidate::new(scrutinee.clone(), &arm.pattern, arm_has_guard);
|
let arm_candidate = Candidate::new(scrutinee.clone(), &arm.pattern, arm_has_guard);
|
||||||
(arm, arm_candidate)
|
(arm, arm_candidate)
|
||||||
|
@ -231,7 +236,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
destination: Place<'tcx>,
|
destination: Place<'tcx>,
|
||||||
scrutinee_place_builder: PlaceBuilder<'tcx>,
|
scrutinee_place_builder: PlaceBuilder<'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<()> {
|
||||||
|
@ -286,7 +291,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
this.source_scope = source_scope;
|
this.source_scope = source_scope;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.expr_into_dest(destination, arm_block, &arm.body)
|
this.expr_into_dest(destination, arm_block, &&this.thir[arm.body])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -313,7 +318,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>,
|
||||||
|
@ -389,7 +394,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`
|
||||||
|
@ -1665,7 +1670,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>,
|
||||||
|
@ -1799,12 +1804,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
self.cfg.push_assign(block, scrutinee_source_info, Place::from(temp), borrow);
|
self.cfg.push_assign(block, scrutinee_source_info, Place::from(temp), borrow);
|
||||||
}
|
}
|
||||||
|
|
||||||
let (guard_span, (post_guard_block, otherwise_post_guard_block)) = match guard {
|
let (guard_span, (post_guard_block, otherwise_post_guard_block)) = match *guard {
|
||||||
Guard::If(e) => {
|
Guard::If(e) => {
|
||||||
|
let e = &self.thir[e];
|
||||||
let source_info = self.source_info(e.span);
|
let source_info = self.source_info(e.span);
|
||||||
(e.span, self.test_bool(block, e, source_info))
|
(e.span, self.test_bool(block, e, source_info))
|
||||||
}
|
}
|
||||||
Guard::IfLet(pat, scrutinee) => {
|
Guard::IfLet(ref pat, scrutinee) => {
|
||||||
|
let scrutinee = &self.thir[scrutinee];
|
||||||
let scrutinee_span = scrutinee.span;
|
let scrutinee_span = scrutinee.span;
|
||||||
let scrutinee_place_builder =
|
let scrutinee_place_builder =
|
||||||
unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span));
|
unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span));
|
||||||
|
@ -1840,7 +1847,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
guard_candidate,
|
guard_candidate,
|
||||||
None,
|
None,
|
||||||
&fake_borrow_temps,
|
&fake_borrow_temps,
|
||||||
scrutinee.span,
|
scrutinee_span,
|
||||||
None,
|
None,
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::build;
|
use crate::build;
|
||||||
use crate::build::expr::as_place::PlaceBuilder;
|
use crate::build::expr::as_place::PlaceBuilder;
|
||||||
use crate::build::scope::DropKind;
|
use crate::build::scope::DropKind;
|
||||||
use crate::thir::{build_thir, Arena, BindingMode, Expr, LintLevel, Pat, PatKind};
|
use crate::thir::{build_thir, BindingMode, Expr, ExprId, LintLevel, Pat, PatKind, Thir};
|
||||||
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;
|
||||||
|
@ -88,7 +88,6 @@ 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 body = if let Some(ErrorReported) = typeck_results.tainted_by_errors {
|
let body = if let Some(ErrorReported) = typeck_results.tainted_by_errors {
|
||||||
|
@ -105,7 +104,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 thir = build_thir(tcx, def, &arena, &body.value);
|
let (thir, expr) = build_thir(tcx, def, &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() {
|
||||||
|
@ -181,6 +180,7 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut mir = build::construct_fn(
|
let mut mir = build::construct_fn(
|
||||||
|
&thir,
|
||||||
&infcx,
|
&infcx,
|
||||||
def,
|
def,
|
||||||
id,
|
id,
|
||||||
|
@ -190,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,
|
||||||
thir,
|
expr,
|
||||||
span_with_body,
|
span_with_body,
|
||||||
);
|
);
|
||||||
if yield_ty.is_some() {
|
if yield_ty.is_some() {
|
||||||
|
@ -213,9 +213,9 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
|
||||||
let return_ty = 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 thir = build_thir(tcx, def, &arena, ast_expr);
|
let (thir, expr) = build_thir(tcx, def, ast_expr);
|
||||||
|
|
||||||
build::construct_const(&infcx, thir, def, id, return_ty, return_ty_span)
|
build::construct_const(&thir, &infcx, expr, def, id, return_ty, return_ty_span)
|
||||||
};
|
};
|
||||||
|
|
||||||
lints::check(tcx, &body);
|
lints::check(tcx, &body);
|
||||||
|
@ -323,6 +323,7 @@ struct Builder<'a, 'tcx> {
|
||||||
region_scope_tree: &'tcx region::ScopeTree,
|
region_scope_tree: &'tcx region::ScopeTree,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
|
|
||||||
|
thir: &'a Thir<'tcx>,
|
||||||
cfg: CFG<'tcx>,
|
cfg: CFG<'tcx>,
|
||||||
|
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
|
@ -633,6 +634,7 @@ struct ArgInfo<'tcx>(
|
||||||
);
|
);
|
||||||
|
|
||||||
fn construct_fn<'tcx, A>(
|
fn construct_fn<'tcx, A>(
|
||||||
|
thir: &Thir<'tcx>,
|
||||||
infcx: &InferCtxt<'_, 'tcx>,
|
infcx: &InferCtxt<'_, 'tcx>,
|
||||||
fn_def: ty::WithOptConstParam<LocalDefId>,
|
fn_def: ty::WithOptConstParam<LocalDefId>,
|
||||||
fn_id: hir::HirId,
|
fn_id: hir::HirId,
|
||||||
|
@ -642,7 +644,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: ExprId,
|
||||||
span_with_body: Span,
|
span_with_body: Span,
|
||||||
) -> Body<'tcx>
|
) -> Body<'tcx>
|
||||||
where
|
where
|
||||||
|
@ -654,6 +656,7 @@ where
|
||||||
let span = tcx.hir().span(fn_id);
|
let span = tcx.hir().span(fn_id);
|
||||||
|
|
||||||
let mut builder = Builder::new(
|
let mut builder = Builder::new(
|
||||||
|
thir,
|
||||||
infcx,
|
infcx,
|
||||||
fn_def,
|
fn_def,
|
||||||
fn_id,
|
fn_id,
|
||||||
|
@ -683,7 +686,7 @@ where
|
||||||
fn_def.did.to_def_id(),
|
fn_def.did.to_def_id(),
|
||||||
&arguments,
|
&arguments,
|
||||||
arg_scope,
|
arg_scope,
|
||||||
expr,
|
&thir[expr],
|
||||||
)
|
)
|
||||||
}))
|
}))
|
||||||
}));
|
}));
|
||||||
|
@ -708,8 +711,9 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn construct_const<'a, 'tcx>(
|
fn construct_const<'a, 'tcx>(
|
||||||
|
thir: &'a Thir<'tcx>,
|
||||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||||
expr: &Expr<'_, 'tcx>,
|
expr: ExprId,
|
||||||
def: ty::WithOptConstParam<LocalDefId>,
|
def: ty::WithOptConstParam<LocalDefId>,
|
||||||
hir_id: hir::HirId,
|
hir_id: hir::HirId,
|
||||||
const_ty: Ty<'tcx>,
|
const_ty: Ty<'tcx>,
|
||||||
|
@ -717,11 +721,21 @@ fn construct_const<'a, 'tcx>(
|
||||||
) -> Body<'tcx> {
|
) -> Body<'tcx> {
|
||||||
let tcx = infcx.tcx;
|
let tcx = infcx.tcx;
|
||||||
let span = tcx.hir().span(hir_id);
|
let span = tcx.hir().span(hir_id);
|
||||||
let mut builder =
|
let mut builder = Builder::new(
|
||||||
Builder::new(infcx, def, hir_id, span, 0, Safety::Safe, const_ty, const_ty_span, None);
|
thir,
|
||||||
|
infcx,
|
||||||
|
def,
|
||||||
|
hir_id,
|
||||||
|
span,
|
||||||
|
0,
|
||||||
|
Safety::Safe,
|
||||||
|
const_ty,
|
||||||
|
const_ty_span,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
|
||||||
let mut block = START_BLOCK;
|
let mut block = START_BLOCK;
|
||||||
unpack!(block = builder.expr_into_dest(Place::return_place(), block, &expr));
|
unpack!(block = builder.expr_into_dest(Place::return_place(), block, &thir[expr]));
|
||||||
|
|
||||||
let source_info = builder.source_info(span);
|
let source_info = builder.source_info(span);
|
||||||
builder.cfg.terminate(block, source_info, TerminatorKind::Return);
|
builder.cfg.terminate(block, source_info, TerminatorKind::Return);
|
||||||
|
@ -761,22 +775,48 @@ fn construct_error<'a, 'tcx>(
|
||||||
hir::BodyOwnerKind::Const => 0,
|
hir::BodyOwnerKind::Const => 0,
|
||||||
hir::BodyOwnerKind::Static(_) => 0,
|
hir::BodyOwnerKind::Static(_) => 0,
|
||||||
};
|
};
|
||||||
let mut builder =
|
let mut cfg = CFG { basic_blocks: IndexVec::new() };
|
||||||
Builder::new(infcx, def, hir_id, span, num_params, Safety::Safe, ty, span, generator_kind);
|
let mut source_scopes = IndexVec::new();
|
||||||
let source_info = builder.source_info(span);
|
let mut local_decls = IndexVec::from_elem_n(LocalDecl::new(ty, span), 1);
|
||||||
|
|
||||||
|
cfg.start_new_block();
|
||||||
|
source_scopes.push(SourceScopeData {
|
||||||
|
span,
|
||||||
|
parent_scope: None,
|
||||||
|
inlined: None,
|
||||||
|
inlined_parent_scope: None,
|
||||||
|
local_data: ClearCrossCrate::Set(SourceScopeLocalData {
|
||||||
|
lint_root: hir_id,
|
||||||
|
safety: Safety::Safe,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
let source_info = SourceInfo { span, scope: OUTERMOST_SOURCE_SCOPE };
|
||||||
|
|
||||||
// Some MIR passes will expect the number of parameters to match the
|
// Some MIR passes will expect the number of parameters to match the
|
||||||
// function declaration.
|
// function declaration.
|
||||||
for _ in 0..num_params {
|
for _ in 0..num_params {
|
||||||
builder.local_decls.push(LocalDecl::with_source_info(ty, source_info));
|
local_decls.push(LocalDecl::with_source_info(ty, source_info));
|
||||||
}
|
}
|
||||||
builder.cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
|
cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
|
||||||
let mut body = builder.finish();
|
|
||||||
|
let mut body = Body::new(
|
||||||
|
MirSource::item(def.did.to_def_id()),
|
||||||
|
cfg.basic_blocks,
|
||||||
|
source_scopes,
|
||||||
|
local_decls,
|
||||||
|
IndexVec::new(),
|
||||||
|
num_params,
|
||||||
|
vec![],
|
||||||
|
span,
|
||||||
|
generator_kind,
|
||||||
|
);
|
||||||
body.generator.as_mut().map(|gen| gen.yield_ty = Some(ty));
|
body.generator.as_mut().map(|gen| gen.yield_ty = Some(ty));
|
||||||
body
|
body
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
fn new(
|
fn new(
|
||||||
|
thir: &'a Thir<'tcx>,
|
||||||
infcx: &'a InferCtxt<'a, 'tcx>,
|
infcx: &'a InferCtxt<'a, 'tcx>,
|
||||||
def: ty::WithOptConstParam<LocalDefId>,
|
def: ty::WithOptConstParam<LocalDefId>,
|
||||||
hir_id: hir::HirId,
|
hir_id: hir::HirId,
|
||||||
|
@ -803,6 +843,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
|
|
||||||
let lint_level = LintLevel::Explicit(hir_id);
|
let lint_level = LintLevel::Explicit(hir_id);
|
||||||
let mut builder = Builder {
|
let mut builder = Builder {
|
||||||
|
thir,
|
||||||
tcx,
|
tcx,
|
||||||
infcx,
|
infcx,
|
||||||
typeck_results: tcx.typeck_opt_const_arg(def),
|
typeck_results: tcx.typeck_opt_const_arg(def),
|
||||||
|
@ -866,7 +907,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() {
|
||||||
|
|
|
@ -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<()> {
|
||||||
|
@ -933,7 +933,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));
|
||||||
|
|
|
@ -1,98 +0,0 @@
|
||||||
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>,
|
|
||||||
]);
|
|
|
@ -7,8 +7,8 @@ use rustc_middle::ty;
|
||||||
|
|
||||||
use rustc_index::vec::Idx;
|
use rustc_index::vec::Idx;
|
||||||
|
|
||||||
impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
impl<'tcx> Cx<'tcx> {
|
||||||
crate fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> Block<'thir, 'tcx> {
|
crate fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> Block {
|
||||||
// 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);
|
||||||
|
@ -37,65 +37,78 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
block_id: hir::ItemLocalId,
|
block_id: hir::ItemLocalId,
|
||||||
stmts: &'tcx [hir::Stmt<'tcx>],
|
stmts: &'tcx [hir::Stmt<'tcx>],
|
||||||
) -> &'thir [Stmt<'thir, 'tcx>] {
|
) -> Box<[StmtId]> {
|
||||||
self.arena.alloc_from_iter(stmts.iter().enumerate().filter_map(|(index, stmt)| {
|
stmts
|
||||||
let hir_id = stmt.hir_id;
|
.iter()
|
||||||
let opt_dxn_ext = self.region_scope_tree.opt_destruction_scope(hir_id.local_id);
|
.enumerate()
|
||||||
match stmt.kind {
|
.filter_map(|(index, stmt)| {
|
||||||
hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => Some(Stmt {
|
let hir_id = stmt.hir_id;
|
||||||
kind: StmtKind::Expr {
|
let opt_dxn_ext = self.region_scope_tree.opt_destruction_scope(hir_id.local_id);
|
||||||
scope: region::Scope { id: hir_id.local_id, data: region::ScopeData::Node },
|
match stmt.kind {
|
||||||
expr: self.mirror_expr(expr),
|
hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => {
|
||||||
},
|
let stmt = Stmt {
|
||||||
opt_destruction_scope: opt_dxn_ext,
|
kind: StmtKind::Expr {
|
||||||
}),
|
scope: region::Scope {
|
||||||
hir::StmtKind::Item(..) => {
|
id: hir_id.local_id,
|
||||||
// ignore for purposes of the MIR
|
data: region::ScopeData::Node,
|
||||||
None
|
},
|
||||||
}
|
expr: self.mirror_expr(expr),
|
||||||
hir::StmtKind::Local(ref local) => {
|
|
||||||
let remainder_scope = region::Scope {
|
|
||||||
id: block_id,
|
|
||||||
data: region::ScopeData::Remainder(region::FirstStatementIndex::new(index)),
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut pattern = self.pattern_from_hir(local.pat);
|
|
||||||
|
|
||||||
if let Some(ty) = &local.ty {
|
|
||||||
if let Some(&user_ty) =
|
|
||||||
self.typeck_results.user_provided_types().get(ty.hir_id)
|
|
||||||
{
|
|
||||||
debug!("mirror_stmts: user_ty={:?}", user_ty);
|
|
||||||
pattern = Pat {
|
|
||||||
ty: pattern.ty,
|
|
||||||
span: pattern.span,
|
|
||||||
kind: Box::new(PatKind::AscribeUserType {
|
|
||||||
ascription: thir::pattern::Ascription {
|
|
||||||
user_ty: PatTyProj::from_user_type(user_ty),
|
|
||||||
user_ty_span: ty.span,
|
|
||||||
variance: ty::Variance::Covariant,
|
|
||||||
},
|
|
||||||
subpattern: pattern,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Some(Stmt {
|
|
||||||
kind: StmtKind::Let {
|
|
||||||
remainder_scope,
|
|
||||||
init_scope: region::Scope {
|
|
||||||
id: hir_id.local_id,
|
|
||||||
data: region::ScopeData::Node,
|
|
||||||
},
|
},
|
||||||
pattern,
|
opt_destruction_scope: opt_dxn_ext,
|
||||||
initializer: local.init.map(|init| self.mirror_expr(init)),
|
};
|
||||||
lint_level: LintLevel::Explicit(local.hir_id),
|
Some(self.thir.stmts.push(stmt))
|
||||||
},
|
}
|
||||||
opt_destruction_scope: opt_dxn_ext,
|
hir::StmtKind::Item(..) => {
|
||||||
})
|
// ignore for purposes of the MIR
|
||||||
|
None
|
||||||
|
}
|
||||||
|
hir::StmtKind::Local(ref local) => {
|
||||||
|
let remainder_scope = region::Scope {
|
||||||
|
id: block_id,
|
||||||
|
data: region::ScopeData::Remainder(region::FirstStatementIndex::new(
|
||||||
|
index,
|
||||||
|
)),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut pattern = self.pattern_from_hir(local.pat);
|
||||||
|
|
||||||
|
if let Some(ty) = &local.ty {
|
||||||
|
if let Some(&user_ty) =
|
||||||
|
self.typeck_results.user_provided_types().get(ty.hir_id)
|
||||||
|
{
|
||||||
|
debug!("mirror_stmts: user_ty={:?}", user_ty);
|
||||||
|
pattern = Pat {
|
||||||
|
ty: pattern.ty,
|
||||||
|
span: pattern.span,
|
||||||
|
kind: Box::new(PatKind::AscribeUserType {
|
||||||
|
ascription: thir::pattern::Ascription {
|
||||||
|
user_ty: PatTyProj::from_user_type(user_ty),
|
||||||
|
user_ty_span: ty.span,
|
||||||
|
variance: ty::Variance::Covariant,
|
||||||
|
},
|
||||||
|
subpattern: pattern,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let stmt = Stmt {
|
||||||
|
kind: StmtKind::Let {
|
||||||
|
remainder_scope,
|
||||||
|
init_scope: region::Scope {
|
||||||
|
id: hir_id.local_id,
|
||||||
|
data: region::ScopeData::Node,
|
||||||
|
},
|
||||||
|
pattern,
|
||||||
|
initializer: local.init.map(|init| self.mirror_expr(init)),
|
||||||
|
lint_level: LintLevel::Explicit(local.hir_id),
|
||||||
|
},
|
||||||
|
opt_destruction_scope: opt_dxn_ext,
|
||||||
|
};
|
||||||
|
Some(self.thir.stmts.push(stmt))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}))
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,34 +17,17 @@ 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;
|
||||||
|
|
||||||
use std::iter;
|
impl<'tcx> Cx<'tcx> {
|
||||||
|
crate fn mirror_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> ExprId {
|
||||||
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> {
|
|
||||||
// `mirror_expr` is recursing very deep. Make sure the stack doesn't overflow.
|
// `mirror_expr` is recursing very deep. Make sure the stack doesn't overflow.
|
||||||
ensure_sufficient_stack(|| self.arena.alloc(self.mirror_expr_inner(expr)))
|
ensure_sufficient_stack(|| self.mirror_expr_inner(expr))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mirrors and allocates a slice of [`hir::Expr`]s. They will be allocated as a
|
crate fn mirror_exprs(&mut self, exprs: &'tcx [hir::Expr<'tcx>]) -> Box<[ExprId]> {
|
||||||
/// contiguous sequence in memory.
|
exprs.iter().map(|expr| self.mirror_expr_inner(expr)).collect()
|
||||||
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.
|
pub(super) fn mirror_expr_inner(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> ExprId {
|
||||||
/// 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 };
|
||||||
|
@ -66,7 +49,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
span: hir_expr.span,
|
span: hir_expr.span,
|
||||||
kind: ExprKind::Scope {
|
kind: ExprKind::Scope {
|
||||||
region_scope: expr_scope,
|
region_scope: expr_scope,
|
||||||
value: self.arena.alloc(expr),
|
value: self.thir.exprs.push(expr),
|
||||||
lint_level: LintLevel::Explicit(hir_expr.hir_id),
|
lint_level: LintLevel::Explicit(hir_expr.hir_id),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
@ -81,22 +64,22 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
span: hir_expr.span,
|
span: hir_expr.span,
|
||||||
kind: ExprKind::Scope {
|
kind: ExprKind::Scope {
|
||||||
region_scope,
|
region_scope,
|
||||||
value: self.arena.alloc(expr),
|
value: self.thir.exprs.push(expr),
|
||||||
lint_level: LintLevel::Inherited,
|
lint_level: LintLevel::Inherited,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// OK, all done!
|
// OK, all done!
|
||||||
expr
|
self.thir.exprs.push(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<'thir, 'tcx>,
|
mut expr: Expr<'tcx>,
|
||||||
adjustment: &Adjustment<'tcx>,
|
adjustment: &Adjustment<'tcx>,
|
||||||
) -> Expr<'thir, 'tcx> {
|
) -> Expr<'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
|
||||||
|
@ -109,10 +92,10 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
// x
|
// x
|
||||||
// // ^ error message points at this expression.
|
// // ^ error message points at this expression.
|
||||||
// }
|
// }
|
||||||
let mut adjust_span = |expr: &mut Expr<'thir, 'tcx>| {
|
let mut adjust_span = |expr: &mut Expr<'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(last_expr) = body.expr {
|
||||||
span = last_expr.span;
|
span = self.thir[last_expr].span;
|
||||||
expr.span = span;
|
expr.span = span;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -121,13 +104,13 @@ impl<'thir, 'tcx> Cx<'thir, '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: self.arena.alloc(expr) }
|
ExprKind::Pointer { cast: PointerCast::Unsize, source: self.thir.exprs.push(expr) }
|
||||||
}
|
}
|
||||||
Adjust::Pointer(cast) => ExprKind::Pointer { cast, source: self.arena.alloc(expr) },
|
Adjust::Pointer(cast) => ExprKind::Pointer { cast, source: self.thir.exprs.push(expr) },
|
||||||
Adjust::NeverToAny => ExprKind::NeverToAny { source: self.arena.alloc(expr) },
|
Adjust::NeverToAny => ExprKind::NeverToAny { source: self.thir.exprs.push(expr) },
|
||||||
Adjust::Deref(None) => {
|
Adjust::Deref(None) => {
|
||||||
adjust_span(&mut expr);
|
adjust_span(&mut expr);
|
||||||
ExprKind::Deref { arg: self.arena.alloc(expr) }
|
ExprKind::Deref { arg: self.thir.exprs.push(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
|
||||||
|
@ -142,30 +125,27 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
span,
|
span,
|
||||||
kind: ExprKind::Borrow {
|
kind: ExprKind::Borrow {
|
||||||
borrow_kind: deref.mutbl.to_borrow_kind(),
|
borrow_kind: deref.mutbl.to_borrow_kind(),
|
||||||
arg: self.arena.alloc(expr),
|
arg: self.thir.exprs.push(expr),
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
self.overloaded_place(
|
let expr = box [self.thir.exprs.push(expr)];
|
||||||
hir_expr,
|
|
||||||
adjustment.target,
|
self.overloaded_place(hir_expr, adjustment.target, Some(call), expr, deref.span)
|
||||||
Some(call),
|
|
||||||
self.arena.alloc_from_iter(iter::once(expr)),
|
|
||||||
deref.span,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
Adjust::Borrow(AutoBorrow::Ref(_, m)) => {
|
|
||||||
ExprKind::Borrow { borrow_kind: m.to_borrow_kind(), arg: self.arena.alloc(expr) }
|
|
||||||
}
|
}
|
||||||
|
Adjust::Borrow(AutoBorrow::Ref(_, m)) => ExprKind::Borrow {
|
||||||
|
borrow_kind: m.to_borrow_kind(),
|
||||||
|
arg: self.thir.exprs.push(expr),
|
||||||
|
},
|
||||||
Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
|
Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => {
|
||||||
ExprKind::AddressOf { mutability, arg: self.arena.alloc(expr) }
|
ExprKind::AddressOf { mutability, arg: self.thir.exprs.push(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<'thir, 'tcx> {
|
fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'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);
|
||||||
|
|
||||||
|
@ -177,7 +157,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
let args = self.mirror_exprs(args);
|
let args = self.mirror_exprs(args);
|
||||||
ExprKind::Call {
|
ExprKind::Call {
|
||||||
ty: expr.ty,
|
ty: expr.ty,
|
||||||
fun: self.arena.alloc(expr),
|
fun: self.thir.exprs.push(expr),
|
||||||
args,
|
args,
|
||||||
from_hir_call: true,
|
from_hir_call: true,
|
||||||
fn_span,
|
fn_span,
|
||||||
|
@ -202,13 +182,12 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
span: expr.span,
|
span: expr.span,
|
||||||
kind: ExprKind::Tuple { fields: self.mirror_exprs(args) },
|
kind: ExprKind::Tuple { fields: self.mirror_exprs(args) },
|
||||||
};
|
};
|
||||||
|
let tupled_args = self.thir.exprs.push(tupled_args);
|
||||||
|
|
||||||
ExprKind::Call {
|
ExprKind::Call {
|
||||||
ty: method.ty,
|
ty: method.ty,
|
||||||
fun: self.arena.alloc(method),
|
fun: self.thir.exprs.push(method),
|
||||||
args: self
|
args: box [self.mirror_expr(fun), tupled_args],
|
||||||
.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,
|
||||||
}
|
}
|
||||||
|
@ -238,10 +217,14 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
});
|
});
|
||||||
debug!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty);
|
debug!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty);
|
||||||
|
|
||||||
let field_refs =
|
let field_refs = args
|
||||||
self.arena.alloc_from_iter(args.iter().enumerate().map(|(idx, e)| {
|
.iter()
|
||||||
FieldExpr { name: Field::new(idx), expr: self.mirror_expr(e) }
|
.enumerate()
|
||||||
}));
|
.map(|(idx, e)| FieldExpr {
|
||||||
|
name: Field::new(idx),
|
||||||
|
expr: self.mirror_expr(e),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
ExprKind::Adt {
|
ExprKind::Adt {
|
||||||
adt_def,
|
adt_def,
|
||||||
substs,
|
substs,
|
||||||
|
@ -278,9 +261,9 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
|
|
||||||
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_inner(lhs);
|
let lhs = self.mirror_expr(lhs);
|
||||||
let rhs = self.mirror_expr_inner(rhs);
|
let rhs = self.mirror_expr(rhs);
|
||||||
self.overloaded_operator(expr, self.arena.alloc_from_iter(vec![lhs, rhs]))
|
self.overloaded_operator(expr, box [lhs, rhs])
|
||||||
} else {
|
} else {
|
||||||
ExprKind::AssignOp {
|
ExprKind::AssignOp {
|
||||||
op: bin_op(op.node),
|
op: bin_op(op.node),
|
||||||
|
@ -298,9 +281,9 @@ impl<'thir, 'tcx> Cx<'thir, '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_inner(lhs);
|
let lhs = self.mirror_expr(lhs);
|
||||||
let rhs = self.mirror_expr_inner(rhs);
|
let rhs = self.mirror_expr(rhs);
|
||||||
self.overloaded_operator(expr, self.arena.alloc_from_iter(vec![lhs, rhs]))
|
self.overloaded_operator(expr, box [lhs, rhs])
|
||||||
} else {
|
} else {
|
||||||
// FIXME overflow
|
// FIXME overflow
|
||||||
match op.node {
|
match op.node {
|
||||||
|
@ -329,15 +312,9 @@ impl<'thir, 'tcx> Cx<'thir, '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_inner(lhs);
|
let lhs = self.mirror_expr(lhs);
|
||||||
let index = self.mirror_expr_inner(index);
|
let index = self.mirror_expr(index);
|
||||||
self.overloaded_place(
|
self.overloaded_place(expr, expr_ty, None, box [lhs, index], expr.span)
|
||||||
expr,
|
|
||||||
expr_ty,
|
|
||||||
None,
|
|
||||||
self.arena.alloc_from_iter(vec![lhs, index]),
|
|
||||||
expr.span,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
ExprKind::Index { lhs: self.mirror_expr(lhs), index: self.mirror_expr(index) }
|
ExprKind::Index { lhs: self.mirror_expr(lhs), index: self.mirror_expr(index) }
|
||||||
}
|
}
|
||||||
|
@ -345,14 +322,8 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
|
|
||||||
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_inner(arg);
|
let arg = self.mirror_expr(arg);
|
||||||
self.overloaded_place(
|
self.overloaded_place(expr, expr_ty, None, box [arg], expr.span)
|
||||||
expr,
|
|
||||||
expr_ty,
|
|
||||||
None,
|
|
||||||
self.arena.alloc_from_iter(iter::once(arg)),
|
|
||||||
expr.span,
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
ExprKind::Deref { arg: self.mirror_expr(arg) }
|
ExprKind::Deref { arg: self.mirror_expr(arg) }
|
||||||
}
|
}
|
||||||
|
@ -360,8 +331,8 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
|
|
||||||
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_inner(arg);
|
let arg = self.mirror_expr(arg);
|
||||||
self.overloaded_operator(expr, self.arena.alloc_from_iter(iter::once(arg)))
|
self.overloaded_operator(expr, box [arg])
|
||||||
} else {
|
} else {
|
||||||
ExprKind::Unary { op: UnOp::Not, arg: self.mirror_expr(arg) }
|
ExprKind::Unary { op: UnOp::Not, arg: self.mirror_expr(arg) }
|
||||||
}
|
}
|
||||||
|
@ -369,8 +340,8 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
|
|
||||||
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_inner(arg);
|
let arg = self.mirror_expr(arg);
|
||||||
self.overloaded_operator(expr, self.arena.alloc_from_iter(iter::once(arg)))
|
self.overloaded_operator(expr, box [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),
|
||||||
|
@ -396,11 +367,10 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
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(base),
|
base: self.mirror_expr(base),
|
||||||
field_types: self.arena.alloc_from_iter(
|
field_types: self.typeck_results().fru_field_types()[expr.hir_id]
|
||||||
self.typeck_results().fru_field_types()[expr.hir_id]
|
.iter()
|
||||||
.iter()
|
.copied()
|
||||||
.cloned(),
|
.collect(),
|
||||||
),
|
|
||||||
}),
|
}),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -447,12 +417,15 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let upvars = self.arena.alloc_from_iter(
|
let upvars = self
|
||||||
self.typeck_results
|
.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)| {
|
||||||
);
|
let upvars = self.capture_upvar(expr, captured_place, ty);
|
||||||
|
self.thir.exprs.push(upvars)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
// Convert the closure fake reads, if any, from hir `Place` to ExprRef
|
// Convert the closure fake reads, if any, from hir `Place` to ExprRef
|
||||||
let fake_reads = match self.typeck_results.closure_fake_reads.get(&def_id) {
|
let fake_reads = match self.typeck_results.closure_fake_reads.get(&def_id) {
|
||||||
|
@ -460,8 +433,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
.iter()
|
.iter()
|
||||||
.map(|(place, cause, hir_id)| {
|
.map(|(place, cause, hir_id)| {
|
||||||
let expr = self.convert_captured_hir_place(expr, place.clone());
|
let expr = self.convert_captured_hir_place(expr, place.clone());
|
||||||
let expr_ref: &'thir Expr<'thir, 'tcx> = self.arena.alloc(expr);
|
(self.thir.exprs.push(expr), *cause, *hir_id)
|
||||||
(expr_ref, *cause, *hir_id)
|
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
None => Vec::new(),
|
None => Vec::new(),
|
||||||
|
@ -477,99 +449,105 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
|
|
||||||
hir::ExprKind::InlineAsm(ref asm) => ExprKind::InlineAsm {
|
hir::ExprKind::InlineAsm(ref asm) => ExprKind::InlineAsm {
|
||||||
template: asm.template,
|
template: asm.template,
|
||||||
operands: self.arena.alloc_from_iter(asm.operands.iter().map(|(op, _op_sp)| {
|
operands: asm
|
||||||
match *op {
|
.operands
|
||||||
hir::InlineAsmOperand::In { reg, ref expr } => {
|
.iter()
|
||||||
InlineAsmOperand::In { reg, expr: self.mirror_expr(expr) }
|
.map(|(op, _op_sp)| {
|
||||||
}
|
match *op {
|
||||||
hir::InlineAsmOperand::Out { reg, late, ref expr } => {
|
hir::InlineAsmOperand::In { reg, ref expr } => {
|
||||||
InlineAsmOperand::Out {
|
InlineAsmOperand::In { reg, expr: self.mirror_expr(expr) }
|
||||||
|
}
|
||||||
|
hir::InlineAsmOperand::Out { reg, late, ref expr } => {
|
||||||
|
InlineAsmOperand::Out {
|
||||||
|
reg,
|
||||||
|
late,
|
||||||
|
expr: expr.as_ref().map(|expr| self.mirror_expr(expr)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
hir::InlineAsmOperand::InOut { reg, late, ref expr } => {
|
||||||
|
InlineAsmOperand::InOut { reg, late, expr: self.mirror_expr(expr) }
|
||||||
|
}
|
||||||
|
hir::InlineAsmOperand::SplitInOut {
|
||||||
reg,
|
reg,
|
||||||
late,
|
late,
|
||||||
expr: expr.as_ref().map(|expr| self.mirror_expr(expr)),
|
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 anon_const } => {
|
||||||
|
let anon_const_def_id =
|
||||||
|
self.tcx.hir().local_def_id(anon_const.hir_id);
|
||||||
|
let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id);
|
||||||
|
let span = self.tcx.hir().span(anon_const.hir_id);
|
||||||
|
|
||||||
|
InlineAsmOperand::Const { value, span }
|
||||||
}
|
}
|
||||||
}
|
hir::InlineAsmOperand::Sym { ref expr } => {
|
||||||
hir::InlineAsmOperand::InOut { reg, late, ref expr } => {
|
let qpath = match expr.kind {
|
||||||
InlineAsmOperand::InOut { reg, late, expr: self.mirror_expr(expr) }
|
hir::ExprKind::Path(ref qpath) => qpath,
|
||||||
}
|
_ => span_bug!(
|
||||||
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 anon_const } => {
|
|
||||||
let anon_const_def_id = self.tcx.hir().local_def_id(anon_const.hir_id);
|
|
||||||
let value = ty::Const::from_anon_const(self.tcx, anon_const_def_id);
|
|
||||||
let span = self.tcx.hir().span(anon_const.hir_id);
|
|
||||||
|
|
||||||
InlineAsmOperand::Const { value, span }
|
|
||||||
}
|
|
||||||
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,
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Res::Def(DefKind::Static, def_id) => {
|
|
||||||
InlineAsmOperand::SymStatic { def_id }
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => {
|
|
||||||
self.tcx.sess.span_err(
|
|
||||||
expr.span,
|
expr.span,
|
||||||
"asm `sym` operand must point to a fn or static",
|
"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.thir.exprs.push(Expr {
|
||||||
|
ty,
|
||||||
|
temp_lifetime,
|
||||||
|
span: expr.span,
|
||||||
|
kind: ExprKind::Literal {
|
||||||
|
literal: ty::Const::zero_sized(self.tcx, ty),
|
||||||
|
user_ty,
|
||||||
|
const_id: None,
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Not a real fn, but we're not reaching codegen anyways...
|
Res::Def(DefKind::Static, def_id) => {
|
||||||
ty = self.tcx.ty_error();
|
InlineAsmOperand::SymStatic { def_id }
|
||||||
InlineAsmOperand::SymFn {
|
}
|
||||||
expr: self.arena.alloc(Expr {
|
|
||||||
ty,
|
_ => {
|
||||||
temp_lifetime,
|
self.tcx.sess.span_err(
|
||||||
span: expr.span,
|
expr.span,
|
||||||
kind: ExprKind::Literal {
|
"asm `sym` operand must point to a fn or static",
|
||||||
literal: ty::Const::zero_sized(self.tcx, ty),
|
);
|
||||||
user_ty: None,
|
|
||||||
const_id: None,
|
// Not a real fn, but we're not reaching codegen anyways...
|
||||||
},
|
ty = self.tcx.ty_error();
|
||||||
}),
|
InlineAsmOperand::SymFn {
|
||||||
|
expr: self.thir.exprs.push(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,
|
||||||
},
|
},
|
||||||
|
@ -616,13 +594,13 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
},
|
},
|
||||||
hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match {
|
hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match {
|
||||||
scrutinee: self.mirror_expr(discr),
|
scrutinee: self.mirror_expr(discr),
|
||||||
arms: self.arena.alloc_from_iter(arms.iter().map(|a| self.convert_arm(a))),
|
arms: arms.iter().map(|a| self.convert_arm(a)).collect(),
|
||||||
},
|
},
|
||||||
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 = self.arena.alloc(Expr {
|
let body = self.thir.exprs.push(Expr {
|
||||||
ty: block_ty,
|
ty: block_ty,
|
||||||
temp_lifetime,
|
temp_lifetime,
|
||||||
span: block.span,
|
span: block.span,
|
||||||
|
@ -692,35 +670,34 @@ impl<'thir, 'tcx> Cx<'thir, '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| {
|
let mk_const = |literal| Expr {
|
||||||
self.arena.alloc(Expr {
|
temp_lifetime,
|
||||||
temp_lifetime,
|
ty: var_ty,
|
||||||
ty: var_ty,
|
span: expr.span,
|
||||||
span: expr.span,
|
kind: ExprKind::Literal { literal, user_ty: None, const_id: None },
|
||||||
kind: ExprKind::Literal { literal, user_ty: None, const_id: None },
|
|
||||||
})
|
|
||||||
};
|
};
|
||||||
let offset = mk_const(ty::Const::from_bits(
|
let offset = self.thir.exprs.push(mk_const(ty::Const::from_bits(
|
||||||
self.tcx,
|
self.tcx,
|
||||||
offset as u128,
|
offset as u128,
|
||||||
self.param_env.and(var_ty),
|
self.param_env.and(var_ty),
|
||||||
));
|
)));
|
||||||
match did {
|
match did {
|
||||||
Some(did) => {
|
Some(did) => {
|
||||||
// in case we are offsetting from a computed discriminant
|
// in case we are offsetting from a computed discriminant
|
||||||
// and not the beginning of discriminants (which is always `0`)
|
// and not the beginning of discriminants (which is always `0`)
|
||||||
let substs = InternalSubsts::identity_for_item(self.tcx(), did);
|
let substs = InternalSubsts::identity_for_item(self.tcx(), did);
|
||||||
let lhs = mk_const(self.tcx().mk_const(ty::Const {
|
let lhs = ty::Const {
|
||||||
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
|
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
|
||||||
def: ty::WithOptConstParam::unknown(did),
|
def: ty::WithOptConstParam::unknown(did),
|
||||||
substs,
|
substs,
|
||||||
promoted: None,
|
promoted: None,
|
||||||
}),
|
}),
|
||||||
ty: var_ty,
|
ty: var_ty,
|
||||||
}));
|
};
|
||||||
|
let lhs = self.thir.exprs.push(mk_const(self.tcx().mk_const(lhs)));
|
||||||
let bin =
|
let bin =
|
||||||
ExprKind::Binary { op: BinOp::Add, lhs: lhs, rhs: offset };
|
ExprKind::Binary { op: BinOp::Add, lhs: lhs, rhs: offset };
|
||||||
self.arena.alloc(Expr {
|
self.thir.exprs.push(Expr {
|
||||||
temp_lifetime,
|
temp_lifetime,
|
||||||
ty: var_ty,
|
ty: var_ty,
|
||||||
span: expr.span,
|
span: expr.span,
|
||||||
|
@ -739,7 +716,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
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 = self.arena.alloc(Expr {
|
let cast_expr = self.thir.exprs.push(Expr {
|
||||||
temp_lifetime,
|
temp_lifetime,
|
||||||
ty: expr_ty,
|
ty: expr_ty,
|
||||||
span: expr.span,
|
span: expr.span,
|
||||||
|
@ -819,7 +796,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
expr: &hir::Expr<'_>,
|
expr: &hir::Expr<'_>,
|
||||||
span: Span,
|
span: Span,
|
||||||
overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
|
overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>,
|
||||||
) -> Expr<'thir, 'tcx> {
|
) -> Expr<'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),
|
||||||
|
@ -846,8 +823,8 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> Arm<'thir, 'tcx> {
|
fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> ArmId {
|
||||||
Arm {
|
let 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(e)),
|
hir::Guard::If(ref e) => Guard::If(self.mirror_expr(e)),
|
||||||
|
@ -859,14 +836,11 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
lint_level: LintLevel::Explicit(arm.hir_id),
|
lint_level: LintLevel::Explicit(arm.hir_id),
|
||||||
scope: region::Scope { id: arm.hir_id.local_id, data: region::ScopeData::Node },
|
scope: region::Scope { id: arm.hir_id.local_id, data: region::ScopeData::Node },
|
||||||
span: arm.span,
|
span: arm.span,
|
||||||
}
|
};
|
||||||
|
self.thir.arms.push(arm)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_path_expr(
|
fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKind<'tcx> {
|
||||||
&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.
|
||||||
|
@ -934,7 +908,7 @@ impl<'thir, 'tcx> Cx<'thir, '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: self.arena.alloc_from_iter(iter::empty()),
|
fields: box [],
|
||||||
base: None,
|
base: None,
|
||||||
},
|
},
|
||||||
_ => bug!("unexpected ty: {:?}", ty),
|
_ => bug!("unexpected ty: {:?}", ty),
|
||||||
|
@ -956,7 +930,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
ExprKind::Deref {
|
ExprKind::Deref {
|
||||||
arg: self.arena.alloc(Expr { ty, temp_lifetime, span: expr.span, kind }),
|
arg: self.thir.exprs.push(Expr { ty, temp_lifetime, span: expr.span, kind }),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -966,7 +940,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn convert_var(&mut self, var_hir_id: hir::HirId) -> ExprKind<'thir, 'tcx> {
|
fn convert_var(&mut self, var_hir_id: hir::HirId) -> ExprKind<'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
|
||||||
|
@ -989,10 +963,17 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
fn overloaded_operator(
|
fn overloaded_operator(
|
||||||
&mut self,
|
&mut self,
|
||||||
expr: &'tcx hir::Expr<'tcx>,
|
expr: &'tcx hir::Expr<'tcx>,
|
||||||
args: &'thir [Expr<'thir, 'tcx>],
|
args: Box<[ExprId]>,
|
||||||
) -> ExprKind<'thir, 'tcx> {
|
) -> ExprKind<'tcx> {
|
||||||
let fun = self.arena.alloc(self.method_callee(expr, expr.span, None));
|
let fun = self.method_callee(expr, expr.span, None);
|
||||||
ExprKind::Call { ty: fun.ty, fun, args, from_hir_call: false, fn_span: expr.span }
|
let fun = self.thir.exprs.push(fun);
|
||||||
|
ExprKind::Call {
|
||||||
|
ty: self.thir[fun].ty,
|
||||||
|
fun,
|
||||||
|
args,
|
||||||
|
from_hir_call: false,
|
||||||
|
fn_span: expr.span,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn overloaded_place(
|
fn overloaded_place(
|
||||||
|
@ -1000,9 +981,9 @@ impl<'thir, 'tcx> Cx<'thir, '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: &'thir [Expr<'thir, 'tcx>],
|
args: Box<[ExprId]>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> ExprKind<'thir, 'tcx> {
|
) -> ExprKind<'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):
|
||||||
|
@ -1010,7 +991,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
// Reconstruct the output assuming it's a reference with the
|
// Reconstruct the output assuming it's a reference with the
|
||||||
// same region and mutability as the receiver. This holds for
|
// same region and mutability as the receiver. This holds for
|
||||||
// `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
|
// `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`.
|
||||||
let (region, mutbl) = match *args[0].ty.kind() {
|
let (region, mutbl) = match *self.thir[args[0]].ty.kind() {
|
||||||
ty::Ref(region, _, mutbl) => (region, mutbl),
|
ty::Ref(region, _, mutbl) => (region, mutbl),
|
||||||
_ => span_bug!(span, "overloaded_place: receiver is not a reference"),
|
_ => span_bug!(span, "overloaded_place: receiver is not a reference"),
|
||||||
};
|
};
|
||||||
|
@ -1019,12 +1000,14 @@ impl<'thir, 'tcx> Cx<'thir, '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 = self.arena.alloc(self.method_callee(expr, span, overloaded_callee));
|
let fun = self.method_callee(expr, span, overloaded_callee);
|
||||||
let ref_expr = self.arena.alloc(Expr {
|
let fun = self.thir.exprs.push(fun);
|
||||||
|
let fun_ty = self.thir[fun].ty;
|
||||||
|
let ref_expr = self.thir.exprs.push(Expr {
|
||||||
temp_lifetime,
|
temp_lifetime,
|
||||||
ty: ref_ty,
|
ty: ref_ty,
|
||||||
span,
|
span,
|
||||||
kind: ExprKind::Call { ty: fun.ty, fun, args, from_hir_call: false, fn_span: span },
|
kind: ExprKind::Call { ty: fun_ty, fun, args, from_hir_call: false, fn_span: span },
|
||||||
});
|
});
|
||||||
|
|
||||||
// construct and return a deref wrapper `*foo()`
|
// construct and return a deref wrapper `*foo()`
|
||||||
|
@ -1035,7 +1018,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
closure_expr: &'tcx hir::Expr<'tcx>,
|
closure_expr: &'tcx hir::Expr<'tcx>,
|
||||||
place: HirPlace<'tcx>,
|
place: HirPlace<'tcx>,
|
||||||
) -> Expr<'thir, 'tcx> {
|
) -> Expr<'tcx> {
|
||||||
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 = place.base_ty;
|
let var_ty = place.base_ty;
|
||||||
|
|
||||||
|
@ -1059,13 +1042,13 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
for proj in place.projections.iter() {
|
for proj in place.projections.iter() {
|
||||||
let kind = match proj.kind {
|
let kind = match proj.kind {
|
||||||
HirProjectionKind::Deref => {
|
HirProjectionKind::Deref => {
|
||||||
ExprKind::Deref { arg: self.arena.alloc(captured_place_expr) }
|
ExprKind::Deref { arg: self.thir.exprs.push(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: self.arena.alloc(captured_place_expr),
|
lhs: self.thir.exprs.push(captured_place_expr),
|
||||||
name: Field::new(field as usize),
|
name: Field::new(field as usize),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1087,7 +1070,7 @@ impl<'thir, 'tcx> Cx<'thir, '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<'thir, 'tcx> {
|
) -> Expr<'tcx> {
|
||||||
let upvar_capture = captured_place.info.capture_kind;
|
let upvar_capture = captured_place.info.capture_kind;
|
||||||
let captured_place_expr =
|
let captured_place_expr =
|
||||||
self.convert_captured_hir_place(closure_expr, captured_place.place.clone());
|
self.convert_captured_hir_place(closure_expr, captured_place.place.clone());
|
||||||
|
@ -1107,7 +1090,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
span: closure_expr.span,
|
span: closure_expr.span,
|
||||||
kind: ExprKind::Borrow {
|
kind: ExprKind::Borrow {
|
||||||
borrow_kind,
|
borrow_kind,
|
||||||
arg: self.arena.alloc(captured_place_expr),
|
arg: self.thir.exprs.push(captured_place_expr),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1115,14 +1098,14 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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(
|
fn field_refs(&mut self, fields: &'tcx [hir::ExprField<'tcx>]) -> Box<[FieldExpr]> {
|
||||||
&mut self,
|
fields
|
||||||
fields: &'tcx [hir::ExprField<'tcx>],
|
.iter()
|
||||||
) -> &'thir [FieldExpr<'thir, 'tcx>] {
|
.map(|field| FieldExpr {
|
||||||
self.arena.alloc_from_iter(fields.iter().map(|field| FieldExpr {
|
name: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)),
|
||||||
name: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)),
|
expr: self.mirror_expr(field.expr),
|
||||||
expr: self.mirror_expr(field.expr),
|
})
|
||||||
}))
|
.collect()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
//! 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::*;
|
||||||
|
|
||||||
|
@ -14,18 +13,19 @@ 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};
|
||||||
|
|
||||||
pub fn build_thir<'thir, 'tcx>(
|
pub fn build_thir<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
owner_def: ty::WithOptConstParam<LocalDefId>,
|
owner_def: ty::WithOptConstParam<LocalDefId>,
|
||||||
arena: &'thir Arena<'thir, 'tcx>,
|
|
||||||
expr: &'tcx hir::Expr<'tcx>,
|
expr: &'tcx hir::Expr<'tcx>,
|
||||||
) -> &'thir Expr<'thir, 'tcx> {
|
) -> (Thir<'tcx>, ExprId) {
|
||||||
Cx::new(tcx, owner_def, &arena).mirror_expr(expr)
|
let mut cx = Cx::new(tcx, owner_def);
|
||||||
|
let expr = cx.mirror_expr(expr);
|
||||||
|
(cx.thir, expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Cx<'thir, 'tcx> {
|
struct Cx<'tcx> {
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
arena: &'thir Arena<'thir, 'tcx>,
|
thir: Thir<'tcx>,
|
||||||
|
|
||||||
crate param_env: ty::ParamEnv<'tcx>,
|
crate param_env: ty::ParamEnv<'tcx>,
|
||||||
|
|
||||||
|
@ -36,16 +36,12 @@ struct Cx<'thir, 'tcx> {
|
||||||
body_owner: DefId,
|
body_owner: DefId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'thir, 'tcx> Cx<'thir, 'tcx> {
|
impl<'tcx> Cx<'tcx> {
|
||||||
fn new(
|
fn new(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam<LocalDefId>) -> Cx<'tcx> {
|
||||||
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,
|
thir: Thir::new(),
|
||||||
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,
|
||||||
|
@ -87,7 +83,7 @@ impl<'thir, 'tcx> Cx<'thir, '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
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_hir::def_id::DefId;
|
use rustc_hir::def_id::DefId;
|
||||||
|
use rustc_index::newtype_index;
|
||||||
|
use rustc_index::vec::IndexVec;
|
||||||
use rustc_middle::infer::canonical::Canonical;
|
use rustc_middle::infer::canonical::Canonical;
|
||||||
use rustc_middle::middle::region;
|
use rustc_middle::middle::region;
|
||||||
use rustc_middle::mir::{BinOp, BorrowKind, FakeReadCause, Field, UnOp};
|
use rustc_middle::mir::{BinOp, BorrowKind, FakeReadCause, Field, UnOp};
|
||||||
|
@ -17,6 +19,8 @@ use rustc_span::Span;
|
||||||
use rustc_target::abi::VariantIdx;
|
use rustc_target::abi::VariantIdx;
|
||||||
use rustc_target::asm::InlineAsmRegOrRegClass;
|
use rustc_target::asm::InlineAsmRegOrRegClass;
|
||||||
|
|
||||||
|
use std::ops::Index;
|
||||||
|
|
||||||
crate mod constant;
|
crate mod constant;
|
||||||
|
|
||||||
crate mod cx;
|
crate mod cx;
|
||||||
|
@ -25,12 +29,62 @@ pub use cx::build_thir;
|
||||||
crate mod pattern;
|
crate mod pattern;
|
||||||
pub use self::pattern::{Ascription, BindingMode, FieldPat, Pat, PatKind, PatRange, PatTyProj};
|
pub use self::pattern::{Ascription, BindingMode, FieldPat, Pat, PatKind, PatRange, PatTyProj};
|
||||||
|
|
||||||
mod arena;
|
|
||||||
pub use arena::Arena;
|
|
||||||
|
|
||||||
mod util;
|
mod util;
|
||||||
pub mod visit;
|
pub mod visit;
|
||||||
|
|
||||||
|
newtype_index! {
|
||||||
|
pub struct ArmId {
|
||||||
|
DEBUG_FORMAT = "a{}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newtype_index! {
|
||||||
|
pub struct ExprId {
|
||||||
|
DEBUG_FORMAT = "e{}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
newtype_index! {
|
||||||
|
pub struct StmtId {
|
||||||
|
DEBUG_FORMAT = "s{}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! thir_with_elements {
|
||||||
|
($($name:ident: $id:ty => $value:ty,)*) => {
|
||||||
|
pub struct Thir<'tcx> {
|
||||||
|
$(
|
||||||
|
$name: IndexVec<$id, $value>,
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Thir<'tcx> {
|
||||||
|
fn new() -> Thir<'tcx> {
|
||||||
|
Thir {
|
||||||
|
$(
|
||||||
|
$name: IndexVec::new(),
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$(
|
||||||
|
impl<'tcx> Index<$id> for Thir<'tcx> {
|
||||||
|
type Output = $value;
|
||||||
|
fn index(&self, index: $id) -> &Self::Output {
|
||||||
|
&self.$name[index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
thir_with_elements! {
|
||||||
|
arms: ArmId => Arm<'tcx>,
|
||||||
|
exprs: ExprId => Expr<'tcx>,
|
||||||
|
stmts: StmtId => Stmt<'tcx>,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub enum LintLevel {
|
pub enum LintLevel {
|
||||||
Inherited,
|
Inherited,
|
||||||
|
@ -38,13 +92,13 @@ pub enum LintLevel {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Block<'thir, 'tcx> {
|
pub struct Block {
|
||||||
pub targeted_by_break: bool,
|
pub targeted_by_break: bool,
|
||||||
pub region_scope: region::Scope,
|
pub region_scope: region::Scope,
|
||||||
pub opt_destruction_scope: Option<region::Scope>,
|
pub opt_destruction_scope: Option<region::Scope>,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub stmts: &'thir [Stmt<'thir, 'tcx>],
|
pub stmts: Box<[StmtId]>,
|
||||||
pub expr: Option<&'thir Expr<'thir, 'tcx>>,
|
pub expr: Option<ExprId>,
|
||||||
pub safety_mode: BlockSafety,
|
pub safety_mode: BlockSafety,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -57,19 +111,19 @@ pub enum BlockSafety {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Stmt<'thir, 'tcx> {
|
pub struct Stmt<'tcx> {
|
||||||
pub kind: StmtKind<'thir, 'tcx>,
|
pub kind: StmtKind<'tcx>,
|
||||||
pub opt_destruction_scope: Option<region::Scope>,
|
pub opt_destruction_scope: Option<region::Scope>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum StmtKind<'thir, 'tcx> {
|
pub enum StmtKind<'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: &'thir Expr<'thir, 'tcx>,
|
expr: ExprId,
|
||||||
},
|
},
|
||||||
|
|
||||||
Let {
|
Let {
|
||||||
|
@ -87,7 +141,7 @@ pub enum StmtKind<'thir, 'tcx> {
|
||||||
pattern: Pat<'tcx>,
|
pattern: Pat<'tcx>,
|
||||||
|
|
||||||
/// let pat: ty = <INIT> ...
|
/// let pat: ty = <INIT> ...
|
||||||
initializer: Option<&'thir Expr<'thir, 'tcx>>,
|
initializer: Option<ExprId>,
|
||||||
|
|
||||||
/// the lint level for this let-statement
|
/// the lint level for this let-statement
|
||||||
lint_level: LintLevel,
|
lint_level: LintLevel,
|
||||||
|
@ -96,12 +150,12 @@ pub enum StmtKind<'thir, '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<'_, '_>, 144);
|
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 `&'thir Expr<'thir, 'tcx>`, which
|
/// reference to an expression in this enum is an `ExprId`, 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
|
||||||
|
@ -113,7 +167,7 @@ rustc_data_structures::static_assert_size!(Expr<'_, '_>, 144);
|
||||||
/// 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)]
|
||||||
pub struct Expr<'thir, 'tcx> {
|
pub struct Expr<'tcx> {
|
||||||
/// type of this expression
|
/// type of this expression
|
||||||
pub ty: Ty<'tcx>,
|
pub ty: Ty<'tcx>,
|
||||||
|
|
||||||
|
@ -125,28 +179,28 @@ pub struct Expr<'thir, 'tcx> {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
|
||||||
/// kind of expression
|
/// kind of expression
|
||||||
pub kind: ExprKind<'thir, 'tcx>,
|
pub kind: ExprKind<'tcx>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ExprKind<'thir, 'tcx> {
|
pub enum ExprKind<'tcx> {
|
||||||
Scope {
|
Scope {
|
||||||
region_scope: region::Scope,
|
region_scope: region::Scope,
|
||||||
lint_level: LintLevel,
|
lint_level: LintLevel,
|
||||||
value: &'thir Expr<'thir, 'tcx>,
|
value: ExprId,
|
||||||
},
|
},
|
||||||
Box {
|
Box {
|
||||||
value: &'thir Expr<'thir, 'tcx>,
|
value: ExprId,
|
||||||
},
|
},
|
||||||
If {
|
If {
|
||||||
cond: &'thir Expr<'thir, 'tcx>,
|
cond: ExprId,
|
||||||
then: &'thir Expr<'thir, 'tcx>,
|
then: ExprId,
|
||||||
else_opt: Option<&'thir Expr<'thir, 'tcx>>,
|
else_opt: Option<ExprId>,
|
||||||
},
|
},
|
||||||
Call {
|
Call {
|
||||||
ty: Ty<'tcx>,
|
ty: Ty<'tcx>,
|
||||||
fun: &'thir Expr<'thir, 'tcx>,
|
fun: ExprId,
|
||||||
args: &'thir [Expr<'thir, 'tcx>],
|
args: Box<[ExprId]>,
|
||||||
/// 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,
|
||||||
|
@ -155,62 +209,62 @@ pub enum ExprKind<'thir, 'tcx> {
|
||||||
fn_span: Span,
|
fn_span: Span,
|
||||||
},
|
},
|
||||||
Deref {
|
Deref {
|
||||||
arg: &'thir Expr<'thir, 'tcx>,
|
arg: ExprId,
|
||||||
}, // NOT overloaded!
|
}, // NOT overloaded!
|
||||||
Binary {
|
Binary {
|
||||||
op: BinOp,
|
op: BinOp,
|
||||||
lhs: &'thir Expr<'thir, 'tcx>,
|
lhs: ExprId,
|
||||||
rhs: &'thir Expr<'thir, 'tcx>,
|
rhs: ExprId,
|
||||||
}, // NOT overloaded!
|
}, // NOT overloaded!
|
||||||
LogicalOp {
|
LogicalOp {
|
||||||
op: LogicalOp,
|
op: LogicalOp,
|
||||||
lhs: &'thir Expr<'thir, 'tcx>,
|
lhs: ExprId,
|
||||||
rhs: &'thir Expr<'thir, 'tcx>,
|
rhs: ExprId,
|
||||||
}, // 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: &'thir Expr<'thir, 'tcx>,
|
arg: ExprId,
|
||||||
}, // NOT overloaded!
|
}, // NOT overloaded!
|
||||||
Cast {
|
Cast {
|
||||||
source: &'thir Expr<'thir, 'tcx>,
|
source: ExprId,
|
||||||
},
|
},
|
||||||
Use {
|
Use {
|
||||||
source: &'thir Expr<'thir, 'tcx>,
|
source: ExprId,
|
||||||
}, // Use a lexpr to get a vexpr.
|
}, // Use a lexpr to get a vexpr.
|
||||||
NeverToAny {
|
NeverToAny {
|
||||||
source: &'thir Expr<'thir, 'tcx>,
|
source: ExprId,
|
||||||
},
|
},
|
||||||
Pointer {
|
Pointer {
|
||||||
cast: PointerCast,
|
cast: PointerCast,
|
||||||
source: &'thir Expr<'thir, 'tcx>,
|
source: ExprId,
|
||||||
},
|
},
|
||||||
Loop {
|
Loop {
|
||||||
body: &'thir Expr<'thir, 'tcx>,
|
body: ExprId,
|
||||||
},
|
},
|
||||||
Match {
|
Match {
|
||||||
scrutinee: &'thir Expr<'thir, 'tcx>,
|
scrutinee: ExprId,
|
||||||
arms: &'thir [Arm<'thir, 'tcx>],
|
arms: Box<[ArmId]>,
|
||||||
},
|
},
|
||||||
Block {
|
Block {
|
||||||
body: Block<'thir, 'tcx>,
|
body: Block,
|
||||||
},
|
},
|
||||||
Assign {
|
Assign {
|
||||||
lhs: &'thir Expr<'thir, 'tcx>,
|
lhs: ExprId,
|
||||||
rhs: &'thir Expr<'thir, 'tcx>,
|
rhs: ExprId,
|
||||||
},
|
},
|
||||||
AssignOp {
|
AssignOp {
|
||||||
op: BinOp,
|
op: BinOp,
|
||||||
lhs: &'thir Expr<'thir, 'tcx>,
|
lhs: ExprId,
|
||||||
rhs: &'thir Expr<'thir, 'tcx>,
|
rhs: ExprId,
|
||||||
},
|
},
|
||||||
Field {
|
Field {
|
||||||
lhs: &'thir Expr<'thir, 'tcx>,
|
lhs: ExprId,
|
||||||
name: Field,
|
name: Field,
|
||||||
},
|
},
|
||||||
Index {
|
Index {
|
||||||
lhs: &'thir Expr<'thir, 'tcx>,
|
lhs: ExprId,
|
||||||
index: &'thir Expr<'thir, 'tcx>,
|
index: ExprId,
|
||||||
},
|
},
|
||||||
VarRef {
|
VarRef {
|
||||||
id: hir::HirId,
|
id: hir::HirId,
|
||||||
|
@ -225,35 +279,35 @@ pub enum ExprKind<'thir, 'tcx> {
|
||||||
},
|
},
|
||||||
Borrow {
|
Borrow {
|
||||||
borrow_kind: BorrowKind,
|
borrow_kind: BorrowKind,
|
||||||
arg: &'thir Expr<'thir, 'tcx>,
|
arg: ExprId,
|
||||||
},
|
},
|
||||||
/// 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: &'thir Expr<'thir, 'tcx>,
|
arg: ExprId,
|
||||||
},
|
},
|
||||||
Break {
|
Break {
|
||||||
label: region::Scope,
|
label: region::Scope,
|
||||||
value: Option<&'thir Expr<'thir, 'tcx>>,
|
value: Option<ExprId>,
|
||||||
},
|
},
|
||||||
Continue {
|
Continue {
|
||||||
label: region::Scope,
|
label: region::Scope,
|
||||||
},
|
},
|
||||||
Return {
|
Return {
|
||||||
value: Option<&'thir Expr<'thir, 'tcx>>,
|
value: Option<ExprId>,
|
||||||
},
|
},
|
||||||
ConstBlock {
|
ConstBlock {
|
||||||
value: &'tcx Const<'tcx>,
|
value: &'tcx Const<'tcx>,
|
||||||
},
|
},
|
||||||
Repeat {
|
Repeat {
|
||||||
value: &'thir Expr<'thir, 'tcx>,
|
value: ExprId,
|
||||||
count: &'tcx Const<'tcx>,
|
count: &'tcx Const<'tcx>,
|
||||||
},
|
},
|
||||||
Array {
|
Array {
|
||||||
fields: &'thir [Expr<'thir, 'tcx>],
|
fields: Box<[ExprId]>,
|
||||||
},
|
},
|
||||||
Tuple {
|
Tuple {
|
||||||
fields: &'thir [Expr<'thir, 'tcx>],
|
fields: Box<[ExprId]>,
|
||||||
},
|
},
|
||||||
Adt {
|
Adt {
|
||||||
adt_def: &'tcx AdtDef,
|
adt_def: &'tcx AdtDef,
|
||||||
|
@ -264,25 +318,25 @@ pub enum ExprKind<'thir, 'tcx> {
|
||||||
/// Bar::<T> { ... }`.
|
/// Bar::<T> { ... }`.
|
||||||
user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
|
user_ty: Option<Canonical<'tcx, UserType<'tcx>>>,
|
||||||
|
|
||||||
fields: &'thir [FieldExpr<'thir, 'tcx>],
|
fields: Box<[FieldExpr]>,
|
||||||
base: Option<FruInfo<'thir, 'tcx>>,
|
base: Option<FruInfo<'tcx>>,
|
||||||
},
|
},
|
||||||
PlaceTypeAscription {
|
PlaceTypeAscription {
|
||||||
source: &'thir Expr<'thir, 'tcx>,
|
source: ExprId,
|
||||||
/// 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: &'thir Expr<'thir, 'tcx>,
|
source: ExprId,
|
||||||
/// 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: &'thir [Expr<'thir, 'tcx>],
|
upvars: Box<[ExprId]>,
|
||||||
movability: Option<hir::Movability>,
|
movability: Option<hir::Movability>,
|
||||||
fake_reads: Vec<(&'thir Expr<'thir, 'tcx>, FakeReadCause, hir::HirId)>,
|
fake_reads: Vec<(ExprId, FakeReadCause, hir::HirId)>,
|
||||||
},
|
},
|
||||||
Literal {
|
Literal {
|
||||||
literal: &'tcx Const<'tcx>,
|
literal: &'tcx Const<'tcx>,
|
||||||
|
@ -302,7 +356,7 @@ pub enum ExprKind<'thir, 'tcx> {
|
||||||
},
|
},
|
||||||
InlineAsm {
|
InlineAsm {
|
||||||
template: &'tcx [InlineAsmTemplatePiece],
|
template: &'tcx [InlineAsmTemplatePiece],
|
||||||
operands: &'thir [InlineAsmOperand<'thir, 'tcx>],
|
operands: Box<[InlineAsmOperand<'tcx>]>,
|
||||||
options: InlineAsmOptions,
|
options: InlineAsmOptions,
|
||||||
line_spans: &'tcx [Span],
|
line_spans: &'tcx [Span],
|
||||||
},
|
},
|
||||||
|
@ -310,40 +364,40 @@ pub enum ExprKind<'thir, 'tcx> {
|
||||||
ThreadLocalRef(DefId),
|
ThreadLocalRef(DefId),
|
||||||
LlvmInlineAsm {
|
LlvmInlineAsm {
|
||||||
asm: &'tcx hir::LlvmInlineAsmInner,
|
asm: &'tcx hir::LlvmInlineAsmInner,
|
||||||
outputs: &'thir [Expr<'thir, 'tcx>],
|
outputs: Box<[ExprId]>,
|
||||||
inputs: &'thir [Expr<'thir, 'tcx>],
|
inputs: Box<[ExprId]>,
|
||||||
},
|
},
|
||||||
Yield {
|
Yield {
|
||||||
value: &'thir Expr<'thir, 'tcx>,
|
value: ExprId,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FieldExpr<'thir, 'tcx> {
|
pub struct FieldExpr {
|
||||||
pub name: Field,
|
pub name: Field,
|
||||||
pub expr: &'thir Expr<'thir, 'tcx>,
|
pub expr: ExprId,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct FruInfo<'thir, 'tcx> {
|
pub struct FruInfo<'tcx> {
|
||||||
pub base: &'thir Expr<'thir, 'tcx>,
|
pub base: ExprId,
|
||||||
pub field_types: &'thir [Ty<'tcx>],
|
pub field_types: Box<[Ty<'tcx>]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct Arm<'thir, 'tcx> {
|
pub struct Arm<'tcx> {
|
||||||
pub pattern: Pat<'tcx>,
|
pub pattern: Pat<'tcx>,
|
||||||
pub guard: Option<Guard<'thir, 'tcx>>,
|
pub guard: Option<Guard<'tcx>>,
|
||||||
pub body: &'thir Expr<'thir, 'tcx>,
|
pub body: ExprId,
|
||||||
pub lint_level: LintLevel,
|
pub lint_level: LintLevel,
|
||||||
pub scope: region::Scope,
|
pub scope: region::Scope,
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Guard<'thir, 'tcx> {
|
pub enum Guard<'tcx> {
|
||||||
If(&'thir Expr<'thir, 'tcx>),
|
If(ExprId),
|
||||||
IfLet(Pat<'tcx>, &'thir Expr<'thir, 'tcx>),
|
IfLet(Pat<'tcx>, ExprId),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
@ -353,33 +407,33 @@ pub enum LogicalOp {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum InlineAsmOperand<'thir, 'tcx> {
|
pub enum InlineAsmOperand<'tcx> {
|
||||||
In {
|
In {
|
||||||
reg: InlineAsmRegOrRegClass,
|
reg: InlineAsmRegOrRegClass,
|
||||||
expr: &'thir Expr<'thir, 'tcx>,
|
expr: ExprId,
|
||||||
},
|
},
|
||||||
Out {
|
Out {
|
||||||
reg: InlineAsmRegOrRegClass,
|
reg: InlineAsmRegOrRegClass,
|
||||||
late: bool,
|
late: bool,
|
||||||
expr: Option<&'thir Expr<'thir, 'tcx>>,
|
expr: Option<ExprId>,
|
||||||
},
|
},
|
||||||
InOut {
|
InOut {
|
||||||
reg: InlineAsmRegOrRegClass,
|
reg: InlineAsmRegOrRegClass,
|
||||||
late: bool,
|
late: bool,
|
||||||
expr: &'thir Expr<'thir, 'tcx>,
|
expr: ExprId,
|
||||||
},
|
},
|
||||||
SplitInOut {
|
SplitInOut {
|
||||||
reg: InlineAsmRegOrRegClass,
|
reg: InlineAsmRegOrRegClass,
|
||||||
late: bool,
|
late: bool,
|
||||||
in_expr: &'thir Expr<'thir, 'tcx>,
|
in_expr: ExprId,
|
||||||
out_expr: Option<&'thir Expr<'thir, 'tcx>>,
|
out_expr: Option<ExprId>,
|
||||||
},
|
},
|
||||||
Const {
|
Const {
|
||||||
value: &'tcx Const<'tcx>,
|
value: &'tcx Const<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
},
|
},
|
||||||
SymFn {
|
SymFn {
|
||||||
expr: &'thir Expr<'thir, 'tcx>,
|
expr: ExprId,
|
||||||
},
|
},
|
||||||
SymStatic {
|
SymStatic {
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue