From 511333fcc41c2a70ece7fa8bd5e0a70adfcb84fd Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Sat, 11 Sep 2021 23:24:55 +0100 Subject: [PATCH] Use Rvalue::ShallowInitBox for box expression --- .../src/build/expr/as_rvalue.rs | 55 ++++++++++++++++++- library/alloc/src/alloc.rs | 1 - 2 files changed, 53 insertions(+), 3 deletions(-) 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 4b40faaf1956..1464ea58ad02 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -5,6 +5,7 @@ use rustc_index::vec::Idx; use crate::build::expr::as_place::PlaceBase; use crate::build::expr::category::{Category, RvalueFunc}; use crate::build::{BlockAnd, BlockAndExtension, Builder}; +use rustc_hir::lang_items::LangItem; use rustc_middle::middle::region; use rustc_middle::mir::AssertKind; use rustc_middle::mir::Place; @@ -88,6 +89,56 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } ExprKind::Box { value } => { let value = &this.thir[value]; + let tcx = this.tcx; + + // `exchange_malloc` is unsafe but box is safe, so need a new scope. + let synth_scope = this.new_source_scope( + expr_span, + LintLevel::Inherited, + Some(Safety::BuiltinUnsafe), + ); + let synth_info = SourceInfo { span: expr_span, scope: synth_scope }; + + let size = this.temp(tcx.types.usize, expr_span); + this.cfg.push_assign( + block, + synth_info, + size, + Rvalue::NullaryOp(NullOp::SizeOf, value.ty), + ); + + let align = this.temp(tcx.types.usize, expr_span); + this.cfg.push_assign( + block, + synth_info, + align, + Rvalue::NullaryOp(NullOp::AlignOf, value.ty), + ); + + // malloc some memory of suitable size and align: + let exchange_malloc = Operand::function_handle( + tcx, + tcx.require_lang_item(LangItem::ExchangeMalloc, Some(expr_span)), + ty::List::empty(), + expr_span, + ); + let storage = this.temp(tcx.mk_mut_ptr(tcx.types.u8), expr_span); + let success = this.cfg.start_new_block(); + this.cfg.terminate( + block, + synth_info, + TerminatorKind::Call { + func: exchange_malloc, + args: vec![Operand::Move(size), Operand::Move(align)], + destination: Some((Place::from(storage), success)), + cleanup: None, + from_hir_call: false, + fn_span: expr_span, + }, + ); + this.diverge_from(block); + block = success; + // 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`. @@ -101,8 +152,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { this.schedule_drop_storage_and_value(expr_span, scope, result); } - // malloc some memory of suitable type (thus far, uninitialized): - let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty); + // Transmute `*mut u8` to the box (thus far, uninitialized): + let box_ = Rvalue::ShallowInitBox(Operand::Move(Place::from(storage)), value.ty); this.cfg.push_assign(block, source_info, Place::from(result), box_); // initialize the box contents: diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 3ed3c2382cac..4a5b0fcf0370 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -307,7 +307,6 @@ unsafe impl Allocator for Global { } /// The allocator for unique pointers. -// This function must not unwind. If it does, MIR codegen will fail. #[cfg(all(not(no_global_oom_handling), not(test)))] #[lang = "exchange_malloc"] #[inline]