diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 75999225c031d..f943157dc66fa 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -104,7 +104,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } sym::pref_align_of - | sym::min_align_of | sym::needs_drop | sym::type_id | sym::type_name diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 3d8ea29160bd0..f2f93f7f3fe20 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -501,6 +501,20 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { ) } + mir::Rvalue::NullaryOp(mir::NullOp::AlignOf, ty) => { + let ty = self.monomorphize(ty); + assert!(bx.cx().type_is_sized(ty)); + let val = bx.cx().const_usize(bx.cx().layout_of(ty).align.abi.bytes()); + let tcx = self.cx.tcx(); + ( + bx, + OperandRef { + val: OperandValue::Immediate(val), + layout: self.cx.layout_of(tcx.types.usize), + }, + ) + } + mir::Rvalue::NullaryOp(mir::NullOp::Box, content_ty) => { let content_ty = self.monomorphize(content_ty); let content_layout = bx.cx().layout_of(content_ty); @@ -544,6 +558,18 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { OperandRef::new_zst(&mut bx, self.cx.layout_of(self.monomorphize(ty))); (bx, operand) } + mir::Rvalue::InitBox(ref operand, content_ty) => { + let operand = self.codegen_operand(&mut bx, operand); + let lloperand = operand.immediate(); + + let content_ty = self.monomorphize(content_ty); + let box_layout = bx.cx().layout_of(bx.tcx().mk_box(content_ty)); + let llty_ptr = bx.cx().backend_type(box_layout); + + let val = bx.pointercast(lloperand, llty_ptr); + let operand = OperandRef { val: OperandValue::Immediate(val), layout: box_layout }; + (bx, operand) + } } } @@ -757,6 +783,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Rvalue::AddressOf(..) | mir::Rvalue::Len(..) | mir::Rvalue::Cast(..) | // (*) + mir::Rvalue::InitBox(..) | // (*) mir::Rvalue::BinaryOp(..) | mir::Rvalue::CheckedBinaryOp(..) | mir::Rvalue::UnaryOp(..) | diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index b85ed0cb4bbe5..9bdaaa4fab21a 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -294,6 +294,7 @@ language_item_table! { BeginPanicFmt, sym::begin_panic_fmt, begin_panic_fmt, Target::Fn, GenericRequirement::None; ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None; + BoxNew, sym::box_new, box_new_fn, Target::Fn, GenericRequirement::Minimum(1); BoxFree, sym::box_free, box_free_fn, Target::Fn, GenericRequirement::Minimum(1); DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1); Oom, sym::oom, oom, Target::Fn, GenericRequirement::None; diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 83f6e79d5fcf6..6c5539dedc9db 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -2170,6 +2170,8 @@ pub enum Rvalue<'tcx> { /// that `Foo` has a destructor. These rvalues can be optimized /// away after type-checking and before lowering. Aggregate(Box>, Vec>), + + InitBox(Operand<'tcx>, Ty<'tcx>), } #[cfg(target_arch = "x86_64")] @@ -2250,6 +2252,8 @@ impl BinOp { pub enum NullOp { /// Returns the size of a value of that type SizeOf, + /// Returns the minimum alignment of a type + AlignOf, /// Creates a new uninitialized box for a value of that type Box, } @@ -2418,6 +2422,10 @@ impl<'tcx> Debug for Rvalue<'tcx> { }), } } + + InitBox(ref place, ref ty) => { + write!(fmt, "{:?} as box {:?}", place, ty) + } } } } diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs index 74d303cee5d1e..986e17941e416 100644 --- a/compiler/rustc_middle/src/mir/tcx.rs +++ b/compiler/rustc_middle/src/mir/tcx.rs @@ -196,7 +196,7 @@ impl<'tcx> Rvalue<'tcx> { Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx), Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx), Rvalue::NullaryOp(NullOp::Box, t) => tcx.mk_box(t), - Rvalue::NullaryOp(NullOp::SizeOf, _) => tcx.types.usize, + Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => tcx.types.usize, Rvalue::Aggregate(ref ak, ref ops) => match **ak { AggregateKind::Array(ty) => tcx.mk_array(ty, ops.len() as u64), AggregateKind::Tuple => tcx.mk_tup(ops.iter().map(|op| op.ty(local_decls, tcx))), @@ -206,6 +206,7 @@ impl<'tcx> Rvalue<'tcx> { tcx.mk_generator(did, substs, movability) } }, + Rvalue::InitBox(_, ty) => tcx.mk_box(ty), } } @@ -215,6 +216,7 @@ impl<'tcx> Rvalue<'tcx> { pub fn initialization_state(&self) -> RvalueInitializationState { match *self { Rvalue::NullaryOp(NullOp::Box, _) => RvalueInitializationState::Shallow, + Rvalue::InitBox(_, _) => RvalueInitializationState::Shallow, _ => RvalueInitializationState::Deep, } } diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs index b2d4a22194c62..c18a12c490f5a 100644 --- a/compiler/rustc_middle/src/mir/type_foldable.rs +++ b/compiler/rustc_middle/src/mir/type_foldable.rs @@ -210,6 +210,7 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { }); Aggregate(kind, fields.fold_with(folder)) } + InitBox(op, ty) => InitBox(op.fold_with(folder), ty.fold_with(folder)), } } @@ -255,6 +256,10 @@ impl<'tcx> TypeFoldable<'tcx> for Rvalue<'tcx> { } fields.visit_with(visitor) } + InitBox(ref op, ty) => { + op.visit_with(visitor)?; + ty.visit_with(visitor) + } } } } diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index af7f779652260..d27e12b9a7dec 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -753,6 +753,11 @@ macro_rules! make_mir_visitor { self.visit_operand(operand, location); } } + + Rvalue::InitBox(operand, ty) => { + self.visit_operand(operand, location); + self.visit_ty(ty, TyContext::Location(location)); + } } } diff --git a/compiler/rustc_mir/src/borrow_check/invalidation.rs b/compiler/rustc_mir/src/borrow_check/invalidation.rs index b83a427f47574..322d23d8f2f43 100644 --- a/compiler/rustc_mir/src/borrow_check/invalidation.rs +++ b/compiler/rustc_mir/src/borrow_check/invalidation.rs @@ -318,9 +318,8 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { Rvalue::Use(ref operand) | Rvalue::Repeat(ref operand, _) | Rvalue::UnaryOp(_ /*un_op*/, ref operand) - | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) => { - self.consume_operand(location, operand) - } + | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) + | Rvalue::InitBox(ref operand, _ /*ty*/) => self.consume_operand(location, operand), Rvalue::Len(place) | Rvalue::Discriminant(place) => { let af = match *rvalue { diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs index 1dcb067656258..998516f978479 100644 --- a/compiler/rustc_mir/src/borrow_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/mod.rs @@ -1341,7 +1341,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { Rvalue::Use(ref operand) | Rvalue::Repeat(ref operand, _) | Rvalue::UnaryOp(_ /*un_op*/, ref operand) - | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) => { + | Rvalue::Cast(_ /*cast_kind*/, ref operand, _ /*ty*/) + | Rvalue::InitBox(ref operand, _ /*ty*/) => { self.consume_operand(location, (operand, span), flow_state) } diff --git a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs index 639bcb8fa94ef..dca638df1a583 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/mod.rs @@ -2320,6 +2320,25 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } } + Rvalue::InitBox(_, ty) => { + // Even with unsized locals cannot box an unsized value. + if self.unsized_feature_enabled() { + let span = body.source_info(location).span; + self.ensure_place_sized(ty, span); + } + + let trait_ref = ty::TraitRef { + def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)), + substs: tcx.mk_substs_trait(ty, &[]), + }; + + self.prove_trait_ref( + trait_ref, + location.to_locations(), + ConstraintCategory::SizedBound, + ); + } + Rvalue::AddressOf(..) | Rvalue::ThreadLocalRef(..) | Rvalue::Use(..) @@ -2343,6 +2362,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { | Rvalue::AddressOf(..) | Rvalue::Len(..) | Rvalue::Cast(..) + | Rvalue::InitBox(..) | Rvalue::BinaryOp(..) | Rvalue::CheckedBinaryOp(..) | Rvalue::NullaryOp(..) diff --git a/compiler/rustc_mir/src/dataflow/impls/borrowed_locals.rs b/compiler/rustc_mir/src/dataflow/impls/borrowed_locals.rs index 65e04ed6831cc..9ec5b5bd58c4a 100644 --- a/compiler/rustc_mir/src/dataflow/impls/borrowed_locals.rs +++ b/compiler/rustc_mir/src/dataflow/impls/borrowed_locals.rs @@ -169,6 +169,7 @@ where } mir::Rvalue::Cast(..) + | mir::Rvalue::InitBox(..) | mir::Rvalue::Use(..) | mir::Rvalue::ThreadLocalRef(..) | mir::Rvalue::Repeat(..) diff --git a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs index cea465ea1ed9d..b504c2295fbd6 100644 --- a/compiler/rustc_mir/src/dataflow/move_paths/builder.rs +++ b/compiler/rustc_mir/src/dataflow/move_paths/builder.rs @@ -327,6 +327,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { Rvalue::Use(ref operand) | Rvalue::Repeat(ref operand, _) | Rvalue::Cast(_, ref operand, _) + | Rvalue::InitBox(ref operand, _) | Rvalue::UnaryOp(_, ref operand) => self.gather_operand(operand), Rvalue::BinaryOp(ref _binop, box (ref lhs, ref rhs)) | Rvalue::CheckedBinaryOp(ref _binop, box (ref lhs, ref rhs)) => { @@ -342,7 +343,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> { | Rvalue::AddressOf(..) | Rvalue::Discriminant(..) | Rvalue::Len(..) - | Rvalue::NullaryOp(NullOp::SizeOf, _) + | Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) | Rvalue::NullaryOp(NullOp::Box, _) => { // This returns an rvalue with uninitialized contents. We can't // move out of it here because it is an rvalue - assignments always diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs index 07e974b72664b..7e1011456869e 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics.rs @@ -160,17 +160,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_scalar(Scalar::from_machine_usize(result, self), dest)?; } - sym::min_align_of - | sym::pref_align_of + sym::pref_align_of | sym::needs_drop | sym::type_id | sym::type_name | sym::variant_count => { let gid = GlobalId { instance, promoted: None }; let ty = match intrinsic_name { - sym::min_align_of | sym::pref_align_of | sym::variant_count => { - self.tcx.types.usize - } + sym::pref_align_of | sym::variant_count => self.tcx.types.usize, sym::needs_drop => self.tcx.types.bool, sym::type_id => self.tcx.types.u64, sym::type_name => self.tcx.mk_static_str(), diff --git a/compiler/rustc_mir/src/interpret/step.rs b/compiler/rustc_mir/src/interpret/step.rs index 1e96581c392d2..ed977bc727d15 100644 --- a/compiler/rustc_mir/src/interpret/step.rs +++ b/compiler/rustc_mir/src/interpret/step.rs @@ -284,6 +284,29 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { self.write_scalar(Scalar::from_machine_usize(layout.size.bytes(), self), &dest)?; } + NullaryOp(mir::NullOp::AlignOf, ty) => { + let ty = self.subst_from_current_frame_and_normalize_erasing_regions(ty); + let layout = self.layout_of(ty)?; + if layout.is_unsized() { + // FIXME: This should be a span_bug (#80742) + self.tcx.sess.delay_span_bug( + self.frame().current_span(), + &format!("SizeOf nullary MIR operator called for unsized type {}", ty), + ); + throw_inval!(SizeOfUnsizedType(ty)); + } + self.write_scalar( + Scalar::from_machine_usize(layout.align.abi.bytes(), self), + &dest, + )?; + } + + InitBox(ref operand, _) => { + let src = self.eval_operand(operand, None)?; + let v = self.read_immediate(&src)?; + self.write_immediate(*v, &dest)?; + } + Cast(cast_kind, ref operand, cast_ty) => { let src = self.eval_operand(operand, None)?; let cast_ty = self.subst_from_current_frame_and_normalize_erasing_regions(cast_ty); diff --git a/compiler/rustc_mir/src/transform/check_consts/check.rs b/compiler/rustc_mir/src/transform/check_consts/check.rs index 0c38127682359..02db1bc48dd31 100644 --- a/compiler/rustc_mir/src/transform/check_consts/check.rs +++ b/compiler/rustc_mir/src/transform/check_consts/check.rs @@ -648,8 +648,9 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { } } - Rvalue::NullaryOp(NullOp::SizeOf, _) => {} + Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => {} Rvalue::NullaryOp(NullOp::Box, _) => self.check_op(ops::HeapAllocation), + Rvalue::InitBox(_, _) => {} Rvalue::UnaryOp(_, ref operand) => { let ty = operand.ty(self.body, self.tcx); @@ -899,6 +900,12 @@ impl Visitor<'tcx> for Checker<'mir, 'tcx> { return; } + let is_box_new = Some(callee) == tcx.lang_items().box_new_fn(); + if is_box_new { + self.check_op(ops::HeapAllocation); + return; + } + // `async` blocks get lowered to `std::future::from_generator(/* a closure */)`. let is_async_block = Some(callee) == tcx.lang_items().from_generator_fn(); if is_async_block { diff --git a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs b/compiler/rustc_mir/src/transform/check_consts/qualifs.rs index 413a9638eb37b..35adbdfc71eea 100644 --- a/compiler/rustc_mir/src/transform/check_consts/qualifs.rs +++ b/compiler/rustc_mir/src/transform/check_consts/qualifs.rs @@ -166,7 +166,8 @@ where Rvalue::Use(operand) | Rvalue::Repeat(operand, _) | Rvalue::UnaryOp(_, operand) - | Rvalue::Cast(_, operand, _) => in_operand::(cx, in_local, operand), + | Rvalue::Cast(_, operand, _) + | Rvalue::InitBox(operand, _) => in_operand::(cx, in_local, operand), Rvalue::BinaryOp(_, box (lhs, rhs)) | Rvalue::CheckedBinaryOp(_, box (lhs, rhs)) => { in_operand::(cx, in_local, lhs) || in_operand::(cx, in_local, rhs) diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs index 71c07be4c6d8d..6bdc1c9d79351 100644 --- a/compiler/rustc_mir/src/transform/const_prop.rs +++ b/compiler/rustc_mir/src/transform/const_prop.rs @@ -723,6 +723,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { | Rvalue::Repeat(..) | Rvalue::Len(..) | Rvalue::Cast(..) + | Rvalue::InitBox(..) | Rvalue::Discriminant(..) | Rvalue::NullaryOp(..) => {} } diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs index 4f5a467a6ee62..011a3f099da69 100644 --- a/compiler/rustc_mir/src/transform/dest_prop.rs +++ b/compiler/rustc_mir/src/transform/dest_prop.rs @@ -969,6 +969,7 @@ impl<'tcx> Visitor<'tcx> for BorrowCollector { } Rvalue::Cast(..) + | Rvalue::InitBox(..) | Rvalue::Use(..) | Rvalue::Repeat(..) | Rvalue::Len(..) diff --git a/compiler/rustc_mir/src/transform/lower_intrinsics.rs b/compiler/rustc_mir/src/transform/lower_intrinsics.rs index e9f1d4f2ce827..24621e8f371dc 100644 --- a/compiler/rustc_mir/src/transform/lower_intrinsics.rs +++ b/compiler/rustc_mir/src/transform/lower_intrinsics.rs @@ -105,6 +105,19 @@ impl<'tcx> MirPass<'tcx> for LowerIntrinsics { terminator.kind = TerminatorKind::Goto { target }; } } + sym::min_align_of => { + if let Some((destination, target)) = *destination { + let tp_ty = substs.type_at(0); + block.statements.push(Statement { + source_info: terminator.source_info, + kind: StatementKind::Assign(Box::new(( + destination, + Rvalue::NullaryOp(NullOp::AlignOf, tp_ty), + ))), + }); + terminator.kind = TerminatorKind::Goto { target }; + } + } sym::discriminant_value => { if let (Some((destination, target)), Some(arg)) = (*destination, args[0].place()) diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs index 1b43670ba3ac1..8f54518acf7c6 100644 --- a/compiler/rustc_mir/src/transform/promote_consts.rs +++ b/compiler/rustc_mir/src/transform/promote_consts.rs @@ -520,8 +520,11 @@ impl<'tcx> Validator<'_, 'tcx> { Rvalue::NullaryOp(op, _) => match op { NullOp::Box => return Err(Unpromotable), NullOp::SizeOf => {} + NullOp::AlignOf => {} }, + Rvalue::InitBox(_, _) => return Err(Unpromotable), + Rvalue::UnaryOp(op, operand) => { match op { // These operations can never fail. diff --git a/compiler/rustc_mir/src/transform/separate_const_switch.rs b/compiler/rustc_mir/src/transform/separate_const_switch.rs index 87cd27984a073..5b1ae5a0e4f4c 100644 --- a/compiler/rustc_mir/src/transform/separate_const_switch.rs +++ b/compiler/rustc_mir/src/transform/separate_const_switch.rs @@ -204,6 +204,7 @@ fn is_likely_const<'tcx>(mut tracked_place: Place<'tcx>, block: &BasicBlockData< | Rvalue::AddressOf(_, _) | Rvalue::Cast(_, Operand::Constant(_), _) | Rvalue::NullaryOp(_, _) + | Rvalue::InitBox(_, _) | Rvalue::UnaryOp(_, Operand::Constant(_)) => return true, // These rvalues make things ambiguous @@ -301,6 +302,7 @@ fn find_determining_place<'tcx>( | Rvalue::ThreadLocalRef(_) | Rvalue::AddressOf(_, _) | Rvalue::NullaryOp(_, _) + | Rvalue::InitBox(_, _) | Rvalue::UnaryOp(_, Operand::Constant(_)) | Rvalue::Cast(_, Operand::Constant(_), _) => return None, 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 68de1af613d9f..c450c4bef9b24 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,54 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } ExprKind::Box { value } => { let value = &this.thir[value]; + let tcx = this.tcx; + + let fake_scope = this.new_source_scope( + expr_span, + LintLevel::Inherited, + Some(Safety::BuiltinUnsafe), + ); + let fake_info = SourceInfo { span: expr_span, scope: fake_scope }; + + let size = this.temp(tcx.types.usize, expr_span); + this.cfg.push_assign( + block, + fake_info, + size, + Rvalue::NullaryOp(NullOp::SizeOf, value.ty), + ); + + let align = this.temp(tcx.types.usize, expr_span); + this.cfg.push_assign( + block, + fake_info, + align, + Rvalue::NullaryOp(NullOp::AlignOf, value.ty), + ); + + 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, + fake_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`. @@ -102,7 +151,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } // malloc some memory of suitable type (thus far, uninitialized): - let box_ = Rvalue::NullaryOp(NullOp::Box, value.ty); + let box_ = Rvalue::InitBox(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/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 24023163cc30e..ae0da6efb02fd 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -364,6 +364,7 @@ symbols! { borrowck_graphviz_postflow, borrowck_graphviz_preflow, box_free, + box_new, box_patterns, box_syntax, bpf_target_feature, diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 3ed3c2382cac6..21b6db3a98e89 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -319,6 +319,18 @@ unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 { } } +#[cfg(not(bootstrap))] +#[cfg(all(not(no_global_oom_handling), not(test)))] +#[lang = "box_new"] +#[inline] +pub(crate) fn box_new() -> *mut u8 { + let layout = Layout::new::(); + match Global.allocate(layout) { + Ok(ptr) => ptr.as_mut_ptr(), + Err(_) => handle_alloc_error(layout), + } +} + #[cfg_attr(not(test), lang = "box_free")] #[inline] // This signature has to be the same as `Box`, otherwise an ICE will happen. diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index e5bbf75c3b0a1..ac4f82a113a8e 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -194,8 +194,9 @@ fn check_rvalue(tcx: TyCtxt<'tcx>, body: &Body<'tcx>, def_id: DefId, rvalue: &Rv )) } }, - Rvalue::NullaryOp(NullOp::SizeOf, _) => Ok(()), + Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, _) => Ok(()), Rvalue::NullaryOp(NullOp::Box, _) => Err((span, "heap allocations are not allowed in const fn".into())), + Rvalue::InitBox(_, _) => Ok(()), Rvalue::UnaryOp(_, operand) => { let ty = operand.ty(body, tcx); if ty.is_integral() || ty.is_bool() {