From 60def4de5e1eb4d8cc4b9733c8bf199b73d8635a Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Wed, 24 Feb 2021 21:29:09 +0100 Subject: [PATCH 1/7] [WIP] Eagerly construct bodies of THIR --- compiler/rustc_mir_build/src/build/block.rs | 65 +- .../src/build/expr/as_constant.rs | 26 +- .../src/build/expr/as_operand.rs | 77 +- .../src/build/expr/as_place.rs | 91 +- .../src/build/expr/as_rvalue.rs | 83 +- .../rustc_mir_build/src/build/expr/as_temp.rs | 28 +- .../rustc_mir_build/src/build/expr/into.rs | 104 +- .../rustc_mir_build/src/build/expr/mod.rs | 2 +- .../rustc_mir_build/src/build/expr/stmt.rs | 59 +- compiler/rustc_mir_build/src/build/into.rs | 55 - .../rustc_mir_build/src/build/matches/mod.rs | 29 +- compiler/rustc_mir_build/src/build/mod.rs | 9 +- compiler/rustc_mir_build/src/build/scope.rs | 8 +- compiler/rustc_mir_build/src/thir/cx/block.rs | 162 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 1789 +++++++++-------- compiler/rustc_mir_build/src/thir/cx/mod.rs | 6 - .../rustc_mir_build/src/thir/cx/to_ref.rs | 65 - compiler/rustc_mir_build/src/thir/mod.rs | 211 +- 18 files changed, 1315 insertions(+), 1554 deletions(-) delete mode 100644 compiler/rustc_mir_build/src/build/into.rs delete mode 100644 compiler/rustc_mir_build/src/thir/cx/to_ref.rs diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index d5f72e6f22dfa..2d1fd4d09d1a4 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -2,7 +2,6 @@ use crate::build::matches::ArmHasGuard; use crate::build::ForGuard::OutsideGuard; use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder}; use crate::thir::*; -use rustc_hir as hir; use rustc_middle::mir::*; use rustc_session::lint::builtin::UNSAFE_OP_IN_UNSAFE_FN; use rustc_session::lint::Level; @@ -13,7 +12,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, destination: Place<'tcx>, block: BasicBlock, - ast_block: &'tcx hir::Block<'tcx>, + ast_block: &Block<'tcx>, source_info: SourceInfo, ) -> BlockAnd<()> { let Block { @@ -24,22 +23,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr, targeted_by_break, safety_mode, - } = self.hir.mirror(ast_block); + } = ast_block; self.in_opt_scope(opt_destruction_scope.map(|de| (de, source_info)), move |this| { - this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| { - if targeted_by_break { - this.in_breakable_scope(None, destination, span, |this| { + this.in_scope((*region_scope, source_info), LintLevel::Inherited, move |this| { + if *targeted_by_break { + this.in_breakable_scope(None, destination, *span, |this| { Some(this.ast_block_stmts( destination, block, - span, - stmts, - expr, - safety_mode, + *span, + &stmts, + expr.as_deref(), + *safety_mode, )) }) } else { - this.ast_block_stmts(destination, block, span, stmts, expr, safety_mode) + this.ast_block_stmts( + destination, + block, + *span, + &stmts, + expr.as_deref(), + *safety_mode, + ) } }) }) @@ -50,8 +56,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination: Place<'tcx>, mut block: BasicBlock, span: Span, - stmts: Vec>, - expr: Option>, + stmts: &[Stmt<'tcx>], + expr: Option<&Expr<'tcx>>, safety_mode: BlockSafety, ) -> BlockAnd<()> { let this = self; @@ -79,8 +85,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.update_source_scope_for_safety_mode(span, safety_mode); let source_info = this.source_info(span); - for stmt in stmts { - let Stmt { kind, opt_destruction_scope } = this.hir.mirror(stmt); + for Stmt { kind, opt_destruction_scope } in stmts { match kind { StmtKind::Expr { scope, expr } => { this.block_context.push(BlockFrame::Statement { ignores_expr_result: true }); @@ -88,10 +93,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block = this.in_opt_scope( opt_destruction_scope.map(|de| (de, source_info)), |this| { - let si = (scope, source_info); + let si = (*scope, source_info); this.in_scope(si, LintLevel::Inherited, |this| { - let expr = this.hir.mirror(expr); - this.stmt_expr(block, expr, Some(scope)) + this.stmt_expr(block, &expr, Some(*scope)) }) } ) @@ -102,7 +106,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.block_context.push(BlockFrame::Statement { ignores_expr_result }); // Enter the remainder scope, i.e., the bindings' destruction scope. - this.push_scope((remainder_scope, source_info)); + this.push_scope((*remainder_scope, source_info)); let_scope_stack.push(remainder_scope); // Declare the bindings, which may create a source scope. @@ -114,14 +118,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Evaluate the initializer, if present. if let Some(init) = initializer { - let initializer_span = init.span(); + let initializer_span = init.span; unpack!( block = this.in_opt_scope( opt_destruction_scope.map(|de| (de, source_info)), |this| { - let scope = (init_scope, source_info); - this.in_scope(scope, lint_level, |this| { + let scope = (*init_scope, source_info); + this.in_scope(scope, *lint_level, |this| { this.declare_bindings( visibility_scope, remainder_span, @@ -129,14 +133,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ArmHasGuard(false), Some((None, initializer_span)), ); - this.expr_into_pattern(block, pattern, init) + this.expr_into_pattern(block, pattern.clone(), &init) }) } ) ); } else { - let scope = (init_scope, source_info); - unpack!(this.in_scope(scope, lint_level, |this| { + let scope = (*init_scope, source_info); + unpack!(this.in_scope(scope, *lint_level, |this| { this.declare_bindings( visibility_scope, remainder_span, @@ -176,13 +180,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if let Some(expr) = expr { let tail_result_is_ignored = destination_ty.is_unit() || this.block_context.currently_ignores_tail_results(); - let span = match expr { - ExprRef::Thir(expr) => expr.span, - ExprRef::Mirror(ref expr) => expr.span, - }; - this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored, span }); + this.block_context + .push(BlockFrame::TailExpr { tail_result_is_ignored, span: expr.span }); - unpack!(block = this.into(destination, block, expr)); + unpack!(block = this.expr_into_dest(destination, block, expr)); let popped = this.block_context.pop(); assert!(popped.map_or(false, |bf| bf.is_tail_expr())); @@ -200,7 +201,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Finally, we pop all the let scopes before exiting out from the scope of block // itself. for scope in let_scope_stack.into_iter().rev() { - unpack!(block = this.pop_scope((scope, source_info), block)); + unpack!(block = this.pop_scope((*scope, source_info), block)); } // Restore the original source scope. this.source_scope = outer_source_scope; diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 3a36ad590c506..1096d2eedfe21 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -8,33 +8,27 @@ use rustc_middle::ty::CanonicalUserTypeAnnotation; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr`, yielding a compile-time constant. Assumes that /// `expr` is a valid compile-time constant! - crate fn as_constant(&mut self, expr: M) -> Constant<'tcx> - where - M: Mirror<'tcx, Output = Expr<'tcx>>, - { - let expr = self.hir.mirror(expr); - self.expr_as_constant(expr) - } - - fn expr_as_constant(&mut self, expr: Expr<'tcx>) -> Constant<'tcx> { + crate fn as_constant(&mut self, expr: &Expr<'tcx>) -> Constant<'tcx> { let this = self; let Expr { ty, temp_lifetime: _, span, kind } = expr; match kind { - ExprKind::Scope { region_scope: _, lint_level: _, value } => this.as_constant(value), + ExprKind::Scope { region_scope: _, lint_level: _, value } => this.as_constant(&value), ExprKind::Literal { literal, user_ty, const_id: _ } => { let user_ty = user_ty.map(|user_ty| { this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { - span, + span: *span, user_ty, inferred_ty: ty, }) }); - assert_eq!(literal.ty, ty); - Constant { span, user_ty, literal } + assert_eq!(literal.ty, *ty); + Constant { span: *span, user_ty, literal } + } + ExprKind::StaticRef { literal, .. } => Constant { span: *span, user_ty: None, literal }, + ExprKind::ConstBlock { value } => { + Constant { span: *span, user_ty: None, literal: value } } - ExprKind::StaticRef { literal, .. } => Constant { span, user_ty: None, literal }, - ExprKind::ConstBlock { value } => Constant { span, user_ty: None, literal: value }, - _ => span_bug!(span, "expression is not a valid constant {:?}", kind), + _ => span_bug!(*span, "expression is not a valid constant {:?}", kind), } } } diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs index 60f8d8c8a9f36..faa8ea759d709 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs @@ -14,10 +14,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// after the current enclosing `ExprKind::Scope` has ended, so /// please do *not* return it from functions to avoid bad /// miscompiles. - crate fn as_local_operand(&mut self, block: BasicBlock, expr: M) -> BlockAnd> - where - M: Mirror<'tcx, Output = Expr<'tcx>>, - { + crate fn as_local_operand( + &mut self, + block: BasicBlock, + expr: &Expr<'tcx>, + ) -> BlockAnd> { let local_scope = self.local_scope(); self.as_operand(block, Some(local_scope), expr) } @@ -70,14 +71,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// value to the stack. /// /// See #68034 for more details. - crate fn as_local_call_operand( + crate fn as_local_call_operand( &mut self, block: BasicBlock, - expr: M, - ) -> BlockAnd> - where - M: Mirror<'tcx, Output = Expr<'tcx>>, - { + expr: &Expr<'tcx>, + ) -> BlockAnd> { let local_scope = self.local_scope(); self.as_call_operand(block, Some(local_scope), expr) } @@ -88,52 +86,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// this time. /// /// The operand is known to be live until the end of `scope`. - crate fn as_operand( - &mut self, - block: BasicBlock, - scope: Option, - expr: M, - ) -> BlockAnd> - where - M: Mirror<'tcx, Output = Expr<'tcx>>, - { - let expr = self.hir.mirror(expr); - self.expr_as_operand(block, scope, expr) - } - + /// /// Like `as_local_call_operand`, except that the argument will /// not be valid once `scope` ends. - fn as_call_operand( - &mut self, - block: BasicBlock, - scope: Option, - expr: M, - ) -> BlockAnd> - where - M: Mirror<'tcx, Output = Expr<'tcx>>, - { - let expr = self.hir.mirror(expr); - self.expr_as_call_operand(block, scope, expr) - } - - fn expr_as_operand( + crate fn as_operand( &mut self, mut block: BasicBlock, scope: Option, - expr: Expr<'tcx>, + expr: &Expr<'tcx>, ) -> BlockAnd> { - debug!("expr_as_operand(block={:?}, expr={:?})", block, expr); + debug!("as_operand(block={:?}, expr={:?})", block, expr); let this = self; - if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind { + if let ExprKind::Scope { region_scope, lint_level, value } = &expr.kind { 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| this.as_operand(block, scope, value)); + .in_scope(region_scope, *lint_level, |this| this.as_operand(block, scope, &value)); } let category = Category::of(&expr.kind).unwrap(); - debug!("expr_as_operand: category={:?} for={:?}", category, expr.kind); + debug!("as_operand: category={:?} for={:?}", category, expr.kind); match category { Category::Constant => { let constant = this.as_constant(expr); @@ -146,20 +119,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - fn expr_as_call_operand( + crate fn as_call_operand( &mut self, mut block: BasicBlock, scope: Option, - expr: Expr<'tcx>, + expr: &Expr<'tcx>, ) -> BlockAnd> { - debug!("expr_as_call_operand(block={:?}, expr={:?})", block, expr); + debug!("as_call_operand(block={:?}, expr={:?})", block, expr); let this = self; - if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind { + if let ExprKind::Scope { region_scope, lint_level, value } = &expr.kind { let source_info = this.source_info(expr.span); - let region_scope = (region_scope, source_info); - return this.in_scope(region_scope, lint_level, |this| { - this.as_call_operand(block, scope, value) + let region_scope = (*region_scope, source_info); + return this.in_scope(region_scope, *lint_level, |this| { + this.as_call_operand(block, scope, &value) }); } @@ -177,8 +150,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // As described above, detect the case where we are passing a value of unsized // type, and that value is coming from the deref of a box. if let ExprKind::Deref { ref arg } = expr.kind { - let arg = this.hir.mirror(arg.clone()); - // Generate let tmp0 = arg0 let operand = unpack!(block = this.as_temp(block, scope, arg, Mutability::Mut)); @@ -193,6 +164,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - this.expr_as_operand(block, scope, expr) + this.as_operand(block, scope, expr) } } diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 89143e244478f..156f8d2e7045c 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -347,25 +347,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Extra care is needed if any user code is allowed to run between calling /// this method and using it, as is the case for `match` and index /// expressions. - crate fn as_place(&mut self, mut block: BasicBlock, expr: M) -> BlockAnd> - where - M: Mirror<'tcx, Output = Expr<'tcx>>, - { + crate fn as_place( + &mut self, + mut block: BasicBlock, + expr: &Expr<'tcx>, + ) -> BlockAnd> { let place_builder = unpack!(block = self.as_place_builder(block, expr)); block.and(place_builder.into_place(self.hir.tcx(), self.hir.typeck_results())) } /// This is used when constructing a compound `Place`, so that we can avoid creating /// intermediate `Place` values until we know the full set of projections. - crate fn as_place_builder( + crate fn as_place_builder( &mut self, block: BasicBlock, - expr: M, - ) -> BlockAnd> - where - M: Mirror<'tcx, Output = Expr<'tcx>>, - { - let expr = self.hir.mirror(expr); + expr: &Expr<'tcx>, + ) -> BlockAnd> { self.expr_as_place(block, expr, Mutability::Mut, None) } @@ -374,14 +371,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// place. The place itself may or may not be mutable: /// * If this expr is a place expr like a.b, then we will return that place. /// * Otherwise, a temporary is created: in that event, it will be an immutable temporary. - crate fn as_read_only_place( + crate fn as_read_only_place( &mut self, mut block: BasicBlock, - expr: M, - ) -> BlockAnd> - where - M: Mirror<'tcx, Output = Expr<'tcx>>, - { + expr: &Expr<'tcx>, + ) -> BlockAnd> { let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr)); block.and(place_builder.into_place(self.hir.tcx(), self.hir.typeck_results())) } @@ -392,22 +386,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// place. The place itself may or may not be mutable: /// * If this expr is a place expr like a.b, then we will return that place. /// * Otherwise, a temporary is created: in that event, it will be an immutable temporary. - fn as_read_only_place_builder( + fn as_read_only_place_builder( &mut self, block: BasicBlock, - expr: M, - ) -> BlockAnd> - where - M: Mirror<'tcx, Output = Expr<'tcx>>, - { - let expr = self.hir.mirror(expr); + expr: &Expr<'tcx>, + ) -> BlockAnd> { self.expr_as_place(block, expr, Mutability::Not, None) } fn expr_as_place( &mut self, mut block: BasicBlock, - expr: Expr<'tcx>, + expr: &Expr<'tcx>, mutability: Mutability, fake_borrow_temps: Option<&mut Vec>, ) -> BlockAnd> { @@ -416,29 +406,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let this = self; let expr_span = expr.span; let source_info = this.source_info(expr_span); - match expr.kind { + match &expr.kind { ExprKind::Scope { region_scope, lint_level, value } => { - this.in_scope((region_scope, source_info), lint_level, |this| { - let value = this.hir.mirror(value); - this.expr_as_place(block, value, mutability, fake_borrow_temps) + this.in_scope((*region_scope, source_info), *lint_level, |this| { + this.expr_as_place(block, &value, mutability, fake_borrow_temps) }) } ExprKind::Field { lhs, name } => { - let lhs = this.hir.mirror(lhs); - let place_builder = - unpack!(block = this.expr_as_place(block, lhs, mutability, fake_borrow_temps,)); - block.and(place_builder.field(name, expr.ty)) + let place_builder = unpack!( + block = this.expr_as_place(block, &lhs, mutability, fake_borrow_temps,) + ); + block.and(place_builder.field(*name, expr.ty)) } ExprKind::Deref { arg } => { - let arg = this.hir.mirror(arg); - let place_builder = - unpack!(block = this.expr_as_place(block, arg, mutability, fake_borrow_temps,)); + let place_builder = unpack!( + block = this.expr_as_place(block, &arg, mutability, fake_borrow_temps,) + ); block.and(place_builder.deref()) } ExprKind::Index { lhs, index } => this.lower_index_expression( block, - lhs, - index, + &lhs, + &index, mutability, fake_borrow_temps, expr.temp_lifetime, @@ -446,31 +435,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_info, ), ExprKind::UpvarRef { closure_def_id, var_hir_id } => { - let upvar_id = ty::UpvarId::new(var_hir_id, closure_def_id.expect_local()); + let upvar_id = ty::UpvarId::new(*var_hir_id, closure_def_id.expect_local()); this.lower_captured_upvar(block, upvar_id) } ExprKind::VarRef { id } => { - let place_builder = if this.is_bound_var_in_guard(id) { - let index = this.var_local_id(id, RefWithinGuard); + let place_builder = if this.is_bound_var_in_guard(*id) { + let index = this.var_local_id(*id, RefWithinGuard); PlaceBuilder::from(index).deref() } else { - let index = this.var_local_id(id, OutsideGuard); + let index = this.var_local_id(*id, OutsideGuard); PlaceBuilder::from(index) }; block.and(place_builder) } ExprKind::PlaceTypeAscription { source, user_ty } => { - let source = this.hir.mirror(source); let place_builder = unpack!( - block = this.expr_as_place(block, source, mutability, fake_borrow_temps,) + block = this.expr_as_place(block, &source, mutability, fake_borrow_temps,) ); if let Some(user_ty) = user_ty { let annotation_index = this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { span: source_info.span, - user_ty, + user_ty: *user_ty, inferred_ty: expr.ty, }); @@ -493,14 +481,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.and(place_builder) } ExprKind::ValueTypeAscription { source, user_ty } => { - let source = this.hir.mirror(source); 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 { let annotation_index = this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { span: source_info.span, - user_ty, + user_ty: *user_ty, inferred_ty: expr.ty, }); this.cfg.push( @@ -599,22 +586,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn lower_index_expression( &mut self, mut block: BasicBlock, - base: ExprRef<'tcx>, - index: ExprRef<'tcx>, + base: &Expr<'tcx>, + index: &Expr<'tcx>, mutability: Mutability, fake_borrow_temps: Option<&mut Vec>, temp_lifetime: Option, expr_span: Span, source_info: SourceInfo, ) -> BlockAnd> { - let lhs = self.hir.mirror(base); - let base_fake_borrow_temps = &mut Vec::new(); let is_outermost_index = fake_borrow_temps.is_none(); let fake_borrow_temps = fake_borrow_temps.unwrap_or(base_fake_borrow_temps); let mut base_place = - unpack!(block = self.expr_as_place(block, lhs, mutability, Some(fake_borrow_temps),)); + unpack!(block = self.expr_as_place(block, base, mutability, Some(fake_borrow_temps),)); // Making this a *fresh* temporary means we do not have to worry about // the index changing later: Nothing will ever change this temporary. diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index fd696f997065c..8082315408c6f 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -19,33 +19,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// The operand returned from this function will *not be valid* after /// an ExprKind::Scope is passed, so please do *not* return it from /// functions to avoid bad miscompiles. - crate fn as_local_rvalue(&mut self, block: BasicBlock, expr: M) -> BlockAnd> - where - M: Mirror<'tcx, Output = Expr<'tcx>>, - { + crate fn as_local_rvalue( + &mut self, + block: BasicBlock, + expr: &Expr<'tcx>, + ) -> BlockAnd> { let local_scope = self.local_scope(); self.as_rvalue(block, Some(local_scope), expr) } /// Compile `expr`, yielding an rvalue. - fn as_rvalue( - &mut self, - block: BasicBlock, - scope: Option, - expr: M, - ) -> BlockAnd> - where - M: Mirror<'tcx, Output = Expr<'tcx>>, - { - let expr = self.hir.mirror(expr); - self.expr_as_rvalue(block, scope, expr) - } - - fn expr_as_rvalue( + crate fn as_rvalue( &mut self, mut block: BasicBlock, scope: Option, - expr: Expr<'tcx>, + expr: &Expr<'tcx>, ) -> BlockAnd> { debug!("expr_as_rvalue(block={:?}, scope={:?}, expr={:?})", block, scope, expr); @@ -53,25 +41,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let expr_span = expr.span; let source_info = this.source_info(expr_span); - match expr.kind { - ExprKind::ThreadLocalRef(did) => block.and(Rvalue::ThreadLocalRef(did)), + match &expr.kind { + ExprKind::ThreadLocalRef(did) => block.and(Rvalue::ThreadLocalRef(*did)), ExprKind::Scope { region_scope, lint_level, value } => { - let region_scope = (region_scope, source_info); - this.in_scope(region_scope, lint_level, |this| this.as_rvalue(block, scope, value)) + let region_scope = (*region_scope, source_info); + this.in_scope(region_scope, *lint_level, |this| { + this.as_rvalue(block, scope, &value) + }) } 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, &value)); block.and(Rvalue::Repeat(value_operand, count)) } ExprKind::Binary { op, lhs, rhs } => { - let lhs = unpack!(block = this.as_operand(block, scope, lhs)); - let rhs = unpack!(block = this.as_operand(block, scope, rhs)); - this.build_binary_op(block, op, expr_span, expr.ty, lhs, rhs) + let lhs = unpack!(block = this.as_operand(block, scope, &lhs)); + let rhs = unpack!(block = this.as_operand(block, scope, &rhs)); + this.build_binary_op(block, *op, expr_span, expr.ty, lhs, rhs) } ExprKind::Unary { op, arg } => { - let arg = unpack!(block = this.as_operand(block, scope, arg)); + let arg = unpack!(block = this.as_operand(block, scope, &arg)); // Check for -MIN on signed integers - if this.hir.check_overflow() && op == UnOp::Neg && expr.ty.is_signed() { + if this.hir.check_overflow() && *op == UnOp::Neg && expr.ty.is_signed() { let bool_ty = this.hir.bool_ty(); let minval = this.minval_literal(expr_span, expr.ty); @@ -92,10 +82,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr_span, ); } - block.and(Rvalue::UnaryOp(op, arg)) + block.and(Rvalue::UnaryOp(*op, arg)) } ExprKind::Box { value } => { - let value = this.hir.mirror(value); // The `Box` temporary created here is not a part of the HIR, // and therefore is not considered during generator auto-trait // determination. See the comment about `box` at `yield_in_scope`. @@ -115,18 +104,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // initialize the box contents: unpack!( - block = - this.into(this.hir.tcx().mk_place_deref(Place::from(result)), block, value) + block = this.expr_into_dest( + this.hir.tcx().mk_place_deref(Place::from(result)), + block, + &value + ) ); block.and(Rvalue::Use(Operand::Move(Place::from(result)))) } ExprKind::Cast { source } => { - let source = unpack!(block = this.as_operand(block, scope, source)); + let source = unpack!(block = this.as_operand(block, scope, &source)); block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty)) } ExprKind::Pointer { cast, source } => { - let source = unpack!(block = this.as_operand(block, scope, source)); - block.and(Rvalue::Cast(CastKind::Pointer(cast), source, expr.ty)) + let source = unpack!(block = this.as_operand(block, scope, &source)); + block.and(Rvalue::Cast(CastKind::Pointer(*cast), source, expr.ty)) } ExprKind::Array { fields } => { // (*) We would (maybe) be closer to codegen if we @@ -159,7 +151,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let el_ty = expr.ty.sequence_element_type(this.hir.tcx()); let fields: Vec<_> = fields .into_iter() - .map(|f| unpack!(block = this.as_operand(block, scope, f))) + .map(|f| unpack!(block = this.as_operand(block, scope, &f))) .collect(); block.and(Rvalue::Aggregate(box AggregateKind::Array(el_ty), fields)) @@ -169,7 +161,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // first process the set of fields let fields: Vec<_> = fields .into_iter() - .map(|f| unpack!(block = this.as_operand(block, scope, f))) + .map(|f| unpack!(block = this.as_operand(block, scope, &f))) .collect(); block.and(Rvalue::Aggregate(box AggregateKind::Tuple, fields)) @@ -179,7 +171,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let operands: Vec<_> = upvars .into_iter() .map(|upvar| { - let upvar = this.hir.mirror(upvar); match Category::of(&upvar.kind) { // Use as_place to avoid creating a temporary when // moving a variable into a closure, so that @@ -190,7 +181,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // This occurs when capturing by copy/move, while // by reference captures use as_operand Some(Category::Place) => { - let place = unpack!(block = this.as_place(block, upvar)); + let place = unpack!(block = this.as_place(block, &upvar)); this.consume_by_copy_or_move(place) } _ => { @@ -198,17 +189,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // borrow captures when capturing an immutable // variable. This is sound because the mutation // that caused the capture will cause an error. - match upvar.kind { + match &upvar.kind { ExprKind::Borrow { borrow_kind: BorrowKind::Mut { allow_two_phase_borrow: false }, arg, } => unpack!( block = this.limit_capture_mutability( - upvar.span, upvar.ty, scope, block, arg, + upvar.span, upvar.ty, scope, block, &arg, ) ), - _ => unpack!(block = this.as_operand(block, scope, upvar)), + _ => unpack!(block = this.as_operand(block, scope, &upvar)), } } } @@ -219,9 +210,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // We implicitly set the discriminant to 0. See // librustc_mir/transform/deaggregator.rs for details. let movability = movability.unwrap(); - box AggregateKind::Generator(closure_id, substs, movability) + box AggregateKind::Generator(*closure_id, substs, movability) } - UpvarSubsts::Closure(substs) => box AggregateKind::Closure(closure_id, substs), + UpvarSubsts::Closure(substs) => box AggregateKind::Closure(*closure_id, substs), }; block.and(Rvalue::Aggregate(result, operands)) } @@ -377,7 +368,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { upvar_ty: Ty<'tcx>, temp_lifetime: Option, mut block: BasicBlock, - arg: ExprRef<'tcx>, + arg: &Expr<'tcx>, ) -> BlockAnd> { let this = self; diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs index 9984b527ffdb4..0f4d05fc03ab9 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs @@ -4,48 +4,42 @@ use crate::build::scope::DropKind; use crate::build::{BlockAnd, BlockAndExtension, Builder}; use crate::thir::*; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_hir as hir; use rustc_middle::middle::region; use rustc_middle::mir::*; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr` into a fresh temporary. This is used when building /// up rvalues so as to freeze the value that will be consumed. - crate fn as_temp( + crate fn as_temp( &mut self, block: BasicBlock, temp_lifetime: Option, - expr: M, + expr: &Expr<'tcx>, mutability: Mutability, - ) -> BlockAnd - where - M: Mirror<'tcx, Output = Expr<'tcx>>, - { - let expr = self.hir.mirror(expr); - // + ) -> BlockAnd { // this is the only place in mir building that we need to truly need to worry about // infinite recursion. Everything else does recurse, too, but it always gets broken up // at some point by inserting an intermediate temporary - ensure_sufficient_stack(|| self.expr_as_temp(block, temp_lifetime, expr, mutability)) + ensure_sufficient_stack(|| self.as_temp_inner(block, temp_lifetime, expr, mutability)) } - fn expr_as_temp( + fn as_temp_inner( &mut self, mut block: BasicBlock, temp_lifetime: Option, - expr: Expr<'tcx>, + expr: &Expr<'tcx>, mutability: Mutability, ) -> BlockAnd { debug!( - "expr_as_temp(block={:?}, temp_lifetime={:?}, expr={:?}, mutability={:?})", + "as_temp(block={:?}, temp_lifetime={:?}, expr={:?}, mutability={:?})", block, temp_lifetime, expr, mutability ); let this = self; let expr_span = expr.span; let source_info = this.source_info(expr_span); - if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind { - return this.in_scope((region_scope, source_info), lint_level, |this| { + if let ExprKind::Scope { region_scope, lint_level, value } = &expr.kind { + return this.in_scope((*region_scope, source_info), *lint_level, |this| { this.as_temp(block, temp_lifetime, value, mutability) }); } @@ -89,7 +83,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Don't bother with StorageLive and Dead for these temporaries, // they are never assigned. ExprKind::Break { .. } | ExprKind::Continue { .. } | ExprKind::Return { .. } => (), - ExprKind::Block { body: hir::Block { expr: None, targeted_by_break: false, .. } } + ExprKind::Block { body: Block { expr: None, targeted_by_break: false, .. } } if expr_ty.is_never() => {} _ => { this.cfg @@ -114,7 +108,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - unpack!(block = this.into(temp_place, block, expr)); + unpack!(block = this.expr_into_dest(temp_place, block, expr)); if let Some(temp_lifetime) = temp_lifetime { this.schedule_drop(expr_span, temp_lifetime, temp, DropKind::Value); diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 235fe14cbf9fd..9c719e36551c4 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -13,13 +13,13 @@ use rustc_middle::ty::CanonicalUserTypeAnnotation; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr`, storing the result into `destination`, which /// is assumed to be uninitialized. - crate fn into_expr( + crate fn expr_into_dest( &mut self, destination: Place<'tcx>, mut block: BasicBlock, - expr: Expr<'tcx>, + expr: &Expr<'tcx>, ) -> BlockAnd<()> { - debug!("into_expr(destination={:?}, block={:?}, expr={:?})", destination, block, expr); + debug!("expr_into_dest(destination={:?}, block={:?}, expr={:?})", destination, block, expr); // since we frequently have to reference `self` from within a // closure, where `self` would be shadowed, it's easier to @@ -35,24 +35,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.block_context.push(BlockFrame::SubExpr); } - let block_and = match expr.kind { + let block_and = match &expr.kind { ExprKind::Scope { region_scope, lint_level, value } => { - let region_scope = (region_scope, source_info); + let region_scope = (*region_scope, source_info); ensure_sufficient_stack(|| { - this.in_scope(region_scope, lint_level, |this| { - this.into(destination, block, value) + this.in_scope(region_scope, *lint_level, |this| { + this.expr_into_dest(destination, block, &value) }) }) } ExprKind::Block { body: ast_block } => { - this.ast_block(destination, block, ast_block, source_info) + this.ast_block(destination, block, &ast_block, source_info) } ExprKind::Match { scrutinee, arms } => { - this.match_expr(destination, expr_span, block, scrutinee, arms) + this.match_expr(destination, expr_span, block, &scrutinee, &arms) } ExprKind::If { cond, then, else_opt } => { let place = unpack!( - block = this.as_temp(block, Some(this.local_scope()), cond, Mutability::Mut) + block = this.as_temp(block, Some(this.local_scope()), &cond, Mutability::Mut) ); let operand = Operand::Move(Place::from(place)); @@ -61,9 +61,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let term = TerminatorKind::if_(this.hir.tcx(), operand, then_block, else_block); this.cfg.terminate(block, source_info, term); - unpack!(then_block = this.into(destination, then_block, then)); + unpack!(then_block = this.expr_into_dest(destination, then_block, &then)); else_block = if let Some(else_opt) = else_opt { - unpack!(this.into(destination, else_block, else_opt)) + unpack!(this.expr_into_dest(destination, else_block, &else_opt)) } else { // Body of the `if` expression without an `else` clause must return `()`, thus // we implicitly generate a `else {}` if it is not specified. @@ -87,14 +87,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { join_block.unit() } ExprKind::NeverToAny { source } => { - let source = this.hir.mirror(source); let is_call = matches!(source.kind, ExprKind::Call { .. } | ExprKind::InlineAsm { .. }); // (#66975) Source could be a const of type `!`, so has to // exist in the generated MIR. unpack!( - block = this.as_temp(block, Some(this.local_scope()), source, Mutability::Mut,) + block = + this.as_temp(block, Some(this.local_scope()), &source, Mutability::Mut,) ); // This is an optimization. If the expression was a call then we already have an @@ -127,7 +127,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.cfg.start_new_block(), ); - let lhs = unpack!(block = this.as_local_operand(block, lhs)); + let lhs = unpack!(block = this.as_local_operand(block, &lhs)); let blocks = match op { LogicalOp::And => (else_block, false_block), LogicalOp::Or => (true_block, else_block), @@ -135,7 +135,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let term = TerminatorKind::if_(this.hir.tcx(), lhs, blocks.0, blocks.1); this.cfg.terminate(block, source_info, term); - let rhs = unpack!(else_block = this.as_local_operand(else_block, rhs)); + let rhs = unpack!(else_block = this.as_local_operand(else_block, &rhs)); let term = TerminatorKind::if_(this.hir.tcx(), rhs, true_block, false_block); this.cfg.terminate(else_block, source_info, term); @@ -188,7 +188,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // introduce a unit temporary as the destination for the loop body. let tmp = this.get_unit_temp(); // Execute the body, branching back to the test. - let body_block_end = unpack!(this.into(tmp, body_block, body)); + let body_block_end = unpack!(this.expr_into_dest(tmp, body_block, &body)); this.cfg.goto(body_block_end, source_info, loop_block); // Loops are only exited by `break` expressions. @@ -196,17 +196,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }) } ExprKind::Call { ty: _, fun, 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, &fun)); let args: Vec<_> = args .into_iter() - .map(|arg| unpack!(block = this.as_local_call_operand(block, arg))) + .map(|arg| unpack!(block = this.as_local_call_operand(block, &arg))) .collect(); let success = this.cfg.start_new_block(); this.record_operands_moved(&args); - debug!("into_expr: fn_span={:?}", fn_span); + debug!("expr_into_dest: fn_span={:?}", fn_span); this.cfg.terminate( block, @@ -223,14 +223,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } else { Some((destination, success)) }, - from_hir_call, - fn_span, + from_hir_call: *from_hir_call, + fn_span: *fn_span, }, ); this.diverge_from(block); success.unit() } - ExprKind::Use { source } => this.into(destination, block, source), + ExprKind::Use { source } => this.expr_into_dest(destination, block, &source), ExprKind::Borrow { arg, borrow_kind } => { // We don't do this in `as_rvalue` because we use `as_place` // for borrow expressions, so we cannot create an `RValue` that @@ -238,20 +238,20 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // by this method anyway, so this shouldn't cause too many // unnecessary temporaries. let arg_place = match borrow_kind { - BorrowKind::Shared => unpack!(block = this.as_read_only_place(block, arg)), - _ => unpack!(block = this.as_place(block, arg)), + BorrowKind::Shared => unpack!(block = this.as_read_only_place(block, &arg)), + _ => unpack!(block = this.as_place(block, &arg)), }; let borrow = - Rvalue::Ref(this.hir.tcx().lifetimes.re_erased, borrow_kind, arg_place); + Rvalue::Ref(this.hir.tcx().lifetimes.re_erased, *borrow_kind, arg_place); this.cfg.push_assign(block, source_info, destination, borrow); block.unit() } ExprKind::AddressOf { mutability, arg } => { let place = match mutability { - hir::Mutability::Not => this.as_read_only_place(block, arg), - hir::Mutability::Mut => this.as_place(block, arg), + hir::Mutability::Not => this.as_read_only_place(block, &arg), + hir::Mutability::Mut => this.as_place(block, &arg), }; - let address_of = Rvalue::AddressOf(mutability, unpack!(block = place)); + let address_of = Rvalue::AddressOf(*mutability, unpack!(block = place)); this.cfg.push_assign(block, source_info, destination, address_of); block.unit() } @@ -267,13 +267,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // (evaluating them in order given by user) let fields_map: FxHashMap<_, _> = fields .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), &f.expr))) + }) .collect(); - let field_names = this.hir.all_fields(adt_def, variant_index); + let field_names = this.hir.all_fields(adt_def, *variant_index); 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, &base)); // MIR does not natively support FRU, so for each // base-supplied field, generate an operand that @@ -307,7 +309,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }); let adt = box AggregateKind::Adt( adt_def, - variant_index, + *variant_index, substs, user_ty, active_field_index, @@ -327,21 +329,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { .into_iter() .map(|op| match op { thir::InlineAsmOperand::In { reg, expr } => mir::InlineAsmOperand::In { - reg, - value: unpack!(block = this.as_local_operand(block, expr)), + reg: *reg, + value: unpack!(block = this.as_local_operand(block, &expr)), }, thir::InlineAsmOperand::Out { reg, late, expr } => { mir::InlineAsmOperand::Out { - reg, - late, - place: expr.map(|expr| unpack!(block = this.as_place(block, expr))), + reg: *reg, + late: *late, + place: expr + .as_ref() + .map(|expr| unpack!(block = this.as_place(block, expr))), } } thir::InlineAsmOperand::InOut { reg, late, expr } => { - let place = unpack!(block = this.as_place(block, expr)); + let place = unpack!(block = this.as_place(block, &expr)); mir::InlineAsmOperand::InOut { - reg, - late, + reg: *reg, + late: *late, // This works because asm operands must be Copy in_value: Operand::Copy(place), out_place: Some(place), @@ -349,22 +353,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } thir::InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => { mir::InlineAsmOperand::InOut { - reg, - late, - in_value: unpack!(block = this.as_local_operand(block, in_expr)), - out_place: out_expr.map(|out_expr| { + reg: *reg, + late: *late, + in_value: unpack!(block = this.as_local_operand(block, &in_expr)), + out_place: out_expr.as_ref().map(|out_expr| { unpack!(block = this.as_place(block, out_expr)) }), } } thir::InlineAsmOperand::Const { expr } => mir::InlineAsmOperand::Const { - value: unpack!(block = this.as_local_operand(block, expr)), + value: unpack!(block = this.as_local_operand(block, &expr)), }, thir::InlineAsmOperand::SymFn { expr } => { - mir::InlineAsmOperand::SymFn { value: box this.as_constant(expr) } + mir::InlineAsmOperand::SymFn { value: box this.as_constant(&expr) } } thir::InlineAsmOperand::SymStatic { def_id } => { - mir::InlineAsmOperand::SymStatic { def_id } + mir::InlineAsmOperand::SymStatic { def_id: *def_id } } }) .collect(); @@ -377,7 +381,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { TerminatorKind::InlineAsm { template, operands, - options, + options: *options, line_spans, destination: if options.contains(InlineAsmOptions::NORETURN) { None @@ -436,7 +440,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::Yield { value } => { 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), &value)); let resume = this.cfg.start_new_block(); this.cfg.terminate( block, diff --git a/compiler/rustc_mir_build/src/build/expr/mod.rs b/compiler/rustc_mir_build/src/build/expr/mod.rs index ac8c7e725e1b4..07338928eb8ef 100644 --- a/compiler/rustc_mir_build/src/build/expr/mod.rs +++ b/compiler/rustc_mir_build/src/build/expr/mod.rs @@ -9,7 +9,7 @@ //! a type that is not `Copy`, then using any of these functions will //! "move" the value out of its current home (if any). //! -//! - `into` -- writes the value into a specific location, which +//! - `expr_into_dest` -- writes the value into a specific location, which //! should be uninitialized //! - `as_operand` -- evaluates the value and yields an `Operand`, //! suitable for use as an argument to an `Rvalue` diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs index f117689d940fd..0d2d99a8b5e87 100644 --- a/compiler/rustc_mir_build/src/build/expr/stmt.rs +++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs @@ -13,7 +13,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn stmt_expr( &mut self, mut block: BasicBlock, - expr: Expr<'tcx>, + expr: &Expr<'tcx>, statement_scope: Option, ) -> BlockAnd<()> { let this = self; @@ -22,16 +22,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Handle a number of expressions that don't need a destination at all. This // avoids needing a mountain of temporary `()` variables. let expr2 = expr.clone(); - match expr.kind { + match &expr.kind { ExprKind::Scope { region_scope, lint_level, value } => { - let value = this.hir.mirror(value); - this.in_scope((region_scope, source_info), lint_level, |this| { - this.stmt_expr(block, value, statement_scope) + this.in_scope((*region_scope, source_info), *lint_level, |this| { + this.stmt_expr(block, &value, statement_scope) }) } ExprKind::Assign { lhs, rhs } => { - let lhs = this.hir.mirror(lhs); - let rhs = this.hir.mirror(rhs); let lhs_span = lhs.span; // Note: we evaluate assignments right-to-left. This @@ -44,12 +41,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Generate better code for things that don't need to be // dropped. if this.hir.needs_drop(lhs.ty) { - let rhs = unpack!(block = this.as_local_operand(block, rhs)); - let lhs = unpack!(block = this.as_place(block, lhs)); + let rhs = unpack!(block = this.as_local_operand(block, &rhs)); + let lhs = unpack!(block = this.as_place(block, &lhs)); unpack!(block = this.build_drop_and_replace(block, lhs_span, lhs, rhs)); } else { - let rhs = unpack!(block = this.as_local_rvalue(block, rhs)); - let lhs = unpack!(block = this.as_place(block, lhs)); + let rhs = unpack!(block = this.as_local_rvalue(block, &rhs)); + let lhs = unpack!(block = this.as_place(block, &lhs)); this.cfg.push_assign(block, source_info, lhs, rhs); } @@ -65,22 +62,27 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // only affects weird things like `x += {x += 1; x}` // -- is that equal to `x + (x + 1)` or `2*(x+1)`? - let lhs = this.hir.mirror(lhs); let lhs_ty = lhs.ty; debug!("stmt_expr AssignOp block_context.push(SubExpr) : {:?}", expr2); this.block_context.push(BlockFrame::SubExpr); // As above, RTL. - let rhs = unpack!(block = this.as_local_operand(block, rhs)); - let lhs = unpack!(block = this.as_place(block, lhs)); + let rhs = unpack!(block = this.as_local_operand(block, &rhs)); + let lhs = unpack!(block = this.as_place(block, &lhs)); // we don't have to drop prior contents or anything // because AssignOp is only legal for Copy types // (overloaded ops should be desugared into a call). let result = unpack!( - block = - this.build_binary_op(block, op, expr_span, lhs_ty, Operand::Copy(lhs), rhs) + block = this.build_binary_op( + block, + *op, + expr_span, + lhs_ty, + Operand::Copy(lhs), + rhs + ) ); this.cfg.push_assign(block, source_info, lhs, result); @@ -88,26 +90,29 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.unit() } ExprKind::Continue { label } => { - this.break_scope(block, None, BreakableTarget::Continue(label), source_info) - } - ExprKind::Break { label, value } => { - this.break_scope(block, value, BreakableTarget::Break(label), source_info) + this.break_scope(block, None, BreakableTarget::Continue(*label), source_info) } + ExprKind::Break { label, value } => this.break_scope( + block, + value.as_deref(), + BreakableTarget::Break(*label), + source_info, + ), ExprKind::Return { value } => { - this.break_scope(block, value, BreakableTarget::Return, source_info) + this.break_scope(block, value.as_deref(), BreakableTarget::Return, source_info) } ExprKind::LlvmInlineAsm { asm, outputs, inputs } => { debug!("stmt_expr LlvmInlineAsm block_context.push(SubExpr) : {:?}", expr2); this.block_context.push(BlockFrame::SubExpr); let outputs = outputs .into_iter() - .map(|output| unpack!(block = this.as_place(block, output))) + .map(|output| unpack!(block = this.as_place(block, &output))) .collect::>() .into_boxed_slice(); let inputs = inputs .into_iter() .map(|input| { - (input.span(), unpack!(block = this.as_local_operand(block, input))) + (input.span, unpack!(block = this.as_local_operand(block, &input))) }) .collect::>() .into_boxed_slice(); @@ -116,7 +121,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Statement { source_info, kind: StatementKind::LlvmInlineAsm(box LlvmInlineAsm { - asm: asm.clone(), + asm: (*asm).clone(), outputs, inputs, }), @@ -140,10 +145,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // it is usually better to focus on `the_value` rather // than the entirety of block(s) surrounding it. let adjusted_span = (|| { - if let ExprKind::Block { body } = expr.kind { + if let ExprKind::Block { body } = &expr.kind { if let Some(tail_expr) = &body.expr { - let mut expr = tail_expr; - while let rustc_hir::ExprKind::Block(subblock, _label) = &expr.kind { + let mut expr = &*tail_expr; + while let ExprKind::Block { body: subblock } = &expr.kind { if let Some(subtail_expr) = &subblock.expr { expr = subtail_expr } else { diff --git a/compiler/rustc_mir_build/src/build/into.rs b/compiler/rustc_mir_build/src/build/into.rs deleted file mode 100644 index 7264e495b84fd..0000000000000 --- a/compiler/rustc_mir_build/src/build/into.rs +++ /dev/null @@ -1,55 +0,0 @@ -//! In general, there are a number of things for which it's convenient -//! to just call `builder.into` and have it emit its result into a -//! given location. This is basically for expressions or things that can be -//! wrapped up as expressions (e.g., blocks). To make this ergonomic, we use this -//! latter `EvalInto` trait. - -use crate::build::{BlockAnd, Builder}; -use crate::thir::*; -use rustc_middle::mir::*; - -pub(in crate::build) trait EvalInto<'tcx> { - fn eval_into( - self, - builder: &mut Builder<'_, 'tcx>, - destination: Place<'tcx>, - block: BasicBlock, - ) -> BlockAnd<()>; -} - -impl<'a, 'tcx> Builder<'a, 'tcx> { - crate fn into( - &mut self, - destination: Place<'tcx>, - block: BasicBlock, - expr: E, - ) -> BlockAnd<()> - where - E: EvalInto<'tcx>, - { - expr.eval_into(self, destination, block) - } -} - -impl<'tcx> EvalInto<'tcx> for ExprRef<'tcx> { - fn eval_into( - self, - builder: &mut Builder<'_, 'tcx>, - destination: Place<'tcx>, - block: BasicBlock, - ) -> BlockAnd<()> { - let expr = builder.hir.mirror(self); - builder.into_expr(destination, block, expr) - } -} - -impl<'tcx> EvalInto<'tcx> for Expr<'tcx> { - fn eval_into( - self, - builder: &mut Builder<'_, 'tcx>, - destination: Place<'tcx>, - block: BasicBlock, - ) -> BlockAnd<()> { - builder.into_expr(destination, block, self) - } -} diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index fde007ec011ba..6a828c1864fc9 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -89,10 +89,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination: Place<'tcx>, span: Span, mut block: BasicBlock, - scrutinee: ExprRef<'tcx>, - arms: Vec>, + scrutinee: &Expr<'tcx>, + arms: &[Arm<'tcx>], ) -> BlockAnd<()> { - let scrutinee_span = scrutinee.span(); + let scrutinee_span = scrutinee.span; let scrutinee_place = unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span,)); @@ -119,7 +119,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn lower_scrutinee( &mut self, mut block: BasicBlock, - scrutinee: ExprRef<'tcx>, + scrutinee: &Expr<'tcx>, scrutinee_span: Span, ) -> BlockAnd> { let scrutinee_place = unpack!(block = self.as_place(block, scrutinee)); @@ -236,7 +236,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let arm_source_info = self.source_info(arm.span); let arm_scope = (arm.scope, arm_source_info); self.in_scope(arm_scope, arm.lint_level, |this| { - let body = this.hir.mirror(arm.body.clone()); let scope = this.declare_bindings( None, arm.span, @@ -259,7 +258,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.source_scope = source_scope; } - this.into(destination, arm_block, body) + this.expr_into_dest(destination, arm_block, &arm.body) }) }) .collect(); @@ -362,14 +361,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, mut block: BasicBlock, irrefutable_pat: Pat<'tcx>, - initializer: ExprRef<'tcx>, + initializer: &Expr<'tcx>, ) -> BlockAnd<()> { match *irrefutable_pat.kind { // Optimize the case of `let x = ...` to write directly into `x` PatKind::Binding { mode: BindingMode::ByValue, var, subpattern: None, .. } => { let place = self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true); - unpack!(block = self.into(place, block, initializer)); + unpack!(block = self.expr_into_dest(place, block, initializer)); // Inject a fake read, see comments on `FakeReadCause::ForLet`. let source_info = self.source_info(irrefutable_pat.span); @@ -404,7 +403,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } => { let place = self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard, true); - unpack!(block = self.into(place, block, initializer)); + unpack!(block = self.expr_into_dest(place, block, initializer)); // Inject a fake read, see comments on `FakeReadCause::ForLet`. let pattern_source_info = self.source_info(irrefutable_pat.span); @@ -1749,15 +1748,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let (guard_span, (post_guard_block, otherwise_post_guard_block)) = match guard { Guard::If(e) => { - let e = self.hir.mirror(e.clone()); let source_info = self.source_info(e.span); (e.span, self.test_bool(block, e, source_info)) } Guard::IfLet(pat, scrutinee) => { - let scrutinee_span = scrutinee.span(); - let scrutinee_place = unpack!( - block = self.lower_scrutinee(block, scrutinee.clone(), scrutinee_span) - ); + let scrutinee_span = scrutinee.span; + let scrutinee_place = + unpack!(block = self.lower_scrutinee(block, &scrutinee, scrutinee_span)); let mut guard_candidate = Candidate::new(scrutinee_place, &pat, false); let wildcard = Pat::wildcard_from_ty(pat.ty); let mut otherwise_candidate = Candidate::new(scrutinee_place, &wildcard, false); @@ -1772,14 +1769,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { pat.span.to(arm_span.unwrap()), pat, ArmHasGuard(false), - Some((Some(&scrutinee_place), scrutinee.span())), + Some((Some(&scrutinee_place), scrutinee.span)), ); let post_guard_block = self.bind_pattern( self.source_info(pat.span), guard_candidate, None, &fake_borrow_temps, - scrutinee.span(), + scrutinee.span, None, None, ); diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index b928458df8ee4..f9bed4454f2ed 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -667,8 +667,8 @@ fn construct_const<'a, 'tcx>( let mut block = START_BLOCK; let ast_expr = &tcx.hir().body(body_id).value; - let expr = builder.hir.mirror(ast_expr); - unpack!(block = builder.into_expr(Place::return_place(), block, expr)); + let expr = builder.hir.mirror_expr(ast_expr); + unpack!(block = builder.expr_into_dest(Place::return_place(), block, &expr)); let source_info = builder.source_info(span); builder.cfg.terminate(block, source_info, TerminatorKind::Return); @@ -953,8 +953,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.source_scope = source_scope; } - let body = self.hir.mirror(ast_body); - self.into(Place::return_place(), block, body) + let body = self.hir.mirror_expr(ast_body); + self.expr_into_dest(Place::return_place(), block, &body) } fn set_correct_source_scope_for_arg( @@ -1001,7 +1001,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { mod block; mod cfg; mod expr; -mod into; mod matches; mod misc; mod scope; diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 5e9d780d17977..fccff023d0872 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -82,7 +82,7 @@ that contains only loops and breakable blocks. It tracks where a `break`, */ use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder, CFG}; -use crate::thir::{Expr, ExprRef, LintLevel}; +use crate::thir::{Expr, LintLevel}; use rustc_data_structures::fx::FxHashMap; use rustc_index::vec::IndexVec; use rustc_middle::middle::region; @@ -575,7 +575,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn break_scope( &mut self, mut block: BasicBlock, - value: Option>, + value: Option<&Expr<'tcx>>, target: BreakableTarget, source_info: SourceInfo, ) -> BlockAnd<()> { @@ -612,7 +612,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if let Some(value) = value { debug!("stmt_expr Break val block_context.push(SubExpr)"); self.block_context.push(BlockFrame::SubExpr); - unpack!(block = self.into(destination, block, value)); + unpack!(block = self.expr_into_dest(destination, block, value)); self.block_context.pop(); } else { self.cfg.push_assign_unit(block, source_info, destination, self.hir.tcx()) @@ -920,7 +920,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn test_bool( &mut self, mut block: BasicBlock, - condition: Expr<'tcx>, + condition: &Expr<'tcx>, source_info: SourceInfo, ) -> (BasicBlock, BasicBlock) { let cond = unpack!(block = self.as_local_operand(block, condition)); diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index 980888df7fee4..9c1440aba4204 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -1,4 +1,3 @@ -use crate::thir::cx::to_ref::ToRef; use crate::thir::cx::Cx; use crate::thir::{self, *}; @@ -8,110 +7,101 @@ use rustc_middle::ty; use rustc_index::vec::Idx; -impl<'tcx> Mirror<'tcx> for &'tcx hir::Block<'tcx> { - type Output = Block<'tcx>; - - fn make_mirror(self, cx: &mut Cx<'_, 'tcx>) -> Block<'tcx> { +impl<'a, 'tcx> Cx<'a, 'tcx> { + crate fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> Block<'tcx> { // We have to eagerly lower the "spine" of the statements // in order to get the lexical scoping correctly. - let stmts = mirror_stmts(cx, self.hir_id.local_id, &*self.stmts); + let stmts = self.mirror_stmts(block.hir_id.local_id, &*block.stmts); let opt_destruction_scope = - cx.region_scope_tree.opt_destruction_scope(self.hir_id.local_id); + self.region_scope_tree.opt_destruction_scope(block.hir_id.local_id); Block { - targeted_by_break: self.targeted_by_break, - region_scope: region::Scope { id: self.hir_id.local_id, data: region::ScopeData::Node }, + targeted_by_break: block.targeted_by_break, + region_scope: region::Scope { + id: block.hir_id.local_id, + data: region::ScopeData::Node, + }, opt_destruction_scope, - span: self.span, + span: block.span, stmts, - expr: self.expr.to_ref(), - safety_mode: match self.rules { + expr: block.expr.as_ref().map(|expr| self.mirror_expr_boxed(expr)), + safety_mode: match block.rules { hir::BlockCheckMode::DefaultBlock => BlockSafety::Safe, - hir::BlockCheckMode::UnsafeBlock(..) => BlockSafety::ExplicitUnsafe(self.hir_id), + hir::BlockCheckMode::UnsafeBlock(..) => BlockSafety::ExplicitUnsafe(block.hir_id), hir::BlockCheckMode::PushUnsafeBlock(..) => BlockSafety::PushUnsafe, hir::BlockCheckMode::PopUnsafeBlock(..) => BlockSafety::PopUnsafe, }, } } -} -fn mirror_stmts<'a, 'tcx>( - cx: &mut Cx<'a, 'tcx>, - block_id: hir::ItemLocalId, - stmts: &'tcx [hir::Stmt<'tcx>], -) -> Vec> { - let mut result = vec![]; - for (index, stmt) in stmts.iter().enumerate() { - let hir_id = stmt.hir_id; - let opt_dxn_ext = cx.region_scope_tree.opt_destruction_scope(hir_id.local_id); - match stmt.kind { - hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => { - result.push(StmtRef::Mirror(Box::new(Stmt { - kind: StmtKind::Expr { - scope: region::Scope { id: hir_id.local_id, data: region::ScopeData::Node }, - expr: expr.to_ref(), - }, - opt_destruction_scope: opt_dxn_ext, - }))) - } - hir::StmtKind::Item(..) => { - // ignore for purposes of the MIR - } - hir::StmtKind::Local(ref local) => { - let remainder_scope = region::Scope { - id: block_id, - data: region::ScopeData::Remainder(region::FirstStatementIndex::new(index)), - }; + fn mirror_stmts( + &mut self, + block_id: hir::ItemLocalId, + stmts: &'tcx [hir::Stmt<'tcx>], + ) -> Vec> { + let mut result = vec![]; + for (index, stmt) in stmts.iter().enumerate() { + let hir_id = stmt.hir_id; + let opt_dxn_ext = self.region_scope_tree.opt_destruction_scope(hir_id.local_id); + match stmt.kind { + hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => { + result.push(Stmt { + kind: StmtKind::Expr { + scope: region::Scope { + id: hir_id.local_id, + data: region::ScopeData::Node, + }, + expr: self.mirror_expr_boxed(expr), + }, + opt_destruction_scope: opt_dxn_ext, + }) + } + hir::StmtKind::Item(..) => { + // ignore for purposes of the MIR + } + hir::StmtKind::Local(ref local) => { + let remainder_scope = region::Scope { + id: block_id, + data: region::ScopeData::Remainder(region::FirstStatementIndex::new(index)), + }; - let mut pattern = cx.pattern_from_hir(&local.pat); + let mut pattern = self.pattern_from_hir(&local.pat); - if let Some(ty) = &local.ty { - if let Some(&user_ty) = cx.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, - }), - }; + 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, + }), + }; + } } - } - result.push(StmtRef::Mirror(Box::new(Stmt { - kind: StmtKind::Let { - remainder_scope, - init_scope: region::Scope { - id: hir_id.local_id, - data: region::ScopeData::Node, + result.push(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_boxed(init)), + lint_level: LintLevel::Explicit(local.hir_id), }, - pattern, - initializer: local.init.to_ref(), - lint_level: LintLevel::Explicit(local.hir_id), - }, - opt_destruction_scope: opt_dxn_ext, - }))); + opt_destruction_scope: opt_dxn_ext, + }); + } } } + result } - result -} - -crate fn to_expr_ref<'a, 'tcx>( - cx: &mut Cx<'a, 'tcx>, - block: &'tcx hir::Block<'tcx>, -) -> ExprRef<'tcx> { - let block_ty = cx.typeck_results().node_type(block.hir_id); - let temp_lifetime = cx.region_scope_tree.temporary_scope(block.hir_id.local_id); - let expr = Expr { - ty: block_ty, - temp_lifetime, - span: block.span, - kind: ExprKind::Block { body: block }, - }; - expr.to_ref() } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 620ce360e7d91..cd5e73a45cd59 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -1,5 +1,3 @@ -use crate::thir::cx::block; -use crate::thir::cx::to_ref::ToRef; use crate::thir::cx::Cx; use crate::thir::util::UserAnnotatedTyHelpers; use crate::thir::*; @@ -17,45 +15,45 @@ use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; use rustc_middle::ty::{self, AdtKind, Ty}; use rustc_span::Span; -impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr<'tcx> { - type Output = Expr<'tcx>; +impl<'a, 'tcx> Cx<'a, 'tcx> { + crate fn mirror_expr(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> { + let temp_lifetime = self.region_scope_tree.temporary_scope(hir_expr.hir_id.local_id); + let expr_scope = + region::Scope { id: hir_expr.hir_id.local_id, data: region::ScopeData::Node }; - fn make_mirror(self, cx: &mut Cx<'_, 'tcx>) -> Expr<'tcx> { - let temp_lifetime = cx.region_scope_tree.temporary_scope(self.hir_id.local_id); - let expr_scope = region::Scope { id: self.hir_id.local_id, data: region::ScopeData::Node }; + debug!("Expr::make_mirror(): id={}, span={:?}", hir_expr.hir_id, hir_expr.span); - debug!("Expr::make_mirror(): id={}, span={:?}", self.hir_id, self.span); - - let mut expr = make_mirror_unadjusted(cx, self); + let mut expr = self.make_mirror_unadjusted(hir_expr); // Now apply adjustments, if any. - for adjustment in cx.typeck_results().expr_adjustments(self) { + for adjustment in self.typeck_results().expr_adjustments(hir_expr) { debug!("make_mirror: expr={:?} applying adjustment={:?}", expr, adjustment); - expr = apply_adjustment(cx, self, expr, adjustment); + expr = self.apply_adjustment(hir_expr, expr, adjustment); } // Next, wrap this up in the expr's scope. expr = Expr { temp_lifetime, ty: expr.ty, - span: self.span, + span: hir_expr.span, kind: ExprKind::Scope { region_scope: expr_scope, - value: expr.to_ref(), - lint_level: LintLevel::Explicit(self.hir_id), + value: Box::new(expr), + lint_level: LintLevel::Explicit(hir_expr.hir_id), }, }; // Finally, create a destruction scope, if any. - if let Some(region_scope) = cx.region_scope_tree.opt_destruction_scope(self.hir_id.local_id) + if let Some(region_scope) = + self.region_scope_tree.opt_destruction_scope(hir_expr.hir_id.local_id) { expr = Expr { temp_lifetime, ty: expr.ty, - span: self.span, + span: hir_expr.span, kind: ExprKind::Scope { region_scope, - value: expr.to_ref(), + value: Box::new(expr), lint_level: LintLevel::Inherited, }, }; @@ -64,687 +62,997 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr<'tcx> { // OK, all done! expr } -} - -fn apply_adjustment<'a, 'tcx>( - cx: &mut Cx<'a, 'tcx>, - hir_expr: &'tcx hir::Expr<'tcx>, - mut expr: Expr<'tcx>, - adjustment: &Adjustment<'tcx>, -) -> Expr<'tcx> { - let Expr { temp_lifetime, mut span, .. } = expr; - - // Adjust the span from the block, to the last expression of the - // block. This is a better span when returning a mutable reference - // with too short a lifetime. The error message will use the span - // from the assignment to the return place, which should only point - // at the returned value, not the entire function body. - // - // fn return_short_lived<'a>(x: &'a mut i32) -> &'static mut i32 { - // x - // // ^ error message points at this expression. - // } - let mut adjust_span = |expr: &mut Expr<'tcx>| { - if let ExprKind::Block { body } = expr.kind { - if let Some(ref last_expr) = body.expr { - span = last_expr.span; - expr.span = span; - } - } - }; - let kind = match adjustment.kind { - Adjust::Pointer(PointerCast::Unsize) => { - adjust_span(&mut expr); - ExprKind::Pointer { cast: PointerCast::Unsize, source: expr.to_ref() } - } - Adjust::Pointer(cast) => ExprKind::Pointer { cast, source: expr.to_ref() }, - Adjust::NeverToAny => ExprKind::NeverToAny { source: expr.to_ref() }, - Adjust::Deref(None) => { - adjust_span(&mut expr); - ExprKind::Deref { arg: expr.to_ref() } - } - Adjust::Deref(Some(deref)) => { - // We don't need to do call adjust_span here since - // deref coercions always start with a built-in deref. - let call = deref.method_call(cx.tcx(), expr.ty); - - expr = Expr { - temp_lifetime, - ty: cx.tcx.mk_ref(deref.region, ty::TypeAndMut { ty: expr.ty, mutbl: deref.mutbl }), - span, - kind: ExprKind::Borrow { - borrow_kind: deref.mutbl.to_borrow_kind(), - arg: expr.to_ref(), - }, - }; + crate fn mirror_exprs(&mut self, exprs: &'tcx [hir::Expr<'tcx>]) -> Vec> { + exprs.iter().map(|expr| self.mirror_expr(expr)).collect() + } - overloaded_place( - cx, - hir_expr, - adjustment.target, - Some(call), - vec![expr.to_ref()], - deref.span, - ) - } - Adjust::Borrow(AutoBorrow::Ref(_, m)) => { - ExprKind::Borrow { borrow_kind: m.to_borrow_kind(), arg: expr.to_ref() } - } - Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => { - ExprKind::AddressOf { mutability, arg: expr.to_ref() } - } - }; + crate fn mirror_expr_boxed(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Box> { + Box::new(self.mirror_expr(expr)) + } - Expr { temp_lifetime, ty: adjustment.target, span, kind } -} + fn apply_adjustment( + &mut self, + hir_expr: &'tcx hir::Expr<'tcx>, + mut expr: Expr<'tcx>, + adjustment: &Adjustment<'tcx>, + ) -> Expr<'tcx> { + let Expr { temp_lifetime, mut span, .. } = expr; + + // Adjust the span from the block, to the last expression of the + // block. This is a better span when returning a mutable reference + // with too short a lifetime. The error message will use the span + // from the assignment to the return place, which should only point + // at the returned value, not the entire function body. + // + // fn return_short_lived<'a>(x: &'a mut i32) -> &'static mut i32 { + // x + // // ^ error message points at this expression. + // } + let mut adjust_span = |expr: &mut Expr<'tcx>| { + if let ExprKind::Block { body } = &expr.kind { + if let Some(ref last_expr) = body.expr { + span = last_expr.span; + expr.span = span; + } + } + }; -fn make_mirror_unadjusted<'a, 'tcx>( - cx: &mut Cx<'a, 'tcx>, - expr: &'tcx hir::Expr<'tcx>, -) -> Expr<'tcx> { - let expr_ty = cx.typeck_results().expr_ty(expr); - let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id); - - let kind = match expr.kind { - // Here comes the interesting stuff: - hir::ExprKind::MethodCall(_, method_span, ref args, fn_span) => { - // Rewrite a.b(c) into UFCS form like Trait::b(a, c) - let expr = method_callee(cx, expr, method_span, None); - let args = args.iter().map(|e| e.to_ref()).collect(); - ExprKind::Call { ty: expr.ty, fun: expr.to_ref(), args, from_hir_call: true, fn_span } - } + let kind = match adjustment.kind { + Adjust::Pointer(PointerCast::Unsize) => { + adjust_span(&mut expr); + ExprKind::Pointer { cast: PointerCast::Unsize, source: Box::new(expr) } + } + Adjust::Pointer(cast) => ExprKind::Pointer { cast, source: Box::new(expr) }, + Adjust::NeverToAny => ExprKind::NeverToAny { source: Box::new(expr) }, + Adjust::Deref(None) => { + adjust_span(&mut expr); + ExprKind::Deref { arg: Box::new(expr) } + } + Adjust::Deref(Some(deref)) => { + // We don't need to do call adjust_span here since + // deref coercions always start with a built-in deref. + let call = deref.method_call(self.tcx(), expr.ty); - hir::ExprKind::Call(ref fun, ref args) => { - if cx.typeck_results().is_method_call(expr) { - // The callee is something implementing Fn, FnMut, or FnOnce. - // Find the actual method implementation being called and - // build the appropriate UFCS call expression with the - // callee-object as expr parameter. + expr = Expr { + temp_lifetime, + ty: self + .tcx + .mk_ref(deref.region, ty::TypeAndMut { ty: expr.ty, mutbl: deref.mutbl }), + span, + kind: ExprKind::Borrow { + borrow_kind: deref.mutbl.to_borrow_kind(), + arg: Box::new(expr), + }, + }; - // rewrite f(u, v) into FnOnce::call_once(f, (u, v)) + self.overloaded_place( + hir_expr, + adjustment.target, + Some(call), + vec![expr], + deref.span, + ) + } + Adjust::Borrow(AutoBorrow::Ref(_, m)) => { + ExprKind::Borrow { borrow_kind: m.to_borrow_kind(), arg: Box::new(expr) } + } + Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => { + ExprKind::AddressOf { mutability, arg: Box::new(expr) } + } + }; - let method = method_callee(cx, expr, fun.span, None); + Expr { temp_lifetime, ty: adjustment.target, span, kind } + } - let arg_tys = args.iter().map(|e| cx.typeck_results().expr_ty_adjusted(e)); - let tupled_args = Expr { - ty: cx.tcx.mk_tup(arg_tys), - temp_lifetime, - span: expr.span, - kind: ExprKind::Tuple { fields: args.iter().map(ToRef::to_ref).collect() }, - }; + fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> { + let expr_ty = self.typeck_results().expr_ty(expr); + let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); + let kind = match expr.kind { + // Here comes the interesting stuff: + hir::ExprKind::MethodCall(_, method_span, ref args, fn_span) => { + // Rewrite a.b(c) into UFCS form like Trait::b(a, c) + let expr = self.method_callee(expr, method_span, None); + let args = self.mirror_exprs(args); ExprKind::Call { - ty: method.ty, - fun: method.to_ref(), - args: vec![fun.to_ref(), tupled_args.to_ref()], + ty: expr.ty, + fun: Box::new(expr), + args, from_hir_call: true, - fn_span: expr.span, + fn_span, } - } else { - let adt_data = - if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = fun.kind { - // Tuple-like ADTs are represented as ExprKind::Call. We convert them here. - expr_ty.ty_adt_def().and_then(|adt_def| match path.res { - Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_id) => { - Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id))) - } - Res::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))), - _ => None, - }) - } else { - None + } + + hir::ExprKind::Call(ref fun, ref args) => { + if self.typeck_results().is_method_call(expr) { + // The callee is something implementing Fn, FnMut, or FnOnce. + // Find the actual method implementation being called and + // build the appropriate UFCS call expression with the + // callee-object as expr parameter. + + // rewrite f(u, v) into FnOnce::call_once(f, (u, v)) + + let method = self.method_callee(expr, fun.span, None); + + let arg_tys = args.iter().map(|e| self.typeck_results().expr_ty_adjusted(e)); + let tupled_args = Expr { + ty: self.tcx.mk_tup(arg_tys), + temp_lifetime, + span: expr.span, + kind: ExprKind::Tuple { fields: self.mirror_exprs(args) }, }; - if let Some((adt_def, index)) = adt_data { - let substs = cx.typeck_results().node_substs(fun.hir_id); - let user_provided_types = cx.typeck_results().user_provided_types(); - let user_ty = user_provided_types.get(fun.hir_id).copied().map(|mut u_ty| { - if let UserType::TypeOf(ref mut did, _) = &mut u_ty.value { - *did = adt_def.did; - } - u_ty - }); - debug!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty); - - let field_refs = args - .iter() - .enumerate() - .map(|(idx, e)| FieldExprRef { name: Field::new(idx), expr: e.to_ref() }) - .collect(); - ExprKind::Adt { - adt_def, - substs, - variant_index: index, - fields: field_refs, - user_ty, - base: None, - } - } else { + ExprKind::Call { - ty: cx.typeck_results().node_type(fun.hir_id), - fun: fun.to_ref(), - args: args.to_ref(), + ty: method.ty, + fun: Box::new(method), + args: vec![self.mirror_expr(fun), tupled_args], from_hir_call: true, fn_span: expr.span, } + } else { + let adt_data = + if let hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) = fun.kind { + // Tuple-like ADTs are represented as ExprKind::Call. We convert them here. + expr_ty.ty_adt_def().and_then(|adt_def| match path.res { + Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_id) => { + Some((adt_def, adt_def.variant_index_with_ctor_id(ctor_id))) + } + Res::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))), + _ => None, + }) + } else { + None + }; + if let Some((adt_def, index)) = adt_data { + let substs = self.typeck_results().node_substs(fun.hir_id); + let user_provided_types = self.typeck_results().user_provided_types(); + let user_ty = + user_provided_types.get(fun.hir_id).copied().map(|mut u_ty| { + if let UserType::TypeOf(ref mut did, _) = &mut u_ty.value { + *did = adt_def.did; + } + u_ty + }); + debug!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty); + + let field_refs = args + .iter() + .enumerate() + .map(|(idx, e)| FieldExpr { + name: Field::new(idx), + expr: self.mirror_expr(e), + }) + .collect(); + ExprKind::Adt { + adt_def, + substs, + variant_index: index, + fields: field_refs, + user_ty, + base: None, + } + } else { + ExprKind::Call { + ty: self.typeck_results().node_type(fun.hir_id), + fun: self.mirror_expr_boxed(fun), + args: self.mirror_exprs(args), + from_hir_call: true, + fn_span: expr.span, + } + } } } - } - hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, ref arg) => { - ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg: arg.to_ref() } - } + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, ref arg) => ExprKind::Borrow { + borrow_kind: mutbl.to_borrow_kind(), + arg: self.mirror_expr_boxed(arg), + }, - hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => { - ExprKind::AddressOf { mutability, arg: arg.to_ref() } - } + hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => { + ExprKind::AddressOf { mutability, arg: self.mirror_expr_boxed(arg) } + } - hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: &blk }, + hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: self.mirror_block(blk) }, - hir::ExprKind::Assign(ref lhs, ref rhs, _) => { - ExprKind::Assign { lhs: lhs.to_ref(), rhs: rhs.to_ref() } - } + hir::ExprKind::Assign(ref lhs, ref rhs, _) => ExprKind::Assign { + lhs: self.mirror_expr_boxed(lhs), + rhs: self.mirror_expr_boxed(rhs), + }, - hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => { - if cx.typeck_results().is_method_call(expr) { - overloaded_operator(cx, expr, vec![lhs.to_ref(), rhs.to_ref()]) - } else { - ExprKind::AssignOp { op: bin_op(op.node), lhs: lhs.to_ref(), rhs: rhs.to_ref() } + hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => { + if self.typeck_results().is_method_call(expr) { + let lhs = self.mirror_expr(lhs); + let rhs = self.mirror_expr(rhs); + self.overloaded_operator(expr, vec![lhs, rhs]) + } else { + ExprKind::AssignOp { + op: bin_op(op.node), + lhs: self.mirror_expr_boxed(lhs), + rhs: self.mirror_expr_boxed(rhs), + } + } } - } - hir::ExprKind::Lit(ref lit) => ExprKind::Literal { - literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, false), - user_ty: None, - const_id: None, - }, - - hir::ExprKind::Binary(op, ref lhs, ref rhs) => { - if cx.typeck_results().is_method_call(expr) { - overloaded_operator(cx, expr, vec![lhs.to_ref(), rhs.to_ref()]) - } else { - // FIXME overflow - match (op.node, cx.constness) { - (hir::BinOpKind::And, _) => ExprKind::LogicalOp { - op: LogicalOp::And, - lhs: lhs.to_ref(), - rhs: rhs.to_ref(), - }, - (hir::BinOpKind::Or, _) => ExprKind::LogicalOp { - op: LogicalOp::Or, - lhs: lhs.to_ref(), - rhs: rhs.to_ref(), - }, + hir::ExprKind::Lit(ref lit) => ExprKind::Literal { + literal: self.const_eval_literal(&lit.node, expr_ty, lit.span, false), + user_ty: None, + const_id: None, + }, - _ => { - let op = bin_op(op.node); - ExprKind::Binary { op, lhs: lhs.to_ref(), rhs: rhs.to_ref() } + hir::ExprKind::Binary(op, ref lhs, ref rhs) => { + if self.typeck_results().is_method_call(expr) { + let lhs = self.mirror_expr(lhs); + let rhs = self.mirror_expr(rhs); + self.overloaded_operator(expr, vec![lhs, rhs]) + } else { + // FIXME overflow + match (op.node, self.constness) { + (hir::BinOpKind::And, _) => ExprKind::LogicalOp { + op: LogicalOp::And, + lhs: self.mirror_expr_boxed(lhs), + rhs: self.mirror_expr_boxed(rhs), + }, + (hir::BinOpKind::Or, _) => ExprKind::LogicalOp { + op: LogicalOp::Or, + lhs: self.mirror_expr_boxed(lhs), + rhs: self.mirror_expr_boxed(rhs), + }, + + _ => { + let op = bin_op(op.node); + ExprKind::Binary { + op, + lhs: self.mirror_expr_boxed(lhs), + rhs: self.mirror_expr_boxed(rhs), + } + } } } } - } - hir::ExprKind::Index(ref lhs, ref index) => { - if cx.typeck_results().is_method_call(expr) { - overloaded_place( - cx, - expr, - expr_ty, - None, - vec![lhs.to_ref(), index.to_ref()], - expr.span, - ) - } else { - ExprKind::Index { lhs: lhs.to_ref(), index: index.to_ref() } + hir::ExprKind::Index(ref lhs, ref index) => { + if self.typeck_results().is_method_call(expr) { + let lhs = self.mirror_expr(lhs); + let index = self.mirror_expr(index); + self.overloaded_place(expr, expr_ty, None, vec![lhs, index], expr.span) + } else { + ExprKind::Index { + lhs: self.mirror_expr_boxed(lhs), + index: self.mirror_expr_boxed(index), + } + } } - } - hir::ExprKind::Unary(hir::UnOp::Deref, ref arg) => { - if cx.typeck_results().is_method_call(expr) { - overloaded_place(cx, expr, expr_ty, None, vec![arg.to_ref()], expr.span) - } else { - ExprKind::Deref { arg: arg.to_ref() } + hir::ExprKind::Unary(hir::UnOp::Deref, ref arg) => { + if self.typeck_results().is_method_call(expr) { + let arg = self.mirror_expr(arg); + self.overloaded_place(expr, expr_ty, None, vec![arg], expr.span) + } else { + ExprKind::Deref { arg: self.mirror_expr_boxed(arg) } + } } - } - hir::ExprKind::Unary(hir::UnOp::Not, ref arg) => { - if cx.typeck_results().is_method_call(expr) { - overloaded_operator(cx, expr, vec![arg.to_ref()]) - } else { - ExprKind::Unary { op: UnOp::Not, arg: arg.to_ref() } + hir::ExprKind::Unary(hir::UnOp::Not, ref arg) => { + if self.typeck_results().is_method_call(expr) { + let arg = self.mirror_expr(arg); + self.overloaded_operator(expr, vec![arg]) + } else { + ExprKind::Unary { op: UnOp::Not, arg: self.mirror_expr_boxed(arg) } + } } - } - hir::ExprKind::Unary(hir::UnOp::Neg, ref arg) => { - if cx.typeck_results().is_method_call(expr) { - overloaded_operator(cx, expr, vec![arg.to_ref()]) - } else if let hir::ExprKind::Lit(ref lit) = arg.kind { - ExprKind::Literal { - literal: cx.const_eval_literal(&lit.node, expr_ty, lit.span, true), - user_ty: None, - const_id: None, + hir::ExprKind::Unary(hir::UnOp::Neg, ref arg) => { + if self.typeck_results().is_method_call(expr) { + let arg = self.mirror_expr(arg); + self.overloaded_operator(expr, vec![arg]) + } else if let hir::ExprKind::Lit(ref lit) = arg.kind { + ExprKind::Literal { + literal: self.const_eval_literal(&lit.node, expr_ty, lit.span, true), + user_ty: None, + const_id: None, + } + } else { + ExprKind::Unary { op: UnOp::Neg, arg: self.mirror_expr_boxed(arg) } } - } else { - ExprKind::Unary { op: UnOp::Neg, arg: arg.to_ref() } } - } - hir::ExprKind::Struct(ref qpath, ref fields, ref base) => match expr_ty.kind() { - ty::Adt(adt, substs) => match adt.adt_kind() { - AdtKind::Struct | AdtKind::Union => { - let user_provided_types = cx.typeck_results().user_provided_types(); - let user_ty = user_provided_types.get(expr.hir_id).copied(); - debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty); - ExprKind::Adt { - adt_def: adt, - variant_index: VariantIdx::new(0), - substs, - user_ty, - fields: field_refs(cx, fields), - base: base.as_ref().map(|base| FruInfo { - base: base.to_ref(), - field_types: cx.typeck_results().fru_field_types()[expr.hir_id].clone(), - }), + hir::ExprKind::Struct(ref qpath, ref fields, ref base) => match expr_ty.kind() { + ty::Adt(adt, substs) => match adt.adt_kind() { + AdtKind::Struct | AdtKind::Union => { + let user_provided_types = self.typeck_results().user_provided_types(); + let user_ty = user_provided_types.get(expr.hir_id).copied(); + debug!("make_mirror_unadjusted: (struct/union) user_ty={:?}", user_ty); + ExprKind::Adt { + adt_def: adt, + variant_index: VariantIdx::new(0), + substs, + user_ty, + fields: self.field_refs(fields), + base: base.as_ref().map(|base| FruInfo { + base: self.mirror_expr_boxed(base), + field_types: self.typeck_results().fru_field_types()[expr.hir_id] + .clone(), + }), + } } - } - AdtKind::Enum => { - let res = cx.typeck_results().qpath_res(qpath, expr.hir_id); - match res { - Res::Def(DefKind::Variant, variant_id) => { - assert!(base.is_none()); - - let index = adt.variant_index_with_id(variant_id); - let user_provided_types = cx.typeck_results().user_provided_types(); - let user_ty = user_provided_types.get(expr.hir_id).copied(); - debug!("make_mirror_unadjusted: (variant) user_ty={:?}", user_ty); - ExprKind::Adt { - adt_def: adt, - variant_index: index, - substs, - user_ty, - fields: field_refs(cx, fields), - base: None, + AdtKind::Enum => { + let res = self.typeck_results().qpath_res(qpath, expr.hir_id); + match res { + Res::Def(DefKind::Variant, variant_id) => { + assert!(base.is_none()); + + let index = adt.variant_index_with_id(variant_id); + let user_provided_types = + self.typeck_results().user_provided_types(); + let user_ty = user_provided_types.get(expr.hir_id).copied(); + debug!("make_mirror_unadjusted: (variant) user_ty={:?}", user_ty); + ExprKind::Adt { + adt_def: adt, + variant_index: index, + substs, + user_ty, + fields: self.field_refs(fields), + base: None, + } + } + _ => { + span_bug!(expr.span, "unexpected res: {:?}", res); } - } - _ => { - span_bug!(expr.span, "unexpected res: {:?}", res); } } - } - }, - _ => { - span_bug!(expr.span, "unexpected type for struct literal: {:?}", expr_ty); - } - }, - - hir::ExprKind::Closure(..) => { - let closure_ty = cx.typeck_results().expr_ty(expr); - let (def_id, substs, movability) = match *closure_ty.kind() { - ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs), None), - ty::Generator(def_id, substs, movability) => { - (def_id, UpvarSubsts::Generator(substs), Some(movability)) - } + }, _ => { - span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty); + span_bug!(expr.span, "unexpected type for struct literal: {:?}", expr_ty); } - }; + }, - let upvars = cx - .typeck_results() - .closure_min_captures_flattened(def_id) - .zip(substs.upvar_tys()) - .map(|(captured_place, ty)| capture_upvar(cx, expr, captured_place, ty)) - .collect(); - ExprKind::Closure { closure_id: def_id, substs, upvars, movability } - } + hir::ExprKind::Closure(..) => { + let closure_ty = self.typeck_results().expr_ty(expr); + let (def_id, substs, movability) = match *closure_ty.kind() { + ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs), None), + ty::Generator(def_id, substs, movability) => { + (def_id, UpvarSubsts::Generator(substs), Some(movability)) + } + _ => { + span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty); + } + }; - hir::ExprKind::Path(ref qpath) => { - let res = cx.typeck_results().qpath_res(qpath, expr.hir_id); - convert_path_expr(cx, expr, res) - } + let upvars = self + .typeck_results() + .closure_min_captures_flattened(def_id) + .zip(substs.upvar_tys()) + .map(|(captured_place, ty)| self.capture_upvar(expr, captured_place, ty)) + .collect(); + ExprKind::Closure { closure_id: def_id, substs, upvars, movability } + } - hir::ExprKind::InlineAsm(ref asm) => ExprKind::InlineAsm { - template: asm.template, - operands: asm - .operands - .iter() - .map(|(op, _op_sp)| { - match *op { - hir::InlineAsmOperand::In { reg, ref expr } => { - InlineAsmOperand::In { reg, expr: expr.to_ref() } - } - hir::InlineAsmOperand::Out { reg, late, ref expr } => { - InlineAsmOperand::Out { + hir::ExprKind::Path(ref qpath) => { + let res = self.typeck_results().qpath_res(qpath, expr.hir_id); + self.convert_path_expr(expr, res) + } + + hir::ExprKind::InlineAsm(ref asm) => ExprKind::InlineAsm { + template: asm.template, + operands: asm + .operands + .iter() + .map(|(op, _op_sp)| { + match *op { + hir::InlineAsmOperand::In { reg, ref expr } => { + 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, late, - expr: expr.as_ref().map(|expr| expr.to_ref()), + ref in_expr, + ref out_expr, + } => InlineAsmOperand::SplitInOut { + reg, + late, + in_expr: self.mirror_expr(in_expr), + out_expr: out_expr.as_ref().map(|expr| self.mirror_expr(expr)), + }, + hir::InlineAsmOperand::Const { ref expr } => { + InlineAsmOperand::Const { expr: self.mirror_expr(expr) } } - } - hir::InlineAsmOperand::InOut { reg, late, ref expr } => { - InlineAsmOperand::InOut { reg, late, expr: expr.to_ref() } - } - hir::InlineAsmOperand::SplitInOut { - reg, - late, - ref in_expr, - ref out_expr, - } => InlineAsmOperand::SplitInOut { - reg, - late, - in_expr: in_expr.to_ref(), - out_expr: out_expr.as_ref().map(|expr| expr.to_ref()), - }, - hir::InlineAsmOperand::Const { ref expr } => { - InlineAsmOperand::Const { expr: expr.to_ref() } - } - 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 = - cx.region_scope_tree.temporary_scope(expr.hir_id.local_id); - let res = cx.typeck_results().qpath_res(qpath, expr.hir_id); - let ty; - match res { - Res::Def(DefKind::Fn, _) | Res::Def(DefKind::AssocFn, _) => { - ty = cx.typeck_results().node_type(expr.hir_id); - let user_ty = user_substs_applied_to_res(cx, expr.hir_id, res); - InlineAsmOperand::SymFn { - expr: Expr { - ty, - temp_lifetime, - span: expr.span, - kind: ExprKind::Literal { - literal: ty::Const::zero_sized(cx.tcx, ty), - user_ty, - const_id: None, + 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: Expr { + ty, + temp_lifetime, + span: expr.span, + kind: ExprKind::Literal { + literal: ty::Const::zero_sized(self.tcx, ty), + user_ty, + const_id: None, + }, }, } - .to_ref(), } - } - Res::Def(DefKind::Static, def_id) => { - InlineAsmOperand::SymStatic { def_id } - } + Res::Def(DefKind::Static, def_id) => { + InlineAsmOperand::SymStatic { def_id } + } - _ => { - cx.tcx.sess.span_err( - expr.span, - "asm `sym` operand must point to a fn or static", - ); - - // Not a real fn, but we're not reaching codegen anyways... - ty = cx.tcx.ty_error(); - InlineAsmOperand::SymFn { - expr: Expr { - ty, - temp_lifetime, - span: expr.span, - kind: ExprKind::Literal { - literal: ty::Const::zero_sized(cx.tcx, ty), - user_ty: None, - const_id: None, + _ => { + self.tcx.sess.span_err( + expr.span, + "asm `sym` operand must point to a fn or static", + ); + + // Not a real fn, but we're not reaching codegen anyways... + ty = self.tcx.ty_error(); + InlineAsmOperand::SymFn { + expr: Expr { + ty, + temp_lifetime, + span: expr.span, + kind: ExprKind::Literal { + literal: ty::Const::zero_sized(self.tcx, ty), + user_ty: None, + const_id: None, + }, }, } - .to_ref(), } } } } - } - }) - .collect(), - options: asm.options, - line_spans: asm.line_spans, - }, - - hir::ExprKind::LlvmInlineAsm(ref asm) => ExprKind::LlvmInlineAsm { - asm: &asm.inner, - outputs: asm.outputs_exprs.to_ref(), - inputs: asm.inputs_exprs.to_ref(), - }, - - hir::ExprKind::ConstBlock(ref anon_const) => { - let anon_const_def_id = cx.tcx.hir().local_def_id(anon_const.hir_id); - let value = ty::Const::from_anon_const(cx.tcx, anon_const_def_id); - - ExprKind::ConstBlock { value } - } - // Now comes the rote stuff: - hir::ExprKind::Repeat(ref v, ref count) => { - let count_def_id = cx.tcx.hir().local_def_id(count.hir_id); - let count = ty::Const::from_anon_const(cx.tcx, count_def_id); + }) + .collect(), + options: asm.options, + line_spans: asm.line_spans, + }, - ExprKind::Repeat { value: v.to_ref(), count } - } - hir::ExprKind::Ret(ref v) => ExprKind::Return { value: v.to_ref() }, - hir::ExprKind::Break(dest, ref value) => match dest.target_id { - Ok(target_id) => ExprKind::Break { - label: region::Scope { id: target_id.local_id, data: region::ScopeData::Node }, - value: value.to_ref(), + hir::ExprKind::LlvmInlineAsm(ref asm) => ExprKind::LlvmInlineAsm { + asm: &asm.inner, + outputs: self.mirror_exprs(asm.outputs_exprs), + inputs: self.mirror_exprs(asm.inputs_exprs), + }, + + hir::ExprKind::ConstBlock(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); + + ExprKind::ConstBlock { value } + } + // Now comes the rote stuff: + hir::ExprKind::Repeat(ref v, ref count) => { + let count_def_id = self.tcx.hir().local_def_id(count.hir_id); + let count = ty::Const::from_anon_const(self.tcx, count_def_id); + + ExprKind::Repeat { value: self.mirror_expr_boxed(v), count } + } + hir::ExprKind::Ret(ref v) => { + ExprKind::Return { value: v.as_ref().map(|v| self.mirror_expr_boxed(v)) } + } + hir::ExprKind::Break(dest, ref value) => match dest.target_id { + Ok(target_id) => ExprKind::Break { + label: region::Scope { id: target_id.local_id, data: region::ScopeData::Node }, + value: value.as_ref().map(|value| self.mirror_expr_boxed(value)), + }, + Err(err) => bug!("invalid loop id for break: {}", err), + }, + hir::ExprKind::Continue(dest) => match dest.target_id { + Ok(loop_id) => ExprKind::Continue { + label: region::Scope { id: loop_id.local_id, data: region::ScopeData::Node }, + }, + Err(err) => bug!("invalid loop id for continue: {}", err), }, - Err(err) => bug!("invalid loop id for break: {}", err), - }, - hir::ExprKind::Continue(dest) => match dest.target_id { - Ok(loop_id) => ExprKind::Continue { - label: region::Scope { id: loop_id.local_id, data: region::ScopeData::Node }, + hir::ExprKind::If(cond, then, else_opt) => ExprKind::If { + cond: self.mirror_expr_boxed(cond), + then: self.mirror_expr_boxed(then), + else_opt: else_opt.map(|el| self.mirror_expr_boxed(el)), }, - Err(err) => bug!("invalid loop id for continue: {}", err), - }, - hir::ExprKind::If(cond, then, else_opt) => ExprKind::If { - cond: cond.to_ref(), - then: then.to_ref(), - else_opt: else_opt.map(|el| el.to_ref()), - }, - hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match { - scrutinee: discr.to_ref(), - arms: arms.iter().map(|a| convert_arm(cx, a)).collect(), - }, - hir::ExprKind::Loop(ref body, ..) => ExprKind::Loop { body: block::to_expr_ref(cx, body) }, - hir::ExprKind::Field(ref source, ..) => ExprKind::Field { - lhs: source.to_ref(), - name: Field::new(cx.tcx.field_index(expr.hir_id, cx.typeck_results)), - }, - hir::ExprKind::Cast(ref source, ref cast_ty) => { - // Check for a user-given type annotation on this `cast` - let user_provided_types = cx.typeck_results.user_provided_types(); - let user_ty = user_provided_types.get(cast_ty.hir_id); - - debug!( - "cast({:?}) has ty w/ hir_id {:?} and user provided ty {:?}", - expr, cast_ty.hir_id, user_ty, - ); - - // Check to see if this cast is a "coercion cast", where the cast is actually done - // using a coercion (or is a no-op). - let cast = if cx.typeck_results().is_coercion_cast(source.hir_id) { - // Convert the lexpr to a vexpr. - ExprKind::Use { source: source.to_ref() } - } else if cx.typeck_results().expr_ty(source).is_region_ptr() { - // Special cased so that we can type check that the element - // type of the source matches the pointed to type of the - // destination. - ExprKind::Pointer { source: source.to_ref(), cast: PointerCast::ArrayToPointer } - } else { - // check whether this is casting an enum variant discriminant - // to prevent cycles, we refer to the discriminant initializer - // which is always an integer and thus doesn't need to know the - // enum's layout (or its tag type) to compute it during const eval - // Example: - // enum Foo { - // A, - // B = A as isize + 4, - // } - // The correct solution would be to add symbolic computations to miri, - // so we wouldn't have to compute and store the actual value - let var = if let hir::ExprKind::Path(ref qpath) = source.kind { - let res = cx.typeck_results().qpath_res(qpath, source.hir_id); - cx.typeck_results().node_type(source.hir_id).ty_adt_def().and_then(|adt_def| { - match res { - Res::Def( - DefKind::Ctor(CtorOf::Variant, CtorKind::Const), - variant_ctor_id, - ) => { - let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id); - let (d, o) = adt_def.discriminant_def_for_variant(idx); - use rustc_middle::ty::util::IntTypeExt; - let ty = adt_def.repr.discr_type(); - let ty = ty.to_ty(cx.tcx()); - Some((d, o, ty)) - } - _ => None, - } - }) + hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match { + scrutinee: self.mirror_expr_boxed(discr), + arms: arms.iter().map(|a| self.convert_arm(a)).collect(), + }, + hir::ExprKind::Loop(ref body, ..) => { + 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 block = self.mirror_block(body); + let body = Box::new(Expr { + ty: block_ty, + temp_lifetime, + span: block.span, + kind: ExprKind::Block { body: block }, + }); + ExprKind::Loop { body } + } + hir::ExprKind::Field(ref source, ..) => ExprKind::Field { + lhs: self.mirror_expr_boxed(source), + name: Field::new(self.tcx.field_index(expr.hir_id, self.typeck_results)), + }, + hir::ExprKind::Cast(ref source, ref cast_ty) => { + // Check for a user-given type annotation on this `cast` + let user_provided_types = self.typeck_results.user_provided_types(); + let user_ty = user_provided_types.get(cast_ty.hir_id); + + debug!( + "cast({:?}) has ty w/ hir_id {:?} and user provided ty {:?}", + expr, cast_ty.hir_id, user_ty, + ); + + // Check to see if this cast is a "coercion cast", where the cast is actually done + // using a coercion (or is a no-op). + let cast = if self.typeck_results().is_coercion_cast(source.hir_id) { + // Convert the lexpr to a vexpr. + ExprKind::Use { source: self.mirror_expr_boxed(source) } + } else if self.typeck_results().expr_ty(source).is_region_ptr() { + // Special cased so that we can type check that the element + // type of the source matches the pointed to type of the + // destination. + ExprKind::Pointer { + source: self.mirror_expr_boxed(source), + cast: PointerCast::ArrayToPointer, + } } else { - None - }; + // check whether this is casting an enum variant discriminant + // to prevent cycles, we refer to the discriminant initializer + // which is always an integer and thus doesn't need to know the + // enum's layout (or its tag type) to compute it during const eval + // Example: + // enum Foo { + // A, + // B = A as isize + 4, + // } + // The correct solution would be to add symbolic computations to miri, + // so we wouldn't have to compute and store the actual value + let var = if let hir::ExprKind::Path(ref qpath) = source.kind { + let res = self.typeck_results().qpath_res(qpath, source.hir_id); + self.typeck_results().node_type(source.hir_id).ty_adt_def().and_then( + |adt_def| match res { + Res::Def( + DefKind::Ctor(CtorOf::Variant, CtorKind::Const), + variant_ctor_id, + ) => { + let idx = adt_def.variant_index_with_ctor_id(variant_ctor_id); + let (d, o) = adt_def.discriminant_def_for_variant(idx); + use rustc_middle::ty::util::IntTypeExt; + let ty = adt_def.repr.discr_type(); + let ty = ty.to_ty(self.tcx()); + Some((d, o, ty)) + } + _ => None, + }, + ) + } else { + None + }; - let source = if let Some((did, offset, var_ty)) = var { - let mk_const = |literal| { - Expr { + let source = if let Some((did, offset, var_ty)) = var { + let mk_const = |literal| Expr { temp_lifetime, ty: var_ty, span: expr.span, kind: ExprKind::Literal { literal, user_ty: None, const_id: None }, + }; + let offset = mk_const(ty::Const::from_bits( + self.tcx, + offset as u128, + self.param_env.and(var_ty), + )); + match did { + Some(did) => { + // in case we are offsetting from a computed discriminant + // and not the beginning of discriminants (which is always `0`) + let substs = InternalSubsts::identity_for_item(self.tcx(), did); + let lhs = mk_const(self.tcx().mk_const(ty::Const { + val: ty::ConstKind::Unevaluated( + ty::WithOptConstParam::unknown(did), + substs, + None, + ), + ty: var_ty, + })); + let bin = ExprKind::Binary { + op: BinOp::Add, + lhs: Box::new(lhs), + rhs: Box::new(offset), + }; + Expr { temp_lifetime, ty: var_ty, span: expr.span, kind: bin } + } + None => offset, } - .to_ref() + } else { + self.mirror_expr(source) }; - let offset = mk_const(ty::Const::from_bits( - cx.tcx, - offset as u128, - cx.param_env.and(var_ty), - )); - match did { - Some(did) => { - // in case we are offsetting from a computed discriminant - // and not the beginning of discriminants (which is always `0`) - let substs = InternalSubsts::identity_for_item(cx.tcx(), did); - let lhs = mk_const(cx.tcx().mk_const(ty::Const { - val: ty::ConstKind::Unevaluated( - ty::WithOptConstParam::unknown(did), - substs, - None, - ), - ty: var_ty, - })); - let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset }; - Expr { temp_lifetime, ty: var_ty, span: expr.span, kind: bin }.to_ref() - } - None => offset, - } - } else { - source.to_ref() - }; - ExprKind::Cast { source } - }; + ExprKind::Cast { source: Box::new(source) } + }; - if let Some(user_ty) = user_ty { - // NOTE: Creating a new Expr and wrapping a Cast inside of it may be - // inefficient, revisit this when performance becomes an issue. - let cast_expr = Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind: cast }; - debug!("make_mirror_unadjusted: (cast) 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 + // inefficient, revisit this when performance becomes an issue. + let cast_expr = + Box::new(Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind: cast }); + debug!("make_mirror_unadjusted: (cast) user_ty={:?}", user_ty); - ExprKind::ValueTypeAscription { - source: cast_expr.to_ref(), - user_ty: Some(*user_ty), + ExprKind::ValueTypeAscription { source: cast_expr, user_ty: Some(*user_ty) } + } else { + cast } - } else { - cast } - } - hir::ExprKind::Type(ref source, ref ty) => { - let user_provided_types = cx.typeck_results.user_provided_types(); - let user_ty = user_provided_types.get(ty.hir_id).copied(); - debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty); - if source.is_syntactic_place_expr() { - ExprKind::PlaceTypeAscription { source: source.to_ref(), user_ty } - } else { - ExprKind::ValueTypeAscription { source: source.to_ref(), user_ty } + hir::ExprKind::Type(ref source, ref ty) => { + let user_provided_types = self.typeck_results.user_provided_types(); + let user_ty = user_provided_types.get(ty.hir_id).copied(); + debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty); + let mirrored = self.mirror_expr_boxed(source); + if source.is_syntactic_place_expr() { + ExprKind::PlaceTypeAscription { source: mirrored, user_ty } + } else { + ExprKind::ValueTypeAscription { source: mirrored, user_ty } + } + } + hir::ExprKind::DropTemps(ref source) => { + ExprKind::Use { source: self.mirror_expr_boxed(source) } + } + hir::ExprKind::Box(ref value) => ExprKind::Box { value: self.mirror_expr_boxed(value) }, + hir::ExprKind::Array(ref fields) => ExprKind::Array { + fields: fields.iter().map(|field| self.mirror_expr(field)).collect(), + }, + hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { + fields: fields.iter().map(|field| self.mirror_expr(field)).collect(), + }, + + hir::ExprKind::Yield(ref v, _) => ExprKind::Yield { value: self.mirror_expr_boxed(v) }, + hir::ExprKind::Err => unreachable!(), + }; + + Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind } + } + + fn user_substs_applied_to_res( + &mut self, + hir_id: hir::HirId, + res: Res, + ) -> Option> { + debug!("user_substs_applied_to_res: res={:?}", res); + let user_provided_type = match res { + // A reference to something callable -- e.g., a fn, method, or + // a tuple-struct or tuple-variant. This has the type of a + // `Fn` but with the user-given substitutions. + Res::Def(DefKind::Fn, _) + | Res::Def(DefKind::AssocFn, _) + | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) + | Res::Def(DefKind::Const, _) + | Res::Def(DefKind::AssocConst, _) => { + self.typeck_results().user_provided_types().get(hir_id).copied() + } + + // A unit struct/variant which is used as a value (e.g., + // `None`). This has the type of the enum/struct that defines + // this variant -- but with the substitutions given by the + // user. + Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => { + self.user_substs_applied_to_ty_of_hir_id(hir_id) + } + + // `Self` is used in expression as a tuple struct constructor or an unit struct constructor + Res::SelfCtor(_) => self.user_substs_applied_to_ty_of_hir_id(hir_id), + + _ => bug!("user_substs_applied_to_res: unexpected res {:?} at {:?}", res, hir_id), + }; + debug!("user_substs_applied_to_res: user_provided_type={:?}", user_provided_type); + user_provided_type + } + + fn method_callee( + &mut self, + expr: &hir::Expr<'_>, + span: Span, + overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>, + ) -> Expr<'tcx> { + let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); + let (def_id, substs, user_ty) = match overloaded_callee { + Some((def_id, substs)) => (def_id, substs, None), + None => { + let (kind, def_id) = + self.typeck_results().type_dependent_def(expr.hir_id).unwrap_or_else(|| { + span_bug!(expr.span, "no type-dependent def for method callee") + }); + let user_ty = self.user_substs_applied_to_res(expr.hir_id, Res::Def(kind, def_id)); + debug!("method_callee: user_ty={:?}", user_ty); + (def_id, self.typeck_results().node_substs(expr.hir_id), user_ty) } + }; + let ty = self.tcx().mk_fn_def(def_id, substs); + Expr { + temp_lifetime, + ty, + span, + kind: ExprKind::Literal { + literal: ty::Const::zero_sized(self.tcx(), ty), + user_ty, + const_id: None, + }, + } + } + + fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> Arm<'tcx> { + Arm { + pattern: self.pattern_from_hir(&arm.pat), + guard: arm.guard.as_ref().map(|g| match g { + hir::Guard::If(ref e) => Guard::If(self.mirror_expr_boxed(e)), + hir::Guard::IfLet(ref pat, ref e) => { + Guard::IfLet(self.pattern_from_hir(pat), self.mirror_expr_boxed(e)) + } + }), + body: self.mirror_expr(arm.body), + lint_level: LintLevel::Explicit(arm.hir_id), + scope: region::Scope { id: arm.hir_id.local_id, data: region::ScopeData::Node }, + span: arm.span, } - hir::ExprKind::DropTemps(ref source) => ExprKind::Use { source: source.to_ref() }, - hir::ExprKind::Box(ref value) => ExprKind::Box { value: value.to_ref() }, - hir::ExprKind::Array(ref fields) => ExprKind::Array { fields: fields.to_ref() }, - hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { fields: fields.to_ref() }, + } - hir::ExprKind::Yield(ref v, _) => ExprKind::Yield { value: v.to_ref() }, - hir::ExprKind::Err => unreachable!(), - }; + fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKind<'tcx> { + let substs = self.typeck_results().node_substs(expr.hir_id); + match res { + // A regular function, constructor function or a constant. + Res::Def(DefKind::Fn, _) + | Res::Def(DefKind::AssocFn, _) + | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) + | Res::SelfCtor(..) => { + let user_ty = self.user_substs_applied_to_res(expr.hir_id, res); + debug!("convert_path_expr: user_ty={:?}", user_ty); + ExprKind::Literal { + literal: ty::Const::zero_sized( + self.tcx, + self.typeck_results().node_type(expr.hir_id), + ), + user_ty, + const_id: None, + } + } - Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind } -} + Res::Def(DefKind::ConstParam, def_id) => { + let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + let item_id = self.tcx.hir().get_parent_node(hir_id); + let item_def_id = self.tcx.hir().local_def_id(item_id); + let generics = self.tcx.generics_of(item_def_id); + let index = generics.param_def_id_to_index[&def_id]; + let name = self.tcx.hir().name(hir_id); + let val = ty::ConstKind::Param(ty::ParamConst::new(index, name)); + ExprKind::Literal { + literal: self.tcx.mk_const(ty::Const { + val, + ty: self.typeck_results().node_type(expr.hir_id), + }), + user_ty: None, + const_id: Some(def_id), + } + } + + Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => { + let user_ty = self.user_substs_applied_to_res(expr.hir_id, res); + debug!("convert_path_expr: (const) user_ty={:?}", user_ty); + ExprKind::Literal { + literal: self.tcx.mk_const(ty::Const { + val: ty::ConstKind::Unevaluated( + ty::WithOptConstParam::unknown(def_id), + substs, + None, + ), + ty: self.typeck_results().node_type(expr.hir_id), + }), + user_ty, + const_id: Some(def_id), + } + } + + Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id) => { + let user_provided_types = self.typeck_results.user_provided_types(); + let user_provided_type = user_provided_types.get(expr.hir_id).copied(); + debug!("convert_path_expr: user_provided_type={:?}", user_provided_type); + let ty = self.typeck_results().node_type(expr.hir_id); + match ty.kind() { + // A unit struct/variant which is used as a value. + // We return a completely different ExprKind here to account for this special case. + ty::Adt(adt_def, substs) => ExprKind::Adt { + adt_def, + variant_index: adt_def.variant_index_with_ctor_id(def_id), + substs, + user_ty: user_provided_type, + fields: vec![], + base: None, + }, + _ => bug!("unexpected ty: {:?}", ty), + } + } + + // We encode uses of statics as a `*&STATIC` where the `&STATIC` part is + // a constant reference (or constant raw pointer for `static mut`) in MIR + Res::Def(DefKind::Static, id) => { + let ty = self.tcx.static_ptr_ty(id); + let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); + let kind = if self.tcx.is_thread_local_static(id) { + ExprKind::ThreadLocalRef(id) + } else { + let ptr = self.tcx.create_static_alloc(id); + ExprKind::StaticRef { + literal: ty::Const::from_scalar(self.tcx, Scalar::Ptr(ptr.into()), ty), + def_id: id, + } + }; + ExprKind::Deref { arg: Box::new(Expr { ty, temp_lifetime, span: expr.span, kind }) } + } + + Res::Local(var_hir_id) => self.convert_var(var_hir_id), -fn user_substs_applied_to_res<'tcx>( - cx: &mut Cx<'_, 'tcx>, - hir_id: hir::HirId, - res: Res, -) -> Option> { - debug!("user_substs_applied_to_res: res={:?}", res); - let user_provided_type = match res { - // A reference to something callable -- e.g., a fn, method, or - // a tuple-struct or tuple-variant. This has the type of a - // `Fn` but with the user-given substitutions. - Res::Def(DefKind::Fn, _) - | Res::Def(DefKind::AssocFn, _) - | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) - | Res::Def(DefKind::Const, _) - | Res::Def(DefKind::AssocConst, _) => { - cx.typeck_results().user_provided_types().get(hir_id).copied() + _ => span_bug!(expr.span, "res `{:?}` not yet implemented", res), } + } - // A unit struct/variant which is used as a value (e.g., - // `None`). This has the type of the enum/struct that defines - // this variant -- but with the substitutions given by the - // user. - Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => { - cx.user_substs_applied_to_ty_of_hir_id(hir_id) + fn convert_var(&mut self, var_hir_id: hir::HirId) -> ExprKind<'tcx> { + // We want upvars here not captures. + // Captures will be handled in MIR. + let is_upvar = self + .tcx + .upvars_mentioned(self.body_owner) + .map_or(false, |upvars| upvars.contains_key(&var_hir_id)); + + debug!( + "convert_var({:?}): is_upvar={}, body_owner={:?}", + var_hir_id, is_upvar, self.body_owner + ); + + if is_upvar { + ExprKind::UpvarRef { closure_def_id: self.body_owner, var_hir_id } + } else { + ExprKind::VarRef { id: var_hir_id } } + } - // `Self` is used in expression as a tuple struct constructor or an unit struct constructor - Res::SelfCtor(_) => cx.user_substs_applied_to_ty_of_hir_id(hir_id), + fn overloaded_operator( + &mut self, + expr: &'tcx hir::Expr<'tcx>, + args: Vec>, + ) -> ExprKind<'tcx> { + let fun = Box::new(self.method_callee(expr, expr.span, None)); + ExprKind::Call { ty: fun.ty, fun, args, from_hir_call: false, fn_span: expr.span } + } - _ => bug!("user_substs_applied_to_res: unexpected res {:?} at {:?}", res, hir_id), - }; - debug!("user_substs_applied_to_res: user_provided_type={:?}", user_provided_type); - user_provided_type -} + fn overloaded_place( + &mut self, + expr: &'tcx hir::Expr<'tcx>, + place_ty: Ty<'tcx>, + overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>, + args: Vec>, + span: Span, + ) -> ExprKind<'tcx> { + // 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 + // line up (this is because `*x` and `x[y]` represent places): + + // Reconstruct the output assuming it's a reference with the + // same region and mutability as the receiver. This holds for + // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`. + let (region, mutbl) = match *args[0].ty.kind() { + ty::Ref(region, _, mutbl) => (region, mutbl), + _ => span_bug!(span, "overloaded_place: receiver is not a reference"), + }; + let ref_ty = self.tcx.mk_ref(region, ty::TypeAndMut { ty: place_ty, mutbl }); + + // construct the complete expression `foo()` for the overloaded call, + // which will yield the &T type + let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); + let fun = Box::new(self.method_callee(expr, span, overloaded_callee)); + let ref_expr = Box::new(Expr { + temp_lifetime, + ty: ref_ty, + span, + kind: ExprKind::Call { ty: fun.ty, fun, args, from_hir_call: false, fn_span: span }, + }); + + // construct and return a deref wrapper `*foo()` + ExprKind::Deref { arg: ref_expr } + } + + fn capture_upvar( + &mut self, + closure_expr: &'tcx hir::Expr<'tcx>, + captured_place: &'a ty::CapturedPlace<'tcx>, + upvar_ty: Ty<'tcx>, + ) -> Expr<'tcx> { + let upvar_capture = captured_place.info.capture_kind; + let temp_lifetime = self.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id); + let var_ty = captured_place.place.base_ty; + + // The result of capture analysis in `rustc_typeck/check/upvar.rs`represents a captured path + // as it's seen for use within the closure and not at the time of closure creation. + // + // That is we see expect to see it start from a captured upvar and not something that is local + // to the closure's parent. + let var_hir_id = match captured_place.place.base { + HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id, + base => bug!("Expected an upvar, found {:?}", base), + }; + + let mut captured_place_expr = Expr { + temp_lifetime, + ty: var_ty, + span: closure_expr.span, + kind: self.convert_var(var_hir_id), + }; + + for proj in captured_place.place.projections.iter() { + let kind = match proj.kind { + HirProjectionKind::Deref => ExprKind::Deref { arg: Box::new(captured_place_expr) }, + HirProjectionKind::Field(field, ..) => { + // Variant index will always be 0, because for multi-variant + // enums, we capture the enum entirely. + ExprKind::Field { + lhs: Box::new(captured_place_expr), + name: Field::new(field as usize), + } + } + HirProjectionKind::Index | HirProjectionKind::Subslice => { + // We don't capture these projections, so we can ignore them here + continue; + } + }; -fn method_callee<'a, 'tcx>( - cx: &mut Cx<'a, 'tcx>, - expr: &hir::Expr<'_>, - span: Span, - overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>, -) -> Expr<'tcx> { - let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id); - let (def_id, substs, user_ty) = match overloaded_callee { - Some((def_id, substs)) => (def_id, substs, None), - None => { - let (kind, def_id) = cx - .typeck_results() - .type_dependent_def(expr.hir_id) - .unwrap_or_else(|| span_bug!(expr.span, "no type-dependent def for method callee")); - let user_ty = user_substs_applied_to_res(cx, expr.hir_id, Res::Def(kind, def_id)); - debug!("method_callee: user_ty={:?}", user_ty); - (def_id, cx.typeck_results().node_substs(expr.hir_id), user_ty) + captured_place_expr = + Expr { temp_lifetime, ty: proj.ty, span: closure_expr.span, kind }; + } + + match upvar_capture { + ty::UpvarCapture::ByValue(_) => captured_place_expr, + ty::UpvarCapture::ByRef(upvar_borrow) => { + let borrow_kind = match upvar_borrow.kind { + ty::BorrowKind::ImmBorrow => BorrowKind::Shared, + ty::BorrowKind::UniqueImmBorrow => BorrowKind::Unique, + ty::BorrowKind::MutBorrow => BorrowKind::Mut { allow_two_phase_borrow: false }, + }; + Expr { + temp_lifetime, + ty: upvar_ty, + span: closure_expr.span, + kind: ExprKind::Borrow { borrow_kind, arg: Box::new(captured_place_expr) }, + } + } } - }; - let ty = cx.tcx().mk_fn_def(def_id, substs); - Expr { - temp_lifetime, - ty, - span, - kind: ExprKind::Literal { - literal: ty::Const::zero_sized(cx.tcx(), ty), - user_ty, - const_id: None, - }, + } + + /// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExpr. + fn field_refs(&mut self, fields: &'tcx [hir::Field<'tcx>]) -> Vec> { + fields + .iter() + .map(|field| FieldExpr { + name: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)), + expr: self.mirror_expr(field.expr), + }) + .collect() } } @@ -776,135 +1084,6 @@ impl ToBorrowKind for hir::Mutability { } } -fn convert_arm<'tcx>(cx: &mut Cx<'_, 'tcx>, arm: &'tcx hir::Arm<'tcx>) -> Arm<'tcx> { - Arm { - pattern: cx.pattern_from_hir(&arm.pat), - guard: arm.guard.as_ref().map(|g| match g { - hir::Guard::If(ref e) => Guard::If(e.to_ref()), - hir::Guard::IfLet(ref pat, ref e) => Guard::IfLet(cx.pattern_from_hir(pat), e.to_ref()), - }), - body: arm.body.to_ref(), - lint_level: LintLevel::Explicit(arm.hir_id), - scope: region::Scope { id: arm.hir_id.local_id, data: region::ScopeData::Node }, - span: arm.span, - } -} - -fn convert_path_expr<'a, 'tcx>( - cx: &mut Cx<'a, 'tcx>, - expr: &'tcx hir::Expr<'tcx>, - res: Res, -) -> ExprKind<'tcx> { - let substs = cx.typeck_results().node_substs(expr.hir_id); - match res { - // A regular function, constructor function or a constant. - Res::Def(DefKind::Fn, _) - | Res::Def(DefKind::AssocFn, _) - | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) - | Res::SelfCtor(..) => { - let user_ty = user_substs_applied_to_res(cx, expr.hir_id, res); - debug!("convert_path_expr: user_ty={:?}", user_ty); - ExprKind::Literal { - literal: ty::Const::zero_sized(cx.tcx, cx.typeck_results().node_type(expr.hir_id)), - user_ty, - const_id: None, - } - } - - Res::Def(DefKind::ConstParam, def_id) => { - let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); - let item_id = cx.tcx.hir().get_parent_node(hir_id); - let item_def_id = cx.tcx.hir().local_def_id(item_id); - let generics = cx.tcx.generics_of(item_def_id); - let index = generics.param_def_id_to_index[&def_id]; - let name = cx.tcx.hir().name(hir_id); - let val = ty::ConstKind::Param(ty::ParamConst::new(index, name)); - ExprKind::Literal { - literal: cx - .tcx - .mk_const(ty::Const { val, ty: cx.typeck_results().node_type(expr.hir_id) }), - user_ty: None, - const_id: Some(def_id), - } - } - - Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => { - let user_ty = user_substs_applied_to_res(cx, expr.hir_id, res); - debug!("convert_path_expr: (const) user_ty={:?}", user_ty); - ExprKind::Literal { - literal: cx.tcx.mk_const(ty::Const { - val: ty::ConstKind::Unevaluated( - ty::WithOptConstParam::unknown(def_id), - substs, - None, - ), - ty: cx.typeck_results().node_type(expr.hir_id), - }), - user_ty, - const_id: Some(def_id), - } - } - - Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id) => { - let user_provided_types = cx.typeck_results.user_provided_types(); - let user_provided_type = user_provided_types.get(expr.hir_id).copied(); - debug!("convert_path_expr: user_provided_type={:?}", user_provided_type); - let ty = cx.typeck_results().node_type(expr.hir_id); - match ty.kind() { - // A unit struct/variant which is used as a value. - // We return a completely different ExprKind here to account for this special case. - ty::Adt(adt_def, substs) => ExprKind::Adt { - adt_def, - variant_index: adt_def.variant_index_with_ctor_id(def_id), - substs, - user_ty: user_provided_type, - fields: vec![], - base: None, - }, - _ => bug!("unexpected ty: {:?}", ty), - } - } - - // We encode uses of statics as a `*&STATIC` where the `&STATIC` part is - // a constant reference (or constant raw pointer for `static mut`) in MIR - Res::Def(DefKind::Static, id) => { - let ty = cx.tcx.static_ptr_ty(id); - let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id); - let kind = if cx.tcx.is_thread_local_static(id) { - ExprKind::ThreadLocalRef(id) - } else { - let ptr = cx.tcx.create_static_alloc(id); - ExprKind::StaticRef { - literal: ty::Const::from_scalar(cx.tcx, Scalar::Ptr(ptr.into()), ty), - def_id: id, - } - }; - ExprKind::Deref { arg: Expr { ty, temp_lifetime, span: expr.span, kind }.to_ref() } - } - - Res::Local(var_hir_id) => convert_var(cx, var_hir_id), - - _ => span_bug!(expr.span, "res `{:?}` not yet implemented", res), - } -} - -fn convert_var<'tcx>(cx: &mut Cx<'_, 'tcx>, var_hir_id: hir::HirId) -> ExprKind<'tcx> { - // We want upvars here not captures. - // Captures will be handled in MIR. - let is_upvar = cx - .tcx - .upvars_mentioned(cx.body_owner) - .map_or(false, |upvars| upvars.contains_key(&var_hir_id)); - - debug!("convert_var({:?}): is_upvar={}, body_owner={:?}", var_hir_id, is_upvar, cx.body_owner); - - if is_upvar { - ExprKind::UpvarRef { closure_def_id: cx.body_owner, var_hir_id } - } else { - ExprKind::VarRef { id: var_hir_id } - } -} - fn bin_op(op: hir::BinOpKind) -> BinOp { match op { hir::BinOpKind::Add => BinOp::Add, @@ -926,139 +1105,3 @@ fn bin_op(op: hir::BinOpKind) -> BinOp { _ => bug!("no equivalent for ast binop {:?}", op), } } - -fn overloaded_operator<'a, 'tcx>( - cx: &mut Cx<'a, 'tcx>, - expr: &'tcx hir::Expr<'tcx>, - args: Vec>, -) -> ExprKind<'tcx> { - let fun = method_callee(cx, expr, expr.span, None); - ExprKind::Call { ty: fun.ty, fun: fun.to_ref(), args, from_hir_call: false, fn_span: expr.span } -} - -fn overloaded_place<'a, 'tcx>( - cx: &mut Cx<'a, 'tcx>, - expr: &'tcx hir::Expr<'tcx>, - place_ty: Ty<'tcx>, - overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>, - args: Vec>, - span: Span, -) -> ExprKind<'tcx> { - // 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 - // line up (this is because `*x` and `x[y]` represent places): - - let recv_ty = match args[0] { - ExprRef::Thir(e) => cx.typeck_results().expr_ty_adjusted(e), - ExprRef::Mirror(ref e) => e.ty, - }; - - // Reconstruct the output assuming it's a reference with the - // same region and mutability as the receiver. This holds for - // `Deref(Mut)::Deref(_mut)` and `Index(Mut)::index(_mut)`. - let (region, mutbl) = match *recv_ty.kind() { - ty::Ref(region, _, mutbl) => (region, mutbl), - _ => span_bug!(span, "overloaded_place: receiver is not a reference"), - }; - let ref_ty = cx.tcx.mk_ref(region, ty::TypeAndMut { ty: place_ty, mutbl }); - - // construct the complete expression `foo()` for the overloaded call, - // which will yield the &T type - let temp_lifetime = cx.region_scope_tree.temporary_scope(expr.hir_id.local_id); - let fun = method_callee(cx, expr, span, overloaded_callee); - let ref_expr = Expr { - temp_lifetime, - ty: ref_ty, - span, - kind: ExprKind::Call { - ty: fun.ty, - fun: fun.to_ref(), - args, - from_hir_call: false, - fn_span: span, - }, - }; - - // construct and return a deref wrapper `*foo()` - ExprKind::Deref { arg: ref_expr.to_ref() } -} - -fn capture_upvar<'a, 'tcx>( - cx: &mut Cx<'_, 'tcx>, - closure_expr: &'tcx hir::Expr<'tcx>, - captured_place: &'a ty::CapturedPlace<'tcx>, - upvar_ty: Ty<'tcx>, -) -> ExprRef<'tcx> { - let upvar_capture = captured_place.info.capture_kind; - let temp_lifetime = cx.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id); - let var_ty = captured_place.place.base_ty; - - // The result of capture analysis in `rustc_typeck/check/upvar.rs`represents a captured path - // as it's seen for use within the closure and not at the time of closure creation. - // - // That is we see expect to see it start from a captured upvar and not something that is local - // to the closure's parent. - let var_hir_id = match captured_place.place.base { - HirPlaceBase::Upvar(upvar_id) => upvar_id.var_path.hir_id, - base => bug!("Expected an upvar, found {:?}", base), - }; - - let mut captured_place_expr = Expr { - temp_lifetime, - ty: var_ty, - span: closure_expr.span, - kind: convert_var(cx, var_hir_id), - }; - - for proj in captured_place.place.projections.iter() { - let kind = match proj.kind { - HirProjectionKind::Deref => ExprKind::Deref { arg: captured_place_expr.to_ref() }, - HirProjectionKind::Field(field, ..) => { - // Variant index will always be 0, because for multi-variant - // enums, we capture the enum entirely. - ExprKind::Field { - lhs: captured_place_expr.to_ref(), - name: Field::new(field as usize), - } - } - HirProjectionKind::Index | HirProjectionKind::Subslice => { - // We don't capture these projections, so we can ignore them here - continue; - } - }; - - captured_place_expr = Expr { temp_lifetime, ty: proj.ty, span: closure_expr.span, kind }; - } - - match upvar_capture { - ty::UpvarCapture::ByValue(_) => captured_place_expr.to_ref(), - ty::UpvarCapture::ByRef(upvar_borrow) => { - let borrow_kind = match upvar_borrow.kind { - ty::BorrowKind::ImmBorrow => BorrowKind::Shared, - ty::BorrowKind::UniqueImmBorrow => BorrowKind::Unique, - ty::BorrowKind::MutBorrow => BorrowKind::Mut { allow_two_phase_borrow: false }, - }; - Expr { - temp_lifetime, - ty: upvar_ty, - span: closure_expr.span, - kind: ExprKind::Borrow { borrow_kind, arg: captured_place_expr.to_ref() }, - } - .to_ref() - } - } -} - -/// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExprRef. -fn field_refs<'a, 'tcx>( - cx: &mut Cx<'a, 'tcx>, - fields: &'tcx [hir::Field<'tcx>], -) -> Vec> { - fields - .iter() - .map(|field| FieldExprRef { - name: Field::new(cx.tcx.field_index(field.hir_id, cx.typeck_results)), - expr: field.expr.to_ref(), - }) - .collect() -} diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 465808cea9dd5..6b3b3be514c03 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -93,11 +93,6 @@ impl<'a, 'tcx> Cx<'a, 'tcx> { } impl<'a, 'tcx> Cx<'a, 'tcx> { - /// Normalizes `ast` into the appropriate "mirror" type. - crate fn mirror>(&mut self, ast: M) -> M::Output { - ast.make_mirror(self) - } - crate fn usize_ty(&mut self) -> Ty<'tcx> { self.tcx.types.usize } @@ -219,4 +214,3 @@ impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'_, 'tcx> { mod block; mod expr; -mod to_ref; diff --git a/compiler/rustc_mir_build/src/thir/cx/to_ref.rs b/compiler/rustc_mir_build/src/thir/cx/to_ref.rs deleted file mode 100644 index 53a988ebb79e2..0000000000000 --- a/compiler/rustc_mir_build/src/thir/cx/to_ref.rs +++ /dev/null @@ -1,65 +0,0 @@ -use crate::thir::*; - -use rustc_hir as hir; - -crate trait ToRef { - type Output; - fn to_ref(self) -> Self::Output; -} - -impl<'tcx> ToRef for &'tcx hir::Expr<'tcx> { - type Output = ExprRef<'tcx>; - - fn to_ref(self) -> ExprRef<'tcx> { - ExprRef::Thir(self) - } -} - -impl<'tcx> ToRef for &'tcx &'tcx hir::Expr<'tcx> { - type Output = ExprRef<'tcx>; - - fn to_ref(self) -> ExprRef<'tcx> { - ExprRef::Thir(&**self) - } -} - -impl<'tcx> ToRef for Expr<'tcx> { - type Output = ExprRef<'tcx>; - - fn to_ref(self) -> ExprRef<'tcx> { - ExprRef::Mirror(Box::new(self)) - } -} - -impl<'tcx, T, U> ToRef for &'tcx Option -where - &'tcx T: ToRef, -{ - type Output = Option; - - fn to_ref(self) -> Option { - self.as_ref().map(|expr| expr.to_ref()) - } -} - -impl<'tcx, T, U> ToRef for &'tcx Vec -where - &'tcx T: ToRef, -{ - type Output = Vec; - - fn to_ref(self) -> Vec { - self.iter().map(|expr| expr.to_ref()).collect() - } -} - -impl<'tcx, T, U> ToRef for &'tcx [T] -where - &'tcx T: ToRef, -{ - type Output = Vec; - - fn to_ref(self) -> Vec { - self.iter().map(|expr| expr.to_ref()).collect() - } -} diff --git a/compiler/rustc_mir_build/src/thir/mod.rs b/compiler/rustc_mir_build/src/thir/mod.rs index ce0098fdf860b..f934dd32c5381 100644 --- a/compiler/rustc_mir_build/src/thir/mod.rs +++ b/compiler/rustc_mir_build/src/thir/mod.rs @@ -4,7 +4,6 @@ //! unit-tested and separated from the Rust source and compiler data //! structures. -use self::cx::Cx; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_hir as hir; use rustc_hir::def_id::DefId; @@ -39,8 +38,8 @@ crate struct Block<'tcx> { crate region_scope: region::Scope, crate opt_destruction_scope: Option, crate span: Span, - crate stmts: Vec>, - crate expr: Option>, + crate stmts: Vec>, + crate expr: Option>>, crate safety_mode: BlockSafety, } @@ -52,11 +51,6 @@ crate enum BlockSafety { PopUnsafe, } -#[derive(Clone, Debug)] -crate enum StmtRef<'tcx> { - Mirror(Box>), -} - #[derive(Clone, Debug)] crate struct Stmt<'tcx> { crate kind: StmtKind<'tcx>, @@ -70,7 +64,7 @@ crate enum StmtKind<'tcx> { scope: region::Scope, /// expression being evaluated in this statement - expr: ExprRef<'tcx>, + expr: Box>, }, Let { @@ -88,7 +82,7 @@ crate enum StmtKind<'tcx> { pattern: Pat<'tcx>, /// let pat: ty = ... - initializer: Option>, + initializer: Option>>, /// the lint level for this let-statement lint_level: LintLevel, @@ -97,12 +91,12 @@ crate enum StmtKind<'tcx> { // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Expr<'_>, 168); +rustc_data_structures::static_assert_size!(Expr<'_>, 160); /// The Thir trait implementor lowers their expressions (`&'tcx H::Expr`) /// into instances of this `Expr` enum. This lowering can be done /// basically as lazily or as eagerly as desired: every recursive -/// reference to an expression in this enum is an `ExprRef<'tcx>`, which +/// reference to an expression in this enum is an `Box>`, which /// may in turn be another instance of this enum (boxed), or else an /// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very /// short-lived. They are created by `Thir::to_expr`, analyzed and @@ -134,84 +128,84 @@ crate enum ExprKind<'tcx> { Scope { region_scope: region::Scope, lint_level: LintLevel, - value: ExprRef<'tcx>, + value: Box>, }, Box { - value: ExprRef<'tcx>, + value: Box>, }, If { - cond: ExprRef<'tcx>, - then: ExprRef<'tcx>, - else_opt: Option>, + cond: Box>, + then: Box>, + else_opt: Option>>, }, Call { ty: Ty<'tcx>, - fun: ExprRef<'tcx>, - args: Vec>, - // Whether this is from a call in HIR, rather than from an overloaded - // operator. True for overloaded function call. + fun: Box>, + args: Vec>, + /// Whether this is from a call in HIR, rather than from an overloaded + /// operator. `true` for overloaded function call. from_hir_call: bool, /// This `Span` is the span of the function, without the dot and receiver /// (e.g. `foo(a, b)` in `x.foo(a, b)` fn_span: Span, }, Deref { - arg: ExprRef<'tcx>, + arg: Box>, }, // NOT overloaded! Binary { op: BinOp, - lhs: ExprRef<'tcx>, - rhs: ExprRef<'tcx>, + lhs: Box>, + rhs: Box>, }, // NOT overloaded! LogicalOp { op: LogicalOp, - lhs: ExprRef<'tcx>, - rhs: ExprRef<'tcx>, + lhs: Box>, + rhs: Box>, }, // NOT overloaded! // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands. Unary { op: UnOp, - arg: ExprRef<'tcx>, + arg: Box>, }, // NOT overloaded! Cast { - source: ExprRef<'tcx>, + source: Box>, }, Use { - source: ExprRef<'tcx>, + source: Box>, }, // Use a lexpr to get a vexpr. NeverToAny { - source: ExprRef<'tcx>, + source: Box>, }, Pointer { cast: PointerCast, - source: ExprRef<'tcx>, + source: Box>, }, Loop { - body: ExprRef<'tcx>, + body: Box>, }, Match { - scrutinee: ExprRef<'tcx>, + scrutinee: Box>, arms: Vec>, }, Block { - body: &'tcx hir::Block<'tcx>, + body: Block<'tcx>, }, Assign { - lhs: ExprRef<'tcx>, - rhs: ExprRef<'tcx>, + lhs: Box>, + rhs: Box>, }, AssignOp { op: BinOp, - lhs: ExprRef<'tcx>, - rhs: ExprRef<'tcx>, + lhs: Box>, + rhs: Box>, }, Field { - lhs: ExprRef<'tcx>, + lhs: Box>, name: Field, }, Index { - lhs: ExprRef<'tcx>, - index: ExprRef<'tcx>, + lhs: Box>, + index: Box>, }, VarRef { id: hir::HirId, @@ -226,35 +220,35 @@ crate enum ExprKind<'tcx> { }, Borrow { borrow_kind: BorrowKind, - arg: ExprRef<'tcx>, + arg: Box>, }, /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`. AddressOf { mutability: hir::Mutability, - arg: ExprRef<'tcx>, + arg: Box>, }, Break { label: region::Scope, - value: Option>, + value: Option>>, }, Continue { label: region::Scope, }, Return { - value: Option>, + value: Option>>, }, ConstBlock { value: &'tcx Const<'tcx>, }, Repeat { - value: ExprRef<'tcx>, + value: Box>, count: &'tcx Const<'tcx>, }, Array { - fields: Vec>, + fields: Vec>, }, Tuple { - fields: Vec>, + fields: Vec>, }, Adt { adt_def: &'tcx AdtDef, @@ -265,23 +259,23 @@ crate enum ExprKind<'tcx> { /// Bar:: { ... }`. user_ty: Option>>, - fields: Vec>, + fields: Vec>, base: Option>, }, PlaceTypeAscription { - source: ExprRef<'tcx>, + source: Box>, /// Type that the user gave to this expression user_ty: Option>>, }, ValueTypeAscription { - source: ExprRef<'tcx>, + source: Box>, /// Type that the user gave to this expression user_ty: Option>>, }, Closure { closure_id: DefId, substs: UpvarSubsts<'tcx>, - upvars: Vec>, + upvars: Vec>, movability: Option, }, Literal { @@ -310,29 +304,23 @@ crate enum ExprKind<'tcx> { ThreadLocalRef(DefId), LlvmInlineAsm { asm: &'tcx hir::LlvmInlineAsmInner, - outputs: Vec>, - inputs: Vec>, + outputs: Vec>, + inputs: Vec>, }, Yield { - value: ExprRef<'tcx>, + value: Box>, }, } #[derive(Clone, Debug)] -crate enum ExprRef<'tcx> { - Thir(&'tcx hir::Expr<'tcx>), - Mirror(Box>), -} - -#[derive(Clone, Debug)] -crate struct FieldExprRef<'tcx> { +crate struct FieldExpr<'tcx> { crate name: Field, - crate expr: ExprRef<'tcx>, + crate expr: Expr<'tcx>, } #[derive(Clone, Debug)] crate struct FruInfo<'tcx> { - crate base: ExprRef<'tcx>, + crate base: Box>, crate field_types: Vec>, } @@ -340,7 +328,7 @@ crate struct FruInfo<'tcx> { crate struct Arm<'tcx> { crate pattern: Pat<'tcx>, crate guard: Option>, - crate body: ExprRef<'tcx>, + crate body: Expr<'tcx>, crate lint_level: LintLevel, crate scope: region::Scope, crate span: Span, @@ -348,8 +336,8 @@ crate struct Arm<'tcx> { #[derive(Clone, Debug)] crate enum Guard<'tcx> { - If(ExprRef<'tcx>), - IfLet(Pat<'tcx>, ExprRef<'tcx>), + If(Box>), + IfLet(Pat<'tcx>, Box>), } #[derive(Copy, Clone, Debug)] @@ -358,110 +346,35 @@ crate enum LogicalOp { Or, } -impl<'tcx> ExprRef<'tcx> { - crate fn span(&self) -> Span { - match self { - ExprRef::Thir(expr) => expr.span, - ExprRef::Mirror(expr) => expr.span, - } - } -} - #[derive(Clone, Debug)] crate enum InlineAsmOperand<'tcx> { In { reg: InlineAsmRegOrRegClass, - expr: ExprRef<'tcx>, + expr: Expr<'tcx>, }, Out { reg: InlineAsmRegOrRegClass, late: bool, - expr: Option>, + expr: Option>, }, InOut { reg: InlineAsmRegOrRegClass, late: bool, - expr: ExprRef<'tcx>, + expr: Expr<'tcx>, }, SplitInOut { reg: InlineAsmRegOrRegClass, late: bool, - in_expr: ExprRef<'tcx>, - out_expr: Option>, + in_expr: Expr<'tcx>, + out_expr: Option>, }, Const { - expr: ExprRef<'tcx>, + expr: Expr<'tcx>, }, SymFn { - expr: ExprRef<'tcx>, + expr: Expr<'tcx>, }, SymStatic { def_id: DefId, }, } - -/////////////////////////////////////////////////////////////////////////// -// The Mirror trait - -/// "Mirroring" is the process of converting from a HIR type into one -/// of the THIR types defined in this file. This is basically a "on -/// the fly" desugaring step that hides a lot of the messiness in the -/// tcx. For example, the mirror of a `&'tcx hir::Expr` is an -/// `Expr<'tcx>`. -/// -/// Mirroring is gradual: when you mirror an outer expression like `e1 -/// + e2`, the references to the inner expressions `e1` and `e2` are -/// `ExprRef<'tcx>` instances, and they may or may not be eagerly -/// mirrored. This allows a single AST node from the compiler to -/// expand into one or more Thir nodes, which lets the Thir nodes be -/// simpler. -crate trait Mirror<'tcx> { - type Output; - - fn make_mirror(self, cx: &mut Cx<'_, 'tcx>) -> Self::Output; -} - -impl<'tcx> Mirror<'tcx> for Expr<'tcx> { - type Output = Expr<'tcx>; - - fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Expr<'tcx> { - self - } -} - -impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> { - type Output = Expr<'tcx>; - - fn make_mirror(self, hir: &mut Cx<'_, 'tcx>) -> Expr<'tcx> { - match self { - ExprRef::Thir(h) => h.make_mirror(hir), - ExprRef::Mirror(m) => *m, - } - } -} - -impl<'tcx> Mirror<'tcx> for Stmt<'tcx> { - type Output = Stmt<'tcx>; - - fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Stmt<'tcx> { - self - } -} - -impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> { - type Output = Stmt<'tcx>; - - fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Stmt<'tcx> { - match self { - StmtRef::Mirror(m) => *m, - } - } -} - -impl<'tcx> Mirror<'tcx> for Block<'tcx> { - type Output = Block<'tcx>; - - fn make_mirror(self, _: &mut Cx<'_, 'tcx>) -> Block<'tcx> { - self - } -} From 2a2b4d72578a531ec95ca7a5ab17e4136d9756fc Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Wed, 3 Mar 2021 16:35:54 +0100 Subject: [PATCH 2/7] Pull `thir::Cx` out of the MIR `Builder` --- compiler/rustc_mir_build/src/build/block.rs | 9 +- .../src/build/expr/as_operand.rs | 4 +- .../src/build/expr/as_place.rs | 25 ++- .../src/build/expr/as_rvalue.rs | 32 ++-- .../rustc_mir_build/src/build/expr/as_temp.rs | 4 +- .../rustc_mir_build/src/build/expr/into.rs | 33 ++-- .../rustc_mir_build/src/build/expr/stmt.rs | 2 +- .../rustc_mir_build/src/build/matches/mod.rs | 20 +- .../src/build/matches/simplify.rs | 8 +- .../rustc_mir_build/src/build/matches/test.rs | 75 +++++--- .../rustc_mir_build/src/build/matches/util.rs | 7 +- compiler/rustc_mir_build/src/build/misc.rs | 14 +- compiler/rustc_mir_build/src/build/mod.rs | 172 +++++++++++------- compiler/rustc_mir_build/src/build/scope.rs | 18 +- compiler/rustc_mir_build/src/thir/cx/block.rs | 2 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 14 +- compiler/rustc_mir_build/src/thir/cx/mod.rs | 144 +-------------- 17 files changed, 254 insertions(+), 329 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index 2d1fd4d09d1a4..7bb141058d22e 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -110,8 +110,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let_scope_stack.push(remainder_scope); // Declare the bindings, which may create a source scope. - let remainder_span = - remainder_scope.span(this.hir.tcx(), &this.hir.region_scope_tree); + let remainder_span = remainder_scope.span(this.tcx, &this.region_scope_tree); let visibility_scope = Some(this.new_source_scope(remainder_span, LintLevel::Inherited, None)); @@ -175,7 +174,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Then, the block may have an optional trailing expression which is a “return” value // of the block, which is stored into `destination`. - let tcx = this.hir.tcx(); + let tcx = this.tcx; let destination_ty = destination.ty(&this.local_decls, tcx).ty; if let Some(expr) = expr { let tail_result_is_ignored = @@ -195,7 +194,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if destination_ty.is_unit() { // We only want to assign an implicit `()` as the return value of the block if the // block does not diverge. (Otherwise, we may try to assign a unit to a `!`-type.) - this.cfg.push_assign_unit(block, source_info, destination, this.hir.tcx()); + this.cfg.push_assign_unit(block, source_info, destination, this.tcx); } } // Finally, we pop all the let scopes before exiting out from the scope of block @@ -221,7 +220,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Safety::Safe => {} // no longer treat `unsafe fn`s as `unsafe` contexts (see RFC #2585) Safety::FnUnsafe - if self.hir.tcx().lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, hir_id).0 + if self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, hir_id).0 != Level::Allow => {} _ => return, } diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs index faa8ea759d709..81428e098699d 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs @@ -136,12 +136,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }); } - let tcx = this.hir.tcx(); + let tcx = this.tcx; if tcx.features().unsized_fn_params { let ty = expr.ty; let span = expr.span; - let param_env = this.hir.param_env; + let param_env = this.param_env; if !ty.is_sized(tcx.at(span), param_env) { // !sized means !copy, so this is an unsized move diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 156f8d2e7045c..3581ca1ee5bd5 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -353,7 +353,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr: &Expr<'tcx>, ) -> BlockAnd> { let place_builder = unpack!(block = self.as_place_builder(block, expr)); - block.and(place_builder.into_place(self.hir.tcx(), self.hir.typeck_results())) + block.and(place_builder.into_place(self.tcx, self.typeck_results)) } /// This is used when constructing a compound `Place`, so that we can avoid creating @@ -377,7 +377,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr: &Expr<'tcx>, ) -> BlockAnd> { let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr)); - block.and(place_builder.into_place(self.hir.tcx(), self.hir.typeck_results())) + block.and(place_builder.into_place(self.tcx, self.typeck_results)) } /// This is used when constructing a compound `Place`, so that we can avoid creating @@ -462,8 +462,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { inferred_ty: expr.ty, }); - let place = - place_builder.clone().into_place(this.hir.tcx(), this.hir.typeck_results()); + let place = place_builder.clone().into_place(this.tcx, this.typeck_results); this.cfg.push( block, Statement { @@ -557,12 +556,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { upvar_id: ty::UpvarId, ) -> BlockAnd> { let closure_ty = self - .hir - .typeck_results() - .node_type(self.hir.tcx().hir().local_def_id_to_hir_id(upvar_id.closure_expr_id)); + .typeck_results + .node_type(self.tcx.hir().local_def_id_to_hir_id(upvar_id.closure_expr_id)); let closure_kind = if let ty::Closure(_, closure_substs) = closure_ty.kind() { - self.hir.infcx().closure_kind(closure_substs).unwrap() + self.infcx.closure_kind(closure_substs).unwrap() } else { // Generators are considered FnOnce. ty::ClosureKind::FnOnce @@ -608,7 +606,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block = self.bounds_check( block, - base_place.clone().into_place(self.hir.tcx(), self.hir.typeck_results()), + base_place.clone().into_place(self.tcx, self.typeck_results), idx, expr_span, source_info, @@ -617,8 +615,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if is_outermost_index { self.read_fake_borrows(block, fake_borrow_temps, source_info) } else { - base_place = - base_place.expect_upvars_resolved(self.hir.tcx(), self.hir.typeck_results()); + base_place = base_place.expect_upvars_resolved(self.tcx, self.typeck_results); self.add_fake_borrows_of_base( &base_place, block, @@ -639,8 +636,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr_span: Span, source_info: SourceInfo, ) -> BasicBlock { - let usize_ty = self.hir.usize_ty(); - let bool_ty = self.hir.bool_ty(); + let usize_ty = self.tcx.types.usize; + let bool_ty = self.tcx.types.bool; // bounds check: let len = self.temp(usize_ty, expr_span); let lt = self.temp(bool_ty, expr_span); @@ -670,7 +667,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr_span: Span, source_info: SourceInfo, ) { - let tcx = self.hir.tcx(); + let tcx = self.tcx; let local = match base_place.base { PlaceBase::Local(local) => local, PlaceBase::Upvar { .. } => bug!("Expected PlacseBase::Local found Upvar"), diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 8082315408c6f..89a179bd4510d 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -61,8 +61,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::Unary { op, arg } => { let arg = unpack!(block = this.as_operand(block, scope, &arg)); // Check for -MIN on signed integers - if this.hir.check_overflow() && *op == UnOp::Neg && expr.ty.is_signed() { - let bool_ty = this.hir.bool_ty(); + if this.check_overflow && *op == UnOp::Neg && expr.ty.is_signed() { + let bool_ty = this.tcx.types.bool; let minval = this.minval_literal(expr_span, expr.ty); let is_min = this.temp(bool_ty, expr_span); @@ -105,7 +105,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // initialize the box contents: unpack!( block = this.expr_into_dest( - this.hir.tcx().mk_place_deref(Place::from(result)), + this.tcx.mk_place_deref(Place::from(result)), block, &value ) @@ -148,7 +148,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // to the same MIR as `let x = ();`. // first process the set of fields - let el_ty = expr.ty.sequence_element_type(this.hir.tcx()); + let el_ty = expr.ty.sequence_element_type(this.tcx); let fields: Vec<_> = fields .into_iter() .map(|f| unpack!(block = this.as_operand(block, scope, &f))) @@ -221,7 +221,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.and(Rvalue::Use(Operand::Constant(box Constant { span: expr_span, user_ty: None, - literal: ty::Const::zero_sized(this.hir.tcx(), this.hir.tcx().types.unit), + literal: ty::Const::zero_sized(this.tcx, this.tcx.types.unit), }))) } ExprKind::Yield { .. } @@ -273,9 +273,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { rhs: Operand<'tcx>, ) -> BlockAnd> { let source_info = self.source_info(span); - let bool_ty = self.hir.bool_ty(); - if self.hir.check_overflow() && op.is_checkable() && ty.is_integral() { - let result_tup = self.hir.tcx().intern_tup(&[ty, bool_ty]); + let bool_ty = self.tcx.types.bool; + if self.check_overflow && op.is_checkable() && ty.is_integral() { + let result_tup = self.tcx.intern_tup(&[ty, bool_ty]); let result_value = self.temp(result_tup, span); self.cfg.push_assign( @@ -287,7 +287,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let val_fld = Field::new(0); let of_fld = Field::new(1); - let tcx = self.hir.tcx(); + let tcx = self.tcx; let val = tcx.mk_place_field(result_value, val_fld, ty); let of = tcx.mk_place_field(result_value, of_fld, bool_ty); @@ -389,7 +389,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // is same as that of the capture in the parent closure. PlaceBase::Upvar { .. } => { let enclosing_upvars_resolved = - arg_place_builder.clone().into_place(this.hir.tcx(), this.hir.typeck_results()); + arg_place_builder.clone().into_place(this.tcx, this.typeck_results); match enclosing_upvars_resolved.as_ref() { PlaceRef { @@ -426,13 +426,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Mutability::Mut => BorrowKind::Mut { allow_two_phase_borrow: false }, }; - let arg_place = arg_place_builder.into_place(this.hir.tcx(), this.hir.typeck_results()); + let arg_place = arg_place_builder.into_place(this.tcx, this.typeck_results); this.cfg.push_assign( block, source_info, Place::from(temp), - Rvalue::Ref(this.hir.tcx().lifetimes.re_erased, borrow_kind, arg_place), + Rvalue::Ref(this.tcx.lifetimes.re_erased, borrow_kind, arg_place), ); // See the comment in `expr_as_temp` and on the `rvalue_scopes` field for why @@ -447,9 +447,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Helper to get a `-1` value of the appropriate type fn neg_1_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { let param_ty = ty::ParamEnv::empty().and(ty); - let bits = self.hir.tcx().layout_of(param_ty).unwrap().size.bits(); + let bits = self.tcx.layout_of(param_ty).unwrap().size.bits(); let n = (!0u128) >> (128 - bits); - let literal = ty::Const::from_bits(self.hir.tcx(), n, param_ty); + let literal = ty::Const::from_bits(self.tcx, n, param_ty); self.literal_operand(span, literal) } @@ -458,9 +458,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn minval_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { assert!(ty.is_signed()); let param_ty = ty::ParamEnv::empty().and(ty); - let bits = self.hir.tcx().layout_of(param_ty).unwrap().size.bits(); + let bits = self.tcx.layout_of(param_ty).unwrap().size.bits(); let n = 1 << (bits - 1); - let literal = ty::Const::from_bits(self.hir.tcx(), n, param_ty); + let literal = ty::Const::from_bits(self.tcx, n, param_ty); self.literal_operand(span, literal) } diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs index 0f4d05fc03ab9..8b032032bfc43 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs @@ -59,13 +59,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } match expr.kind { ExprKind::StaticRef { def_id, .. } => { - assert!(!this.hir.tcx().is_thread_local_static(def_id)); + assert!(!this.tcx.is_thread_local_static(def_id)); local_decl.internal = true; local_decl.local_info = Some(box LocalInfo::StaticRef { def_id, is_thread_local: false }); } ExprKind::ThreadLocalRef(def_id) => { - assert!(this.hir.tcx().is_thread_local_static(def_id)); + assert!(this.tcx.is_thread_local_static(def_id)); local_decl.internal = true; local_decl.local_info = Some(box LocalInfo::StaticRef { def_id, is_thread_local: true }); diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 9c719e36551c4..83a09a005084a 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -7,8 +7,9 @@ use rustc_ast::InlineAsmOptions; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; +use rustc_index::vec::Idx; use rustc_middle::mir::*; -use rustc_middle::ty::CanonicalUserTypeAnnotation; +use rustc_middle::ty::{self, CanonicalUserTypeAnnotation}; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr`, storing the result into `destination`, which @@ -58,7 +59,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let mut then_block = this.cfg.start_new_block(); let mut else_block = this.cfg.start_new_block(); - let term = TerminatorKind::if_(this.hir.tcx(), operand, then_block, else_block); + let term = TerminatorKind::if_(this.tcx, operand, then_block, else_block); this.cfg.terminate(block, source_info, term); unpack!(then_block = this.expr_into_dest(destination, then_block, &then)); @@ -68,7 +69,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Body of the `if` expression without an `else` clause must return `()`, thus // we implicitly generate a `else {}` if it is not specified. let correct_si = this.source_info(expr_span.shrink_to_hi()); - this.cfg.push_assign_unit(else_block, correct_si, destination, this.hir.tcx()); + this.cfg.push_assign_unit(else_block, correct_si, destination, this.tcx); else_block }; @@ -132,25 +133,33 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { LogicalOp::And => (else_block, false_block), LogicalOp::Or => (true_block, else_block), }; - let term = TerminatorKind::if_(this.hir.tcx(), lhs, blocks.0, blocks.1); + let term = TerminatorKind::if_(this.tcx, lhs, blocks.0, blocks.1); this.cfg.terminate(block, source_info, term); let rhs = unpack!(else_block = this.as_local_operand(else_block, &rhs)); - let term = TerminatorKind::if_(this.hir.tcx(), rhs, true_block, false_block); + let term = TerminatorKind::if_(this.tcx, rhs, true_block, false_block); this.cfg.terminate(else_block, source_info, term); this.cfg.push_assign_constant( true_block, source_info, destination, - Constant { span: expr_span, user_ty: None, literal: this.hir.true_literal() }, + Constant { + span: expr_span, + user_ty: None, + literal: ty::Const::from_bool(this.tcx, true), + }, ); this.cfg.push_assign_constant( false_block, source_info, destination, - Constant { span: expr_span, user_ty: None, literal: this.hir.false_literal() }, + Constant { + span: expr_span, + user_ty: None, + literal: ty::Const::from_bool(this.tcx, false), + }, ); // Link up both branches: @@ -241,8 +250,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { BorrowKind::Shared => unpack!(block = this.as_read_only_place(block, &arg)), _ => unpack!(block = this.as_place(block, &arg)), }; - let borrow = - Rvalue::Ref(this.hir.tcx().lifetimes.re_erased, *borrow_kind, arg_place); + let borrow = Rvalue::Ref(this.tcx.lifetimes.re_erased, *borrow_kind, arg_place); this.cfg.push_assign(block, source_info, destination, borrow); block.unit() } @@ -272,7 +280,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }) .collect(); - let field_names = this.hir.all_fields(adt_def, *variant_index); + let field_names: Vec<_> = + (0..adt_def.variants[*variant_index].fields.len()).map(Field::new).collect(); let fields: Vec<_> = if let Some(FruInfo { base, field_types }) = base { let place_builder = unpack!(block = this.as_place_builder(block, &base)); @@ -290,7 +299,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.consume_by_copy_or_move( place_builder .field(n, ty) - .into_place(this.hir.tcx(), this.hir.typeck_results()), + .into_place(this.tcx, this.typeck_results), ) } }) @@ -398,7 +407,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { | ExprKind::AssignOp { .. } | ExprKind::LlvmInlineAsm { .. } => { unpack!(block = this.stmt_expr(block, expr, None)); - this.cfg.push_assign_unit(block, source_info, destination, this.hir.tcx()); + this.cfg.push_assign_unit(block, source_info, destination, this.tcx); block.unit() } diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs index 0d2d99a8b5e87..8e907a40f43fa 100644 --- a/compiler/rustc_mir_build/src/build/expr/stmt.rs +++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs @@ -40,7 +40,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Generate better code for things that don't need to be // dropped. - if this.hir.needs_drop(lhs.ty) { + if lhs.ty.needs_drop(this.tcx, this.param_env) { let rhs = unpack!(block = this.as_local_operand(block, &rhs)); let lhs = unpack!(block = this.as_place(block, &lhs)); unpack!(block = this.build_drop_and_replace(block, lhs_span, lhs, rhs)); diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 6a828c1864fc9..d93fc6149c213 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -413,7 +413,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let ty_source_info = self.source_info(user_ty_span); let user_ty = pat_ascription_ty.user_ty( &mut self.canonical_user_type_annotations, - place.ty(&self.local_decls, self.hir.tcx()).ty, + place.ty(&self.local_decls, self.tcx).ty, ty_source_info.span, ); self.cfg.push( @@ -555,7 +555,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let local_id = self.var_local_id(var, for_guard); let source_info = self.source_info(span); self.cfg.push(block, Statement { source_info, kind: StatementKind::StorageLive(local_id) }); - let region_scope = self.hir.region_scope_tree.var_scope(var.local_id); + let region_scope = self.region_scope_tree.var_scope(var.local_id); if schedule_drop { self.schedule_drop(span, region_scope, local_id, DropKind::Storage); } @@ -564,7 +564,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn schedule_drop_for_binding(&mut self, var: HirId, span: Span, for_guard: ForGuard) { let local_id = self.var_local_id(var, for_guard); - let region_scope = self.hir.region_scope_tree.var_scope(var.local_id); + let region_scope = self.region_scope_tree.var_scope(var.local_id); self.schedule_drop(span, region_scope, local_id, DropKind::Value); } @@ -1070,7 +1070,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fake_borrows.insert(Place { local: source.local, - projection: self.hir.tcx().intern_place_elems(proj_base), + projection: self.tcx.intern_place_elems(proj_base), }); } } @@ -1549,7 +1549,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fake_borrows: &'b FxHashSet>, temp_span: Span, ) -> Vec<(Place<'tcx>, Local)> { - let tcx = self.hir.tcx(); + let tcx = self.tcx; debug!("add_fake_borrows fake_borrows = {:?}", fake_borrows); @@ -1726,7 +1726,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // * So we eagerly create the reference for the arm and then take a // reference to that. if let Some(guard) = guard { - let tcx = self.hir.tcx(); + let tcx = self.tcx; let bindings = parent_bindings .iter() .flat_map(|(bindings, _)| bindings) @@ -1885,7 +1885,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let user_ty = ascription.user_ty.clone().user_ty( &mut self.canonical_user_type_annotations, - ascription.source.ty(&self.local_decls, self.hir.tcx()).ty, + ascription.source.ty(&self.local_decls, self.tcx).ty, source_info.span, ); self.cfg.push( @@ -1914,7 +1914,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Assign each of the bindings. Since we are binding for a // guard expression, this will never trigger moves out of the // candidate. - let re_erased = self.hir.tcx().lifetimes.re_erased; + let re_erased = self.tcx.lifetimes.re_erased; for binding in bindings { debug!("bind_matched_candidate_for_guard(binding={:?})", binding); let source_info = self.source_info(binding.span); @@ -1963,7 +1963,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { { debug!("bind_matched_candidate_for_arm_body(block={:?})", block); - let re_erased = self.hir.tcx().lifetimes.re_erased; + let re_erased = self.tcx.lifetimes.re_erased; // Assign each of the bindings. This may trigger moves out of the candidate. for binding in bindings { let source_info = self.source_info(binding.span); @@ -2012,7 +2012,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { var_id, name, mode, var_ty, visibility_scope, source_info ); - let tcx = self.hir.tcx(); + let tcx = self.tcx; let debug_source_info = SourceInfo { span: source_info.span, scope: visibility_scope }; let binding_mode = match mode { BindingMode::ByValue => ty::BindingMode::BindByValue(mutability), diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index ddfaeafc07cf1..9931cdf3b9e91 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -147,7 +147,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match_pair: MatchPair<'pat, 'tcx>, candidate: &mut Candidate<'pat, 'tcx>, ) -> Result<(), MatchPair<'pat, 'tcx>> { - let tcx = self.hir.tcx(); + let tcx = self.tcx; match *match_pair.pattern.kind { PatKind::AscribeUserType { ref subpattern, @@ -251,13 +251,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { PatKind::Variant { adt_def, substs, variant_index, ref subpatterns } => { let irrefutable = adt_def.variants.iter_enumerated().all(|(i, v)| { i == variant_index || { - self.hir.tcx().features().exhaustive_patterns + self.tcx.features().exhaustive_patterns && !v .uninhabited_from( - self.hir.tcx(), + self.tcx, substs, adt_def.adt_kind(), - self.hir.param_env, + self.param_env, ) .is_empty() } diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index c428ed817b1f8..48abaa8d35f82 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -13,9 +13,11 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_hir::{LangItem, RangeEnd}; use rustc_index::bit_set::BitSet; use rustc_middle::mir::*; +use rustc_middle::ty::subst::{GenericArg, Subst}; use rustc_middle::ty::util::IntTypeExt; -use rustc_middle::ty::{self, adjustment::PointerCast, Ty}; -use rustc_span::symbol::sym; +use rustc_middle::ty::{self, adjustment::PointerCast, Ty, TyCtxt}; +use rustc_span::def_id::DefId; +use rustc_span::symbol::{sym, Symbol}; use rustc_target::abi::VariantIdx; use std::cmp::Ordering; @@ -93,9 +95,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match *match_pair.pattern.kind { PatKind::Constant { value } => { - options.entry(value).or_insert_with(|| { - value.eval_bits(self.hir.tcx(), self.hir.param_env, switch_ty) - }); + options + .entry(value) + .or_insert_with(|| value.eval_bits(self.tcx, self.param_env, switch_ty)); true } PatKind::Variant { .. } => { @@ -157,7 +159,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { "perform_test({:?}, {:?}: {:?}, {:?})", block, place, - place.ty(&self.local_decls, self.hir.tcx()), + place.ty(&self.local_decls, self.tcx), test ); @@ -169,7 +171,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let num_enum_variants = adt_def.variants.len(); debug_assert_eq!(target_blocks.len(), num_enum_variants + 1); let otherwise_block = *target_blocks.last().unwrap(); - let tcx = self.hir.tcx(); + let tcx = self.tcx; let switch_targets = SwitchTargets::new( adt_def.discriminants(tcx).filter_map(|(idx, discr)| { if variants.contains(idx) { @@ -217,7 +219,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { 0 => (second_bb, first_bb), v => span_bug!(test.span, "expected boolean value but got {:?}", v), }; - TerminatorKind::if_(self.hir.tcx(), Operand::Copy(place), true_bb, false_bb) + TerminatorKind::if_(self.tcx, Operand::Copy(place), true_bb, false_bb) } else { bug!("`TestKind::SwitchInt` on `bool` should have two targets") } @@ -292,7 +294,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { TestKind::Len { len, op } => { let target_blocks = make_target_blocks(self); - let usize_ty = self.hir.usize_ty(); + let usize_ty = self.tcx.types.usize; let actual = self.temp(usize_ty, test.span); // actual = len(place) @@ -331,7 +333,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { left: Operand<'tcx>, right: Operand<'tcx>, ) { - let bool_ty = self.hir.bool_ty(); + let bool_ty = self.tcx.types.bool; let result = self.temp(bool_ty, source_info.span); // result = op(left, right) @@ -341,7 +343,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.terminate( block, source_info, - TerminatorKind::if_(self.hir.tcx(), Operand::Move(result), success_block, fail_block), + TerminatorKind::if_(self.tcx, Operand::Move(result), success_block, fail_block), ); } @@ -377,7 +379,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // nothing to do, neither is an array (None, None) => {} (Some((region, elem_ty, _)), _) | (None, Some((region, elem_ty, _))) => { - let tcx = self.hir.tcx(); + let tcx = self.tcx; // make both a slice ty = tcx.mk_imm_ref(region, tcx.mk_slice(elem_ty)); if opt_ref_ty.is_some() { @@ -408,10 +410,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { _ => bug!("non_scalar_compare called on non-reference type: {}", ty), }; - let eq_def_id = self.hir.tcx().require_lang_item(LangItem::PartialEq, None); - let method = self.hir.trait_method(eq_def_id, sym::eq, deref_ty, &[deref_ty.into()]); + let eq_def_id = self.tcx.require_lang_item(LangItem::PartialEq, None); + let method = trait_method(self.tcx, eq_def_id, sym::eq, deref_ty, &[deref_ty.into()]); - let bool_ty = self.hir.bool_ty(); + let bool_ty = self.tcx.types.bool; let eq_result = self.temp(bool_ty, source_info.span); let eq_block = self.cfg.start_new_block(); self.cfg.terminate( @@ -443,12 +445,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.terminate( eq_block, source_info, - TerminatorKind::if_( - self.hir.tcx(), - Operand::Move(eq_result), - success_block, - fail_block, - ), + TerminatorKind::if_(self.tcx, Operand::Move(eq_result), success_block, fail_block), ); } else { bug!("`TestKind::Eq` should have two target blocks") @@ -632,11 +629,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { use rustc_hir::RangeEnd::*; use std::cmp::Ordering::*; - let tcx = self.hir.tcx(); + let tcx = self.tcx; let test_ty = test.lo.ty; - let lo = compare_const_vals(tcx, test.lo, pat.hi, self.hir.param_env, test_ty)?; - let hi = compare_const_vals(tcx, test.hi, pat.lo, self.hir.param_env, test_ty)?; + let lo = compare_const_vals(tcx, test.lo, pat.hi, self.param_env, test_ty)?; + let hi = compare_const_vals(tcx, test.hi, pat.lo, self.param_env, test_ty)?; match (test.end, pat.end, lo, hi) { // pat < test @@ -731,7 +728,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { candidate: &mut Candidate<'pat, 'tcx>, ) { let match_pair = candidate.match_pairs.remove(match_pair_index); - let tcx = self.hir.tcx(); + let tcx = self.tcx; // So, if we have a match-pattern like `x @ Enum::Variant(P1, P2)`, // we want to create a set of derived match-patterns like @@ -762,10 +759,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) -> Option { use std::cmp::Ordering::*; - let tcx = self.hir.tcx(); + let tcx = self.tcx; - let a = compare_const_vals(tcx, range.lo, value, self.hir.param_env, range.lo.ty)?; - let b = compare_const_vals(tcx, value, range.hi, self.hir.param_env, range.lo.ty)?; + let a = compare_const_vals(tcx, range.lo, value, self.param_env, range.lo.ty)?; + let b = compare_const_vals(tcx, value, range.hi, self.param_env, range.lo.ty)?; match (b, range.end) { (Less, _) | (Equal, RangeEnd::Included) if a != Greater => Some(true), @@ -815,3 +812,25 @@ impl Test<'_> { fn is_switch_ty(ty: Ty<'_>) -> bool { ty.is_integral() || ty.is_char() || ty.is_bool() } + +fn trait_method<'tcx>( + tcx: TyCtxt<'tcx>, + trait_def_id: DefId, + method_name: Symbol, + self_ty: Ty<'tcx>, + params: &[GenericArg<'tcx>], +) -> &'tcx ty::Const<'tcx> { + let substs = tcx.mk_substs_trait(self_ty, params); + + // The unhygienic comparison here is acceptable because this is only + // used on known traits. + let item = tcx + .associated_items(trait_def_id) + .filter_by_name_unhygienic(method_name) + .find(|item| item.kind == ty::AssocKind::Fn) + .expect("trait method not found"); + + let method_ty = tcx.type_of(item.def_id); + let method_ty = method_ty.subst(tcx, substs); + ty::Const::zero_sized(tcx, method_ty) +} diff --git a/compiler/rustc_mir_build/src/build/matches/util.rs b/compiler/rustc_mir_build/src/build/matches/util.rs index db1f678a5c68d..15aca0203aa01 100644 --- a/compiler/rustc_mir_build/src/build/matches/util.rs +++ b/compiler/rustc_mir_build/src/build/matches/util.rs @@ -15,8 +15,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { subpatterns .iter() .map(|fieldpat| { - let place = - self.hir.tcx().mk_place_field(place, fieldpat.field, fieldpat.pattern.ty); + let place = self.tcx.mk_place_field(place, fieldpat.field, fieldpat.pattern.ty); MatchPair::new(place, &fieldpat.pattern) }) .collect() @@ -30,9 +29,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { opt_slice: Option<&'pat Pat<'tcx>>, suffix: &'pat [Pat<'tcx>], ) { - let tcx = self.hir.tcx(); + let tcx = self.tcx; let (min_length, exact_size) = match place.ty(&self.local_decls, tcx).ty.kind() { - ty::Array(_, length) => (length.eval_usize(tcx, self.hir.param_env), true), + ty::Array(_, length) => (length.eval_usize(tcx, self.param_env), true), _ => ((prefix.len() + suffix.len()).try_into().unwrap(), false), }; diff --git a/compiler/rustc_mir_build/src/build/misc.rs b/compiler/rustc_mir_build/src/build/misc.rs index 29651d9bc663a..62c217a12aaad 100644 --- a/compiler/rustc_mir_build/src/build/misc.rs +++ b/compiler/rustc_mir_build/src/build/misc.rs @@ -3,10 +3,10 @@ use crate::build::Builder; -use rustc_middle::ty::{self, Ty}; - use rustc_middle::mir::*; +use rustc_middle::ty::{self, Ty}; use rustc_span::{Span, DUMMY_SP}; +use rustc_trait_selection::infer::InferCtxtExt; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Adds a new temporary value of type `ty` storing the result of @@ -37,7 +37,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Returns a zero literal operand for the appropriate type, works for // bool, char and integers. crate fn zero_literal(&mut self, span: Span, ty: Ty<'tcx>) -> Operand<'tcx> { - let literal = ty::Const::from_bits(self.hir.tcx(), 0, ty::ParamEnv::empty().and(ty)); + let literal = ty::Const::from_bits(self.tcx, 0, ty::ParamEnv::empty().and(ty)); self.literal_operand(span, literal) } @@ -48,7 +48,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_info: SourceInfo, value: u64, ) -> Place<'tcx> { - let usize_ty = self.hir.usize_ty(); + let usize_ty = self.tcx.types.usize; let temp = self.temp(usize_ty, source_info.span); self.cfg.push_assign_constant( block, @@ -57,16 +57,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Constant { span: source_info.span, user_ty: None, - literal: self.hir.usize_literal(value), + literal: ty::Const::from_usize(self.tcx, value), }, ); temp } crate fn consume_by_copy_or_move(&self, place: Place<'tcx>) -> Operand<'tcx> { - let tcx = self.hir.tcx(); + let tcx = self.tcx; let ty = place.ty(&self.local_decls, tcx).ty; - if !self.hir.type_is_copy_modulo_regions(ty, DUMMY_SP) { + if !self.infcx.type_is_copy_modulo_regions(self.param_env, ty, DUMMY_SP) { Operand::Move(place) } else { Operand::Copy(place) diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index f9bed4454f2ed..ecc5f2f260e7d 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -1,7 +1,7 @@ use crate::build; use crate::build::scope::DropKind; use crate::thir::cx::Cx; -use crate::thir::{BindingMode, LintLevel, PatKind}; +use crate::thir::{BindingMode, Expr, LintLevel, Pat, PatKind}; use rustc_attr::{self as attr, UnwindAttr}; use rustc_errors::ErrorReported; use rustc_hir as hir; @@ -9,13 +9,13 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::lang_items::LangItem; use rustc_hir::{GeneratorKind, HirIdMap, Node}; use rustc_index::vec::{Idx, IndexVec}; -use rustc_infer::infer::TyCtxtInferExt; +use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_middle::hir::place::PlaceBase as HirPlaceBase; use rustc_middle::middle::region; use rustc_middle::mir::*; use rustc_middle::ty::subst::Subst; -use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc_span::symbol::kw; +use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeckResults}; +use rustc_span::symbol::{kw, sym}; use rustc_span::Span; use rustc_target::spec::abi::Abi; use rustc_target::spec::PanicStrategy; @@ -42,6 +42,7 @@ crate fn mir_built<'tcx>( /// Construct the MIR for a given `DefId`. fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_> { let id = tcx.hir().local_def_id_to_hir_id(def.did); + let body_owner_kind = tcx.hir().body_owner_kind(id); // Figure out what primary body this item has. let (body_id, return_ty_span, span_with_body) = match tcx.hir().get(id) { @@ -88,13 +89,13 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ let span_with_body = span_with_body.unwrap_or_else(|| tcx.hir().span(id)); tcx.infer_ctxt().enter(|infcx| { - let cx = Cx::new(&infcx, def, id); - let body = if let Some(ErrorReported) = cx.typeck_results().tainted_by_errors { - build::construct_error(cx, body_id) - } else if cx.body_owner_kind.is_fn_or_closure() { + let mut cx = Cx::new(tcx, def); + let body = if let Some(ErrorReported) = cx.typeck_results.tainted_by_errors { + build::construct_error(&infcx, def, id, body_id, body_owner_kind) + } else if body_owner_kind.is_fn_or_closure() { // fetch the fully liberated fn signature (that is, all bound // types/lifetimes replaced) - let fn_sig = cx.typeck_results().liberated_fn_sigs()[id]; + let fn_sig = cx.typeck_results.liberated_fn_sigs()[id]; let fn_def_id = tcx.hir().local_def_id(id); let safety = match fn_sig.unsafety { @@ -103,6 +104,7 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ }; let body = tcx.hir().body(body_id); + let expr = cx.mirror_expr(&body.value); let ty = tcx.type_of(fn_def_id); let mut abi = fn_sig.abi; let implicit_argument = match ty.kind() { @@ -178,7 +180,8 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ }; let mut mir = build::construct_fn( - cx, + &infcx, + def, id, arguments, safety, @@ -186,6 +189,7 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ return_ty, return_ty_span, body, + expr, span_with_body, ); if yield_ty.is_some() { @@ -205,9 +209,12 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ // place to be the type of the constant because NLL typeck will // equate them. - let return_ty = cx.typeck_results().node_type(id); + let return_ty = cx.typeck_results.node_type(id); - build::construct_const(cx, body_id, return_ty, return_ty_span) + let ast_expr = &tcx.hir().body(body_id).value; + let expr = cx.mirror_expr(ast_expr); + + build::construct_const(&infcx, expr, def, id, return_ty, return_ty_span) }; lints::check(tcx, &body); @@ -304,10 +311,17 @@ impl BlockFrame { struct BlockContext(Vec); struct Builder<'a, 'tcx> { - hir: Cx<'a, 'tcx>, + tcx: TyCtxt<'tcx>, + infcx: &'a InferCtxt<'a, 'tcx>, + typeck_results: &'tcx TypeckResults<'tcx>, + region_scope_tree: &'tcx region::ScopeTree, + param_env: ty::ParamEnv<'tcx>, + cfg: CFG<'tcx>, def_id: DefId, + hir_id: hir::HirId, + check_overflow: bool, fn_span: Span, arg_count: usize, generator_kind: Option, @@ -577,8 +591,9 @@ struct ArgInfo<'tcx>( Option, ); -fn construct_fn<'a, 'tcx, A>( - hir: Cx<'a, 'tcx>, +fn construct_fn<'tcx, A>( + infcx: &InferCtxt<'_, 'tcx>, + fn_def: ty::WithOptConstParam, fn_id: hir::HirId, arguments: A, safety: Safety, @@ -586,6 +601,7 @@ fn construct_fn<'a, 'tcx, A>( return_ty: Ty<'tcx>, return_ty_span: Span, body: &'tcx hir::Body<'tcx>, + expr: Expr<'tcx>, span_with_body: Span, ) -> Body<'tcx> where @@ -593,15 +609,13 @@ where { let arguments: Vec<_> = arguments.collect(); - let tcx = hir.tcx(); - let tcx_hir = tcx.hir(); - let span = tcx_hir.span(fn_id); - - let fn_def_id = tcx_hir.local_def_id(fn_id); + let tcx = infcx.tcx; + let span = tcx.hir().span(fn_id); let mut builder = Builder::new( - hir, - fn_def_id.to_def_id(), + infcx, + fn_def, + fn_id, span_with_body, arguments.len(), safety, @@ -625,16 +639,16 @@ where Some(builder.in_scope(arg_scope_s, LintLevel::Inherited, |builder| { builder.args_and_body( START_BLOCK, - fn_def_id.to_def_id(), + fn_def.did.to_def_id(), &arguments, arg_scope, - &body.value, + &expr, ) })) })); let source_info = builder.source_info(fn_end); builder.cfg.terminate(return_block, source_info, TerminatorKind::Return); - let should_abort = should_abort_on_panic(tcx, fn_def_id, abi); + let should_abort = should_abort_on_panic(tcx, fn_def.did, abi); builder.build_drop_trees(should_abort); return_block.unit() })); @@ -645,7 +659,7 @@ where } else { None }; - debug!("fn_id {:?} has attrs {:?}", fn_def_id, tcx.get_attrs(fn_def_id.to_def_id())); + debug!("fn_id {:?} has attrs {:?}", fn_def, tcx.get_attrs(fn_def.did.to_def_id())); let mut body = builder.finish(); body.spread_arg = spread_arg; @@ -653,21 +667,19 @@ where } fn construct_const<'a, 'tcx>( - hir: Cx<'a, 'tcx>, - body_id: hir::BodyId, + infcx: &'a InferCtxt<'a, 'tcx>, + expr: Expr<'tcx>, + def: ty::WithOptConstParam, + hir_id: hir::HirId, const_ty: Ty<'tcx>, const_ty_span: Span, ) -> Body<'tcx> { - let tcx = hir.tcx(); - let owner_id = tcx.hir().body_owner(body_id); - let def_id = tcx.hir().local_def_id(owner_id); - let span = tcx.hir().span(owner_id); + let tcx = infcx.tcx; + let span = tcx.hir().span(hir_id); let mut builder = - Builder::new(hir, def_id.to_def_id(), span, 0, Safety::Safe, const_ty, const_ty_span, None); + Builder::new(infcx, def, hir_id, span, 0, Safety::Safe, const_ty, const_ty_span, None); let mut block = START_BLOCK; - let ast_expr = &tcx.hir().body(body_id).value; - let expr = builder.hir.mirror_expr(ast_expr); unpack!(block = builder.expr_into_dest(Place::return_place(), block, &expr)); let source_info = builder.source_info(span); @@ -682,15 +694,19 @@ fn construct_const<'a, 'tcx>( /// /// This is required because we may still want to run MIR passes on an item /// with type errors, but normal MIR construction can't handle that in general. -fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'tcx> { - let tcx = hir.tcx(); - let owner_id = tcx.hir().body_owner(body_id); - let def_id = tcx.hir().local_def_id(owner_id); - let span = tcx.hir().span(owner_id); +fn construct_error<'a, 'tcx>( + infcx: &'a InferCtxt<'a, 'tcx>, + def: ty::WithOptConstParam, + hir_id: hir::HirId, + body_id: hir::BodyId, + body_owner_kind: hir::BodyOwnerKind, +) -> Body<'tcx> { + let tcx = infcx.tcx; + let span = tcx.hir().span(hir_id); let ty = tcx.ty_error(); let generator_kind = tcx.hir().body(body_id).generator_kind; - let num_params = match hir.body_owner_kind { - hir::BodyOwnerKind::Fn => tcx.hir().fn_decl_by_hir_id(owner_id).unwrap().inputs.len(), + let num_params = match body_owner_kind { + hir::BodyOwnerKind::Fn => tcx.hir().fn_decl_by_hir_id(hir_id).unwrap().inputs.len(), hir::BodyOwnerKind::Closure => { if generator_kind.is_some() { // Generators have an implicit `self` parameter *and* a possibly @@ -698,22 +714,14 @@ fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'t 2 } else { // The implicit self parameter adds another local in MIR. - 1 + tcx.hir().fn_decl_by_hir_id(owner_id).unwrap().inputs.len() + 1 + tcx.hir().fn_decl_by_hir_id(hir_id).unwrap().inputs.len() } } hir::BodyOwnerKind::Const => 0, hir::BodyOwnerKind::Static(_) => 0, }; - let mut builder = Builder::new( - hir, - def_id.to_def_id(), - span, - num_params, - Safety::Safe, - ty, - span, - generator_kind, - ); + let mut builder = + Builder::new(infcx, def, hir_id, span, num_params, Safety::Safe, ty, span, generator_kind); let source_info = builder.source_info(span); // Some MIR passes will expect the number of parameters to match the // function declaration. @@ -728,8 +736,9 @@ fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'t impl<'a, 'tcx> Builder<'a, 'tcx> { fn new( - hir: Cx<'a, 'tcx>, - def_id: DefId, + infcx: &'a InferCtxt<'a, 'tcx>, + def: ty::WithOptConstParam, + hir_id: hir::HirId, span: Span, arg_count: usize, safety: Safety, @@ -737,10 +746,30 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { return_span: Span, generator_kind: Option, ) -> Builder<'a, 'tcx> { - let lint_level = LintLevel::Explicit(hir.root_lint_level); + let tcx = infcx.tcx; + let attrs = tcx.hir().attrs(hir_id); + // Some functions always have overflow checks enabled, + // however, they may not get codegen'd, depending on + // the settings for the crate they are codegened in. + let mut check_overflow = tcx.sess.contains_name(attrs, sym::rustc_inherit_overflow_checks); + // Respect -C overflow-checks. + check_overflow |= tcx.sess.overflow_checks(); + // Constants always need overflow checks. + check_overflow |= matches!( + tcx.hir().body_owner_kind(hir_id), + hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) + ); + + let lint_level = LintLevel::Explicit(hir_id); let mut builder = Builder { - hir, - def_id, + tcx, + infcx, + typeck_results: tcx.typeck_opt_const_arg(def), + region_scope_tree: tcx.region_scope_tree(def.did), + param_env: tcx.param_env(def.did), + def_id: def.did.to_def_id(), + hir_id, + check_overflow, cfg: CFG { basic_blocks: IndexVec::new() }, fn_span: span, arg_count, @@ -796,7 +825,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn_def_id: DefId, arguments: &[ArgInfo<'tcx>], argument_scope: region::Scope, - ast_body: &'tcx hir::Expr<'tcx>, + expr: &Expr<'tcx>, ) -> BlockAnd<()> { // Allocate locals for the function arguments for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() { @@ -816,9 +845,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - let tcx = self.hir.tcx(); + let tcx = self.tcx; let tcx_hir = tcx.hir(); - let hir_typeck_results = self.hir.typeck_results(); + let hir_typeck_results = self.typeck_results; // In analyze_closure() in upvar.rs we gathered a list of upvars used by a // indexed closure and we stored in a map called closure_captures in TypeckResults @@ -894,14 +923,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Make sure we drop (parts of) the argument even when not matched on. self.schedule_drop( - arg_opt.as_ref().map_or(ast_body.span, |arg| arg.pat.span), + arg_opt.as_ref().map_or(expr.span, |arg| arg.pat.span), argument_scope, local, DropKind::Value, ); if let Some(arg) = arg_opt { - let pattern = self.hir.pattern_from_hir(&arg.pat); + let pat = match tcx.hir().get(arg.pat.hir_id) { + Node::Pat(pat) | Node::Binding(pat) => pat, + node => bug!("pattern became {:?}", node), + }; + let pattern = Pat::from_hir(tcx, self.param_env, self.typeck_results, pat); let original_source_scope = self.source_scope; let span = pattern.span; self.set_correct_source_scope_for_arg(arg.hir_id, original_source_scope, span); @@ -936,7 +969,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { _ => { scope = self.declare_bindings( scope, - ast_body.span, + expr.span, &pattern, matches::ArmHasGuard(false), Some((Some(&place), span)), @@ -953,8 +986,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.source_scope = source_scope; } - let body = self.hir.mirror_expr(ast_body); - self.expr_into_dest(Place::return_place(), block, &body) + self.expr_into_dest(Place::return_place(), block, &expr) } fn set_correct_source_scope_for_arg( @@ -963,15 +995,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { original_source_scope: SourceScope, pattern_span: Span, ) { - let tcx = self.hir.tcx(); - let current_root = tcx.maybe_lint_level_root_bounded(arg_hir_id, self.hir.root_lint_level); + let tcx = self.tcx; + let current_root = tcx.maybe_lint_level_root_bounded(arg_hir_id, self.hir_id); let parent_root = tcx.maybe_lint_level_root_bounded( self.source_scopes[original_source_scope] .local_data .as_ref() .assert_crate_local() .lint_root, - self.hir.root_lint_level, + self.hir_id, ); if current_root != parent_root { self.source_scope = @@ -983,7 +1015,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { match self.unit_temp { Some(tmp) => tmp, None => { - let ty = self.hir.unit_ty(); + let ty = self.tcx.mk_unit(); let fn_span = self.fn_span; let tmp = self.temp(ty, fn_span); self.unit_temp = Some(tmp); diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index fccff023d0872..6c58528a3c5c6 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -516,7 +516,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { { debug!("in_scope(region_scope={:?})", region_scope); let source_scope = self.source_scope; - let tcx = self.hir.tcx(); + let tcx = self.tcx; if let LintLevel::Explicit(current_hir_id) = lint_level { // Use `maybe_lint_level_root_bounded` with `root_lint_level` as a bound // to avoid adding Hir dependences on our parents. @@ -524,10 +524,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let parent_root = tcx.maybe_lint_level_root_bounded( self.source_scopes[source_scope].local_data.as_ref().assert_crate_local().lint_root, - self.hir.root_lint_level, + self.hir_id, ); - let current_root = - tcx.maybe_lint_level_root_bounded(current_hir_id, self.hir.root_lint_level); + let current_root = tcx.maybe_lint_level_root_bounded(current_hir_id, self.hir_id); if parent_root != current_root { self.source_scope = self.new_source_scope( @@ -615,7 +614,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { unpack!(block = self.expr_into_dest(destination, block, value)); self.block_context.pop(); } else { - self.cfg.push_assign_unit(block, source_info, destination, self.hir.tcx()) + self.cfg.push_assign_unit(block, source_info, destination, self.tcx) } } else { assert!(value.is_none(), "`return` and `break` should have a destination"); @@ -763,7 +762,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) { let needs_drop = match drop_kind { DropKind::Value => { - if !self.hir.needs_drop(self.local_decls[local].ty) { + if !self.local_decls[local].ty.needs_drop(self.tcx, self.param_env) { return; } true @@ -834,10 +833,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } if scope.region_scope == region_scope { - let region_scope_span = - region_scope.span(self.hir.tcx(), &self.hir.region_scope_tree); + let region_scope_span = region_scope.span(self.tcx, &self.region_scope_tree); // Attribute scope exit drops to scope's closing brace. - let scope_end = self.hir.tcx().sess.source_map().end_point(region_scope_span); + let scope_end = self.tcx.sess.source_map().end_point(region_scope_span); scope.drops.push(DropData { source_info: SourceInfo { span: scope_end, scope: scope.source_scope }, @@ -926,7 +924,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let cond = unpack!(block = self.as_local_operand(block, condition)); let true_block = self.cfg.start_new_block(); let false_block = self.cfg.start_new_block(); - let term = TerminatorKind::if_(self.hir.tcx(), cond.clone(), true_block, false_block); + let term = TerminatorKind::if_(self.tcx, cond.clone(), true_block, false_block); self.cfg.terminate(block, source_info, term); match cond { diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index 9c1440aba4204..25af65d1c6538 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -7,7 +7,7 @@ use rustc_middle::ty; use rustc_index::vec::Idx; -impl<'a, 'tcx> Cx<'a, 'tcx> { +impl<'tcx> Cx<'tcx> { crate fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> Block<'tcx> { // We have to eagerly lower the "spine" of the statements // in order to get the lexical scoping correctly. diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index cd5e73a45cd59..2d1170ca3a89d 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; use rustc_middle::ty::{self, AdtKind, Ty}; use rustc_span::Span; -impl<'a, 'tcx> Cx<'a, 'tcx> { +impl<'tcx> Cx<'tcx> { crate fn mirror_expr(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> { let temp_lifetime = self.region_scope_tree.temporary_scope(hir_expr.hir_id.local_id); let expr_scope = @@ -26,7 +26,7 @@ impl<'a, 'tcx> Cx<'a, 'tcx> { let mut expr = self.make_mirror_unadjusted(hir_expr); // Now apply adjustments, if any. - for adjustment in self.typeck_results().expr_adjustments(hir_expr) { + for adjustment in self.typeck_results.expr_adjustments(hir_expr) { debug!("make_mirror: expr={:?} applying adjustment={:?}", expr, adjustment); expr = self.apply_adjustment(hir_expr, expr, adjustment); } @@ -287,13 +287,13 @@ impl<'a, 'tcx> Cx<'a, 'tcx> { self.overloaded_operator(expr, vec![lhs, rhs]) } else { // FIXME overflow - match (op.node, self.constness) { - (hir::BinOpKind::And, _) => ExprKind::LogicalOp { + match op.node { + hir::BinOpKind::And => ExprKind::LogicalOp { op: LogicalOp::And, lhs: self.mirror_expr_boxed(lhs), rhs: self.mirror_expr_boxed(rhs), }, - (hir::BinOpKind::Or, _) => ExprKind::LogicalOp { + hir::BinOpKind::Or => ExprKind::LogicalOp { op: LogicalOp::Or, lhs: self.mirror_expr_boxed(lhs), rhs: self.mirror_expr_boxed(rhs), @@ -420,7 +420,7 @@ impl<'a, 'tcx> Cx<'a, 'tcx> { }; let upvars = self - .typeck_results() + .typeck_results .closure_min_captures_flattened(def_id) .zip(substs.upvar_tys()) .map(|(captured_place, ty)| self.capture_upvar(expr, captured_place, ty)) @@ -981,7 +981,7 @@ impl<'a, 'tcx> Cx<'a, 'tcx> { fn capture_upvar( &mut self, closure_expr: &'tcx hir::Expr<'tcx>, - captured_place: &'a ty::CapturedPlace<'tcx>, + captured_place: &'tcx ty::CapturedPlace<'tcx>, upvar_ty: Ty<'tcx>, ) -> Expr<'tcx> { let upvar_capture = captured_place.info.capture_kind; diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 6b3b3be514c03..c00e9ff8dd98e 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -9,114 +9,37 @@ use rustc_ast as ast; use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::Node; -use rustc_index::vec::Idx; -use rustc_infer::infer::InferCtxt; use rustc_middle::middle::region; use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; -use rustc_middle::ty::subst::Subst; -use rustc_middle::ty::subst::{GenericArg, InternalSubsts}; use rustc_middle::ty::{self, Ty, TyCtxt}; -use rustc_span::symbol::{sym, Symbol}; -use rustc_target::abi::VariantIdx; -use rustc_trait_selection::infer::InferCtxtExt; #[derive(Clone)] -crate struct Cx<'a, 'tcx> { +crate struct Cx<'tcx> { tcx: TyCtxt<'tcx>, - infcx: &'a InferCtxt<'a, 'tcx>, - crate root_lint_level: hir::HirId, crate param_env: ty::ParamEnv<'tcx>, - /// Identity `InternalSubsts` for use with const-evaluation. - crate identity_substs: &'tcx InternalSubsts<'tcx>, - crate region_scope_tree: &'tcx region::ScopeTree, - crate typeck_results: &'a ty::TypeckResults<'tcx>, - - /// This is `Constness::Const` if we are compiling a `static`, - /// `const`, or the body of a `const fn`. - constness: hir::Constness, + crate typeck_results: &'tcx ty::TypeckResults<'tcx>, /// The `DefId` of the owner of this body. body_owner: DefId, - - /// What kind of body is being compiled. - crate body_owner_kind: hir::BodyOwnerKind, - - /// Whether this constant/function needs overflow checks. - check_overflow: bool, } -impl<'a, 'tcx> Cx<'a, 'tcx> { - crate fn new( - infcx: &'a InferCtxt<'a, 'tcx>, - def: ty::WithOptConstParam, - src_id: hir::HirId, - ) -> Cx<'a, 'tcx> { - let tcx = infcx.tcx; +impl<'tcx> Cx<'tcx> { + crate fn new(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam) -> Cx<'tcx> { let typeck_results = tcx.typeck_opt_const_arg(def); - let body_owner_kind = tcx.hir().body_owner_kind(src_id); - - let constness = match body_owner_kind { - hir::BodyOwnerKind::Const | hir::BodyOwnerKind::Static(_) => hir::Constness::Const, - hir::BodyOwnerKind::Closure | hir::BodyOwnerKind::Fn => hir::Constness::NotConst, - }; - - let attrs = tcx.hir().attrs(src_id); - - // Some functions always have overflow checks enabled, - // however, they may not get codegen'd, depending on - // the settings for the crate they are codegened in. - let mut check_overflow = tcx.sess.contains_name(attrs, sym::rustc_inherit_overflow_checks); - - // Respect -C overflow-checks. - check_overflow |= tcx.sess.overflow_checks(); - - // Constants always need overflow checks. - check_overflow |= constness == hir::Constness::Const; - Cx { tcx, - infcx, - root_lint_level: src_id, param_env: tcx.param_env(def.did), - identity_substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()), region_scope_tree: tcx.region_scope_tree(def.did), typeck_results, - constness, body_owner: def.did.to_def_id(), - body_owner_kind, - check_overflow, } } } -impl<'a, 'tcx> Cx<'a, 'tcx> { - crate fn usize_ty(&mut self) -> Ty<'tcx> { - self.tcx.types.usize - } - - crate fn usize_literal(&mut self, value: u64) -> &'tcx ty::Const<'tcx> { - ty::Const::from_usize(self.tcx, value) - } - - crate fn bool_ty(&mut self) -> Ty<'tcx> { - self.tcx.types.bool - } - - crate fn unit_ty(&mut self) -> Ty<'tcx> { - self.tcx.mk_unit() - } - - crate fn true_literal(&mut self) -> &'tcx ty::Const<'tcx> { - ty::Const::from_bool(self.tcx, true) - } - - crate fn false_literal(&mut self) -> &'tcx ty::Const<'tcx> { - ty::Const::from_bool(self.tcx, false) - } - +impl<'tcx> Cx<'tcx> { crate fn const_eval_literal( &mut self, lit: &'tcx ast::LitKind, @@ -149,66 +72,15 @@ impl<'a, 'tcx> Cx<'a, 'tcx> { }; Pat::from_hir(self.tcx, self.param_env, self.typeck_results(), p) } - - crate fn trait_method( - &mut self, - trait_def_id: DefId, - method_name: Symbol, - self_ty: Ty<'tcx>, - params: &[GenericArg<'tcx>], - ) -> &'tcx ty::Const<'tcx> { - let substs = self.tcx.mk_substs_trait(self_ty, params); - - // The unhygienic comparison here is acceptable because this is only - // used on known traits. - let item = self - .tcx - .associated_items(trait_def_id) - .filter_by_name_unhygienic(method_name) - .find(|item| item.kind == ty::AssocKind::Fn) - .expect("trait method not found"); - - let method_ty = self.tcx.type_of(item.def_id); - let method_ty = method_ty.subst(self.tcx, substs); - ty::Const::zero_sized(self.tcx, method_ty) - } - - crate fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: VariantIdx) -> Vec { - (0..adt_def.variants[variant_index].fields.len()).map(Field::new).collect() - } - - crate fn needs_drop(&mut self, ty: Ty<'tcx>) -> bool { - ty.needs_drop(self.tcx, self.param_env) - } - - crate fn infcx(&self) -> &'a InferCtxt<'a, 'tcx> { - self.infcx - } - - crate fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx - } - - crate fn typeck_results(&self) -> &'a ty::TypeckResults<'tcx> { - self.typeck_results - } - - crate fn check_overflow(&self) -> bool { - self.check_overflow - } - - crate fn type_is_copy_modulo_regions(&self, ty: Ty<'tcx>, span: Span) -> bool { - self.infcx.type_is_copy_modulo_regions(self.param_env, ty, span) - } } -impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'_, 'tcx> { +impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { - self.tcx() + self.tcx } fn typeck_results(&self) -> &ty::TypeckResults<'tcx> { - self.typeck_results() + self.typeck_results } } From a9f4dfc8fa90420548bb96d2df4b0d76eea9c862 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Wed, 3 Mar 2021 18:07:57 +0100 Subject: [PATCH 3/7] Remove `Clone` impl for `thir::Expr` --- .../rustc_mir_build/src/build/expr/stmt.rs | 7 +++---- compiler/rustc_mir_build/src/thir/mod.rs | 20 +++++++++---------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs index 8e907a40f43fa..470a3eaaa3c87 100644 --- a/compiler/rustc_mir_build/src/build/expr/stmt.rs +++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs @@ -21,7 +21,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let source_info = this.source_info(expr.span); // Handle a number of expressions that don't need a destination at all. This // avoids needing a mountain of temporary `()` variables. - let expr2 = expr.clone(); match &expr.kind { ExprKind::Scope { region_scope, lint_level, value } => { this.in_scope((*region_scope, source_info), *lint_level, |this| { @@ -35,7 +34,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // is better for borrowck interaction with overloaded // operators like x[j] = x[i]. - debug!("stmt_expr Assign block_context.push(SubExpr) : {:?}", expr2); + debug!("stmt_expr Assign block_context.push(SubExpr) : {:?}", expr); this.block_context.push(BlockFrame::SubExpr); // Generate better code for things that don't need to be @@ -64,7 +63,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let lhs_ty = lhs.ty; - debug!("stmt_expr AssignOp block_context.push(SubExpr) : {:?}", expr2); + debug!("stmt_expr AssignOp block_context.push(SubExpr) : {:?}", expr); this.block_context.push(BlockFrame::SubExpr); // As above, RTL. @@ -102,7 +101,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.break_scope(block, value.as_deref(), BreakableTarget::Return, source_info) } ExprKind::LlvmInlineAsm { asm, outputs, inputs } => { - debug!("stmt_expr LlvmInlineAsm block_context.push(SubExpr) : {:?}", expr2); + debug!("stmt_expr LlvmInlineAsm block_context.push(SubExpr) : {:?}", expr); this.block_context.push(BlockFrame::SubExpr); let outputs = outputs .into_iter() diff --git a/compiler/rustc_mir_build/src/thir/mod.rs b/compiler/rustc_mir_build/src/thir/mod.rs index f934dd32c5381..6e7094307b17d 100644 --- a/compiler/rustc_mir_build/src/thir/mod.rs +++ b/compiler/rustc_mir_build/src/thir/mod.rs @@ -32,7 +32,7 @@ crate enum LintLevel { Explicit(hir::HirId), } -#[derive(Clone, Debug)] +#[derive(Debug)] crate struct Block<'tcx> { crate targeted_by_break: bool, crate region_scope: region::Scope, @@ -51,13 +51,13 @@ crate enum BlockSafety { PopUnsafe, } -#[derive(Clone, Debug)] +#[derive(Debug)] crate struct Stmt<'tcx> { crate kind: StmtKind<'tcx>, crate opt_destruction_scope: Option, } -#[derive(Clone, Debug)] +#[derive(Debug)] crate enum StmtKind<'tcx> { Expr { /// scope for this statement; may be used as lifetime of temporaries @@ -107,7 +107,7 @@ rustc_data_structures::static_assert_size!(Expr<'_>, 160); /// MIR simplifications are already done in the impl of `Thir`. For /// example, method calls and overloaded operators are absent: they are /// expected to be converted into `Expr::Call` instances. -#[derive(Clone, Debug)] +#[derive(Debug)] crate struct Expr<'tcx> { /// type of this expression crate ty: Ty<'tcx>, @@ -123,7 +123,7 @@ crate struct Expr<'tcx> { crate kind: ExprKind<'tcx>, } -#[derive(Clone, Debug)] +#[derive(Debug)] crate enum ExprKind<'tcx> { Scope { region_scope: region::Scope, @@ -312,19 +312,19 @@ crate enum ExprKind<'tcx> { }, } -#[derive(Clone, Debug)] +#[derive(Debug)] crate struct FieldExpr<'tcx> { crate name: Field, crate expr: Expr<'tcx>, } -#[derive(Clone, Debug)] +#[derive(Debug)] crate struct FruInfo<'tcx> { crate base: Box>, crate field_types: Vec>, } -#[derive(Clone, Debug)] +#[derive(Debug)] crate struct Arm<'tcx> { crate pattern: Pat<'tcx>, crate guard: Option>, @@ -334,7 +334,7 @@ crate struct Arm<'tcx> { crate span: Span, } -#[derive(Clone, Debug)] +#[derive(Debug)] crate enum Guard<'tcx> { If(Box>), IfLet(Pat<'tcx>, Box>), @@ -346,7 +346,7 @@ crate enum LogicalOp { Or, } -#[derive(Clone, Debug)] +#[derive(Debug)] crate enum InlineAsmOperand<'tcx> { In { reg: InlineAsmRegOrRegClass, From c2c432289195eaf65e42566ed0b95f82a913bcb3 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Fri, 5 Mar 2021 21:56:02 +0100 Subject: [PATCH 4/7] Make arena allocation for the THIR work --- compiler/rustc_mir_build/src/build/block.rs | 6 +- .../src/build/expr/as_constant.rs | 2 +- .../src/build/expr/as_operand.rs | 8 +- .../src/build/expr/as_place.rs | 14 +- .../src/build/expr/as_rvalue.rs | 6 +- .../rustc_mir_build/src/build/expr/as_temp.rs | 4 +- .../src/build/expr/category.rs | 2 +- .../rustc_mir_build/src/build/expr/into.rs | 2 +- .../rustc_mir_build/src/build/expr/stmt.rs | 2 +- .../rustc_mir_build/src/build/matches/mod.rs | 18 +- compiler/rustc_mir_build/src/build/mod.rs | 27 +- compiler/rustc_mir_build/src/build/scope.rs | 4 +- compiler/rustc_mir_build/src/thir/arena.rs | 98 ++++ compiler/rustc_mir_build/src/thir/cx/block.rs | 40 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 494 ++++++++++-------- compiler/rustc_mir_build/src/thir/cx/mod.rs | 27 +- compiler/rustc_mir_build/src/thir/mod.rs | 155 +++--- 17 files changed, 526 insertions(+), 383 deletions(-) create mode 100644 compiler/rustc_mir_build/src/thir/arena.rs diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index 7bb141058d22e..e93c796c97059 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -12,7 +12,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, destination: Place<'tcx>, block: BasicBlock, - ast_block: &Block<'tcx>, + ast_block: &Block<'_, 'tcx>, source_info: SourceInfo, ) -> BlockAnd<()> { let Block { @@ -56,8 +56,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination: Place<'tcx>, mut block: BasicBlock, span: Span, - stmts: &[Stmt<'tcx>], - expr: Option<&Expr<'tcx>>, + stmts: &[Stmt<'_, 'tcx>], + expr: Option<&Expr<'_, 'tcx>>, safety_mode: BlockSafety, ) -> BlockAnd<()> { let this = self; diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 1096d2eedfe21..ce341c0c06cdf 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -8,7 +8,7 @@ use rustc_middle::ty::CanonicalUserTypeAnnotation; impl<'a, 'tcx> Builder<'a, 'tcx> { /// Compile `expr`, yielding a compile-time constant. Assumes that /// `expr` is a valid compile-time constant! - crate fn as_constant(&mut self, expr: &Expr<'tcx>) -> Constant<'tcx> { + crate fn as_constant(&mut self, expr: &Expr<'_, 'tcx>) -> Constant<'tcx> { let this = self; let Expr { ty, temp_lifetime: _, span, kind } = expr; match kind { diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs index 81428e098699d..28262287b6339 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs @@ -17,7 +17,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn as_local_operand( &mut self, block: BasicBlock, - expr: &Expr<'tcx>, + expr: &Expr<'_, 'tcx>, ) -> BlockAnd> { let local_scope = self.local_scope(); self.as_operand(block, Some(local_scope), expr) @@ -74,7 +74,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn as_local_call_operand( &mut self, block: BasicBlock, - expr: &Expr<'tcx>, + expr: &Expr<'_, 'tcx>, ) -> BlockAnd> { let local_scope = self.local_scope(); self.as_call_operand(block, Some(local_scope), expr) @@ -93,7 +93,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, mut block: BasicBlock, scope: Option, - expr: &Expr<'tcx>, + expr: &Expr<'_, 'tcx>, ) -> BlockAnd> { debug!("as_operand(block={:?}, expr={:?})", block, expr); let this = self; @@ -123,7 +123,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, mut block: BasicBlock, scope: Option, - expr: &Expr<'tcx>, + expr: &Expr<'_, 'tcx>, ) -> BlockAnd> { debug!("as_call_operand(block={:?}, expr={:?})", block, expr); let this = self; diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 3581ca1ee5bd5..30262e164201b 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -350,7 +350,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn as_place( &mut self, mut block: BasicBlock, - expr: &Expr<'tcx>, + expr: &Expr<'_, 'tcx>, ) -> BlockAnd> { let place_builder = unpack!(block = self.as_place_builder(block, expr)); block.and(place_builder.into_place(self.tcx, self.typeck_results)) @@ -361,7 +361,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn as_place_builder( &mut self, block: BasicBlock, - expr: &Expr<'tcx>, + expr: &Expr<'_, 'tcx>, ) -> BlockAnd> { self.expr_as_place(block, expr, Mutability::Mut, None) } @@ -374,7 +374,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn as_read_only_place( &mut self, mut block: BasicBlock, - expr: &Expr<'tcx>, + expr: &Expr<'_, 'tcx>, ) -> BlockAnd> { let place_builder = unpack!(block = self.as_read_only_place_builder(block, expr)); block.and(place_builder.into_place(self.tcx, self.typeck_results)) @@ -389,7 +389,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn as_read_only_place_builder( &mut self, block: BasicBlock, - expr: &Expr<'tcx>, + expr: &Expr<'_, 'tcx>, ) -> BlockAnd> { self.expr_as_place(block, expr, Mutability::Not, None) } @@ -397,7 +397,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn expr_as_place( &mut self, mut block: BasicBlock, - expr: &Expr<'tcx>, + expr: &Expr<'_, 'tcx>, mutability: Mutability, fake_borrow_temps: Option<&mut Vec>, ) -> BlockAnd> { @@ -584,8 +584,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn lower_index_expression( &mut self, mut block: BasicBlock, - base: &Expr<'tcx>, - index: &Expr<'tcx>, + base: &Expr<'_, 'tcx>, + index: &Expr<'_, 'tcx>, mutability: Mutability, fake_borrow_temps: Option<&mut Vec>, temp_lifetime: Option, diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 89a179bd4510d..335ea4dca6006 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -22,7 +22,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn as_local_rvalue( &mut self, block: BasicBlock, - expr: &Expr<'tcx>, + expr: &Expr<'_, 'tcx>, ) -> BlockAnd> { let local_scope = self.local_scope(); self.as_rvalue(block, Some(local_scope), expr) @@ -33,7 +33,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, mut block: BasicBlock, scope: Option, - expr: &Expr<'tcx>, + expr: &Expr<'_, 'tcx>, ) -> BlockAnd> { debug!("expr_as_rvalue(block={:?}, scope={:?}, expr={:?})", block, scope, expr); @@ -368,7 +368,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { upvar_ty: Ty<'tcx>, temp_lifetime: Option, mut block: BasicBlock, - arg: &Expr<'tcx>, + arg: &Expr<'_, 'tcx>, ) -> BlockAnd> { let this = self; diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs index 8b032032bfc43..12029b04a08f3 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs @@ -14,7 +14,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, block: BasicBlock, temp_lifetime: Option, - expr: &Expr<'tcx>, + expr: &Expr<'_, 'tcx>, mutability: Mutability, ) -> BlockAnd { // 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 block: BasicBlock, temp_lifetime: Option, - expr: &Expr<'tcx>, + expr: &Expr<'_, 'tcx>, mutability: Mutability, ) -> BlockAnd { debug!( diff --git a/compiler/rustc_mir_build/src/build/expr/category.rs b/compiler/rustc_mir_build/src/build/expr/category.rs index 9320b5810e396..0cadfa2f0a1af 100644 --- a/compiler/rustc_mir_build/src/build/expr/category.rs +++ b/compiler/rustc_mir_build/src/build/expr/category.rs @@ -31,7 +31,7 @@ crate enum RvalueFunc { /// Determines the category for a given expression. Note that scope /// and paren expressions have no category. impl Category { - crate fn of(ek: &ExprKind<'_>) -> Option { + crate fn of(ek: &ExprKind<'_, '_>) -> Option { match *ek { ExprKind::Scope { .. } => None, diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 83a09a005084a..4baf26dce6ad5 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -18,7 +18,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, destination: Place<'tcx>, mut block: BasicBlock, - expr: &Expr<'tcx>, + expr: &Expr<'_, 'tcx>, ) -> BlockAnd<()> { debug!("expr_into_dest(destination={:?}, block={:?}, expr={:?})", destination, block, expr); diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs index 470a3eaaa3c87..23e23f0885b77 100644 --- a/compiler/rustc_mir_build/src/build/expr/stmt.rs +++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs @@ -13,7 +13,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn stmt_expr( &mut self, mut block: BasicBlock, - expr: &Expr<'tcx>, + expr: &Expr<'_, 'tcx>, statement_scope: Option, ) -> BlockAnd<()> { let this = self; diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index d93fc6149c213..098ed8b3eb8ce 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -89,8 +89,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination: Place<'tcx>, span: Span, mut block: BasicBlock, - scrutinee: &Expr<'tcx>, - arms: &[Arm<'tcx>], + scrutinee: &Expr<'_, 'tcx>, + arms: &[Arm<'_, 'tcx>], ) -> BlockAnd<()> { let scrutinee_span = scrutinee.span; let scrutinee_place = @@ -119,7 +119,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn lower_scrutinee( &mut self, mut block: BasicBlock, - scrutinee: &Expr<'tcx>, + scrutinee: &Expr<'_, 'tcx>, scrutinee_span: Span, ) -> BlockAnd> { let scrutinee_place = unpack!(block = self.as_place(block, scrutinee)); @@ -149,8 +149,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn create_match_candidates<'pat>( &mut self, scrutinee: Place<'tcx>, - arms: &'pat [Arm<'tcx>], - ) -> Vec<(&'pat Arm<'tcx>, Candidate<'pat, 'tcx>)> { + arms: &'pat [Arm<'pat, 'tcx>], + ) -> Vec<(&'pat Arm<'pat, 'tcx>, Candidate<'pat, 'tcx>)> { // Assemble a list of candidates: there is one candidate per pattern, // which means there may be more than one candidate *per arm*. arms.iter() @@ -224,7 +224,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { destination: Place<'tcx>, scrutinee_place: Place<'tcx>, scrutinee_span: Span, - arm_candidates: Vec<(&'_ Arm<'tcx>, Candidate<'_, 'tcx>)>, + arm_candidates: Vec<(&'_ Arm<'_, 'tcx>, Candidate<'_, 'tcx>)>, outer_source_info: SourceInfo, fake_borrow_temps: Vec<(Place<'tcx>, Local)>, ) -> BlockAnd<()> { @@ -285,7 +285,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, outer_source_info: SourceInfo, candidate: Candidate<'_, 'tcx>, - guard: Option<&Guard<'tcx>>, + guard: Option<&Guard<'_, 'tcx>>, fake_borrow_temps: &Vec<(Place<'tcx>, Local)>, scrutinee_span: Span, arm_span: Option, @@ -361,7 +361,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, mut block: BasicBlock, irrefutable_pat: Pat<'tcx>, - initializer: &Expr<'tcx>, + initializer: &Expr<'_, 'tcx>, ) -> BlockAnd<()> { match *irrefutable_pat.kind { // Optimize the case of `let x = ...` to write directly into `x` @@ -1612,7 +1612,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { &mut self, candidate: Candidate<'pat, 'tcx>, parent_bindings: &[(Vec>, Vec>)], - guard: Option<&Guard<'tcx>>, + guard: Option<&Guard<'_, 'tcx>>, fake_borrows: &Vec<(Place<'tcx>, Local)>, scrutinee_span: Span, arm_span: Option, diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index ecc5f2f260e7d..ef531a2392183 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -1,7 +1,7 @@ use crate::build; use crate::build::scope::DropKind; -use crate::thir::cx::Cx; -use crate::thir::{BindingMode, Expr, LintLevel, Pat, PatKind}; +use crate::thir::cx::build_thir; +use crate::thir::{Arena, BindingMode, Expr, LintLevel, Pat, PatKind}; use rustc_attr::{self as attr, UnwindAttr}; use rustc_errors::ErrorReported; use rustc_hir as hir; @@ -43,6 +43,7 @@ crate fn mir_built<'tcx>( fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_> { let id = tcx.hir().local_def_id_to_hir_id(def.did); let body_owner_kind = tcx.hir().body_owner_kind(id); + let typeck_results = tcx.typeck_opt_const_arg(def); // Figure out what primary body this item has. let (body_id, return_ty_span, span_with_body) = match tcx.hir().get(id) { @@ -87,15 +88,15 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ // If we don't have a specialized span for the body, just use the // normal def span. let span_with_body = span_with_body.unwrap_or_else(|| tcx.hir().span(id)); + let arena = Arena::default(); tcx.infer_ctxt().enter(|infcx| { - let mut cx = Cx::new(tcx, def); - let body = if let Some(ErrorReported) = cx.typeck_results.tainted_by_errors { + let body = if let Some(ErrorReported) = typeck_results.tainted_by_errors { build::construct_error(&infcx, def, id, body_id, body_owner_kind) } else if body_owner_kind.is_fn_or_closure() { // fetch the fully liberated fn signature (that is, all bound // types/lifetimes replaced) - let fn_sig = cx.typeck_results.liberated_fn_sigs()[id]; + let fn_sig = typeck_results.liberated_fn_sigs()[id]; let fn_def_id = tcx.hir().local_def_id(id); let safety = match fn_sig.unsafety { @@ -104,7 +105,7 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ }; let body = tcx.hir().body(body_id); - let expr = cx.mirror_expr(&body.value); + let thir = build_thir(tcx, def, &arena, &body.value); let ty = tcx.type_of(fn_def_id); let mut abi = fn_sig.abi; let implicit_argument = match ty.kind() { @@ -189,7 +190,7 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ return_ty, return_ty_span, body, - expr, + thir, span_with_body, ); if yield_ty.is_some() { @@ -209,12 +210,12 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> Body<'_ // place to be the type of the constant because NLL typeck will // equate them. - let return_ty = cx.typeck_results.node_type(id); + let return_ty = typeck_results.node_type(id); let ast_expr = &tcx.hir().body(body_id).value; - let expr = cx.mirror_expr(ast_expr); + let thir = build_thir(tcx, def, &arena, ast_expr); - build::construct_const(&infcx, expr, def, id, return_ty, return_ty_span) + build::construct_const(&infcx, thir, def, id, return_ty, return_ty_span) }; lints::check(tcx, &body); @@ -601,7 +602,7 @@ fn construct_fn<'tcx, A>( return_ty: Ty<'tcx>, return_ty_span: Span, body: &'tcx hir::Body<'tcx>, - expr: Expr<'tcx>, + expr: &Expr<'_, 'tcx>, span_with_body: Span, ) -> Body<'tcx> where @@ -668,7 +669,7 @@ where fn construct_const<'a, 'tcx>( infcx: &'a InferCtxt<'a, 'tcx>, - expr: Expr<'tcx>, + expr: &Expr<'_, 'tcx>, def: ty::WithOptConstParam, hir_id: hir::HirId, const_ty: Ty<'tcx>, @@ -825,7 +826,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { fn_def_id: DefId, arguments: &[ArgInfo<'tcx>], argument_scope: region::Scope, - expr: &Expr<'tcx>, + expr: &Expr<'_, 'tcx>, ) -> BlockAnd<()> { // Allocate locals for the function arguments for &ArgInfo(ty, _, arg_opt, _) in arguments.iter() { diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 6c58528a3c5c6..b637b9b70bdc6 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -574,7 +574,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn break_scope( &mut self, mut block: BasicBlock, - value: Option<&Expr<'tcx>>, + value: Option<&Expr<'_, 'tcx>>, target: BreakableTarget, source_info: SourceInfo, ) -> BlockAnd<()> { @@ -918,7 +918,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { crate fn test_bool( &mut self, mut block: BasicBlock, - condition: &Expr<'tcx>, + condition: &Expr<'_, 'tcx>, source_info: SourceInfo, ) -> (BasicBlock, BasicBlock) { let cond = unpack!(block = self.as_local_operand(block, condition)); diff --git a/compiler/rustc_mir_build/src/thir/arena.rs b/compiler/rustc_mir_build/src/thir/arena.rs new file mode 100644 index 0000000000000..aacc7b12a42f9 --- /dev/null +++ b/compiler/rustc_mir_build/src/thir/arena.rs @@ -0,0 +1,98 @@ +use crate::thir::*; + +macro_rules! declare_arena { + ([], [$($a:tt $name:ident: $ty:ty,)*]) => { + #[derive(Default)] + pub struct Arena<'thir, 'tcx> { + pub dropless: rustc_arena::DroplessArena, + drop: rustc_arena::DropArena, + $($name: rustc_arena::arena_for_type!($a[$ty]),)* + } + + pub trait ArenaAllocatable<'thir, 'tcx, T = Self>: Sized { + fn allocate_on(self, arena: &'thir Arena<'thir, 'tcx>) -> &'thir mut Self; + fn allocate_from_iter( + arena: &'thir Arena<'thir, 'tcx>, + iter: impl ::std::iter::IntoIterator, + ) -> &'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, + ) -> &'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::() { + return arena.dropless.alloc(self); + } + match rustc_arena::which_arena_for_type!($a[&arena.$name]) { + ::std::option::Option::<&rustc_arena::TypedArena>::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, + ) -> &'thir mut [Self] { + if !::std::mem::needs_drop::() { + return arena.dropless.alloc_from_iter(iter); + } + match rustc_arena::which_arena_for_type!($a[&arena.$name]) { + ::std::option::Option::<&rustc_arena::TypedArena>::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, U>(&'thir self, value: T) -> &'thir mut T { + value.allocate_on(self) + } + + #[allow(dead_code)] // function is never used + #[inline] + pub fn alloc_slice(&'thir self, value: &[T]) -> &'thir mut [T] { + if value.is_empty() { + return &mut []; + } + self.dropless.alloc_slice(value) + } + + pub fn alloc_from_iter, U>( + &'thir self, + iter: impl ::std::iter::IntoIterator, + ) -> &'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>, +]); diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index 25af65d1c6538..2ec102282c28e 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -7,8 +7,8 @@ use rustc_middle::ty; use rustc_index::vec::Idx; -impl<'tcx> Cx<'tcx> { - crate fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> Block<'tcx> { +impl<'thir, 'tcx> Cx<'thir, 'tcx> { + crate fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> Block<'thir, 'tcx> { // We have to eagerly lower the "spine" of the statements // in order to get the lexical scoping correctly. let stmts = self.mirror_stmts(block.hir_id.local_id, &*block.stmts); @@ -23,7 +23,7 @@ impl<'tcx> Cx<'tcx> { opt_destruction_scope, span: block.span, stmts, - expr: block.expr.as_ref().map(|expr| self.mirror_expr_boxed(expr)), + expr: block.expr.as_ref().map(|expr| self.mirror_expr(expr)), safety_mode: match block.rules { hir::BlockCheckMode::DefaultBlock => BlockSafety::Safe, hir::BlockCheckMode::UnsafeBlock(..) => BlockSafety::ExplicitUnsafe(block.hir_id), @@ -37,26 +37,21 @@ impl<'tcx> Cx<'tcx> { &mut self, block_id: hir::ItemLocalId, stmts: &'tcx [hir::Stmt<'tcx>], - ) -> Vec> { - let mut result = vec![]; - for (index, stmt) in stmts.iter().enumerate() { + ) -> &'thir [Stmt<'thir, 'tcx>] { + self.arena.alloc_from_iter(stmts.iter().enumerate().filter_map(|(index, stmt)| { let hir_id = stmt.hir_id; let opt_dxn_ext = self.region_scope_tree.opt_destruction_scope(hir_id.local_id); match stmt.kind { - hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => { - result.push(Stmt { - kind: StmtKind::Expr { - scope: region::Scope { - id: hir_id.local_id, - data: region::ScopeData::Node, - }, - expr: self.mirror_expr_boxed(expr), - }, - opt_destruction_scope: opt_dxn_ext, - }) - } + hir::StmtKind::Expr(ref expr) | hir::StmtKind::Semi(ref expr) => Some(Stmt { + kind: StmtKind::Expr { + scope: region::Scope { id: hir_id.local_id, data: region::ScopeData::Node }, + expr: self.mirror_expr(expr), + }, + 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 { @@ -86,7 +81,7 @@ impl<'tcx> Cx<'tcx> { } } - result.push(Stmt { + Some(Stmt { kind: StmtKind::Let { remainder_scope, init_scope: region::Scope { @@ -94,14 +89,13 @@ impl<'tcx> Cx<'tcx> { data: region::ScopeData::Node, }, pattern, - initializer: local.init.map(|init| self.mirror_expr_boxed(init)), + initializer: local.init.map(|init| self.mirror_expr(init)), lint_level: LintLevel::Explicit(local.hir_id), }, opt_destruction_scope: opt_dxn_ext, - }); + }) } } - } - result + })) } } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 2d1170ca3a89d..73ec9ac4dcf86 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -15,8 +15,33 @@ use rustc_middle::ty::subst::{InternalSubsts, SubstsRef}; use rustc_middle::ty::{self, AdtKind, Ty}; use rustc_span::Span; -impl<'tcx> Cx<'tcx> { - crate fn mirror_expr(&mut self, hir_expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> { +use std::iter; + +impl<'thir, 'tcx> Cx<'thir, 'tcx> { + /// Mirrors and allocates a single [`hir::Expr`]. If you need to mirror a whole slice + /// of expressions, prefer using [`mirror_exprs`]. + /// + /// [`mirror_exprs`]: Self::mirror_exprs + crate fn mirror_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> &'thir Expr<'thir, 'tcx> { + self.arena.alloc(self.mirror_expr_inner(expr)) + } + + /// Mirrors and allocates a slice of [`hir::Expr`]s. They will be allocated as a + /// contiguous sequence in memory. + crate fn mirror_exprs(&mut self, exprs: &'tcx [hir::Expr<'tcx>]) -> &'thir [Expr<'thir, 'tcx>] { + self.arena.alloc_from_iter(exprs.iter().map(|expr| self.mirror_expr_inner(expr))) + } + + /// Mirrors a [`hir::Expr`] without allocating it into the arena. + /// This is a separate, private function so that [`mirror_expr`] and [`mirror_exprs`] can + /// decide how to allocate this expression (alone or within a slice). + /// + /// [`mirror_expr`]: Self::mirror_expr + /// [`mirror_exprs`]: Self::mirror_exprs + pub(super) fn mirror_expr_inner( + &mut self, + hir_expr: &'tcx hir::Expr<'tcx>, + ) -> Expr<'thir, 'tcx> { let temp_lifetime = self.region_scope_tree.temporary_scope(hir_expr.hir_id.local_id); let expr_scope = region::Scope { id: hir_expr.hir_id.local_id, data: region::ScopeData::Node }; @@ -38,7 +63,7 @@ impl<'tcx> Cx<'tcx> { span: hir_expr.span, kind: ExprKind::Scope { region_scope: expr_scope, - value: Box::new(expr), + value: self.arena.alloc(expr), lint_level: LintLevel::Explicit(hir_expr.hir_id), }, }; @@ -53,7 +78,7 @@ impl<'tcx> Cx<'tcx> { span: hir_expr.span, kind: ExprKind::Scope { region_scope, - value: Box::new(expr), + value: self.arena.alloc(expr), lint_level: LintLevel::Inherited, }, }; @@ -63,20 +88,12 @@ impl<'tcx> Cx<'tcx> { expr } - crate fn mirror_exprs(&mut self, exprs: &'tcx [hir::Expr<'tcx>]) -> Vec> { - exprs.iter().map(|expr| self.mirror_expr(expr)).collect() - } - - crate fn mirror_expr_boxed(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Box> { - Box::new(self.mirror_expr(expr)) - } - fn apply_adjustment( &mut self, hir_expr: &'tcx hir::Expr<'tcx>, - mut expr: Expr<'tcx>, + mut expr: Expr<'thir, 'tcx>, adjustment: &Adjustment<'tcx>, - ) -> Expr<'tcx> { + ) -> Expr<'thir, 'tcx> { let Expr { temp_lifetime, mut span, .. } = expr; // Adjust the span from the block, to the last expression of the @@ -89,7 +106,7 @@ impl<'tcx> Cx<'tcx> { // x // // ^ error message points at this expression. // } - let mut adjust_span = |expr: &mut Expr<'tcx>| { + let mut adjust_span = |expr: &mut Expr<'thir, 'tcx>| { if let ExprKind::Block { body } = &expr.kind { if let Some(ref last_expr) = body.expr { span = last_expr.span; @@ -101,13 +118,13 @@ impl<'tcx> Cx<'tcx> { let kind = match adjustment.kind { Adjust::Pointer(PointerCast::Unsize) => { adjust_span(&mut expr); - ExprKind::Pointer { cast: PointerCast::Unsize, source: Box::new(expr) } + ExprKind::Pointer { cast: PointerCast::Unsize, source: self.arena.alloc(expr) } } - Adjust::Pointer(cast) => ExprKind::Pointer { cast, source: Box::new(expr) }, - Adjust::NeverToAny => ExprKind::NeverToAny { source: Box::new(expr) }, + Adjust::Pointer(cast) => ExprKind::Pointer { cast, source: self.arena.alloc(expr) }, + Adjust::NeverToAny => ExprKind::NeverToAny { source: self.arena.alloc(expr) }, Adjust::Deref(None) => { adjust_span(&mut expr); - ExprKind::Deref { arg: Box::new(expr) } + ExprKind::Deref { arg: self.arena.alloc(expr) } } Adjust::Deref(Some(deref)) => { // We don't need to do call adjust_span here since @@ -122,7 +139,7 @@ impl<'tcx> Cx<'tcx> { span, kind: ExprKind::Borrow { borrow_kind: deref.mutbl.to_borrow_kind(), - arg: Box::new(expr), + arg: self.arena.alloc(expr), }, }; @@ -130,22 +147,22 @@ impl<'tcx> Cx<'tcx> { hir_expr, adjustment.target, Some(call), - vec![expr], + self.arena.alloc_from_iter(iter::once(expr)), deref.span, ) } Adjust::Borrow(AutoBorrow::Ref(_, m)) => { - ExprKind::Borrow { borrow_kind: m.to_borrow_kind(), arg: Box::new(expr) } + ExprKind::Borrow { borrow_kind: m.to_borrow_kind(), arg: self.arena.alloc(expr) } } Adjust::Borrow(AutoBorrow::RawPtr(mutability)) => { - ExprKind::AddressOf { mutability, arg: Box::new(expr) } + ExprKind::AddressOf { mutability, arg: self.arena.alloc(expr) } } }; Expr { temp_lifetime, ty: adjustment.target, span, kind } } - fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> { + fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'thir, 'tcx> { let expr_ty = self.typeck_results().expr_ty(expr); let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); @@ -157,7 +174,7 @@ impl<'tcx> Cx<'tcx> { let args = self.mirror_exprs(args); ExprKind::Call { ty: expr.ty, - fun: Box::new(expr), + fun: self.arena.alloc(expr), args, from_hir_call: true, fn_span, @@ -185,8 +202,10 @@ impl<'tcx> Cx<'tcx> { ExprKind::Call { ty: method.ty, - fun: Box::new(method), - args: vec![self.mirror_expr(fun), tupled_args], + fun: self.arena.alloc(method), + args: &*self + .arena + .alloc_from_iter(vec![self.mirror_expr_inner(fun), tupled_args]), from_hir_call: true, fn_span: expr.span, } @@ -216,26 +235,22 @@ impl<'tcx> Cx<'tcx> { }); debug!("make_mirror_unadjusted: (call) user_ty={:?}", user_ty); - let field_refs = args - .iter() - .enumerate() - .map(|(idx, e)| FieldExpr { - name: Field::new(idx), - expr: self.mirror_expr(e), - }) - .collect(); + let field_refs = + self.arena.alloc_from_iter(args.iter().enumerate().map(|(idx, e)| { + FieldExpr { name: Field::new(idx), expr: self.mirror_expr(e) } + })); ExprKind::Adt { adt_def, substs, variant_index: index, - fields: field_refs, + fields: &*field_refs, user_ty, base: None, } } else { ExprKind::Call { ty: self.typeck_results().node_type(fun.hir_id), - fun: self.mirror_expr_boxed(fun), + fun: self.mirror_expr(fun), args: self.mirror_exprs(args), from_hir_call: true, fn_span: expr.span, @@ -244,32 +259,30 @@ impl<'tcx> Cx<'tcx> { } } - hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, ref arg) => ExprKind::Borrow { - borrow_kind: mutbl.to_borrow_kind(), - arg: self.mirror_expr_boxed(arg), - }, + hir::ExprKind::AddrOf(hir::BorrowKind::Ref, mutbl, ref arg) => { + ExprKind::Borrow { borrow_kind: mutbl.to_borrow_kind(), arg: self.mirror_expr(arg) } + } hir::ExprKind::AddrOf(hir::BorrowKind::Raw, mutability, ref arg) => { - ExprKind::AddressOf { mutability, arg: self.mirror_expr_boxed(arg) } + ExprKind::AddressOf { mutability, arg: self.mirror_expr(arg) } } hir::ExprKind::Block(ref blk, _) => ExprKind::Block { body: self.mirror_block(blk) }, - hir::ExprKind::Assign(ref lhs, ref rhs, _) => ExprKind::Assign { - lhs: self.mirror_expr_boxed(lhs), - rhs: self.mirror_expr_boxed(rhs), - }, + hir::ExprKind::Assign(ref lhs, ref rhs, _) => { + ExprKind::Assign { lhs: self.mirror_expr(lhs), rhs: self.mirror_expr(rhs) } + } hir::ExprKind::AssignOp(op, ref lhs, ref rhs) => { if self.typeck_results().is_method_call(expr) { - let lhs = self.mirror_expr(lhs); - let rhs = self.mirror_expr(rhs); - self.overloaded_operator(expr, vec![lhs, rhs]) + let lhs = self.mirror_expr_inner(lhs); + let rhs = self.mirror_expr_inner(rhs); + self.overloaded_operator(expr, &*self.arena.alloc_from_iter(vec![lhs, rhs])) } else { ExprKind::AssignOp { op: bin_op(op.node), - lhs: self.mirror_expr_boxed(lhs), - rhs: self.mirror_expr_boxed(rhs), + lhs: self.mirror_expr(lhs), + rhs: self.mirror_expr(rhs), } } } @@ -282,29 +295,29 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::Binary(op, ref lhs, ref rhs) => { if self.typeck_results().is_method_call(expr) { - let lhs = self.mirror_expr(lhs); - let rhs = self.mirror_expr(rhs); - self.overloaded_operator(expr, vec![lhs, rhs]) + let lhs = self.mirror_expr_inner(lhs); + let rhs = self.mirror_expr_inner(rhs); + self.overloaded_operator(expr, &*self.arena.alloc_from_iter(vec![lhs, rhs])) } else { // FIXME overflow match op.node { hir::BinOpKind::And => ExprKind::LogicalOp { op: LogicalOp::And, - lhs: self.mirror_expr_boxed(lhs), - rhs: self.mirror_expr_boxed(rhs), + lhs: self.mirror_expr(lhs), + rhs: self.mirror_expr(rhs), }, hir::BinOpKind::Or => ExprKind::LogicalOp { op: LogicalOp::Or, - lhs: self.mirror_expr_boxed(lhs), - rhs: self.mirror_expr_boxed(rhs), + lhs: self.mirror_expr(lhs), + rhs: self.mirror_expr(rhs), }, _ => { let op = bin_op(op.node); ExprKind::Binary { op, - lhs: self.mirror_expr_boxed(lhs), - rhs: self.mirror_expr_boxed(rhs), + lhs: self.mirror_expr(lhs), + rhs: self.mirror_expr(rhs), } } } @@ -313,39 +326,48 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::Index(ref lhs, ref index) => { if self.typeck_results().is_method_call(expr) { - let lhs = self.mirror_expr(lhs); - let index = self.mirror_expr(index); - self.overloaded_place(expr, expr_ty, None, vec![lhs, index], expr.span) + let lhs = self.mirror_expr_inner(lhs); + let index = self.mirror_expr_inner(index); + self.overloaded_place( + expr, + expr_ty, + None, + &*self.arena.alloc_from_iter(vec![lhs, index]), + expr.span, + ) } else { - ExprKind::Index { - lhs: self.mirror_expr_boxed(lhs), - index: self.mirror_expr_boxed(index), - } + ExprKind::Index { lhs: self.mirror_expr(lhs), index: self.mirror_expr(index) } } } hir::ExprKind::Unary(hir::UnOp::Deref, ref arg) => { if self.typeck_results().is_method_call(expr) { - let arg = self.mirror_expr(arg); - self.overloaded_place(expr, expr_ty, None, vec![arg], expr.span) + let arg = self.mirror_expr_inner(arg); + self.overloaded_place( + expr, + expr_ty, + None, + &*self.arena.alloc_from_iter(iter::once(arg)), + expr.span, + ) } else { - ExprKind::Deref { arg: self.mirror_expr_boxed(arg) } + ExprKind::Deref { arg: self.mirror_expr(arg) } } } hir::ExprKind::Unary(hir::UnOp::Not, ref arg) => { if self.typeck_results().is_method_call(expr) { - let arg = self.mirror_expr(arg); - self.overloaded_operator(expr, vec![arg]) + let arg = self.mirror_expr_inner(arg); + self.overloaded_operator(expr, &*self.arena.alloc_from_iter(iter::once(arg))) } else { - ExprKind::Unary { op: UnOp::Not, arg: self.mirror_expr_boxed(arg) } + ExprKind::Unary { op: UnOp::Not, arg: self.mirror_expr(arg) } } } hir::ExprKind::Unary(hir::UnOp::Neg, ref arg) => { if self.typeck_results().is_method_call(expr) { - let arg = self.mirror_expr(arg); - self.overloaded_operator(expr, vec![arg]) + let arg = self.mirror_expr_inner(arg); + self.overloaded_operator(expr, &*self.arena.alloc_from_iter(iter::once(arg))) } else if let hir::ExprKind::Lit(ref lit) = arg.kind { ExprKind::Literal { literal: self.const_eval_literal(&lit.node, expr_ty, lit.span, true), @@ -353,7 +375,7 @@ impl<'tcx> Cx<'tcx> { const_id: None, } } else { - ExprKind::Unary { op: UnOp::Neg, arg: self.mirror_expr_boxed(arg) } + ExprKind::Unary { op: UnOp::Neg, arg: self.mirror_expr(arg) } } } @@ -370,9 +392,12 @@ impl<'tcx> Cx<'tcx> { user_ty, fields: self.field_refs(fields), base: base.as_ref().map(|base| FruInfo { - base: self.mirror_expr_boxed(base), - field_types: self.typeck_results().fru_field_types()[expr.hir_id] - .clone(), + base: self.mirror_expr(base), + field_types: self.arena.alloc_from_iter( + self.typeck_results().fru_field_types()[expr.hir_id] + .iter() + .cloned(), + ), }), } } @@ -419,12 +444,12 @@ impl<'tcx> Cx<'tcx> { } }; - let upvars = self - .typeck_results - .closure_min_captures_flattened(def_id) - .zip(substs.upvar_tys()) - .map(|(captured_place, ty)| self.capture_upvar(expr, captured_place, ty)) - .collect(); + let upvars = self.arena.alloc_from_iter( + self.typeck_results + .closure_min_captures_flattened(def_id) + .zip(substs.upvar_tys()) + .map(|(captured_place, ty)| self.capture_upvar(expr, captured_place, ty)), + ); ExprKind::Closure { closure_id: def_id, substs, upvars, movability } } @@ -435,100 +460,95 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::InlineAsm(ref asm) => ExprKind::InlineAsm { template: asm.template, - operands: asm - .operands - .iter() - .map(|(op, _op_sp)| { - match *op { - hir::InlineAsmOperand::In { reg, ref expr } => { - 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, - late, - ref in_expr, - ref out_expr, - } => InlineAsmOperand::SplitInOut { + operands: self.arena.alloc_from_iter(asm.operands.iter().map(|(op, _op_sp)| { + match *op { + hir::InlineAsmOperand::In { reg, ref expr } => { + InlineAsmOperand::In { reg, expr: self.mirror_expr(expr) } + } + hir::InlineAsmOperand::Out { reg, late, ref expr } => { + InlineAsmOperand::Out { reg, late, - in_expr: self.mirror_expr(in_expr), - out_expr: out_expr.as_ref().map(|expr| self.mirror_expr(expr)), - }, - hir::InlineAsmOperand::Const { ref expr } => { - InlineAsmOperand::Const { expr: self.mirror_expr(expr) } + expr: expr.as_ref().map(|expr| self.mirror_expr(expr)), } - hir::InlineAsmOperand::Sym { ref expr } => { - let qpath = match expr.kind { - hir::ExprKind::Path(ref qpath) => qpath, - _ => span_bug!( - expr.span, - "asm `sym` operand should be a path, found {:?}", - expr.kind - ), - }; - let temp_lifetime = - self.region_scope_tree.temporary_scope(expr.hir_id.local_id); - let res = self.typeck_results().qpath_res(qpath, expr.hir_id); - let ty; - match res { - Res::Def(DefKind::Fn, _) | Res::Def(DefKind::AssocFn, _) => { - ty = self.typeck_results().node_type(expr.hir_id); - let user_ty = - self.user_substs_applied_to_res(expr.hir_id, res); - InlineAsmOperand::SymFn { - expr: Expr { - ty, - temp_lifetime, - span: expr.span, - kind: ExprKind::Literal { - literal: ty::Const::zero_sized(self.tcx, ty), - user_ty, - const_id: None, - }, + } + hir::InlineAsmOperand::InOut { reg, late, ref expr } => { + InlineAsmOperand::InOut { reg, late, expr: self.mirror_expr(expr) } + } + hir::InlineAsmOperand::SplitInOut { + reg, + late, + ref in_expr, + ref out_expr, + } => InlineAsmOperand::SplitInOut { + reg, + late, + in_expr: self.mirror_expr(in_expr), + out_expr: out_expr.as_ref().map(|expr| self.mirror_expr(expr)), + }, + hir::InlineAsmOperand::Const { ref expr } => { + InlineAsmOperand::Const { expr: self.mirror_expr(expr) } + } + hir::InlineAsmOperand::Sym { ref expr } => { + let qpath = match expr.kind { + hir::ExprKind::Path(ref qpath) => qpath, + _ => span_bug!( + expr.span, + "asm `sym` operand should be a path, found {:?}", + expr.kind + ), + }; + let temp_lifetime = + self.region_scope_tree.temporary_scope(expr.hir_id.local_id); + let res = self.typeck_results().qpath_res(qpath, expr.hir_id); + let ty; + match res { + Res::Def(DefKind::Fn, _) | Res::Def(DefKind::AssocFn, _) => { + ty = self.typeck_results().node_type(expr.hir_id); + let user_ty = self.user_substs_applied_to_res(expr.hir_id, res); + InlineAsmOperand::SymFn { + expr: self.arena.alloc(Expr { + ty, + temp_lifetime, + span: expr.span, + kind: ExprKind::Literal { + literal: ty::Const::zero_sized(self.tcx, ty), + user_ty, + const_id: None, }, - } + }), } + } - Res::Def(DefKind::Static, def_id) => { - InlineAsmOperand::SymStatic { def_id } - } + Res::Def(DefKind::Static, def_id) => { + InlineAsmOperand::SymStatic { def_id } + } - _ => { - self.tcx.sess.span_err( - expr.span, - "asm `sym` operand must point to a fn or static", - ); - - // Not a real fn, but we're not reaching codegen anyways... - ty = self.tcx.ty_error(); - InlineAsmOperand::SymFn { - expr: Expr { - ty, - temp_lifetime, - span: expr.span, - kind: ExprKind::Literal { - literal: ty::Const::zero_sized(self.tcx, ty), - user_ty: None, - const_id: None, - }, + _ => { + self.tcx.sess.span_err( + expr.span, + "asm `sym` operand must point to a fn or static", + ); + + // Not a real fn, but we're not reaching codegen anyways... + ty = self.tcx.ty_error(); + InlineAsmOperand::SymFn { + expr: self.arena.alloc(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, line_spans: asm.line_spans, }, @@ -550,15 +570,15 @@ impl<'tcx> Cx<'tcx> { let count_def_id = self.tcx.hir().local_def_id(count.hir_id); let count = ty::Const::from_anon_const(self.tcx, count_def_id); - ExprKind::Repeat { value: self.mirror_expr_boxed(v), count } + ExprKind::Repeat { value: self.mirror_expr(v), count } } hir::ExprKind::Ret(ref v) => { - ExprKind::Return { value: v.as_ref().map(|v| self.mirror_expr_boxed(v)) } + ExprKind::Return { value: v.as_ref().map(|v| self.mirror_expr(v)) } } hir::ExprKind::Break(dest, ref value) => match dest.target_id { Ok(target_id) => ExprKind::Break { label: region::Scope { id: target_id.local_id, data: region::ScopeData::Node }, - value: value.as_ref().map(|value| self.mirror_expr_boxed(value)), + value: value.as_ref().map(|value| self.mirror_expr(value)), }, Err(err) => bug!("invalid loop id for break: {}", err), }, @@ -569,19 +589,19 @@ impl<'tcx> Cx<'tcx> { Err(err) => bug!("invalid loop id for continue: {}", err), }, hir::ExprKind::If(cond, then, else_opt) => ExprKind::If { - cond: self.mirror_expr_boxed(cond), - then: self.mirror_expr_boxed(then), - else_opt: else_opt.map(|el| self.mirror_expr_boxed(el)), + cond: self.mirror_expr(cond), + then: self.mirror_expr(then), + else_opt: else_opt.map(|el| self.mirror_expr(el)), }, hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match { - scrutinee: self.mirror_expr_boxed(discr), - arms: arms.iter().map(|a| self.convert_arm(a)).collect(), + scrutinee: self.mirror_expr(discr), + arms: self.arena.alloc_from_iter(arms.iter().map(|a| self.convert_arm(a))), }, hir::ExprKind::Loop(ref body, ..) => { 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 block = self.mirror_block(body); - let body = Box::new(Expr { + let body = self.arena.alloc(Expr { ty: block_ty, temp_lifetime, span: block.span, @@ -590,7 +610,7 @@ impl<'tcx> Cx<'tcx> { ExprKind::Loop { body } } hir::ExprKind::Field(ref source, ..) => ExprKind::Field { - lhs: self.mirror_expr_boxed(source), + lhs: self.mirror_expr(source), name: Field::new(self.tcx.field_index(expr.hir_id, self.typeck_results)), }, hir::ExprKind::Cast(ref source, ref cast_ty) => { @@ -607,13 +627,13 @@ impl<'tcx> Cx<'tcx> { // using a coercion (or is a no-op). let cast = if self.typeck_results().is_coercion_cast(source.hir_id) { // Convert the lexpr to a vexpr. - ExprKind::Use { source: self.mirror_expr_boxed(source) } + ExprKind::Use { source: self.mirror_expr(source) } } else if self.typeck_results().expr_ty(source).is_region_ptr() { // Special cased so that we can type check that the element // type of the source matches the pointed to type of the // destination. ExprKind::Pointer { - source: self.mirror_expr_boxed(source), + source: self.mirror_expr(source), cast: PointerCast::ArrayToPointer, } } else { @@ -651,11 +671,13 @@ impl<'tcx> Cx<'tcx> { }; let source = if let Some((did, offset, var_ty)) = var { - let mk_const = |literal| Expr { - temp_lifetime, - ty: var_ty, - span: expr.span, - kind: ExprKind::Literal { literal, user_ty: None, const_id: None }, + let mk_const = |literal| { + self.arena.alloc(Expr { + temp_lifetime, + ty: var_ty, + span: expr.span, + kind: ExprKind::Literal { literal, user_ty: None, const_id: None }, + }) }; let offset = mk_const(ty::Const::from_bits( self.tcx, @@ -675,12 +697,14 @@ impl<'tcx> Cx<'tcx> { ), ty: var_ty, })); - let bin = ExprKind::Binary { - op: BinOp::Add, - lhs: Box::new(lhs), - rhs: Box::new(offset), - }; - Expr { temp_lifetime, ty: var_ty, span: expr.span, kind: bin } + let bin = + ExprKind::Binary { op: BinOp::Add, lhs: lhs, rhs: offset }; + self.arena.alloc(Expr { + temp_lifetime, + ty: var_ty, + span: expr.span, + kind: bin, + }) } None => offset, } @@ -688,14 +712,18 @@ impl<'tcx> Cx<'tcx> { self.mirror_expr(source) }; - ExprKind::Cast { source: Box::new(source) } + ExprKind::Cast { source: source } }; if let Some(user_ty) = user_ty { // NOTE: Creating a new Expr and wrapping a Cast inside of it may be // inefficient, revisit this when performance becomes an issue. - let cast_expr = - Box::new(Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind: cast }); + let cast_expr = self.arena.alloc(Expr { + temp_lifetime, + ty: expr_ty, + span: expr.span, + kind: cast, + }); debug!("make_mirror_unadjusted: (cast) user_ty={:?}", user_ty); ExprKind::ValueTypeAscription { source: cast_expr, user_ty: Some(*user_ty) } @@ -707,7 +735,7 @@ impl<'tcx> Cx<'tcx> { let user_provided_types = self.typeck_results.user_provided_types(); let user_ty = user_provided_types.get(ty.hir_id).copied(); debug!("make_mirror_unadjusted: (type) user_ty={:?}", user_ty); - let mirrored = self.mirror_expr_boxed(source); + let mirrored = self.mirror_expr(source); if source.is_syntactic_place_expr() { ExprKind::PlaceTypeAscription { source: mirrored, user_ty } } else { @@ -715,17 +743,15 @@ impl<'tcx> Cx<'tcx> { } } hir::ExprKind::DropTemps(ref source) => { - ExprKind::Use { source: self.mirror_expr_boxed(source) } + ExprKind::Use { source: self.mirror_expr(source) } } - hir::ExprKind::Box(ref value) => ExprKind::Box { value: self.mirror_expr_boxed(value) }, - hir::ExprKind::Array(ref fields) => ExprKind::Array { - fields: fields.iter().map(|field| self.mirror_expr(field)).collect(), - }, - hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { - fields: fields.iter().map(|field| self.mirror_expr(field)).collect(), - }, + hir::ExprKind::Box(ref value) => ExprKind::Box { value: self.mirror_expr(value) }, + hir::ExprKind::Array(ref fields) => { + ExprKind::Array { fields: self.mirror_exprs(fields) } + } + hir::ExprKind::Tup(ref fields) => ExprKind::Tuple { fields: self.mirror_exprs(fields) }, - hir::ExprKind::Yield(ref v, _) => ExprKind::Yield { value: self.mirror_expr_boxed(v) }, + hir::ExprKind::Yield(ref v, _) => ExprKind::Yield { value: self.mirror_expr(v) }, hir::ExprKind::Err => unreachable!(), }; @@ -772,7 +798,7 @@ impl<'tcx> Cx<'tcx> { expr: &hir::Expr<'_>, span: Span, overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>, - ) -> Expr<'tcx> { + ) -> Expr<'thir, 'tcx> { let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); let (def_id, substs, user_ty) = match overloaded_callee { Some((def_id, substs)) => (def_id, substs, None), @@ -799,13 +825,13 @@ impl<'tcx> Cx<'tcx> { } } - fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> Arm<'tcx> { + fn convert_arm(&mut self, arm: &'tcx hir::Arm<'tcx>) -> Arm<'thir, 'tcx> { Arm { pattern: self.pattern_from_hir(&arm.pat), guard: arm.guard.as_ref().map(|g| match g { - hir::Guard::If(ref e) => Guard::If(self.mirror_expr_boxed(e)), + hir::Guard::If(ref e) => Guard::If(self.mirror_expr(e)), hir::Guard::IfLet(ref pat, ref e) => { - Guard::IfLet(self.pattern_from_hir(pat), self.mirror_expr_boxed(e)) + Guard::IfLet(self.pattern_from_hir(pat), self.mirror_expr(e)) } }), body: self.mirror_expr(arm.body), @@ -815,7 +841,11 @@ impl<'tcx> Cx<'tcx> { } } - fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKind<'tcx> { + fn convert_path_expr( + &mut self, + expr: &'tcx hir::Expr<'tcx>, + res: Res, + ) -> ExprKind<'thir, 'tcx> { let substs = self.typeck_results().node_substs(expr.hir_id); match res { // A regular function, constructor function or a constant. @@ -883,7 +913,7 @@ impl<'tcx> Cx<'tcx> { variant_index: adt_def.variant_index_with_ctor_id(def_id), substs, user_ty: user_provided_type, - fields: vec![], + fields: self.arena.alloc_from_iter(iter::empty()), base: None, }, _ => bug!("unexpected ty: {:?}", ty), @@ -904,7 +934,9 @@ impl<'tcx> Cx<'tcx> { def_id: id, } }; - ExprKind::Deref { arg: Box::new(Expr { ty, temp_lifetime, span: expr.span, kind }) } + ExprKind::Deref { + arg: self.arena.alloc(Expr { ty, temp_lifetime, span: expr.span, kind }), + } } Res::Local(var_hir_id) => self.convert_var(var_hir_id), @@ -913,7 +945,7 @@ impl<'tcx> Cx<'tcx> { } } - fn convert_var(&mut self, var_hir_id: hir::HirId) -> ExprKind<'tcx> { + fn convert_var(&mut self, var_hir_id: hir::HirId) -> ExprKind<'thir, 'tcx> { // We want upvars here not captures. // Captures will be handled in MIR. let is_upvar = self @@ -936,9 +968,9 @@ impl<'tcx> Cx<'tcx> { fn overloaded_operator( &mut self, expr: &'tcx hir::Expr<'tcx>, - args: Vec>, - ) -> ExprKind<'tcx> { - let fun = Box::new(self.method_callee(expr, expr.span, None)); + args: &'thir [Expr<'thir, 'tcx>], + ) -> ExprKind<'thir, 'tcx> { + let fun = self.arena.alloc(self.method_callee(expr, expr.span, None)); ExprKind::Call { ty: fun.ty, fun, args, from_hir_call: false, fn_span: expr.span } } @@ -947,9 +979,9 @@ impl<'tcx> Cx<'tcx> { expr: &'tcx hir::Expr<'tcx>, place_ty: Ty<'tcx>, overloaded_callee: Option<(DefId, SubstsRef<'tcx>)>, - args: Vec>, + args: &'thir [Expr<'thir, 'tcx>], span: Span, - ) -> ExprKind<'tcx> { + ) -> ExprKind<'thir, 'tcx> { // 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 // line up (this is because `*x` and `x[y]` represent places): @@ -966,8 +998,8 @@ impl<'tcx> Cx<'tcx> { // construct the complete expression `foo()` for the overloaded call, // which will yield the &T type let temp_lifetime = self.region_scope_tree.temporary_scope(expr.hir_id.local_id); - let fun = Box::new(self.method_callee(expr, span, overloaded_callee)); - let ref_expr = Box::new(Expr { + let fun = self.arena.alloc(self.method_callee(expr, span, overloaded_callee)); + let ref_expr = self.arena.alloc(Expr { temp_lifetime, ty: ref_ty, span, @@ -983,7 +1015,7 @@ impl<'tcx> Cx<'tcx> { closure_expr: &'tcx hir::Expr<'tcx>, captured_place: &'tcx ty::CapturedPlace<'tcx>, upvar_ty: Ty<'tcx>, - ) -> Expr<'tcx> { + ) -> Expr<'thir, 'tcx> { let upvar_capture = captured_place.info.capture_kind; let temp_lifetime = self.region_scope_tree.temporary_scope(closure_expr.hir_id.local_id); let var_ty = captured_place.place.base_ty; @@ -1007,12 +1039,14 @@ impl<'tcx> Cx<'tcx> { for proj in captured_place.place.projections.iter() { let kind = match proj.kind { - HirProjectionKind::Deref => ExprKind::Deref { arg: Box::new(captured_place_expr) }, + HirProjectionKind::Deref => { + ExprKind::Deref { arg: self.arena.alloc(captured_place_expr) } + } HirProjectionKind::Field(field, ..) => { // Variant index will always be 0, because for multi-variant // enums, we capture the enum entirely. ExprKind::Field { - lhs: Box::new(captured_place_expr), + lhs: self.arena.alloc(captured_place_expr), name: Field::new(field as usize), } } @@ -1038,21 +1072,21 @@ impl<'tcx> Cx<'tcx> { temp_lifetime, ty: upvar_ty, span: closure_expr.span, - kind: ExprKind::Borrow { borrow_kind, arg: Box::new(captured_place_expr) }, + kind: ExprKind::Borrow { + borrow_kind, + arg: self.arena.alloc(captured_place_expr), + }, } } } } /// Converts a list of named fields (i.e., for struct-like struct/enum ADTs) into FieldExpr. - fn field_refs(&mut self, fields: &'tcx [hir::Field<'tcx>]) -> Vec> { - fields - .iter() - .map(|field| FieldExpr { - name: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)), - expr: self.mirror_expr(field.expr), - }) - .collect() + fn field_refs(&mut self, fields: &'tcx [hir::Field<'tcx>]) -> &'thir [FieldExpr<'thir, 'tcx>] { + self.arena.alloc_from_iter(fields.iter().map(|field| FieldExpr { + name: Field::new(self.tcx.field_index(field.hir_id, self.typeck_results)), + expr: self.mirror_expr(field.expr), + })) } } diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index c00e9ff8dd98e..66c11ea95286d 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -2,6 +2,7 @@ //! structures into the THIR. The `builder` is generally ignorant of the tcx, //! 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::*; @@ -13,9 +14,18 @@ use rustc_middle::middle::region; use rustc_middle::mir::interpret::{LitToConstError, LitToConstInput}; use rustc_middle::ty::{self, Ty, TyCtxt}; -#[derive(Clone)] -crate struct Cx<'tcx> { +crate fn build_thir<'thir, 'tcx>( tcx: TyCtxt<'tcx>, + owner_def: ty::WithOptConstParam, + arena: &'thir Arena<'thir, 'tcx>, + expr: &'tcx hir::Expr<'tcx>, +) -> &'thir Expr<'thir, 'tcx> { + Cx::new(tcx, owner_def, &arena).mirror_expr(expr) +} + +struct Cx<'thir, 'tcx> { + tcx: TyCtxt<'tcx>, + arena: &'thir Arena<'thir, 'tcx>, crate param_env: ty::ParamEnv<'tcx>, @@ -26,20 +36,23 @@ crate struct Cx<'tcx> { body_owner: DefId, } -impl<'tcx> Cx<'tcx> { - crate fn new(tcx: TyCtxt<'tcx>, def: ty::WithOptConstParam) -> Cx<'tcx> { +impl<'thir, 'tcx> Cx<'thir, 'tcx> { + fn new( + tcx: TyCtxt<'tcx>, + def: ty::WithOptConstParam, + arena: &'thir Arena<'thir, 'tcx>, + ) -> Cx<'thir, 'tcx> { let typeck_results = tcx.typeck_opt_const_arg(def); Cx { tcx, + arena, param_env: tcx.param_env(def.did), region_scope_tree: tcx.region_scope_tree(def.did), typeck_results, body_owner: def.did.to_def_id(), } } -} -impl<'tcx> Cx<'tcx> { crate fn const_eval_literal( &mut self, lit: &'tcx ast::LitKind, @@ -74,7 +87,7 @@ impl<'tcx> Cx<'tcx> { } } -impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'tcx> { +impl<'tcx> UserAnnotatedTyHelpers<'tcx> for Cx<'_, 'tcx> { fn tcx(&self) -> TyCtxt<'tcx> { self.tcx } diff --git a/compiler/rustc_mir_build/src/thir/mod.rs b/compiler/rustc_mir_build/src/thir/mod.rs index 6e7094307b17d..27a7e99951c3b 100644 --- a/compiler/rustc_mir_build/src/thir/mod.rs +++ b/compiler/rustc_mir_build/src/thir/mod.rs @@ -24,6 +24,9 @@ crate mod pattern; crate use self::pattern::PatTyProj; crate use self::pattern::{BindingMode, FieldPat, Pat, PatKind, PatRange}; +mod arena; +crate use arena::Arena; + mod util; #[derive(Copy, Clone, Debug)] @@ -33,13 +36,13 @@ crate enum LintLevel { } #[derive(Debug)] -crate struct Block<'tcx> { +crate struct Block<'thir, 'tcx> { crate targeted_by_break: bool, crate region_scope: region::Scope, crate opt_destruction_scope: Option, crate span: Span, - crate stmts: Vec>, - crate expr: Option>>, + crate stmts: &'thir [Stmt<'thir, 'tcx>], + crate expr: Option<&'thir Expr<'thir, 'tcx>>, crate safety_mode: BlockSafety, } @@ -52,19 +55,19 @@ crate enum BlockSafety { } #[derive(Debug)] -crate struct Stmt<'tcx> { - crate kind: StmtKind<'tcx>, +crate struct Stmt<'thir, 'tcx> { + crate kind: StmtKind<'thir, 'tcx>, crate opt_destruction_scope: Option, } #[derive(Debug)] -crate enum StmtKind<'tcx> { +crate enum StmtKind<'thir, 'tcx> { Expr { /// scope for this statement; may be used as lifetime of temporaries scope: region::Scope, /// expression being evaluated in this statement - expr: Box>, + expr: &'thir Expr<'thir, 'tcx>, }, Let { @@ -82,7 +85,7 @@ crate enum StmtKind<'tcx> { pattern: Pat<'tcx>, /// let pat: ty = ... - initializer: Option>>, + initializer: Option<&'thir Expr<'thir, 'tcx>>, /// the lint level for this let-statement lint_level: LintLevel, @@ -91,12 +94,12 @@ crate enum StmtKind<'tcx> { // `Expr` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))] -rustc_data_structures::static_assert_size!(Expr<'_>, 160); +rustc_data_structures::static_assert_size!(Expr<'_, '_>, 144); /// The Thir trait implementor lowers their expressions (`&'tcx H::Expr`) /// into instances of this `Expr` enum. This lowering can be done /// basically as lazily or as eagerly as desired: every recursive -/// reference to an expression in this enum is an `Box>`, which +/// reference to an expression in this enum is an `&'thir Expr<'thir, 'tcx>`, which /// may in turn be another instance of this enum (boxed), or else an /// unlowered `&'tcx H::Expr`. Note that instances of `Expr` are very /// short-lived. They are created by `Thir::to_expr`, analyzed and @@ -108,7 +111,7 @@ rustc_data_structures::static_assert_size!(Expr<'_>, 160); /// example, method calls and overloaded operators are absent: they are /// expected to be converted into `Expr::Call` instances. #[derive(Debug)] -crate struct Expr<'tcx> { +crate struct Expr<'thir, 'tcx> { /// type of this expression crate ty: Ty<'tcx>, @@ -120,28 +123,28 @@ crate struct Expr<'tcx> { crate span: Span, /// kind of expression - crate kind: ExprKind<'tcx>, + crate kind: ExprKind<'thir, 'tcx>, } #[derive(Debug)] -crate enum ExprKind<'tcx> { +crate enum ExprKind<'thir, 'tcx> { Scope { region_scope: region::Scope, lint_level: LintLevel, - value: Box>, + value: &'thir Expr<'thir, 'tcx>, }, Box { - value: Box>, + value: &'thir Expr<'thir, 'tcx>, }, If { - cond: Box>, - then: Box>, - else_opt: Option>>, + cond: &'thir Expr<'thir, 'tcx>, + then: &'thir Expr<'thir, 'tcx>, + else_opt: Option<&'thir Expr<'thir, 'tcx>>, }, Call { ty: Ty<'tcx>, - fun: Box>, - args: Vec>, + fun: &'thir Expr<'thir, 'tcx>, + args: &'thir [Expr<'thir, 'tcx>], /// Whether this is from a call in HIR, rather than from an overloaded /// operator. `true` for overloaded function call. from_hir_call: bool, @@ -150,62 +153,62 @@ crate enum ExprKind<'tcx> { fn_span: Span, }, Deref { - arg: Box>, + arg: &'thir Expr<'thir, 'tcx>, }, // NOT overloaded! Binary { op: BinOp, - lhs: Box>, - rhs: Box>, + lhs: &'thir Expr<'thir, 'tcx>, + rhs: &'thir Expr<'thir, 'tcx>, }, // NOT overloaded! LogicalOp { op: LogicalOp, - lhs: Box>, - rhs: Box>, + lhs: &'thir Expr<'thir, 'tcx>, + rhs: &'thir Expr<'thir, 'tcx>, }, // NOT overloaded! // LogicalOp is distinct from BinaryOp because of lazy evaluation of the operands. Unary { op: UnOp, - arg: Box>, + arg: &'thir Expr<'thir, 'tcx>, }, // NOT overloaded! Cast { - source: Box>, + source: &'thir Expr<'thir, 'tcx>, }, Use { - source: Box>, + source: &'thir Expr<'thir, 'tcx>, }, // Use a lexpr to get a vexpr. NeverToAny { - source: Box>, + source: &'thir Expr<'thir, 'tcx>, }, Pointer { cast: PointerCast, - source: Box>, + source: &'thir Expr<'thir, 'tcx>, }, Loop { - body: Box>, + body: &'thir Expr<'thir, 'tcx>, }, Match { - scrutinee: Box>, - arms: Vec>, + scrutinee: &'thir Expr<'thir, 'tcx>, + arms: &'thir [Arm<'thir, 'tcx>], }, Block { - body: Block<'tcx>, + body: Block<'thir, 'tcx>, }, Assign { - lhs: Box>, - rhs: Box>, + lhs: &'thir Expr<'thir, 'tcx>, + rhs: &'thir Expr<'thir, 'tcx>, }, AssignOp { op: BinOp, - lhs: Box>, - rhs: Box>, + lhs: &'thir Expr<'thir, 'tcx>, + rhs: &'thir Expr<'thir, 'tcx>, }, Field { - lhs: Box>, + lhs: &'thir Expr<'thir, 'tcx>, name: Field, }, Index { - lhs: Box>, - index: Box>, + lhs: &'thir Expr<'thir, 'tcx>, + index: &'thir Expr<'thir, 'tcx>, }, VarRef { id: hir::HirId, @@ -220,35 +223,35 @@ crate enum ExprKind<'tcx> { }, Borrow { borrow_kind: BorrowKind, - arg: Box>, + arg: &'thir Expr<'thir, 'tcx>, }, /// A `&raw [const|mut] $place_expr` raw borrow resulting in type `*[const|mut] T`. AddressOf { mutability: hir::Mutability, - arg: Box>, + arg: &'thir Expr<'thir, 'tcx>, }, Break { label: region::Scope, - value: Option>>, + value: Option<&'thir Expr<'thir, 'tcx>>, }, Continue { label: region::Scope, }, Return { - value: Option>>, + value: Option<&'thir Expr<'thir, 'tcx>>, }, ConstBlock { value: &'tcx Const<'tcx>, }, Repeat { - value: Box>, + value: &'thir Expr<'thir, 'tcx>, count: &'tcx Const<'tcx>, }, Array { - fields: Vec>, + fields: &'thir [Expr<'thir, 'tcx>], }, Tuple { - fields: Vec>, + fields: &'thir [Expr<'thir, 'tcx>], }, Adt { adt_def: &'tcx AdtDef, @@ -259,23 +262,23 @@ crate enum ExprKind<'tcx> { /// Bar:: { ... }`. user_ty: Option>>, - fields: Vec>, - base: Option>, + fields: &'thir [FieldExpr<'thir, 'tcx>], + base: Option>, }, PlaceTypeAscription { - source: Box>, + source: &'thir Expr<'thir, 'tcx>, /// Type that the user gave to this expression user_ty: Option>>, }, ValueTypeAscription { - source: Box>, + source: &'thir Expr<'thir, 'tcx>, /// Type that the user gave to this expression user_ty: Option>>, }, Closure { closure_id: DefId, substs: UpvarSubsts<'tcx>, - upvars: Vec>, + upvars: &'thir [Expr<'thir, 'tcx>], movability: Option, }, Literal { @@ -296,7 +299,7 @@ crate enum ExprKind<'tcx> { }, InlineAsm { template: &'tcx [InlineAsmTemplatePiece], - operands: Vec>, + operands: &'thir [InlineAsmOperand<'thir, 'tcx>], options: InlineAsmOptions, line_spans: &'tcx [Span], }, @@ -304,40 +307,40 @@ crate enum ExprKind<'tcx> { ThreadLocalRef(DefId), LlvmInlineAsm { asm: &'tcx hir::LlvmInlineAsmInner, - outputs: Vec>, - inputs: Vec>, + outputs: &'thir [Expr<'thir, 'tcx>], + inputs: &'thir [Expr<'thir, 'tcx>], }, Yield { - value: Box>, + value: &'thir Expr<'thir, 'tcx>, }, } #[derive(Debug)] -crate struct FieldExpr<'tcx> { +crate struct FieldExpr<'thir, 'tcx> { crate name: Field, - crate expr: Expr<'tcx>, + crate expr: &'thir Expr<'thir, 'tcx>, } #[derive(Debug)] -crate struct FruInfo<'tcx> { - crate base: Box>, - crate field_types: Vec>, +crate struct FruInfo<'thir, 'tcx> { + crate base: &'thir Expr<'thir, 'tcx>, + crate field_types: &'thir [Ty<'tcx>], } #[derive(Debug)] -crate struct Arm<'tcx> { +crate struct Arm<'thir, 'tcx> { crate pattern: Pat<'tcx>, - crate guard: Option>, - crate body: Expr<'tcx>, + crate guard: Option>, + crate body: &'thir Expr<'thir, 'tcx>, crate lint_level: LintLevel, crate scope: region::Scope, crate span: Span, } #[derive(Debug)] -crate enum Guard<'tcx> { - If(Box>), - IfLet(Pat<'tcx>, Box>), +crate enum Guard<'thir, 'tcx> { + If(&'thir Expr<'thir, 'tcx>), + IfLet(Pat<'tcx>, &'thir Expr<'thir, 'tcx>), } #[derive(Copy, Clone, Debug)] @@ -347,32 +350,32 @@ crate enum LogicalOp { } #[derive(Debug)] -crate enum InlineAsmOperand<'tcx> { +crate enum InlineAsmOperand<'thir, 'tcx> { In { reg: InlineAsmRegOrRegClass, - expr: Expr<'tcx>, + expr: &'thir Expr<'thir, 'tcx>, }, Out { reg: InlineAsmRegOrRegClass, late: bool, - expr: Option>, + expr: Option<&'thir Expr<'thir, 'tcx>>, }, InOut { reg: InlineAsmRegOrRegClass, late: bool, - expr: Expr<'tcx>, + expr: &'thir Expr<'thir, 'tcx>, }, SplitInOut { reg: InlineAsmRegOrRegClass, late: bool, - in_expr: Expr<'tcx>, - out_expr: Option>, + in_expr: &'thir Expr<'thir, 'tcx>, + out_expr: Option<&'thir Expr<'thir, 'tcx>>, }, Const { - expr: Expr<'tcx>, + expr: &'thir Expr<'thir, 'tcx>, }, SymFn { - expr: Expr<'tcx>, + expr: &'thir Expr<'thir, 'tcx>, }, SymStatic { def_id: DefId, From cd049ef9ea2e2084e64d0964b1a58b46839c640d Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Sat, 6 Mar 2021 22:24:04 +0100 Subject: [PATCH 5/7] Remove useless references/dereferences --- compiler/rustc_mir_build/src/build/block.rs | 39 ++++---- .../src/build/expr/as_constant.rs | 16 ++-- .../src/build/expr/as_operand.rs | 16 ++-- .../src/build/expr/as_place.rs | 38 ++++---- .../src/build/expr/as_rvalue.rs | 48 +++++----- .../rustc_mir_build/src/build/expr/as_temp.rs | 4 +- .../rustc_mir_build/src/build/expr/into.rs | 95 +++++++++---------- .../rustc_mir_build/src/build/expr/stmt.rs | 34 +++---- .../rustc_mir_build/src/build/matches/mod.rs | 2 +- compiler/rustc_mir_build/src/build/mod.rs | 2 +- compiler/rustc_mir_build/src/thir/cx/block.rs | 6 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 16 ++-- 12 files changed, 148 insertions(+), 168 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs index e93c796c97059..808c6e3ff644b 100644 --- a/compiler/rustc_mir_build/src/build/block.rs +++ b/compiler/rustc_mir_build/src/build/block.rs @@ -23,29 +23,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr, targeted_by_break, safety_mode, - } = ast_block; + } = *ast_block; self.in_opt_scope(opt_destruction_scope.map(|de| (de, source_info)), move |this| { - this.in_scope((*region_scope, source_info), LintLevel::Inherited, move |this| { - if *targeted_by_break { - this.in_breakable_scope(None, destination, *span, |this| { + this.in_scope((region_scope, source_info), LintLevel::Inherited, move |this| { + if targeted_by_break { + this.in_breakable_scope(None, destination, span, |this| { Some(this.ast_block_stmts( destination, block, - *span, - &stmts, - expr.as_deref(), - *safety_mode, + span, + stmts, + expr, + safety_mode, )) }) } else { - this.ast_block_stmts( - destination, - block, - *span, - &stmts, - expr.as_deref(), - *safety_mode, - ) + this.ast_block_stmts(destination, block, span, stmts, expr, safety_mode) } }) }) @@ -87,15 +80,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let source_info = this.source_info(span); for Stmt { kind, opt_destruction_scope } in stmts { match kind { - StmtKind::Expr { scope, expr } => { + &StmtKind::Expr { scope, expr } => { this.block_context.push(BlockFrame::Statement { ignores_expr_result: true }); unpack!( block = this.in_opt_scope( opt_destruction_scope.map(|de| (de, source_info)), |this| { - let si = (*scope, source_info); + let si = (scope, source_info); this.in_scope(si, LintLevel::Inherited, |this| { - this.stmt_expr(block, &expr, Some(*scope)) + this.stmt_expr(block, expr, Some(scope)) }) } ) @@ -110,7 +103,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let_scope_stack.push(remainder_scope); // Declare the bindings, which may create a source scope. - let remainder_span = remainder_scope.span(this.tcx, &this.region_scope_tree); + let remainder_span = remainder_scope.span(this.tcx, this.region_scope_tree); let visibility_scope = Some(this.new_source_scope(remainder_span, LintLevel::Inherited, None)); @@ -128,11 +121,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.declare_bindings( visibility_scope, remainder_span, - &pattern, + pattern, ArmHasGuard(false), Some((None, initializer_span)), ); - this.expr_into_pattern(block, pattern.clone(), &init) + this.expr_into_pattern(block, pattern.clone(), init) }) } ) @@ -143,7 +136,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.declare_bindings( visibility_scope, remainder_span, - &pattern, + pattern, ArmHasGuard(false), None, ); diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index ce341c0c06cdf..727aedb0ef854 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -10,25 +10,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// `expr` is a valid compile-time constant! crate fn as_constant(&mut self, expr: &Expr<'_, 'tcx>) -> Constant<'tcx> { let this = self; - let Expr { ty, temp_lifetime: _, span, kind } = expr; + let Expr { ty, temp_lifetime: _, span, ref kind } = *expr; match kind { - ExprKind::Scope { region_scope: _, lint_level: _, value } => this.as_constant(&value), + ExprKind::Scope { region_scope: _, lint_level: _, value } => this.as_constant(value), ExprKind::Literal { literal, user_ty, const_id: _ } => { let user_ty = user_ty.map(|user_ty| { this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { - span: *span, + span, user_ty, inferred_ty: ty, }) }); - assert_eq!(literal.ty, *ty); - Constant { span: *span, user_ty, literal } + assert_eq!(literal.ty, ty); + Constant { span, user_ty, literal } } - ExprKind::StaticRef { literal, .. } => Constant { span: *span, user_ty: None, literal }, + ExprKind::StaticRef { literal, .. } => Constant { span, user_ty: None, literal }, ExprKind::ConstBlock { value } => { - Constant { span: *span, user_ty: None, literal: value } + Constant { span: span, user_ty: None, literal: value } } - _ => span_bug!(*span, "expression is not a valid constant {:?}", kind), + _ => span_bug!(span, "expression is not a valid constant {:?}", kind), } } } diff --git a/compiler/rustc_mir_build/src/build/expr/as_operand.rs b/compiler/rustc_mir_build/src/build/expr/as_operand.rs index 28262287b6339..c393878e0b995 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_operand.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_operand.rs @@ -98,11 +98,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { debug!("as_operand(block={:?}, expr={:?})", block, expr); let this = self; - 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 region_scope = (*region_scope, source_info); + let region_scope = (region_scope, source_info); return this - .in_scope(region_scope, *lint_level, |this| this.as_operand(block, scope, &value)); + .in_scope(region_scope, lint_level, |this| this.as_operand(block, scope, value)); } let category = Category::of(&expr.kind).unwrap(); @@ -128,11 +128,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { debug!("as_call_operand(block={:?}, expr={:?})", block, expr); let this = self; - 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 region_scope = (*region_scope, source_info); - return this.in_scope(region_scope, *lint_level, |this| { - this.as_call_operand(block, scope, &value) + let region_scope = (region_scope, source_info); + return this.in_scope(region_scope, lint_level, |this| { + this.as_call_operand(block, scope, value) }); } @@ -149,7 +149,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // As described above, detect the case where we are passing a value of unsized // type, and that value is coming from the deref of a box. - if let ExprKind::Deref { ref arg } = expr.kind { + if let ExprKind::Deref { arg } = expr.kind { // Generate let tmp0 = arg0 let operand = unpack!(block = this.as_temp(block, scope, arg, Mutability::Mut)); diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 30262e164201b..532c725c823ef 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -406,28 +406,26 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let this = self; let expr_span = expr.span; let source_info = this.source_info(expr_span); - match &expr.kind { + match expr.kind { ExprKind::Scope { region_scope, lint_level, value } => { - this.in_scope((*region_scope, source_info), *lint_level, |this| { - this.expr_as_place(block, &value, mutability, fake_borrow_temps) + this.in_scope((region_scope, source_info), lint_level, |this| { + this.expr_as_place(block, value, mutability, fake_borrow_temps) }) } ExprKind::Field { lhs, name } => { - let place_builder = unpack!( - block = this.expr_as_place(block, &lhs, mutability, fake_borrow_temps,) - ); - block.and(place_builder.field(*name, expr.ty)) + let place_builder = + unpack!(block = this.expr_as_place(block, lhs, mutability, fake_borrow_temps,)); + block.and(place_builder.field(name, expr.ty)) } ExprKind::Deref { arg } => { - let place_builder = unpack!( - block = this.expr_as_place(block, &arg, mutability, fake_borrow_temps,) - ); + let place_builder = + unpack!(block = this.expr_as_place(block, arg, mutability, fake_borrow_temps,)); block.and(place_builder.deref()) } ExprKind::Index { lhs, index } => this.lower_index_expression( block, - &lhs, - &index, + lhs, + index, mutability, fake_borrow_temps, expr.temp_lifetime, @@ -435,16 +433,16 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { source_info, ), ExprKind::UpvarRef { closure_def_id, var_hir_id } => { - let upvar_id = ty::UpvarId::new(*var_hir_id, closure_def_id.expect_local()); + let upvar_id = ty::UpvarId::new(var_hir_id, closure_def_id.expect_local()); this.lower_captured_upvar(block, upvar_id) } ExprKind::VarRef { id } => { - let place_builder = if this.is_bound_var_in_guard(*id) { - let index = this.var_local_id(*id, RefWithinGuard); + let place_builder = if this.is_bound_var_in_guard(id) { + let index = this.var_local_id(id, RefWithinGuard); PlaceBuilder::from(index).deref() } else { - let index = this.var_local_id(*id, OutsideGuard); + let index = this.var_local_id(id, OutsideGuard); PlaceBuilder::from(index) }; block.and(place_builder) @@ -452,13 +450,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::PlaceTypeAscription { source, user_ty } => { let place_builder = unpack!( - block = this.expr_as_place(block, &source, mutability, fake_borrow_temps,) + block = this.expr_as_place(block, source, mutability, fake_borrow_temps,) ); if let Some(user_ty) = user_ty { let annotation_index = this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { span: source_info.span, - user_ty: *user_ty, + user_ty, inferred_ty: expr.ty, }); @@ -481,12 +479,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } ExprKind::ValueTypeAscription { source, user_ty } => { 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 { let annotation_index = this.canonical_user_type_annotations.push(CanonicalUserTypeAnnotation { span: source_info.span, - user_ty: *user_ty, + user_ty, inferred_ty: expr.ty, }); this.cfg.push( diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 335ea4dca6006..d73e5eef70ca6 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -41,27 +41,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let expr_span = expr.span; let source_info = this.source_info(expr_span); - match &expr.kind { - ExprKind::ThreadLocalRef(did) => block.and(Rvalue::ThreadLocalRef(*did)), + match expr.kind { + ExprKind::ThreadLocalRef(did) => block.and(Rvalue::ThreadLocalRef(did)), ExprKind::Scope { region_scope, lint_level, value } => { - let region_scope = (*region_scope, source_info); - this.in_scope(region_scope, *lint_level, |this| { - this.as_rvalue(block, scope, &value) - }) + let region_scope = (region_scope, source_info); + this.in_scope(region_scope, lint_level, |this| this.as_rvalue(block, scope, value)) } 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, value)); block.and(Rvalue::Repeat(value_operand, count)) } ExprKind::Binary { op, lhs, rhs } => { - let lhs = unpack!(block = this.as_operand(block, scope, &lhs)); - let rhs = unpack!(block = this.as_operand(block, scope, &rhs)); - this.build_binary_op(block, *op, expr_span, expr.ty, lhs, rhs) + let lhs = unpack!(block = this.as_operand(block, scope, lhs)); + let rhs = unpack!(block = this.as_operand(block, scope, rhs)); + this.build_binary_op(block, op, expr_span, expr.ty, lhs, rhs) } ExprKind::Unary { op, arg } => { - let arg = unpack!(block = this.as_operand(block, scope, &arg)); + let arg = unpack!(block = this.as_operand(block, scope, arg)); // 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 minval = this.minval_literal(expr_span, expr.ty); @@ -82,7 +80,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { expr_span, ); } - block.and(Rvalue::UnaryOp(*op, arg)) + block.and(Rvalue::UnaryOp(op, arg)) } ExprKind::Box { value } => { // The `Box` temporary created here is not a part of the HIR, @@ -107,18 +105,18 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block = this.expr_into_dest( this.tcx.mk_place_deref(Place::from(result)), block, - &value + value ) ); block.and(Rvalue::Use(Operand::Move(Place::from(result)))) } ExprKind::Cast { source } => { - let source = unpack!(block = this.as_operand(block, scope, &source)); + let source = unpack!(block = this.as_operand(block, scope, source)); block.and(Rvalue::Cast(CastKind::Misc, source, expr.ty)) } ExprKind::Pointer { cast, source } => { - let source = unpack!(block = this.as_operand(block, scope, &source)); - block.and(Rvalue::Cast(CastKind::Pointer(*cast), source, expr.ty)) + let source = unpack!(block = this.as_operand(block, scope, source)); + block.and(Rvalue::Cast(CastKind::Pointer(cast), source, expr.ty)) } ExprKind::Array { fields } => { // (*) We would (maybe) be closer to codegen if we @@ -151,7 +149,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let el_ty = expr.ty.sequence_element_type(this.tcx); let fields: Vec<_> = fields .into_iter() - .map(|f| unpack!(block = this.as_operand(block, scope, &f))) + .map(|f| unpack!(block = this.as_operand(block, scope, f))) .collect(); block.and(Rvalue::Aggregate(box AggregateKind::Array(el_ty), fields)) @@ -161,7 +159,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // first process the set of fields let fields: Vec<_> = fields .into_iter() - .map(|f| unpack!(block = this.as_operand(block, scope, &f))) + .map(|f| unpack!(block = this.as_operand(block, scope, f))) .collect(); block.and(Rvalue::Aggregate(box AggregateKind::Tuple, fields)) @@ -181,7 +179,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // This occurs when capturing by copy/move, while // by reference captures use as_operand Some(Category::Place) => { - let place = unpack!(block = this.as_place(block, &upvar)); + let place = unpack!(block = this.as_place(block, upvar)); this.consume_by_copy_or_move(place) } _ => { @@ -189,17 +187,17 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // borrow captures when capturing an immutable // variable. This is sound because the mutation // that caused the capture will cause an error. - match &upvar.kind { + match upvar.kind { ExprKind::Borrow { borrow_kind: BorrowKind::Mut { allow_two_phase_borrow: false }, arg, } => unpack!( block = this.limit_capture_mutability( - upvar.span, upvar.ty, scope, block, &arg, + upvar.span, upvar.ty, scope, block, arg, ) ), - _ => unpack!(block = this.as_operand(block, scope, &upvar)), + _ => unpack!(block = this.as_operand(block, scope, upvar)), } } } @@ -210,9 +208,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // We implicitly set the discriminant to 0. See // librustc_mir/transform/deaggregator.rs for details. let movability = movability.unwrap(); - box AggregateKind::Generator(*closure_id, substs, movability) + box AggregateKind::Generator(closure_id, substs, movability) } - UpvarSubsts::Closure(substs) => box AggregateKind::Closure(*closure_id, substs), + UpvarSubsts::Closure(substs) => box AggregateKind::Closure(closure_id, substs), }; block.and(Rvalue::Aggregate(result, operands)) } diff --git a/compiler/rustc_mir_build/src/build/expr/as_temp.rs b/compiler/rustc_mir_build/src/build/expr/as_temp.rs index 12029b04a08f3..98b910ab21c16 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_temp.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_temp.rs @@ -38,8 +38,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let expr_span = expr.span; let source_info = this.source_info(expr_span); - if let ExprKind::Scope { region_scope, lint_level, value } = &expr.kind { - return this.in_scope((*region_scope, source_info), *lint_level, |this| { + if let ExprKind::Scope { region_scope, lint_level, value } = expr.kind { + return this.in_scope((region_scope, source_info), lint_level, |this| { this.as_temp(block, temp_lifetime, value, mutability) }); } diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index 4baf26dce6ad5..47f75825fb6af 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -36,24 +36,24 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.block_context.push(BlockFrame::SubExpr); } - let block_and = match &expr.kind { + let block_and = match expr.kind { ExprKind::Scope { region_scope, lint_level, value } => { - let region_scope = (*region_scope, source_info); + let region_scope = (region_scope, source_info); ensure_sufficient_stack(|| { - this.in_scope(region_scope, *lint_level, |this| { - this.expr_into_dest(destination, block, &value) + this.in_scope(region_scope, lint_level, |this| { + this.expr_into_dest(destination, block, value) }) }) } - ExprKind::Block { body: ast_block } => { - this.ast_block(destination, block, &ast_block, source_info) + ExprKind::Block { body: ref ast_block } => { + this.ast_block(destination, block, ast_block, source_info) } ExprKind::Match { scrutinee, arms } => { - this.match_expr(destination, expr_span, block, &scrutinee, &arms) + this.match_expr(destination, expr_span, block, scrutinee, arms) } ExprKind::If { cond, then, else_opt } => { let place = unpack!( - block = this.as_temp(block, Some(this.local_scope()), &cond, Mutability::Mut) + block = this.as_temp(block, Some(this.local_scope()), cond, Mutability::Mut) ); let operand = Operand::Move(Place::from(place)); @@ -62,9 +62,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let term = TerminatorKind::if_(this.tcx, operand, then_block, else_block); 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, then)); 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, else_opt)) } else { // Body of the `if` expression without an `else` clause must return `()`, thus // we implicitly generate a `else {}` if it is not specified. @@ -94,8 +94,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // (#66975) Source could be a const of type `!`, so has to // exist in the generated MIR. unpack!( - block = - this.as_temp(block, Some(this.local_scope()), &source, Mutability::Mut,) + block = this.as_temp(block, Some(this.local_scope()), source, Mutability::Mut,) ); // This is an optimization. If the expression was a call then we already have an @@ -128,7 +127,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.cfg.start_new_block(), ); - let lhs = unpack!(block = this.as_local_operand(block, &lhs)); + let lhs = unpack!(block = this.as_local_operand(block, lhs)); let blocks = match op { LogicalOp::And => (else_block, false_block), LogicalOp::Or => (true_block, else_block), @@ -136,7 +135,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let term = TerminatorKind::if_(this.tcx, lhs, blocks.0, blocks.1); this.cfg.terminate(block, source_info, term); - let rhs = unpack!(else_block = this.as_local_operand(else_block, &rhs)); + let rhs = unpack!(else_block = this.as_local_operand(else_block, rhs)); let term = TerminatorKind::if_(this.tcx, rhs, true_block, false_block); this.cfg.terminate(else_block, source_info, term); @@ -197,7 +196,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // introduce a unit temporary as the destination for the loop body. let tmp = this.get_unit_temp(); // 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, body)); this.cfg.goto(body_block_end, source_info, loop_block); // Loops are only exited by `break` expressions. @@ -205,10 +204,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }) } ExprKind::Call { ty: _, fun, 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, fun)); let args: Vec<_> = args .into_iter() - .map(|arg| unpack!(block = this.as_local_call_operand(block, &arg))) + .map(|arg| unpack!(block = this.as_local_call_operand(block, arg))) .collect(); let success = this.cfg.start_new_block(); @@ -232,14 +231,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } else { Some((destination, success)) }, - from_hir_call: *from_hir_call, - fn_span: *fn_span, + from_hir_call, + fn_span, }, ); this.diverge_from(block); success.unit() } - ExprKind::Use { source } => this.expr_into_dest(destination, block, &source), + ExprKind::Use { source } => this.expr_into_dest(destination, block, source), ExprKind::Borrow { arg, borrow_kind } => { // We don't do this in `as_rvalue` because we use `as_place` // for borrow expressions, so we cannot create an `RValue` that @@ -247,23 +246,23 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // by this method anyway, so this shouldn't cause too many // unnecessary temporaries. let arg_place = match borrow_kind { - BorrowKind::Shared => unpack!(block = this.as_read_only_place(block, &arg)), - _ => unpack!(block = this.as_place(block, &arg)), + BorrowKind::Shared => unpack!(block = this.as_read_only_place(block, arg)), + _ => unpack!(block = this.as_place(block, arg)), }; - let borrow = Rvalue::Ref(this.tcx.lifetimes.re_erased, *borrow_kind, arg_place); + let borrow = Rvalue::Ref(this.tcx.lifetimes.re_erased, borrow_kind, arg_place); this.cfg.push_assign(block, source_info, destination, borrow); block.unit() } ExprKind::AddressOf { mutability, arg } => { let place = match mutability { - hir::Mutability::Not => this.as_read_only_place(block, &arg), - hir::Mutability::Mut => this.as_place(block, &arg), + hir::Mutability::Not => this.as_read_only_place(block, arg), + hir::Mutability::Mut => this.as_place(block, arg), }; - let address_of = Rvalue::AddressOf(*mutability, unpack!(block = place)); + let address_of = Rvalue::AddressOf(mutability, unpack!(block = place)); this.cfg.push_assign(block, source_info, destination, address_of); block.unit() } - ExprKind::Adt { adt_def, variant_index, substs, user_ty, fields, base } => { + ExprKind::Adt { adt_def, variant_index, substs, user_ty, fields, ref base } => { // See the notes for `ExprKind::Array` in `as_rvalue` and for // `ExprKind::Borrow` above. let is_union = adt_def.is_union(); @@ -275,16 +274,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // (evaluating them in order given by user) let fields_map: FxHashMap<_, _> = fields .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), f.expr)))) .collect(); 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 place_builder = unpack!(block = this.as_place_builder(block, &base)); + let place_builder = unpack!(block = this.as_place_builder(block, base)); // MIR does not natively support FRU, so for each // base-supplied field, generate an operand that @@ -318,7 +315,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }); let adt = box AggregateKind::Adt( adt_def, - *variant_index, + variant_index, substs, user_ty, active_field_index, @@ -336,25 +333,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { use rustc_middle::mir; let operands = operands .into_iter() - .map(|op| match op { + .map(|op| match *op { thir::InlineAsmOperand::In { reg, expr } => mir::InlineAsmOperand::In { - reg: *reg, - value: unpack!(block = this.as_local_operand(block, &expr)), + reg, + value: unpack!(block = this.as_local_operand(block, expr)), }, thir::InlineAsmOperand::Out { reg, late, expr } => { mir::InlineAsmOperand::Out { - reg: *reg, - late: *late, + reg, + late, place: expr .as_ref() .map(|expr| unpack!(block = this.as_place(block, expr))), } } thir::InlineAsmOperand::InOut { reg, late, expr } => { - let place = unpack!(block = this.as_place(block, &expr)); + let place = unpack!(block = this.as_place(block, expr)); mir::InlineAsmOperand::InOut { - reg: *reg, - late: *late, + reg, + late, // This works because asm operands must be Copy in_value: Operand::Copy(place), out_place: Some(place), @@ -362,22 +359,22 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } thir::InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => { mir::InlineAsmOperand::InOut { - reg: *reg, - late: *late, - in_value: unpack!(block = this.as_local_operand(block, &in_expr)), + reg, + late, + in_value: unpack!(block = this.as_local_operand(block, in_expr)), out_place: out_expr.as_ref().map(|out_expr| { unpack!(block = this.as_place(block, out_expr)) }), } } thir::InlineAsmOperand::Const { expr } => mir::InlineAsmOperand::Const { - value: unpack!(block = this.as_local_operand(block, &expr)), + value: unpack!(block = this.as_local_operand(block, expr)), }, thir::InlineAsmOperand::SymFn { expr } => { - mir::InlineAsmOperand::SymFn { value: box this.as_constant(&expr) } + mir::InlineAsmOperand::SymFn { value: box this.as_constant(expr) } } thir::InlineAsmOperand::SymStatic { def_id } => { - mir::InlineAsmOperand::SymStatic { def_id: *def_id } + mir::InlineAsmOperand::SymStatic { def_id } } }) .collect(); @@ -390,7 +387,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { TerminatorKind::InlineAsm { template, operands, - options: *options, + options, line_spans, destination: if options.contains(InlineAsmOptions::NORETURN) { None @@ -449,7 +446,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::Yield { value } => { 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), value)); let resume = this.cfg.start_new_block(); this.cfg.terminate( block, diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs index 23e23f0885b77..a3fbd21642d90 100644 --- a/compiler/rustc_mir_build/src/build/expr/stmt.rs +++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs @@ -21,10 +21,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let source_info = this.source_info(expr.span); // Handle a number of expressions that don't need a destination at all. This // avoids needing a mountain of temporary `()` variables. - match &expr.kind { + match expr.kind { ExprKind::Scope { region_scope, lint_level, value } => { - this.in_scope((*region_scope, source_info), *lint_level, |this| { - this.stmt_expr(block, &value, statement_scope) + this.in_scope((region_scope, source_info), lint_level, |this| { + this.stmt_expr(block, value, statement_scope) }) } ExprKind::Assign { lhs, rhs } => { @@ -40,12 +40,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Generate better code for things that don't need to be // dropped. if lhs.ty.needs_drop(this.tcx, this.param_env) { - let rhs = unpack!(block = this.as_local_operand(block, &rhs)); - let lhs = unpack!(block = this.as_place(block, &lhs)); + let rhs = unpack!(block = this.as_local_operand(block, rhs)); + let lhs = unpack!(block = this.as_place(block, lhs)); unpack!(block = this.build_drop_and_replace(block, lhs_span, lhs, rhs)); } else { - let rhs = unpack!(block = this.as_local_rvalue(block, &rhs)); - let lhs = unpack!(block = this.as_place(block, &lhs)); + let rhs = unpack!(block = this.as_local_rvalue(block, rhs)); + let lhs = unpack!(block = this.as_place(block, lhs)); this.cfg.push_assign(block, source_info, lhs, rhs); } @@ -67,21 +67,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.block_context.push(BlockFrame::SubExpr); // As above, RTL. - let rhs = unpack!(block = this.as_local_operand(block, &rhs)); - let lhs = unpack!(block = this.as_place(block, &lhs)); + let rhs = unpack!(block = this.as_local_operand(block, rhs)); + let lhs = unpack!(block = this.as_place(block, lhs)); // we don't have to drop prior contents or anything // because AssignOp is only legal for Copy types // (overloaded ops should be desugared into a call). let result = unpack!( - block = this.build_binary_op( - block, - *op, - expr_span, - lhs_ty, - Operand::Copy(lhs), - rhs - ) + block = + this.build_binary_op(block, op, expr_span, lhs_ty, Operand::Copy(lhs), rhs) ); this.cfg.push_assign(block, source_info, lhs, result); @@ -89,12 +83,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { block.unit() } ExprKind::Continue { label } => { - this.break_scope(block, None, BreakableTarget::Continue(*label), source_info) + this.break_scope(block, None, BreakableTarget::Continue(label), source_info) } ExprKind::Break { label, value } => this.break_scope( block, value.as_deref(), - BreakableTarget::Break(*label), + BreakableTarget::Break(label), source_info, ), ExprKind::Return { value } => { @@ -120,7 +114,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Statement { source_info, kind: StatementKind::LlvmInlineAsm(box LlvmInlineAsm { - asm: (*asm).clone(), + asm: asm.clone(), outputs, inputs, }), diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 098ed8b3eb8ce..6c31528be73f7 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -1754,7 +1754,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { Guard::IfLet(pat, scrutinee) => { let scrutinee_span = scrutinee.span; let scrutinee_place = - unpack!(block = self.lower_scrutinee(block, &scrutinee, scrutinee_span)); + unpack!(block = self.lower_scrutinee(block, scrutinee, scrutinee_span)); let mut guard_candidate = Candidate::new(scrutinee_place, &pat, false); let wildcard = Pat::wildcard_from_ty(pat.ty); let mut otherwise_candidate = Candidate::new(scrutinee_place, &wildcard, false); diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index ef531a2392183..cb53c7ef5a601 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -643,7 +643,7 @@ where fn_def.did.to_def_id(), &arguments, arg_scope, - &expr, + expr, ) })) })); diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs index 2ec102282c28e..d450f8a265d99 100644 --- a/compiler/rustc_mir_build/src/thir/cx/block.rs +++ b/compiler/rustc_mir_build/src/thir/cx/block.rs @@ -11,7 +11,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { crate fn mirror_block(&mut self, block: &'tcx hir::Block<'tcx>) -> Block<'thir, 'tcx> { // We have to eagerly lower the "spine" of the statements // in order to get the lexical scoping correctly. - let stmts = self.mirror_stmts(block.hir_id.local_id, &*block.stmts); + let stmts = self.mirror_stmts(block.hir_id.local_id, block.stmts); let opt_destruction_scope = self.region_scope_tree.opt_destruction_scope(block.hir_id.local_id); Block { @@ -23,7 +23,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { opt_destruction_scope, span: block.span, stmts, - expr: block.expr.as_ref().map(|expr| self.mirror_expr(expr)), + expr: block.expr.map(|expr| self.mirror_expr(expr)), safety_mode: match block.rules { hir::BlockCheckMode::DefaultBlock => BlockSafety::Safe, hir::BlockCheckMode::UnsafeBlock(..) => BlockSafety::ExplicitUnsafe(block.hir_id), @@ -59,7 +59,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { data: region::ScopeData::Remainder(region::FirstStatementIndex::new(index)), }; - let mut pattern = self.pattern_from_hir(&local.pat); + let mut pattern = self.pattern_from_hir(local.pat); if let Some(ty) = &local.ty { if let Some(&user_ty) = diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 73ec9ac4dcf86..00456a8bcc3dc 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -203,7 +203,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { ExprKind::Call { ty: method.ty, fun: self.arena.alloc(method), - args: &*self + args: self .arena .alloc_from_iter(vec![self.mirror_expr_inner(fun), tupled_args]), from_hir_call: true, @@ -243,7 +243,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { adt_def, substs, variant_index: index, - fields: &*field_refs, + fields: field_refs, user_ty, base: None, } @@ -277,7 +277,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { if self.typeck_results().is_method_call(expr) { let lhs = self.mirror_expr_inner(lhs); let rhs = self.mirror_expr_inner(rhs); - self.overloaded_operator(expr, &*self.arena.alloc_from_iter(vec![lhs, rhs])) + self.overloaded_operator(expr, self.arena.alloc_from_iter(vec![lhs, rhs])) } else { ExprKind::AssignOp { op: bin_op(op.node), @@ -297,7 +297,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { if self.typeck_results().is_method_call(expr) { let lhs = self.mirror_expr_inner(lhs); let rhs = self.mirror_expr_inner(rhs); - self.overloaded_operator(expr, &*self.arena.alloc_from_iter(vec![lhs, rhs])) + self.overloaded_operator(expr, self.arena.alloc_from_iter(vec![lhs, rhs])) } else { // FIXME overflow match op.node { @@ -332,7 +332,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { expr, expr_ty, None, - &*self.arena.alloc_from_iter(vec![lhs, index]), + self.arena.alloc_from_iter(vec![lhs, index]), expr.span, ) } else { @@ -347,7 +347,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { expr, expr_ty, None, - &*self.arena.alloc_from_iter(iter::once(arg)), + self.arena.alloc_from_iter(iter::once(arg)), expr.span, ) } else { @@ -358,7 +358,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { hir::ExprKind::Unary(hir::UnOp::Not, ref arg) => { if self.typeck_results().is_method_call(expr) { let arg = self.mirror_expr_inner(arg); - self.overloaded_operator(expr, &*self.arena.alloc_from_iter(iter::once(arg))) + self.overloaded_operator(expr, self.arena.alloc_from_iter(iter::once(arg))) } else { ExprKind::Unary { op: UnOp::Not, arg: self.mirror_expr(arg) } } @@ -367,7 +367,7 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { hir::ExprKind::Unary(hir::UnOp::Neg, ref arg) => { if self.typeck_results().is_method_call(expr) { let arg = self.mirror_expr_inner(arg); - self.overloaded_operator(expr, &*self.arena.alloc_from_iter(iter::once(arg))) + self.overloaded_operator(expr, self.arena.alloc_from_iter(iter::once(arg))) } else if let hir::ExprKind::Lit(ref lit) = arg.kind { ExprKind::Literal { literal: self.const_eval_literal(&lit.node, expr_ty, lit.span, true), From 5f38c839ad306bf230adb5f27b98983f1d04722b Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Sat, 6 Mar 2021 22:41:47 +0100 Subject: [PATCH 6/7] Prevent stack overflow when building THIR --- compiler/rustc_mir_build/src/thir/cx/expr.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 00456a8bcc3dc..dfcb52c83c0d7 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -1,6 +1,7 @@ use crate::thir::cx::Cx; use crate::thir::util::UserAnnotatedTyHelpers; use crate::thir::*; +use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_hir as hir; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_index::vec::Idx; @@ -23,7 +24,8 @@ impl<'thir, 'tcx> Cx<'thir, 'tcx> { /// /// [`mirror_exprs`]: Self::mirror_exprs crate fn mirror_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> &'thir Expr<'thir, 'tcx> { - self.arena.alloc(self.mirror_expr_inner(expr)) + // `mirror_expr` is recursing very deep. Make sure the stack doesn't overflow. + ensure_sufficient_stack(|| self.arena.alloc(self.mirror_expr_inner(expr))) } /// Mirrors and allocates a slice of [`hir::Expr`]s. They will be allocated as a From d6c737adb50e194beca9cf0c0a87037738ae8a58 Mon Sep 17 00:00:00 2001 From: LeSeulArtichaut Date: Sun, 7 Mar 2021 00:21:14 +0100 Subject: [PATCH 7/7] Take into account `ExprKind::Scope` when calculating span of temporary --- compiler/rustc_mir_build/src/build/expr/stmt.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_mir_build/src/build/expr/stmt.rs b/compiler/rustc_mir_build/src/build/expr/stmt.rs index a3fbd21642d90..f01315fc5db04 100644 --- a/compiler/rustc_mir_build/src/build/expr/stmt.rs +++ b/compiler/rustc_mir_build/src/build/expr/stmt.rs @@ -141,12 +141,12 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { if let ExprKind::Block { body } = &expr.kind { if let Some(tail_expr) = &body.expr { let mut expr = &*tail_expr; - while let ExprKind::Block { body: subblock } = &expr.kind { - if let Some(subtail_expr) = &subblock.expr { - expr = subtail_expr - } else { - break; - } + while let ExprKind::Block { + body: Block { expr: Some(nested_expr), .. }, + } + | ExprKind::Scope { value: nested_expr, .. } = &expr.kind + { + expr = nested_expr; } this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored: true,