Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 0 additions & 5 deletions compiler/rustc_codegen_cranelift/example/mini_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -622,11 +622,6 @@ impl<T: ?Sized> Deref for Box<T> {
}
}

#[lang = "exchange_malloc"]
unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
unsafe { libc::malloc(size) }
}

#[lang = "drop"]
pub trait Drop {
fn drop(&mut self);
Expand Down
5 changes: 0 additions & 5 deletions compiler/rustc_codegen_gcc/example/mini_core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -628,11 +628,6 @@ impl<T: ?Sized, A: Allocator> Deref for Box<T, A> {
}
}

#[lang = "exchange_malloc"]
unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
libc::malloc(size)
}

#[lang = "drop"]
pub trait Drop {
fn drop(&mut self);
Expand Down
6 changes: 0 additions & 6 deletions compiler/rustc_const_eval/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -384,12 +384,6 @@ const_eval_too_many_caller_args =

const_eval_unallowed_fn_pointer_call = function pointer calls are not allowed in {const_eval_const_context}s

const_eval_unallowed_heap_allocations =
allocations are not allowed in {const_eval_const_context}s
.label = allocation not allowed in {const_eval_const_context}s
.teach_note =
The runtime heap is not yet available at compile-time, so no runtime heap allocations can be created.

const_eval_unallowed_inline_asm =
inline assembly is not allowed in {const_eval_const_context}s

Expand Down
7 changes: 0 additions & 7 deletions compiler/rustc_const_eval/src/check_consts/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -845,13 +845,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
return;
}

// This can be called on stable via the `vec!` macro.
if tcx.is_lang_item(callee, LangItem::ExchangeMalloc) {
self.check_op(ops::HeapAllocation);
// Allow this call, skip all the checks below.
return;
}

// Intrinsics are language primitives, not regular calls, so treat them separately.
if let Some(intrinsic) = tcx.intrinsic(callee) {
if !tcx.is_const_fn(callee) {
Expand Down
12 changes: 0 additions & 12 deletions compiler/rustc_const_eval/src/check_consts/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -541,18 +541,6 @@ impl<'tcx> NonConstOp<'tcx> for Coroutine {
}
}

#[derive(Debug)]
pub(crate) struct HeapAllocation;
impl<'tcx> NonConstOp<'tcx> for HeapAllocation {
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
ccx.dcx().create_err(errors::UnallowedHeapAllocations {
span,
kind: ccx.const_kind(),
teach: ccx.tcx.sess.teach(E0010),
})
}
}

#[derive(Debug)]
pub(crate) struct InlineAsm;
impl<'tcx> NonConstOp<'tcx> for InlineAsm {
Expand Down
11 changes: 0 additions & 11 deletions compiler/rustc_const_eval/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,17 +215,6 @@ pub(crate) struct UnallowedOpInConstContext {
pub msg: String,
}

#[derive(Diagnostic)]
#[diag(const_eval_unallowed_heap_allocations, code = E0010)]
pub(crate) struct UnallowedHeapAllocations {
#[primary_span]
#[label]
pub span: Span,
pub kind: ConstContext,
#[note(const_eval_teach_note)]
pub teach: bool,
}

#[derive(Diagnostic)]
#[diag(const_eval_unallowed_inline_asm, code = E0015)]
pub(crate) struct UnallowedInlineAsm {
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_error_codes/src/error_codes/E0010.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
#### Note: this error code is no longer emitted by the compiler.

The value of statics and constants must be known at compile time, and they live
for the entire lifetime of a program. Creating a boxed value allocates memory on
the heap at runtime, and therefore cannot be done at compile time.

Erroneous code example:

```compile_fail,E0010
```ignore (no longer emitted)
const CON : Vec<i32> = vec![1, 2, 3];
```
3 changes: 2 additions & 1 deletion compiler/rustc_error_codes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
//
// Do *not* remove entries from this list. Instead, just add a note th the corresponding markdown
// file saying that this error is not emitted by the compiler any more (see E0001.md for an
// example), and remove all code examples that do not build any more.
// example), and remove all code examples that do not build any more by marking them
// with `ignore (no longer emitted)`.
#[macro_export]
macro_rules! error_codes {
($macro:path) => (
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_hir/src/lang_items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,6 @@ language_item_table! {
FormatArgument, sym::format_argument, format_argument, Target::Struct, GenericRequirement::None;
FormatArguments, sym::format_arguments, format_arguments, Target::Struct, GenericRequirement::None;

ExchangeMalloc, sym::exchange_malloc, exchange_malloc_fn, Target::Fn, GenericRequirement::None;
DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1);
AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None;

Expand Down
11 changes: 8 additions & 3 deletions compiler/rustc_hir_analysis/src/check/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
| sym::autodiff
| sym::bitreverse
| sym::black_box
| sym::box_new
| sym::breakpoint
| sym::bswap
| sym::caller_location
Expand Down Expand Up @@ -217,6 +216,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
| sym::wrapping_add
| sym::wrapping_mul
| sym::wrapping_sub
| sym::write_box_via_move
// tidy-alphabetical-end
=> hir::Safety::Safe,
_ => hir::Safety::Unsafe,
Expand Down Expand Up @@ -556,6 +556,13 @@ pub(crate) fn check_intrinsic_type(
sym::write_via_move => {
(1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit)
}
sym::write_box_via_move => {
let t = param(0);
let maybe_uninit_t = Ty::new_maybe_uninit(tcx, t);
let box_mu_t = Ty::new_box(tcx, maybe_uninit_t);

(1, 0, vec![box_mu_t, param(0)], box_mu_t)
}

sym::typed_swap_nonoverlapping => {
(1, 0, vec![Ty::new_mut_ptr(tcx, param(0)); 2], tcx.types.unit)
Expand Down Expand Up @@ -648,8 +655,6 @@ pub(crate) fn check_intrinsic_type(

sym::ub_checks | sym::overflow_checks => (0, 0, Vec::new(), tcx.types.bool),

sym::box_new => (1, 0, vec![param(0)], Ty::new_box(tcx, param(0))),

// contract_check_requires::<C>(C) -> bool, where C: impl Fn() -> bool
sym::contract_check_requires => (1, 0, vec![param(0)], tcx.types.unit),
sym::contract_check_ensures => {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3033,6 +3033,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{
let deref_kind = if checked_ty.is_box() {
// detect Box::new(..)
// FIXME: use `box_new` diagnostic item instead?
if let ExprKind::Call(box_new, [_]) = expr.kind
&& let ExprKind::Path(qpath) = &box_new.kind
&& let Res::Def(DefKind::AssocFn, fn_id) =
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_middle/src/thir.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,10 +274,6 @@ pub enum ExprKind<'tcx> {
lint_level: LintLevel,
value: ExprId,
},
/// A `box <value>` expression.
Box {
value: ExprId,
},
/// An `if` expression.
If {
if_then_scope: region::Scope,
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_middle/src/thir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
Scope { value, region_scope: _, lint_level: _ } => {
visitor.visit_expr(&visitor.thir()[value])
}
Box { value } => visitor.visit_expr(&visitor.thir()[value]),
If { cond, then, else_opt, if_then_scope: _ } => {
visitor.visit_expr(&visitor.thir()[cond]);
visitor.visit_expr(&visitor.thir()[then]);
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_mir_build/src/builder/expr/as_place.rs
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
| ExprKind::Unary { .. }
| ExprKind::Binary { .. }
| ExprKind::LogicalOp { .. }
| ExprKind::Box { .. }
| ExprKind::Cast { .. }
| ExprKind::Use { .. }
| ExprKind::NeverToAny { .. }
Expand Down
60 changes: 0 additions & 60 deletions compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
//! See docs in `build/expr/mod.rs`.

use rustc_abi::FieldIdx;
use rustc_hir::lang_items::LangItem;
use rustc_index::{Idx, IndexVec};
use rustc_middle::bug;
use rustc_middle::middle::region::{self, TempLifetime};
Expand Down Expand Up @@ -121,65 +120,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
}
block.and(Rvalue::UnaryOp(op, arg))
}
ExprKind::Box { value } => {
let value_ty = this.thir[value].ty;
let tcx = this.tcx;
let source_info = this.source_info(expr_span);

let size = tcx.require_lang_item(LangItem::SizeOf, expr_span);
let size = Operand::unevaluated_constant(tcx, size, &[value_ty.into()], expr_span);

let align = tcx.require_lang_item(LangItem::AlignOf, expr_span);
let align =
Operand::unevaluated_constant(tcx, align, &[value_ty.into()], expr_span);

// malloc some memory of suitable size and align:
let exchange_malloc = Operand::function_handle(
tcx,
tcx.require_lang_item(LangItem::ExchangeMalloc, expr_span),
[],
expr_span,
);
let storage = this.temp(Ty::new_mut_ptr(tcx, tcx.types.u8), expr_span);
let success = this.cfg.start_new_block();
this.cfg.terminate(
block,
source_info,
TerminatorKind::Call {
func: exchange_malloc,
args: [
Spanned { node: size, span: DUMMY_SP },
Spanned { node: align, span: DUMMY_SP },
]
.into(),
destination: storage,
target: Some(success),
unwind: UnwindAction::Continue,
call_source: CallSource::Misc,
fn_span: expr_span,
},
);
this.diverge_from(block);
block = success;

let result = this.local_decls.push(LocalDecl::new(expr.ty, expr_span));
this.cfg
.push(block, Statement::new(source_info, StatementKind::StorageLive(result)));
if let Some(scope) = scope.temp_lifetime {
// schedule a shallow free of that memory, lest we unwind:
this.schedule_drop_storage_and_value(expr_span, scope, result);
}

// Transmute `*mut u8` to the box (thus far, uninitialized):
let box_ = Rvalue::ShallowInitBox(Operand::Move(storage), value_ty);
this.cfg.push_assign(block, source_info, Place::from(result), box_);

// initialize the box contents:
block = this
.expr_into_dest(this.tcx.mk_place_deref(Place::from(result)), block, value)
.into_block();
block.and(Rvalue::Use(Operand::Move(Place::from(result))))
}
ExprKind::Cast { source } => {
let source_expr = &this.thir[source];

Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_mir_build/src/builder/expr/category.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,6 @@ impl Category {
| ExprKind::Closure { .. }
| ExprKind::Unary { .. }
| ExprKind::Binary { .. }
| ExprKind::Box { .. }
| ExprKind::Cast { .. }
| ExprKind::PointerCoercion { .. }
| ExprKind::Repeat { .. }
Expand Down
89 changes: 87 additions & 2 deletions compiler/rustc_mir_build/src/builder/expr/into.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
//! See docs in build/expr/mod.rs

use rustc_abi::FieldIdx;
use rustc_ast::{AsmMacro, InlineAsmOptions};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack;
Expand All @@ -9,8 +10,8 @@ use rustc_middle::mir::*;
use rustc_middle::span_bug;
use rustc_middle::thir::*;
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty};
use rustc_span::DUMMY_SP;
use rustc_span::source_map::Spanned;
use rustc_span::{DUMMY_SP, sym};
use rustc_trait_selection::infer::InferCtxtExt;
use tracing::{debug, instrument};

Expand Down Expand Up @@ -365,6 +366,91 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
None
})
}
// Some intrinsics are handled here because they desperately want to avoid introducing
// unnecessary copies.
ExprKind::Call { ty, fun, ref args, .. }
if let ty::FnDef(def_id, generic_args) = ty.kind()
&& let Some(intrinsic) = this.tcx.intrinsic(def_id)
&& matches!(intrinsic.name, sym::write_via_move | sym::write_box_via_move) =>
{
// We still have to evaluate the callee expression as normal (but we don't care
// about its result).
let _fun = unpack!(block = this.as_local_operand(block, fun));

match intrinsic.name {
sym::write_via_move => {
// `write_via_move(ptr, val)` becomes `*ptr = val` but without any dropping.

// The destination must have unit type (so we don't actually have to store anything
// into it).
assert!(destination.ty(&this.local_decls, this.tcx).ty.is_unit());

// Compile this to an assignment of the argument into the destination.
let [ptr, val] = **args else {
span_bug!(expr_span, "invalid write_via_move call")
};
let Some(ptr) = unpack!(block = this.as_local_operand(block, ptr)).place()
else {
span_bug!(expr_span, "invalid write_via_move call")
};
let ptr_deref = ptr.project_deeper(&[ProjectionElem::Deref], this.tcx);
this.expr_into_dest(ptr_deref, block, val)
}
sym::write_box_via_move => {
// The signature is:
// `fn write_box_via_move<T>(b: Box<MaybeUninit<T>>, val: T) -> Box<MaybeUninit<T>>`.
// `write_box_via_move(b, val)` becomes
// ```
// (*b).value.value = val;
// b
// ```
// One crucial aspect of this lowering is that the generated code must
// cause the borrow checker to enforce that `val` lives sufficiently
// long to be stored in `b`. The above lowering does this; anything that
// involves a `*const T` or a `NonNull<T>` does not as those are covariant.
let tcx = this.tcx;

// Extract the operands, compile `b`.
let [b, val] = **args else {
span_bug!(expr_span, "invalid init_box_via_move call")
};
let Some(b) = unpack!(block = this.as_local_operand(block, b)).place()
else {
span_bug!(expr_span, "invalid init_box_via_move call")
};

// Projecting to a field requires the type of that field.
// Concretely, we need `T` and `ManuallyDrop<T>`.
let ty = generic_args.type_at(0);
let manually_drop_adt =
tcx.adt_def(tcx.require_lang_item(LangItem::ManuallyDrop, DUMMY_SP));
let manually_drop_ty =
Ty::new_adt(tcx, manually_drop_adt, tcx.mk_args(&[ty.into()]));

// Generate `(*b).value.value = val;`
let ptr_deref = Place::from(b).project_deeper(
&[
ProjectionElem::Deref,
ProjectionElem::Field(FieldIdx::from_u32(1), manually_drop_ty),
ProjectionElem::Field(FieldIdx::ZERO, ty),
],
tcx,
);
unpack!(block = this.expr_into_dest(ptr_deref, block, val));

// Return `b`
this.cfg.push_assign(
block,
source_info,
destination,
// Move from `b` so that does not get dropped any more.
Rvalue::Use(Operand::Move(b)),
);
block.unit()
}
_ => rustc_middle::bug!(),
}
}
ExprKind::Call { ty: _, fun, ref args, from_hir_call, fn_span } => {
let fun = unpack!(block = this.as_local_operand(block, fun));
let args: Box<[_]> = args
Expand Down Expand Up @@ -769,7 +855,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// these are the cases that are more naturally handled by some other mode
ExprKind::Unary { .. }
| ExprKind::Binary { .. }
| ExprKind::Box { .. }
| ExprKind::Cast { .. }
| ExprKind::PointerCoercion { .. }
| ExprKind::Repeat { .. }
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_mir_build/src/check_unsafety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,6 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
| ExprKind::LoopMatch { .. }
| ExprKind::Let { .. }
| ExprKind::Match { .. }
| ExprKind::Box { .. }
| ExprKind::If { .. }
| ExprKind::InlineAsm { .. }
| ExprKind::LogicalOp { .. }
Expand Down
Loading
Loading