add write_box_via_move intrinsic and use it for vec!

This allows us to get rid of box_new entirely
This commit is contained in:
Ralf Jung 2025-10-26 11:04:37 +01:00
parent 93d45480aa
commit 5e65109f21
81 changed files with 1097 additions and 1400 deletions

View file

@ -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);

View file

@ -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);

View file

@ -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) {

View file

@ -540,18 +540,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 {

View file

@ -289,31 +289,6 @@ pub(crate) struct UnallowedOpInConstContext {
pub msg: String,
}
#[derive(Diagnostic)]
#[diag(r#"allocations are not allowed in {$kind ->
[const] constant
[static] static
[const_fn] constant function
*[other] {""}
}s"#, code = E0010)]
pub(crate) struct UnallowedHeapAllocations {
#[primary_span]
#[label(
r#"allocation not allowed in {$kind ->
[const] constant
[static] static
[const_fn] constant function
*[other] {""}
}s"#
)]
pub span: Span,
pub kind: ConstContext,
#[note(
"the runtime heap is not yet available at compile-time, so no runtime heap allocations can be created"
)]
pub teach: bool,
}
#[derive(Diagnostic)]
#[diag(r#"inline assembly is not allowed in {$kind ->
[const] constant

View file

@ -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];
```

View file

@ -20,7 +20,8 @@
//
// Do *not* remove entries from this list. Instead, just add a note to 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]
#[rustfmt::skip]
macro_rules! error_codes {

View file

@ -320,7 +320,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;

View file

@ -77,7 +77,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
@ -223,6 +222,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,
@ -584,6 +584,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)
@ -689,8 +696,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 => {

View file

@ -3110,6 +3110,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) =

View file

@ -268,10 +268,6 @@ pub enum ExprKind<'tcx> {
hir_id: HirId,
value: ExprId,
},
/// A `box <value>` expression.
Box {
value: ExprId,
},
/// An `if` expression.
If {
if_then_scope: region::Scope,

View file

@ -48,7 +48,6 @@ pub fn walk_expr<'thir, 'tcx: 'thir, V: Visitor<'thir, 'tcx>>(
let Expr { kind, ty: _, temp_scope_id: _, span: _ } = expr;
match *kind {
Scope { value, region_scope: _, hir_id: _ } => 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]);

View file

@ -552,7 +552,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
| ExprKind::Unary { .. }
| ExprKind::Binary { .. }
| ExprKind::LogicalOp { .. }
| ExprKind::Box { .. }
| ExprKind::Cast { .. }
| ExprKind::Use { .. }
| ExprKind::NeverToAny { .. }

View file

@ -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};
@ -124,65 +123,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];

View file

@ -64,7 +64,6 @@ impl Category {
| ExprKind::Closure { .. }
| ExprKind::Unary { .. }
| ExprKind::Binary { .. }
| ExprKind::Box { .. }
| ExprKind::Cast { .. }
| ExprKind::PointerCoercion { .. }
| ExprKind::Repeat { .. }

View file

@ -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;
@ -366,17 +367,21 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
None
})
}
// The `write_via_move` intrinsic needs to be special-cased very early to avoid
// introducing unnecessary copies that can be hard to remove again later:
// `write_via_move(ptr, val)` becomes `*ptr = val` but without any dropping.
// 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()
if let ty::FnDef(def_id, generic_args) = ty.kind()
&& let Some(intrinsic) = this.tcx.intrinsic(def_id)
&& intrinsic.name == sym::write_via_move =>
&& 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());
@ -385,12 +390,74 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
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 {
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.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")
};
// Helper to project to a field of an ADT.
let place_project_field = |place: Place<'tcx>, idx: FieldIdx| {
let ty = place.ty(&this.local_decls, tcx).ty;
let ty::Adt(adt, args) = ty.kind() else {
panic!("projecting to field of non-ADT {ty}")
};
let field = &adt.non_enum_variant().fields[idx];
let field_ty = field.ty(tcx, args);
place.project_deeper(&[ProjectionElem::Field(idx, field_ty)], tcx)
};
// `b` is a `Box<MaybeUninit<T>>`.
let place = b.project_deeper(&[ProjectionElem::Deref], tcx);
// Current type: `MaybeUninit<T>`. Field #1 is `ManuallyDrop<T>`.
let place = place_project_field(place, FieldIdx::from_u32(1));
// Current type: `ManuallyDrop<T>`. Field #0 is `MaybeDangling<T>`.
let place = place_project_field(place, FieldIdx::ZERO);
// Current type: `MaybeDangling<T>`. Field #0 is `T`.
let place = place_project_field(place, FieldIdx::ZERO);
// Sanity check.
assert_eq!(place.ty(&this.local_decls, tcx).ty, generic_args.type_at(0));
// Store `val` into place.
unpack!(block = this.expr_into_dest(place, 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
@ -795,7 +862,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 { .. }

View file

@ -449,7 +449,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 { .. }

View file

@ -20,7 +20,7 @@ use rustc_middle::ty::{
self, AdtKind, GenericArgs, InlineConstArgs, InlineConstArgsParts, ScalarInt, Ty, UpvarArgs,
};
use rustc_middle::{bug, span_bug};
use rustc_span::{Span, sym};
use rustc_span::Span;
use tracing::{debug, info, instrument, trace};
use crate::errors::*;
@ -385,24 +385,6 @@ impl<'tcx> ThirBuildCx<'tcx> {
from_hir_call: true,
fn_span: expr.span,
}
} else if let ty::FnDef(def_id, _) = self.typeck_results.expr_ty(fun).kind()
&& let Some(intrinsic) = self.tcx.intrinsic(def_id)
&& intrinsic.name == sym::box_new
{
// We don't actually evaluate `fun` here, so make sure that doesn't miss any side-effects.
if !matches!(fun.kind, hir::ExprKind::Path(_)) {
span_bug!(
expr.span,
"`box_new` intrinsic can only be called via path expression"
);
}
let value = &args[0];
return Expr {
temp_scope_id: expr.hir_id.local_id,
ty: expr_ty,
span: expr.span,
kind: ExprKind::Box { value: self.mirror_expr(value) },
};
} else {
// Tuple-like ADTs are represented as ExprKind::Call. We convert them here.
let adt_data = if let hir::ExprKind::Path(ref qpath) = fun.kind

View file

@ -342,7 +342,6 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
| Binary { .. }
| Block { .. }
| Borrow { .. }
| Box { .. }
| Call { .. }
| ByUse { .. }
| Closure { .. }

View file

@ -223,11 +223,6 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
self.print_expr(*value, depth_lvl + 2);
print_indented!(self, "}", depth_lvl);
}
Box { value } => {
print_indented!(self, "Box {", depth_lvl);
self.print_expr(*value, depth_lvl + 1);
print_indented!(self, "}", depth_lvl);
}
If { if_then_scope, cond, then, else_opt } => {
print_indented!(self, "If {", depth_lvl);
print_indented!(self, format!("if_then_scope: {:?}", if_then_scope), depth_lvl + 1);

View file

@ -990,7 +990,6 @@ symbols! {
exact_div,
except,
exception_handling: "exception-handling",
exchange_malloc,
exclusive_range_pattern,
exhaustive_integer_patterns,
exhaustive_patterns,
@ -2541,6 +2540,7 @@ symbols! {
wrapping_rem_euclid,
wrapping_sub,
wreg,
write_box_via_move,
write_bytes,
write_fmt,
write_macro,

View file

@ -174,7 +174,6 @@ fn recurse_build<'tcx>(
| ExprKind::LoopMatch { .. } => {
error(GenericConstantTooComplexSub::LoopNotSupported(node.span))?
}
ExprKind::Box { .. } => error(GenericConstantTooComplexSub::BoxNotSupported(node.span))?,
ExprKind::ByUse { .. } => {
error(GenericConstantTooComplexSub::ByUseNotSupported(node.span))?
}
@ -260,7 +259,6 @@ impl<'a, 'tcx> IsThirPolymorphic<'a, 'tcx> {
count.has_non_region_param()
}
thir::ExprKind::Scope { .. }
| thir::ExprKind::Box { .. }
| thir::ExprKind::If { .. }
| thir::ExprKind::Call { .. }
| thir::ExprKind::ByUse { .. }

View file

@ -51,8 +51,6 @@ pub(crate) enum GenericConstantTooComplexSub {
YieldNotSupported(#[primary_span] Span),
#[label("loops and loop control flow are not supported in generic constants")]
LoopNotSupported(#[primary_span] Span),
#[label("allocations are not allowed in generic constants")]
BoxNotSupported(#[primary_span] Span),
#[label("unsupported binary operation in generic constants")]
BinaryNotSupported(#[primary_span] Span),
#[label(".use is not allowed in generic constants")]

View file

@ -479,23 +479,6 @@ unsafe impl const Allocator for Global {
}
}
/// The allocator for `Box`.
///
/// # Safety
///
/// `size` and `align` must satisfy the conditions in [`Layout::from_size_align`].
#[cfg(not(no_global_oom_handling))]
#[lang = "exchange_malloc"]
#[inline]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub(crate) unsafe fn exchange_malloc(size: usize, align: usize) -> *mut u8 {
let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
match Global.allocate(layout) {
Ok(ptr) => ptr.as_mut_ptr(),
Err(_) => handle_alloc_error(layout),
}
}
// # Allocation error handler
#[cfg(not(no_global_oom_handling))]

View file

@ -206,7 +206,7 @@ use core::task::{Context, Poll};
#[cfg(not(no_global_oom_handling))]
use crate::alloc::handle_alloc_error;
use crate::alloc::{AllocError, Allocator, Global, Layout, exchange_malloc};
use crate::alloc::{AllocError, Allocator, Global, Layout};
use crate::raw_vec::RawVec;
#[cfg(not(no_global_oom_handling))]
use crate::str::from_boxed_utf8_unchecked;
@ -236,14 +236,34 @@ pub struct Box<
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
>(Unique<T>, A);
/// Constructs a `Box<T>` by calling the `exchange_malloc` lang item and moving the argument into
/// the newly allocated memory. This is an intrinsic to avoid unnecessary copies.
/// Monomorphic function for allocating an uninit `Box`.
///
/// This is the surface syntax for `box <expr>` expressions.
/// # Safety
///
/// size and align need to be safe for `Layout::from_size_align_unchecked`.
#[inline]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
#[cfg(not(no_global_oom_handling))]
unsafe fn box_new_uninit(size: usize, align: usize) -> *mut u8 {
let layout = unsafe { Layout::from_size_align_unchecked(size, align) };
match Global.allocate(layout) {
Ok(ptr) => ptr.as_mut_ptr(),
Err(_) => handle_alloc_error(layout),
}
}
/// Helper for `vec!`.
///
/// This is unsafe, but has to be marked as safe or else we couldn't use it in `vec!`.
#[doc(hidden)]
#[rustc_intrinsic]
#[unstable(feature = "liballoc_internals", issue = "none")]
pub fn box_new<T>(x: T) -> Box<T>;
#[inline(always)]
#[cfg(not(no_global_oom_handling))]
pub fn box_assume_init_into_vec_unsafe<T, const N: usize>(
b: Box<MaybeUninit<[T; N]>>,
) -> crate::vec::Vec<T> {
unsafe { (b.assume_init() as Box<[T]>).into_vec() }
}
impl<T> Box<T> {
/// Allocates memory on the heap and then places `x` into it.
@ -262,9 +282,10 @@ impl<T> Box<T> {
#[rustc_diagnostic_item = "box_new"]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn new(x: T) -> Self {
// SAFETY: the size and align of a valid type `T` are always valid for `Layout`.
// This is `Box::new_uninit` but inlined to avoid build time regressions.
// SAFETY: The size and align of a valid type `T` are always valid for `Layout`.
let ptr = unsafe {
exchange_malloc(<T as SizedTypeProperties>::SIZE, <T as SizedTypeProperties>::ALIGN)
box_new_uninit(<T as SizedTypeProperties>::SIZE, <T as SizedTypeProperties>::ALIGN)
} as *mut T;
// Nothing below can panic so we do not have to worry about deallocating `ptr`.
// SAFETY: we just allocated the box to store `x`.
@ -288,9 +309,21 @@ impl<T> Box<T> {
#[cfg(not(no_global_oom_handling))]
#[stable(feature = "new_uninit", since = "1.82.0")]
#[must_use]
#[inline]
#[inline(always)]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn new_uninit() -> Box<mem::MaybeUninit<T>> {
Self::new_uninit_in(Global)
// This is the same as `Self::new_uninit_in(Global)`, but manually inlined (just like
// `Box::new`).
// SAFETY:
// - The size and align of a valid type `T` are always valid for `Layout`.
// - If `allocate` succeeds, the returned pointer exactly matches what `Box` needs.
unsafe {
mem::transmute(box_new_uninit(
<T as SizedTypeProperties>::SIZE,
<T as SizedTypeProperties>::ALIGN,
))
}
}
/// Constructs a new `Box` with uninitialized contents, with the memory
@ -1150,10 +1183,12 @@ impl<T, A: Allocator> Box<mem::MaybeUninit<T>, A> {
/// assert_eq!(*five, 5)
/// ```
#[stable(feature = "new_uninit", since = "1.82.0")]
#[inline]
#[inline(always)]
pub unsafe fn assume_init(self) -> Box<T, A> {
let (raw, alloc) = Box::into_raw_with_allocator(self);
unsafe { Box::from_raw_in(raw as *mut T, alloc) }
// This is used in the `vec!` macro, so we optimize for minimal IR generation
// even in debug builds.
// SAFETY: `Box<T>` and `Box<MaybeUninit<T>>` have the same layout.
unsafe { core::intrinsics::transmute_unchecked(self) }
}
/// Writes the value and converts to `Box<T, A>`.

View file

@ -0,0 +1,15 @@
//! Intrinsics that cannot be moved to `core` because they depend on `alloc` types.
#![unstable(feature = "liballoc_internals", issue = "none")]
use core::mem::MaybeUninit;
use crate::boxed::Box;
/// Writes `x` into `b`.
///
/// This is needed for `vec!`, which can't afford any extra copies of the argument (or else debug
/// builds regress), has to be written fully as a call chain without `let` (or else this breaks inference
/// of e.g. unsizing coercions), and can't use an `unsafe` block as that would then also
/// include the user-provided `$x`.
#[rustc_intrinsic]
pub fn write_box_via_move<T>(b: Box<MaybeUninit<T>>, x: T) -> Box<MaybeUninit<T>>;

View file

@ -224,6 +224,7 @@ pub mod collections;
#[cfg(all(not(no_rc), not(no_sync), not(no_global_oom_handling)))]
pub mod ffi;
pub mod fmt;
pub mod intrinsics;
#[cfg(not(no_rc))]
pub mod rc;
pub mod slice;

View file

@ -47,10 +47,16 @@ macro_rules! vec {
$crate::vec::from_elem($elem, $n)
);
($($x:expr),+ $(,)?) => (
<[_]>::into_vec(
// Using the intrinsic produces a dramatic improvement in stack usage for
// unoptimized programs using this code path to construct large Vecs.
$crate::boxed::box_new([$($x),+])
// Using `write_box_via_move` produces a dramatic improvement in stack usage for unoptimized
// programs using this code path to construct large Vecs. We can't use `write_via_move`
// because this entire invocation has to remain a call chain without `let` bindings, or else
// inference and temporary lifetimes change and things break (see `vec-macro-rvalue-scope`,
// `vec-macro-coercions`, and `autoderef-vec-box-fn-36786` tests).
//
// `box_assume_init_into_vec_unsafe` isn't actually safe but the way we use it here is. We
// can't use an unsafe block as that would also wrap `$x`.
$crate::boxed::box_assume_init_into_vec_unsafe(
$crate::intrinsics::write_box_via_move($crate::boxed::Box::new_uninit(), [$($x),+])
)
);
}

View file

@ -178,6 +178,24 @@ fn extract_if() {
}
}
fn vec_macro_cleanup() {
// Ensure memory gets deallocated when control flow leaves the `vec!` macro.
#[allow(unreachable_code)]
loop {
let _v = vec![Box::new(0), break];
}
fn panic<T>() -> T {
panic!()
}
// Ensure all memory gets deallocated on a panic: the `Box` we construct, and the `Box`
// constructed inside `vec!` to eventually turn into a `Vec`.
std::panic::catch_unwind(|| {
let _v = vec![Box::new(0), panic()];
})
.unwrap_err();
}
fn main() {
assert_eq!(vec_reallocate().len(), 5);
@ -209,4 +227,5 @@ fn main() {
reverse();
miri_issue_2759();
extract_if();
vec_macro_cleanup();
}

View file

@ -0,0 +1,5 @@
thread 'main' ($TID) panicked at tests/pass/vec.rs:LL:CC:
explicit panic
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect

View file

@ -0,0 +1,5 @@
thread 'main' ($TID) panicked at tests/pass/vec.rs:LL:CC:
explicit panic
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect

View file

@ -2450,7 +2450,6 @@ ui/single-use-lifetime/issue-107998.rs
ui/single-use-lifetime/issue-117965.rs
ui/span/issue-107353.rs
ui/span/issue-11925.rs
ui/span/issue-15480.rs
ui/span/issue-23338-locals-die-before-temps-of-body.rs
ui/span/issue-23729.rs
ui/span/issue-23827.rs

View file

@ -42,7 +42,6 @@ pub fn foo2() -> Box<dyn TestTrait2> {
}
//~ MONO_ITEM fn <TestStruct2 as TestTrait2>::test_func2
//~ MONO_ITEM fn alloc::alloc::exchange_malloc
//~ MONO_ITEM fn foo2
//~ MONO_ITEM fn std::alloc::Global::alloc_impl_runtime
//~ MONO_ITEM fn std::boxed::Box::<TestStruct2>::new

View file

@ -1,89 +0,0 @@
- // MIR for `main` before ElaborateDrops
+ // MIR for `main` after ElaborateDrops
fn main() -> () {
let mut _0: ();
let _1: std::boxed::Box<S>;
let mut _2: *mut u8;
let mut _3: std::boxed::Box<S>;
let _4: ();
let mut _5: std::boxed::Box<S>;
+ let mut _6: &mut std::boxed::Box<S>;
+ let mut _7: ();
+ let mut _8: *const S;
scope 1 {
debug x => _1;
}
bb0: {
StorageLive(_1);
_2 = alloc::alloc::exchange_malloc(const <S as std::mem::SizedTypeProperties>::SIZE, const <S as std::mem::SizedTypeProperties>::ALIGN) -> [return: bb1, unwind continue];
}
bb1: {
StorageLive(_3);
_3 = ShallowInitBox(move _2, S);
(*_3) = S::new() -> [return: bb2, unwind: bb8];
}
bb2: {
_1 = move _3;
- drop(_3) -> [return: bb3, unwind continue];
+ goto -> bb3;
}
bb3: {
StorageDead(_3);
StorageLive(_4);
StorageLive(_5);
_5 = move _1;
_4 = std::mem::drop::<Box<S>>(move _5) -> [return: bb4, unwind: bb6];
}
bb4: {
StorageDead(_5);
StorageDead(_4);
_0 = const ();
- drop(_1) -> [return: bb5, unwind continue];
+ goto -> bb5;
}
bb5: {
StorageDead(_1);
return;
}
bb6 (cleanup): {
- drop(_5) -> [return: bb7, unwind terminate(cleanup)];
+ goto -> bb7;
}
bb7 (cleanup): {
- drop(_1) -> [return: bb9, unwind terminate(cleanup)];
+ goto -> bb9;
}
bb8 (cleanup): {
- drop(_3) -> [return: bb9, unwind terminate(cleanup)];
+ goto -> bb12;
}
bb9 (cleanup): {
resume;
+ }
+
+ bb10 (cleanup): {
+ _6 = &mut _3;
+ _7 = <Box<S> as Drop>::drop(move _6) -> [return: bb9, unwind terminate(cleanup)];
+ }
+
+ bb11 (cleanup): {
+ goto -> bb10;
+ }
+
+ bb12 (cleanup): {
+ _8 = copy ((_3.0: std::ptr::Unique<S>).0: std::ptr::NonNull<S>) as *const S (Transmute);
+ goto -> bb11;
}
}

View file

@ -1,39 +0,0 @@
//@ test-mir-pass: ElaborateDrops
//@ needs-unwind
#![feature(rustc_attrs, liballoc_internals)]
// EMIT_MIR box_expr.main.ElaborateDrops.diff
fn main() {
// CHECK-LABEL: fn main(
// CHECK: [[ptr:_.*]] = move {{_.*}} as *const S (Transmute);
// CHECK: [[nonnull:_.*]] = NonNull::<S> { pointer: move [[ptr]] };
// CHECK: [[unique:_.*]] = std::ptr::Unique::<S> { pointer: move [[nonnull]], _marker: const PhantomData::<S> };
// CHECK: [[box:_.*]] = Box::<S>(move [[unique]], const std::alloc::Global);
// CHECK: [[ptr:_.*]] = copy (([[box]].0: std::ptr::Unique<S>).0: std::ptr::NonNull<S>) as *const S (Transmute);
// CHECK: (*[[ptr]]) = S::new() -> [return: [[ret:bb.*]], unwind: [[unwind:bb.*]]];
// CHECK: [[ret]]: {
// CHECK: [[box2:_.*]] = move [[box]];
// CHECK: [[box3:_.*]] = move [[box2]];
// CHECK: std::mem::drop::<Box<S>>(move [[box3]])
// CHECK: [[unwind]] (cleanup): {
// CHECK: [[boxref:_.*]] = &mut [[box]];
// CHECK: <Box<S> as Drop>::drop(move [[boxref]])
let x = std::boxed::box_new(S::new());
drop(x);
}
struct S;
impl S {
fn new() -> Self {
S
}
}
impl Drop for S {
fn drop(&mut self) {
println!("splat!");
}
}

View file

@ -0,0 +1,68 @@
// MIR for `move_out_by_subslice` after CleanupPostBorrowck
fn move_out_by_subslice() -> () {
let mut _0: ();
let _1: [std::boxed::Box<i32>; 2];
let mut _2: std::boxed::Box<i32>;
let mut _3: std::boxed::Box<i32>;
scope 1 {
debug a => _1;
let _4: [std::boxed::Box<i32>; 2];
scope 2 {
debug _y => _4;
}
}
bb0: {
StorageLive(_1);
StorageLive(_2);
_2 = Box::<i32>::new(const 1_i32) -> [return: bb1, unwind: bb9];
}
bb1: {
StorageLive(_3);
_3 = Box::<i32>::new(const 2_i32) -> [return: bb2, unwind: bb8];
}
bb2: {
_1 = [move _2, move _3];
drop(_3) -> [return: bb3, unwind: bb8];
}
bb3: {
StorageDead(_3);
drop(_2) -> [return: bb4, unwind: bb9];
}
bb4: {
StorageDead(_2);
nop;
PlaceMention(_1);
StorageLive(_4);
_4 = move _1[0..2];
_0 = const ();
drop(_4) -> [return: bb5, unwind: bb7];
}
bb5: {
StorageDead(_4);
drop(_1) -> [return: bb6, unwind: bb9];
}
bb6: {
StorageDead(_1);
return;
}
bb7 (cleanup): {
drop(_1) -> [return: bb9, unwind terminate(cleanup)];
}
bb8 (cleanup): {
drop(_2) -> [return: bb9, unwind terminate(cleanup)];
}
bb9 (cleanup): {
resume;
}
}

View file

@ -1,99 +0,0 @@
// MIR for `move_out_by_subslice` after built
fn move_out_by_subslice() -> () {
let mut _0: ();
let _1: [std::boxed::Box<i32>; 2];
let mut _2: std::boxed::Box<i32>;
let mut _3: *mut u8;
let mut _4: std::boxed::Box<i32>;
let mut _5: std::boxed::Box<i32>;
let mut _6: *mut u8;
let mut _7: std::boxed::Box<i32>;
scope 1 {
debug a => _1;
let _8: [std::boxed::Box<i32>; 2];
scope 2 {
debug _y => _8;
}
}
bb0: {
StorageLive(_1);
StorageLive(_2);
_3 = alloc::alloc::exchange_malloc(const <i32 as std::mem::SizedTypeProperties>::SIZE, const <i32 as std::mem::SizedTypeProperties>::ALIGN) -> [return: bb1, unwind: bb13];
}
bb1: {
StorageLive(_4);
_4 = ShallowInitBox(move _3, i32);
(*_4) = const 1_i32;
_2 = move _4;
drop(_4) -> [return: bb2, unwind: bb12];
}
bb2: {
StorageDead(_4);
StorageLive(_5);
_6 = alloc::alloc::exchange_malloc(const <i32 as std::mem::SizedTypeProperties>::SIZE, const <i32 as std::mem::SizedTypeProperties>::ALIGN) -> [return: bb3, unwind: bb12];
}
bb3: {
StorageLive(_7);
_7 = ShallowInitBox(move _6, i32);
(*_7) = const 2_i32;
_5 = move _7;
drop(_7) -> [return: bb4, unwind: bb11];
}
bb4: {
StorageDead(_7);
_1 = [move _2, move _5];
drop(_5) -> [return: bb5, unwind: bb12];
}
bb5: {
StorageDead(_5);
drop(_2) -> [return: bb6, unwind: bb13];
}
bb6: {
StorageDead(_2);
FakeRead(ForLet(None), _1);
PlaceMention(_1);
StorageLive(_8);
_8 = move _1[0..2];
_0 = const ();
drop(_8) -> [return: bb8, unwind: bb10];
}
bb7: {
FakeRead(ForMatchedPlace(None), _1);
unreachable;
}
bb8: {
StorageDead(_8);
drop(_1) -> [return: bb9, unwind: bb13];
}
bb9: {
StorageDead(_1);
return;
}
bb10 (cleanup): {
drop(_1) -> [return: bb13, unwind terminate(cleanup)];
}
bb11 (cleanup): {
drop(_5) -> [return: bb12, unwind terminate(cleanup)];
}
bb12 (cleanup): {
drop(_2) -> [return: bb13, unwind terminate(cleanup)];
}
bb13 (cleanup): {
resume;
}
}

View file

@ -0,0 +1,68 @@
// MIR for `move_out_from_end` after CleanupPostBorrowck
fn move_out_from_end() -> () {
let mut _0: ();
let _1: [std::boxed::Box<i32>; 2];
let mut _2: std::boxed::Box<i32>;
let mut _3: std::boxed::Box<i32>;
scope 1 {
debug a => _1;
let _4: std::boxed::Box<i32>;
scope 2 {
debug _y => _4;
}
}
bb0: {
StorageLive(_1);
StorageLive(_2);
_2 = Box::<i32>::new(const 1_i32) -> [return: bb1, unwind: bb9];
}
bb1: {
StorageLive(_3);
_3 = Box::<i32>::new(const 2_i32) -> [return: bb2, unwind: bb8];
}
bb2: {
_1 = [move _2, move _3];
drop(_3) -> [return: bb3, unwind: bb8];
}
bb3: {
StorageDead(_3);
drop(_2) -> [return: bb4, unwind: bb9];
}
bb4: {
StorageDead(_2);
nop;
PlaceMention(_1);
StorageLive(_4);
_4 = move _1[1 of 2];
_0 = const ();
drop(_4) -> [return: bb5, unwind: bb7];
}
bb5: {
StorageDead(_4);
drop(_1) -> [return: bb6, unwind: bb9];
}
bb6: {
StorageDead(_1);
return;
}
bb7 (cleanup): {
drop(_1) -> [return: bb9, unwind terminate(cleanup)];
}
bb8 (cleanup): {
drop(_2) -> [return: bb9, unwind terminate(cleanup)];
}
bb9 (cleanup): {
resume;
}
}

View file

@ -1,99 +0,0 @@
// MIR for `move_out_from_end` after built
fn move_out_from_end() -> () {
let mut _0: ();
let _1: [std::boxed::Box<i32>; 2];
let mut _2: std::boxed::Box<i32>;
let mut _3: *mut u8;
let mut _4: std::boxed::Box<i32>;
let mut _5: std::boxed::Box<i32>;
let mut _6: *mut u8;
let mut _7: std::boxed::Box<i32>;
scope 1 {
debug a => _1;
let _8: std::boxed::Box<i32>;
scope 2 {
debug _y => _8;
}
}
bb0: {
StorageLive(_1);
StorageLive(_2);
_3 = alloc::alloc::exchange_malloc(const <i32 as std::mem::SizedTypeProperties>::SIZE, const <i32 as std::mem::SizedTypeProperties>::ALIGN) -> [return: bb1, unwind: bb13];
}
bb1: {
StorageLive(_4);
_4 = ShallowInitBox(move _3, i32);
(*_4) = const 1_i32;
_2 = move _4;
drop(_4) -> [return: bb2, unwind: bb12];
}
bb2: {
StorageDead(_4);
StorageLive(_5);
_6 = alloc::alloc::exchange_malloc(const <i32 as std::mem::SizedTypeProperties>::SIZE, const <i32 as std::mem::SizedTypeProperties>::ALIGN) -> [return: bb3, unwind: bb12];
}
bb3: {
StorageLive(_7);
_7 = ShallowInitBox(move _6, i32);
(*_7) = const 2_i32;
_5 = move _7;
drop(_7) -> [return: bb4, unwind: bb11];
}
bb4: {
StorageDead(_7);
_1 = [move _2, move _5];
drop(_5) -> [return: bb5, unwind: bb12];
}
bb5: {
StorageDead(_5);
drop(_2) -> [return: bb6, unwind: bb13];
}
bb6: {
StorageDead(_2);
FakeRead(ForLet(None), _1);
PlaceMention(_1);
StorageLive(_8);
_8 = move _1[1 of 2];
_0 = const ();
drop(_8) -> [return: bb8, unwind: bb10];
}
bb7: {
FakeRead(ForMatchedPlace(None), _1);
unreachable;
}
bb8: {
StorageDead(_8);
drop(_1) -> [return: bb9, unwind: bb13];
}
bb9: {
StorageDead(_1);
return;
}
bb10 (cleanup): {
drop(_1) -> [return: bb13, unwind terminate(cleanup)];
}
bb11 (cleanup): {
drop(_5) -> [return: bb12, unwind terminate(cleanup)];
}
bb12 (cleanup): {
drop(_2) -> [return: bb13, unwind terminate(cleanup)];
}
bb13 (cleanup): {
resume;
}
}

View file

@ -1,16 +1,17 @@
//@ compile-flags: -Zmir-opt-level=0
// skip-filecheck
#![feature(liballoc_internals, rustc_attrs)]
// EMIT_MIR uniform_array_move_out.move_out_from_end.built.after.mir
// Can't emit `built.after` here as that contains user type annotations which contain DefId that
// change all the time.
// EMIT_MIR uniform_array_move_out.move_out_from_end.CleanupPostBorrowck.after.mir
fn move_out_from_end() {
let a = [std::boxed::box_new(1), std::boxed::box_new(2)];
let a = [Box::new(1), Box::new(2)];
let [.., _y] = a;
}
// EMIT_MIR uniform_array_move_out.move_out_by_subslice.built.after.mir
// EMIT_MIR uniform_array_move_out.move_out_by_subslice.CleanupPostBorrowck.after.mir
fn move_out_by_subslice() {
let a = [std::boxed::box_new(1), std::boxed::box_new(2)];
let a = [Box::new(1), Box::new(2)];
let [_y @ ..] = a;
}

View file

@ -0,0 +1,58 @@
// MIR for `box_new` after CleanupPostBorrowck
fn box_new(_1: T) -> Box<[T; 1024]> {
debug x => _1;
let mut _0: std::boxed::Box<[T; 1024]>;
let mut _2: std::boxed::Box<std::mem::MaybeUninit<[T; 1024]>>;
let mut _3: std::boxed::Box<std::mem::MaybeUninit<[T; 1024]>>;
let mut _4: std::boxed::Box<std::mem::MaybeUninit<[T; 1024]>>;
let mut _5: T;
scope 1 {
debug b => _2;
}
bb0: {
StorageLive(_2);
_2 = Box::<[T; 1024]>::new_uninit() -> [return: bb1, unwind: bb7];
}
bb1: {
nop;
StorageLive(_3);
StorageLive(_4);
_4 = move _2;
StorageLive(_5);
_5 = copy _1;
((((*_4).1: std::mem::ManuallyDrop<[T; 1024]>).0: std::mem::MaybeDangling<[T; 1024]>).0: [T; 1024]) = [move _5; 1024];
StorageDead(_5);
_3 = move _4;
drop(_4) -> [return: bb2, unwind: bb5];
}
bb2: {
StorageDead(_4);
_0 = Box::<MaybeUninit<[T; 1024]>>::assume_init(move _3) -> [return: bb3, unwind: bb5];
}
bb3: {
StorageDead(_3);
drop(_2) -> [return: bb4, unwind: bb7];
}
bb4: {
StorageDead(_2);
return;
}
bb5 (cleanup): {
drop(_3) -> [return: bb6, unwind terminate(cleanup)];
}
bb6 (cleanup): {
drop(_2) -> [return: bb7, unwind terminate(cleanup)];
}
bb7 (cleanup): {
resume;
}
}

View file

@ -0,0 +1,29 @@
//! Ensure we don't generate unnecessary copys for `write_via_move`.
//@ compile-flags: -Zmir-opt-level=0
#![feature(liballoc_internals)]
extern crate alloc;
// Can't emit `built.after` here as that contains user type annotations which contain DefId that
// change all the time.
// EMIT_MIR write_box_via_move.box_new.CleanupPostBorrowck.after.mir
// CHECK-LABEL: fn box_new
#[inline(never)]
fn box_new<T: Copy>(x: T) -> Box<[T; 1024]> {
let mut b = Box::new_uninit();
// Ensure the array gets constructed directly into the deref'd pointer.
// CHECK: (*[[TEMP1:_.+]]) = [{{(move|copy) _.+}}; 1024];
unsafe { alloc::intrinsics::write_box_via_move(b, [x; 1024]).assume_init() }
}
// EMIT_MIR write_box_via_move.vec_macro.CleanupPostBorrowck.after.mir
// CHECK-LABEL: fn vec_macro
fn vec_macro() -> Vec<i32> {
// CHECK: (*[[TEMP1:_.+]]) = [const 0_i32, const 1_i32,
vec![0, 1, 2, 3, 4, 5, 6, 7]
}
fn main() {
box_new(0);
vec_macro();
}

View file

@ -0,0 +1,37 @@
// MIR for `vec_macro` after CleanupPostBorrowck
fn vec_macro() -> Vec<i32> {
let mut _0: std::vec::Vec<i32>;
let mut _1: std::boxed::Box<std::mem::MaybeUninit<[i32; 8]>>;
let mut _2: std::boxed::Box<std::mem::MaybeUninit<[i32; 8]>>;
bb0: {
StorageLive(_1);
StorageLive(_2);
_2 = Box::<[i32; 8]>::new_uninit() -> [return: bb1, unwind: bb5];
}
bb1: {
((((*_2).1: std::mem::ManuallyDrop<[i32; 8]>).0: std::mem::MaybeDangling<[i32; 8]>).0: [i32; 8]) = [const 0_i32, const 1_i32, const 2_i32, const 3_i32, const 4_i32, const 5_i32, const 6_i32, const 7_i32];
_1 = move _2;
drop(_2) -> [return: bb2, unwind: bb4];
}
bb2: {
StorageDead(_2);
_0 = std::boxed::box_assume_init_into_vec_unsafe::<i32, 8>(move _1) -> [return: bb3, unwind: bb4];
}
bb3: {
StorageDead(_1);
return;
}
bb4 (cleanup): {
drop(_1) -> [return: bb5, unwind terminate(cleanup)];
}
bb5 (cleanup): {
resume;
}
}

View file

@ -1,59 +0,0 @@
- // MIR for `main` before GVN
+ // MIR for `main` after GVN
fn main() -> () {
let mut _0: ();
let _1: i32;
let mut _2: i32;
let mut _3: std::boxed::Box<i32>;
let mut _4: *mut u8;
let mut _5: std::boxed::Box<i32>;
let mut _6: *const i32;
let mut _7: std::ptr::NonNull<i32>;
let mut _8: std::ptr::Unique<i32>;
let mut _9: *const i32;
let mut _10: *const i32;
scope 1 {
debug x => _1;
}
bb0: {
StorageLive(_1);
- StorageLive(_2);
+ nop;
StorageLive(_3);
_4 = alloc::alloc::exchange_malloc(const <i32 as std::mem::SizedTypeProperties>::SIZE, const <i32 as std::mem::SizedTypeProperties>::ALIGN) -> [return: bb1, unwind unreachable];
}
bb1: {
StorageLive(_5);
- _6 = move _4 as *const i32 (Transmute);
- _7 = NonNull::<i32> { pointer: move _6 };
- _8 = std::ptr::Unique::<i32> { pointer: move _7, _marker: const PhantomData::<i32> };
+ _6 = copy _4 as *const i32 (PtrToPtr);
+ _7 = NonNull::<i32> { pointer: copy _6 };
+ _8 = std::ptr::Unique::<i32> { pointer: copy _7, _marker: const PhantomData::<i32> };
_5 = Box::<i32>(move _8, const std::alloc::Global);
- _9 = copy ((_5.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
- (*_9) = const 42_i32;
+ _9 = copy _6;
+ (*_6) = const 42_i32;
_3 = move _5;
StorageDead(_5);
_10 = copy ((_3.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
_2 = copy (*_10);
- _1 = Add(move _2, const 0_i32);
- StorageDead(_2);
+ _1 = copy _2;
+ nop;
drop(_3) -> [return: bb2, unwind unreachable];
}
bb2: {
StorageDead(_3);
_0 = const ();
StorageDead(_1);
return;
}
}

View file

@ -1,63 +0,0 @@
- // MIR for `main` before GVN
+ // MIR for `main` after GVN
fn main() -> () {
let mut _0: ();
let _1: i32;
let mut _2: i32;
let mut _3: std::boxed::Box<i32>;
let mut _4: *mut u8;
let mut _5: std::boxed::Box<i32>;
let mut _6: *const i32;
let mut _7: std::ptr::NonNull<i32>;
let mut _8: std::ptr::Unique<i32>;
let mut _9: *const i32;
let mut _10: *const i32;
scope 1 {
debug x => _1;
}
bb0: {
StorageLive(_1);
- StorageLive(_2);
+ nop;
StorageLive(_3);
_4 = alloc::alloc::exchange_malloc(const <i32 as std::mem::SizedTypeProperties>::SIZE, const <i32 as std::mem::SizedTypeProperties>::ALIGN) -> [return: bb1, unwind continue];
}
bb1: {
StorageLive(_5);
- _6 = move _4 as *const i32 (Transmute);
- _7 = NonNull::<i32> { pointer: move _6 };
- _8 = std::ptr::Unique::<i32> { pointer: move _7, _marker: const PhantomData::<i32> };
+ _6 = copy _4 as *const i32 (PtrToPtr);
+ _7 = NonNull::<i32> { pointer: copy _6 };
+ _8 = std::ptr::Unique::<i32> { pointer: copy _7, _marker: const PhantomData::<i32> };
_5 = Box::<i32>(move _8, const std::alloc::Global);
- _9 = copy ((_5.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
- (*_9) = const 42_i32;
+ _9 = copy _6;
+ (*_6) = const 42_i32;
_3 = move _5;
StorageDead(_5);
_10 = copy ((_3.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
_2 = copy (*_10);
- _1 = Add(move _2, const 0_i32);
- StorageDead(_2);
+ _1 = copy _2;
+ nop;
drop(_3) -> [return: bb2, unwind: bb3];
}
bb2: {
StorageDead(_3);
_0 = const ();
StorageDead(_1);
return;
}
bb3 (cleanup): {
resume;
}
}

View file

@ -1,17 +0,0 @@
//@ test-mir-pass: GVN
//@ compile-flags: -O
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
#![feature(rustc_attrs, liballoc_internals)]
// Note: this test verifies that we, in fact, do not const prop `#[rustc_box]`
// EMIT_MIR boxes.main.GVN.diff
fn main() {
// CHECK-LABEL: fn main(
// CHECK: debug x => [[x:_.*]];
// CHECK: (*{{_.*}}) = const 42_i32;
// CHECK: [[tmp:_.*]] = copy (*{{_.*}});
// CHECK: [[x]] = copy [[tmp]];
let x = *(std::boxed::box_new(42)) + 0;
}

View file

@ -11,9 +11,9 @@
let mut _9: *const [()];
let mut _10: std::boxed::Box<()>;
let mut _11: *const ();
let mut _16: usize;
let mut _17: usize;
let mut _26: usize;
let mut _14: usize;
let mut _15: usize;
let mut _24: usize;
scope 1 {
debug vp_ctx => _1;
let _5: *const ();
@ -26,49 +26,49 @@
scope 4 {
debug _x => _8;
}
scope 19 (inlined foo) {
let mut _27: *const [()];
scope 20 (inlined foo) {
let mut _25: *const [()];
}
}
scope 17 (inlined slice_from_raw_parts::<()>) {
scope 18 (inlined std::ptr::from_raw_parts::<[()], ()>) {
scope 18 (inlined slice_from_raw_parts::<()>) {
scope 19 (inlined std::ptr::from_raw_parts::<[()], ()>) {
}
}
}
}
scope 5 (inlined Box::<()>::new) {
let mut _12: *mut u8;
let mut _13: *const ();
let mut _14: std::ptr::NonNull<()>;
let mut _15: std::ptr::Unique<()>;
scope 6 (inlined alloc::alloc::exchange_malloc) {
let _18: std::alloc::Layout;
let mut _19: std::result::Result<std::ptr::NonNull<[u8]>, std::alloc::AllocError>;
let mut _20: isize;
let mut _22: !;
scope 7 {
let _21: std::ptr::NonNull<[u8]>;
let mut _12: *mut ();
let mut _13: *mut u8;
scope 6 {
}
scope 7 (inlined boxed::box_new_uninit) {
let _16: std::alloc::Layout;
let mut _17: std::result::Result<std::ptr::NonNull<[u8]>, std::alloc::AllocError>;
let mut _18: isize;
let mut _20: !;
scope 8 {
scope 12 (inlined NonNull::<[u8]>::as_mut_ptr) {
scope 13 (inlined NonNull::<[u8]>::as_non_null_ptr) {
scope 14 (inlined NonNull::<[u8]>::cast::<u8>) {
let mut _25: *mut [u8];
scope 15 (inlined NonNull::<[u8]>::as_ptr) {
let _19: std::ptr::NonNull<[u8]>;
scope 9 {
scope 13 (inlined NonNull::<[u8]>::as_mut_ptr) {
scope 14 (inlined NonNull::<[u8]>::as_non_null_ptr) {
scope 15 (inlined NonNull::<[u8]>::cast::<u8>) {
let mut _23: *mut [u8];
scope 16 (inlined NonNull::<[u8]>::as_ptr) {
}
}
}
scope 16 (inlined NonNull::<u8>::as_ptr) {
scope 17 (inlined NonNull::<u8>::as_ptr) {
}
}
}
scope 10 (inlined <std::alloc::Global as Allocator>::allocate) {
scope 11 (inlined std::alloc::Global::alloc_impl) {
scope 11 (inlined <std::alloc::Global as Allocator>::allocate) {
scope 12 (inlined std::alloc::Global::alloc_impl) {
}
}
}
scope 9 (inlined #[track_caller] Layout::from_size_align_unchecked) {
let _23: ();
let mut _24: std::ptr::Alignment;
scope 10 (inlined #[track_caller] Layout::from_size_align_unchecked) {
let _21: ();
let mut _22: std::ptr::Alignment;
}
}
}
@ -83,18 +83,16 @@
StorageLive(_12);
StorageLive(_13);
StorageLive(_14);
- _14 = const <() as std::mem::SizedTypeProperties>::SIZE;
+ _14 = const 0_usize;
StorageLive(_15);
- _15 = const <() as std::mem::SizedTypeProperties>::ALIGN;
+ _15 = const 1_usize;
StorageLive(_16);
- _16 = const <() as std::mem::SizedTypeProperties>::SIZE;
+ _16 = const 0_usize;
StorageLive(_17);
- _17 = const <() as std::mem::SizedTypeProperties>::ALIGN;
+ _17 = const 1_usize;
StorageLive(_18);
StorageLive(_19);
StorageLive(_20);
StorageLive(_21);
StorageLive(_22);
StorageLive(_23);
switchInt(UbChecks) -> [0: bb6, otherwise: bb5];
}
@ -109,35 +107,31 @@
}
bb3: {
- _22 = handle_alloc_error(move _18) -> unwind unreachable;
+ _22 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }}) -> unwind unreachable;
- _20 = handle_alloc_error(move _16) -> unwind unreachable;
+ _20 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }}) -> unwind unreachable;
}
bb4: {
_21 = copy ((_19 as Ok).0: std::ptr::NonNull<[u8]>);
- StorageLive(_25);
_19 = copy ((_17 as Ok).0: std::ptr::NonNull<[u8]>);
- StorageLive(_23);
+ nop;
_25 = copy _21 as *mut [u8] (Transmute);
_12 = copy _25 as *mut u8 (PtrToPtr);
- StorageDead(_25);
_23 = copy _19 as *mut [u8] (Transmute);
_13 = copy _23 as *mut u8 (PtrToPtr);
- StorageDead(_23);
+ nop;
StorageDead(_19);
StorageDead(_23);
StorageDead(_22);
StorageDead(_17);
StorageDead(_21);
StorageDead(_20);
StorageDead(_19);
StorageDead(_18);
StorageDead(_17);
StorageDead(_16);
- _13 = copy _12 as *const () (PtrToPtr);
+ _13 = copy _25 as *const () (PtrToPtr);
_14 = NonNull::<()> { pointer: copy _13 };
_15 = std::ptr::Unique::<()> { pointer: copy _14, _marker: const PhantomData::<()> };
_3 = Box::<()>(move _15, const std::alloc::Global);
- (*_13) = move _4;
+ (*_13) = const ();
StorageDead(_15);
StorageDead(_14);
- _12 = copy _13 as *mut () (PtrToPtr);
- (*_12) = move _4;
+ _12 = copy _23 as *mut () (PtrToPtr);
+ (*_12) = const ();
_3 = copy _13 as std::boxed::Box<()> (Transmute);
StorageDead(_13);
StorageDead(_12);
StorageDead(_4);
@ -153,21 +147,21 @@
+ nop;
StorageLive(_7);
_7 = copy _5;
StorageLive(_26);
_26 = const 1_usize;
- _6 = *const [()] from (copy _7, copy _26);
StorageLive(_24);
_24 = const 1_usize;
- _6 = *const [()] from (copy _7, copy _24);
+ _6 = *const [()] from (copy _5, const 1_usize);
StorageDead(_26);
StorageDead(_24);
StorageDead(_7);
StorageLive(_8);
StorageLive(_9);
_9 = copy _6;
StorageLive(_27);
- _27 = copy _9;
StorageLive(_25);
- _25 = copy _9;
- _8 = copy _9 as *mut () (PtrToPtr);
+ _27 = copy _6;
+ _25 = copy _6;
+ _8 = copy _5 as *mut () (PtrToPtr);
StorageDead(_27);
StorageDead(_25);
StorageDead(_9);
_0 = const ();
StorageDead(_8);
@ -179,25 +173,25 @@
}
bb5: {
- _23 = Layout::from_size_align_unchecked::precondition_check(copy _16, copy _17) -> [return: bb6, unwind unreachable];
+ _23 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable];
- _21 = Layout::from_size_align_unchecked::precondition_check(copy _14, copy _15) -> [return: bb6, unwind unreachable];
+ _21 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable];
}
bb6: {
StorageLive(_24);
- _24 = copy _17 as std::ptr::Alignment (Transmute);
- _18 = Layout { size: copy _16, align: move _24 };
+ _24 = const std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }};
+ _18 = const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }};
StorageDead(_24);
StorageLive(_19);
- _19 = std::alloc::Global::alloc_impl_runtime(copy _18, const false) -> [return: bb7, unwind unreachable];
+ _19 = std::alloc::Global::alloc_impl_runtime(const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }}, const false) -> [return: bb7, unwind unreachable];
StorageLive(_22);
- _22 = copy _15 as std::ptr::Alignment (Transmute);
- _16 = Layout { size: copy _14, align: move _22 };
+ _22 = const std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }};
+ _16 = const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }};
StorageDead(_22);
StorageLive(_17);
- _17 = std::alloc::Global::alloc_impl_runtime(copy _16, const false) -> [return: bb7, unwind unreachable];
+ _17 = std::alloc::Global::alloc_impl_runtime(const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }}, const false) -> [return: bb7, unwind unreachable];
}
bb7: {
_20 = discriminant(_19);
switchInt(move _20) -> [0: bb4, 1: bb3, otherwise: bb2];
_18 = discriminant(_17);
switchInt(move _18) -> [0: bb4, 1: bb3, otherwise: bb2];
}
+ }
+

View file

@ -11,9 +11,9 @@
let mut _9: *const [()];
let mut _10: std::boxed::Box<()>;
let mut _11: *const ();
let mut _16: usize;
let mut _17: usize;
let mut _26: usize;
let mut _14: usize;
let mut _15: usize;
let mut _24: usize;
scope 1 {
debug vp_ctx => _1;
let _5: *const ();
@ -26,49 +26,49 @@
scope 4 {
debug _x => _8;
}
scope 19 (inlined foo) {
let mut _27: *const [()];
scope 20 (inlined foo) {
let mut _25: *const [()];
}
}
scope 17 (inlined slice_from_raw_parts::<()>) {
scope 18 (inlined std::ptr::from_raw_parts::<[()], ()>) {
scope 18 (inlined slice_from_raw_parts::<()>) {
scope 19 (inlined std::ptr::from_raw_parts::<[()], ()>) {
}
}
}
}
scope 5 (inlined Box::<()>::new) {
let mut _12: *mut u8;
let mut _13: *const ();
let mut _14: std::ptr::NonNull<()>;
let mut _15: std::ptr::Unique<()>;
scope 6 (inlined alloc::alloc::exchange_malloc) {
let _18: std::alloc::Layout;
let mut _19: std::result::Result<std::ptr::NonNull<[u8]>, std::alloc::AllocError>;
let mut _20: isize;
let mut _22: !;
scope 7 {
let _21: std::ptr::NonNull<[u8]>;
let mut _12: *mut ();
let mut _13: *mut u8;
scope 6 {
}
scope 7 (inlined boxed::box_new_uninit) {
let _16: std::alloc::Layout;
let mut _17: std::result::Result<std::ptr::NonNull<[u8]>, std::alloc::AllocError>;
let mut _18: isize;
let mut _20: !;
scope 8 {
scope 12 (inlined NonNull::<[u8]>::as_mut_ptr) {
scope 13 (inlined NonNull::<[u8]>::as_non_null_ptr) {
scope 14 (inlined NonNull::<[u8]>::cast::<u8>) {
let mut _25: *mut [u8];
scope 15 (inlined NonNull::<[u8]>::as_ptr) {
let _19: std::ptr::NonNull<[u8]>;
scope 9 {
scope 13 (inlined NonNull::<[u8]>::as_mut_ptr) {
scope 14 (inlined NonNull::<[u8]>::as_non_null_ptr) {
scope 15 (inlined NonNull::<[u8]>::cast::<u8>) {
let mut _23: *mut [u8];
scope 16 (inlined NonNull::<[u8]>::as_ptr) {
}
}
}
scope 16 (inlined NonNull::<u8>::as_ptr) {
scope 17 (inlined NonNull::<u8>::as_ptr) {
}
}
}
scope 10 (inlined <std::alloc::Global as Allocator>::allocate) {
scope 11 (inlined std::alloc::Global::alloc_impl) {
scope 11 (inlined <std::alloc::Global as Allocator>::allocate) {
scope 12 (inlined std::alloc::Global::alloc_impl) {
}
}
}
scope 9 (inlined #[track_caller] Layout::from_size_align_unchecked) {
let _23: ();
let mut _24: std::ptr::Alignment;
scope 10 (inlined #[track_caller] Layout::from_size_align_unchecked) {
let _21: ();
let mut _22: std::ptr::Alignment;
}
}
}
@ -83,18 +83,16 @@
StorageLive(_12);
StorageLive(_13);
StorageLive(_14);
- _14 = const <() as std::mem::SizedTypeProperties>::SIZE;
+ _14 = const 0_usize;
StorageLive(_15);
- _15 = const <() as std::mem::SizedTypeProperties>::ALIGN;
+ _15 = const 1_usize;
StorageLive(_16);
- _16 = const <() as std::mem::SizedTypeProperties>::SIZE;
+ _16 = const 0_usize;
StorageLive(_17);
- _17 = const <() as std::mem::SizedTypeProperties>::ALIGN;
+ _17 = const 1_usize;
StorageLive(_18);
StorageLive(_19);
StorageLive(_20);
StorageLive(_21);
StorageLive(_22);
StorageLive(_23);
switchInt(UbChecks) -> [0: bb6, otherwise: bb5];
}
@ -109,35 +107,31 @@
}
bb3: {
- _22 = handle_alloc_error(move _18) -> unwind unreachable;
+ _22 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }}) -> unwind unreachable;
- _20 = handle_alloc_error(move _16) -> unwind unreachable;
+ _20 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }}) -> unwind unreachable;
}
bb4: {
_21 = copy ((_19 as Ok).0: std::ptr::NonNull<[u8]>);
- StorageLive(_25);
_19 = copy ((_17 as Ok).0: std::ptr::NonNull<[u8]>);
- StorageLive(_23);
+ nop;
_25 = copy _21 as *mut [u8] (Transmute);
_12 = copy _25 as *mut u8 (PtrToPtr);
- StorageDead(_25);
_23 = copy _19 as *mut [u8] (Transmute);
_13 = copy _23 as *mut u8 (PtrToPtr);
- StorageDead(_23);
+ nop;
StorageDead(_19);
StorageDead(_23);
StorageDead(_22);
StorageDead(_17);
StorageDead(_21);
StorageDead(_20);
StorageDead(_19);
StorageDead(_18);
StorageDead(_17);
StorageDead(_16);
- _13 = copy _12 as *const () (PtrToPtr);
+ _13 = copy _25 as *const () (PtrToPtr);
_14 = NonNull::<()> { pointer: copy _13 };
_15 = std::ptr::Unique::<()> { pointer: copy _14, _marker: const PhantomData::<()> };
_3 = Box::<()>(move _15, const std::alloc::Global);
- (*_13) = move _4;
+ (*_13) = const ();
StorageDead(_15);
StorageDead(_14);
- _12 = copy _13 as *mut () (PtrToPtr);
- (*_12) = move _4;
+ _12 = copy _23 as *mut () (PtrToPtr);
+ (*_12) = const ();
_3 = copy _13 as std::boxed::Box<()> (Transmute);
StorageDead(_13);
StorageDead(_12);
StorageDead(_4);
@ -153,21 +147,21 @@
+ nop;
StorageLive(_7);
_7 = copy _5;
StorageLive(_26);
_26 = const 1_usize;
- _6 = *const [()] from (copy _7, copy _26);
StorageLive(_24);
_24 = const 1_usize;
- _6 = *const [()] from (copy _7, copy _24);
+ _6 = *const [()] from (copy _5, const 1_usize);
StorageDead(_26);
StorageDead(_24);
StorageDead(_7);
StorageLive(_8);
StorageLive(_9);
_9 = copy _6;
StorageLive(_27);
- _27 = copy _9;
StorageLive(_25);
- _25 = copy _9;
- _8 = copy _9 as *mut () (PtrToPtr);
+ _27 = copy _6;
+ _25 = copy _6;
+ _8 = copy _5 as *mut () (PtrToPtr);
StorageDead(_27);
StorageDead(_25);
StorageDead(_9);
_0 = const ();
StorageDead(_8);
@ -179,25 +173,25 @@
}
bb5: {
- _23 = Layout::from_size_align_unchecked::precondition_check(copy _16, copy _17) -> [return: bb6, unwind unreachable];
+ _23 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable];
- _21 = Layout::from_size_align_unchecked::precondition_check(copy _14, copy _15) -> [return: bb6, unwind unreachable];
+ _21 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable];
}
bb6: {
StorageLive(_24);
- _24 = copy _17 as std::ptr::Alignment (Transmute);
- _18 = Layout { size: copy _16, align: move _24 };
+ _24 = const std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }};
+ _18 = const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }};
StorageDead(_24);
StorageLive(_19);
- _19 = std::alloc::Global::alloc_impl_runtime(copy _18, const false) -> [return: bb7, unwind unreachable];
+ _19 = std::alloc::Global::alloc_impl_runtime(const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }}, const false) -> [return: bb7, unwind unreachable];
StorageLive(_22);
- _22 = copy _15 as std::ptr::Alignment (Transmute);
- _16 = Layout { size: copy _14, align: move _22 };
+ _22 = const std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }};
+ _16 = const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }};
StorageDead(_22);
StorageLive(_17);
- _17 = std::alloc::Global::alloc_impl_runtime(copy _16, const false) -> [return: bb7, unwind unreachable];
+ _17 = std::alloc::Global::alloc_impl_runtime(const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }}, const false) -> [return: bb7, unwind unreachable];
}
bb7: {
_20 = discriminant(_19);
switchInt(move _20) -> [0: bb4, 1: bb3, otherwise: bb2];
_18 = discriminant(_17);
switchInt(move _18) -> [0: bb4, 1: bb3, otherwise: bb2];
}
+ }
+

View file

@ -202,7 +202,7 @@
+ StorageLive(_42);
+ _42 = Option::<()>::None;
+ _35 = copy ((*_37).0: std::option::Option<()>);
+ ((*_37).0: std::option::Option<()>) = copy _42;
+ ((*_37).0: std::option::Option<()>) = move _42;
+ StorageDead(_42);
+ StorageLive(_43);
+ _43 = discriminant(_35);

View file

@ -5,9 +5,9 @@
#![feature(rustc_attrs, liballoc_internals)]
// EMIT_MIR issue_62289.test.ElaborateDrops.before.mir
fn test() -> Option<Box<u32>> {
Some(std::boxed::box_new(None?))
// EMIT_MIR issue_62289.test.ElaborateDrops.after.mir
fn test() -> Option<Vec<u32>> {
Some(vec![None?])
}
fn main() {

View file

@ -0,0 +1,119 @@
// MIR for `test` after ElaborateDrops
fn test() -> Option<Vec<u32>> {
let mut _0: std::option::Option<std::vec::Vec<u32>>;
let mut _1: std::vec::Vec<u32>;
let mut _2: std::boxed::Box<std::mem::MaybeUninit<[u32; 1]>>;
let mut _3: std::boxed::Box<std::mem::MaybeUninit<[u32; 1]>>;
let mut _4: u32;
let mut _5: std::ops::ControlFlow<std::option::Option<std::convert::Infallible>, u32>;
let mut _6: std::option::Option<u32>;
let mut _7: isize;
let _8: std::option::Option<std::convert::Infallible>;
let mut _9: !;
let mut _10: std::option::Option<std::convert::Infallible>;
let _11: u32;
scope 1 {
debug residual => _8;
scope 2 {
}
}
scope 3 {
debug val => _11;
scope 4 {
}
}
bb0: {
StorageLive(_1);
StorageLive(_2);
StorageLive(_3);
_3 = Box::<[u32; 1]>::new_uninit() -> [return: bb1, unwind: bb14];
}
bb1: {
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
_6 = Option::<u32>::None;
_5 = <Option<u32> as Try>::branch(move _6) -> [return: bb2, unwind: bb13];
}
bb2: {
StorageDead(_6);
PlaceMention(_5);
_7 = discriminant(_5);
switchInt(move _7) -> [0: bb4, 1: bb5, otherwise: bb3];
}
bb3: {
unreachable;
}
bb4: {
StorageLive(_11);
_11 = copy ((_5 as Continue).0: u32);
_4 = copy _11;
StorageDead(_11);
((((*_3).1: std::mem::ManuallyDrop<[u32; 1]>).0: std::mem::MaybeDangling<[u32; 1]>).0: [u32; 1]) = [move _4];
StorageDead(_4);
_2 = move _3;
goto -> bb7;
}
bb5: {
StorageLive(_8);
_8 = copy ((_5 as Break).0: std::option::Option<std::convert::Infallible>);
StorageLive(_10);
_10 = copy _8;
_0 = <Option<Vec<u32>> as FromResidual<Option<Infallible>>>::from_residual(move _10) -> [return: bb6, unwind: bb13];
}
bb6: {
StorageDead(_10);
StorageDead(_8);
StorageDead(_4);
drop(_3) -> [return: bb10, unwind: bb14];
}
bb7: {
StorageDead(_3);
_1 = std::boxed::box_assume_init_into_vec_unsafe::<u32, 1>(move _2) -> [return: bb8, unwind: bb12];
}
bb8: {
StorageDead(_2);
_0 = Option::<Vec<u32>>::Some(move _1);
goto -> bb9;
}
bb9: {
StorageDead(_1);
StorageDead(_5);
goto -> bb11;
}
bb10: {
StorageDead(_3);
StorageDead(_2);
StorageDead(_1);
StorageDead(_5);
goto -> bb11;
}
bb11: {
return;
}
bb12 (cleanup): {
goto -> bb14;
}
bb13 (cleanup): {
drop(_3) -> [return: bb14, unwind terminate(cleanup)];
}
bb14 (cleanup): {
resume;
}
}

View file

@ -0,0 +1,119 @@
// MIR for `test` after ElaborateDrops
fn test() -> Option<Vec<u32>> {
let mut _0: std::option::Option<std::vec::Vec<u32>>;
let mut _1: std::vec::Vec<u32>;
let mut _2: std::boxed::Box<std::mem::MaybeUninit<[u32; 1]>>;
let mut _3: std::boxed::Box<std::mem::MaybeUninit<[u32; 1]>>;
let mut _4: u32;
let mut _5: std::ops::ControlFlow<std::option::Option<std::convert::Infallible>, u32>;
let mut _6: std::option::Option<u32>;
let mut _7: isize;
let _8: std::option::Option<std::convert::Infallible>;
let mut _9: !;
let mut _10: std::option::Option<std::convert::Infallible>;
let _11: u32;
scope 1 {
debug residual => _8;
scope 2 {
}
}
scope 3 {
debug val => _11;
scope 4 {
}
}
bb0: {
StorageLive(_1);
StorageLive(_2);
StorageLive(_3);
_3 = Box::<[u32; 1]>::new_uninit() -> [return: bb1, unwind continue];
}
bb1: {
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
_6 = Option::<u32>::None;
_5 = <Option<u32> as Try>::branch(move _6) -> [return: bb2, unwind: bb13];
}
bb2: {
StorageDead(_6);
PlaceMention(_5);
_7 = discriminant(_5);
switchInt(move _7) -> [0: bb4, 1: bb5, otherwise: bb3];
}
bb3: {
unreachable;
}
bb4: {
StorageLive(_11);
_11 = copy ((_5 as Continue).0: u32);
_4 = copy _11;
StorageDead(_11);
((((*_3).1: std::mem::ManuallyDrop<[u32; 1]>).0: std::mem::MaybeDangling<[u32; 1]>).0: [u32; 1]) = [move _4];
StorageDead(_4);
_2 = move _3;
goto -> bb7;
}
bb5: {
StorageLive(_8);
_8 = copy ((_5 as Break).0: std::option::Option<std::convert::Infallible>);
StorageLive(_10);
_10 = copy _8;
_0 = <Option<Vec<u32>> as FromResidual<Option<Infallible>>>::from_residual(move _10) -> [return: bb6, unwind: bb13];
}
bb6: {
StorageDead(_10);
StorageDead(_8);
StorageDead(_4);
drop(_3) -> [return: bb10, unwind: bb14];
}
bb7: {
StorageDead(_3);
_1 = std::boxed::box_assume_init_into_vec_unsafe::<u32, 1>(move _2) -> [return: bb8, unwind: bb12];
}
bb8: {
StorageDead(_2);
_0 = Option::<Vec<u32>>::Some(move _1);
goto -> bb9;
}
bb9: {
StorageDead(_1);
StorageDead(_5);
goto -> bb11;
}
bb10: {
StorageDead(_3);
StorageDead(_2);
StorageDead(_1);
StorageDead(_5);
goto -> bb11;
}
bb11: {
return;
}
bb12 (cleanup): {
goto -> bb14;
}
bb13 (cleanup): {
drop(_3) -> [return: bb14, unwind terminate(cleanup)];
}
bb14 (cleanup): {
resume;
}
}

View file

@ -1,108 +0,0 @@
// MIR for `test` before ElaborateDrops
fn test() -> Option<Box<u32>> {
let mut _0: std::option::Option<std::boxed::Box<u32>>;
let mut _1: std::boxed::Box<u32>;
let mut _2: *mut u8;
let mut _3: std::boxed::Box<u32>;
let mut _4: std::ops::ControlFlow<std::option::Option<std::convert::Infallible>, u32>;
let mut _5: std::option::Option<u32>;
let mut _6: isize;
let _7: std::option::Option<std::convert::Infallible>;
let mut _8: !;
let mut _9: std::option::Option<std::convert::Infallible>;
let _10: u32;
scope 1 {
debug residual => _7;
scope 2 {
}
}
scope 3 {
debug val => _10;
scope 4 {
}
}
bb0: {
StorageLive(_1);
_2 = alloc::alloc::exchange_malloc(const <u32 as std::mem::SizedTypeProperties>::SIZE, const <u32 as std::mem::SizedTypeProperties>::ALIGN) -> [return: bb1, unwind: bb13];
}
bb1: {
StorageLive(_3);
_3 = ShallowInitBox(move _2, u32);
StorageLive(_4);
StorageLive(_5);
_5 = Option::<u32>::None;
_4 = <Option<u32> as Try>::branch(move _5) -> [return: bb2, unwind: bb12];
}
bb2: {
StorageDead(_5);
PlaceMention(_4);
_6 = discriminant(_4);
switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb3];
}
bb3: {
unreachable;
}
bb4: {
StorageLive(_10);
_10 = copy ((_4 as Continue).0: u32);
(*_3) = copy _10;
StorageDead(_10);
_1 = move _3;
drop(_3) -> [return: bb7, unwind: bb11];
}
bb5: {
StorageLive(_7);
_7 = copy ((_4 as Break).0: std::option::Option<std::convert::Infallible>);
StorageLive(_9);
_9 = copy _7;
_0 = <Option<Box<u32>> as FromResidual<Option<Infallible>>>::from_residual(move _9) -> [return: bb6, unwind: bb12];
}
bb6: {
StorageDead(_9);
StorageDead(_7);
drop(_3) -> [return: bb9, unwind: bb13];
}
bb7: {
StorageDead(_3);
_0 = Option::<Box<u32>>::Some(move _1);
drop(_1) -> [return: bb8, unwind: bb13];
}
bb8: {
StorageDead(_1);
StorageDead(_4);
goto -> bb10;
}
bb9: {
StorageDead(_3);
StorageDead(_1);
StorageDead(_4);
goto -> bb10;
}
bb10: {
return;
}
bb11 (cleanup): {
drop(_1) -> [return: bb13, unwind terminate(cleanup)];
}
bb12 (cleanup): {
drop(_3) -> [return: bb13, unwind terminate(cleanup)];
}
bb13 (cleanup): {
resume;
}
}

View file

@ -1,108 +0,0 @@
// MIR for `test` before ElaborateDrops
fn test() -> Option<Box<u32>> {
let mut _0: std::option::Option<std::boxed::Box<u32>>;
let mut _1: std::boxed::Box<u32>;
let mut _2: *mut u8;
let mut _3: std::boxed::Box<u32>;
let mut _4: std::ops::ControlFlow<std::option::Option<std::convert::Infallible>, u32>;
let mut _5: std::option::Option<u32>;
let mut _6: isize;
let _7: std::option::Option<std::convert::Infallible>;
let mut _8: !;
let mut _9: std::option::Option<std::convert::Infallible>;
let _10: u32;
scope 1 {
debug residual => _7;
scope 2 {
}
}
scope 3 {
debug val => _10;
scope 4 {
}
}
bb0: {
StorageLive(_1);
_2 = alloc::alloc::exchange_malloc(const <u32 as std::mem::SizedTypeProperties>::SIZE, const <u32 as std::mem::SizedTypeProperties>::ALIGN) -> [return: bb1, unwind continue];
}
bb1: {
StorageLive(_3);
_3 = ShallowInitBox(move _2, u32);
StorageLive(_4);
StorageLive(_5);
_5 = Option::<u32>::None;
_4 = <Option<u32> as Try>::branch(move _5) -> [return: bb2, unwind: bb12];
}
bb2: {
StorageDead(_5);
PlaceMention(_4);
_6 = discriminant(_4);
switchInt(move _6) -> [0: bb4, 1: bb5, otherwise: bb3];
}
bb3: {
unreachable;
}
bb4: {
StorageLive(_10);
_10 = copy ((_4 as Continue).0: u32);
(*_3) = copy _10;
StorageDead(_10);
_1 = move _3;
drop(_3) -> [return: bb7, unwind: bb11];
}
bb5: {
StorageLive(_7);
_7 = copy ((_4 as Break).0: std::option::Option<std::convert::Infallible>);
StorageLive(_9);
_9 = copy _7;
_0 = <Option<Box<u32>> as FromResidual<Option<Infallible>>>::from_residual(move _9) -> [return: bb6, unwind: bb12];
}
bb6: {
StorageDead(_9);
StorageDead(_7);
drop(_3) -> [return: bb9, unwind continue];
}
bb7: {
StorageDead(_3);
_0 = Option::<Box<u32>>::Some(move _1);
drop(_1) -> [return: bb8, unwind continue];
}
bb8: {
StorageDead(_1);
StorageDead(_4);
goto -> bb10;
}
bb9: {
StorageDead(_3);
StorageDead(_1);
StorageDead(_4);
goto -> bb10;
}
bb10: {
return;
}
bb11 (cleanup): {
drop(_1) -> [return: bb13, unwind terminate(cleanup)];
}
bb12 (cleanup): {
drop(_3) -> [return: bb13, unwind terminate(cleanup)];
}
bb13 (cleanup): {
resume;
}
}

View file

@ -5,33 +5,36 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
debug f => _2;
let mut _0: ();
let mut _10: usize;
let mut _28: std::option::Option<(usize, &T)>;
let mut _31: &impl Fn(usize, &T);
let mut _32: (usize, &T);
let _33: ();
let mut _31: std::option::Option<(usize, &T)>;
let mut _34: &impl Fn(usize, &T);
let mut _35: (usize, &T);
let _36: ();
scope 1 {
debug (((iter: Enumerate<std::slice::Iter<'_, T>>).0: std::slice::Iter<'_, T>).0: std::ptr::NonNull<T>) => _6;
debug (((iter: Enumerate<std::slice::Iter<'_, T>>).0: std::slice::Iter<'_, T>).1: *const T) => _9;
debug (((iter: Enumerate<std::slice::Iter<'_, T>>).0: std::slice::Iter<'_, T>).2: std::marker::PhantomData<&T>) => const ZeroSized: PhantomData<&T>;
debug ((iter: Enumerate<std::slice::Iter<'_, T>>).1: usize) => _10;
let _29: usize;
let _30: &T;
let _32: usize;
let _33: &T;
scope 2 {
debug i => _29;
debug x => _30;
debug i => _32;
debug x => _33;
}
scope 18 (inlined <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next) {
let mut _23: std::option::Option<&T>;
let mut _26: (usize, bool);
let mut _27: (usize, &T);
let mut _21: std::option::Option<std::convert::Infallible>;
let mut _26: std::option::Option<&T>;
let mut _29: (usize, bool);
let mut _30: (usize, &T);
scope 19 {
let _25: usize;
let _28: usize;
scope 24 {
}
}
scope 20 {
scope 21 {
scope 27 (inlined <Option<(usize, &T)> as FromResidual<Option<Infallible>>>::from_residual) {
let mut _20: isize;
let mut _22: bool;
}
}
}
@ -40,7 +43,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
}
}
scope 25 (inlined <Option<&T> as Try>::branch) {
let _24: &T;
let _27: &T;
scope 26 {
}
}
@ -49,8 +52,8 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
let _11: std::ptr::NonNull<T>;
let _13: std::ptr::NonNull<T>;
let mut _16: bool;
let mut _20: usize;
let _22: &T;
let mut _23: usize;
let _25: &T;
scope 29 {
let _12: *const T;
scope 30 {
@ -84,7 +87,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
}
}
scope 43 (inlined NonNull::<T>::as_ref::<'_>) {
let _21: *const T;
let _24: *const T;
scope 44 (inlined NonNull::<T>::as_ptr) {
}
scope 45 (inlined std::ptr::mut_ptr::<impl *mut T>::cast_const) {
@ -169,16 +172,16 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
}
bb4: {
StorageLive(_31);
StorageLive(_28);
StorageLive(_25);
StorageLive(_29);
StorageLive(_26);
StorageLive(_23);
StorageLive(_11);
StorageLive(_12);
StorageLive(_19);
StorageLive(_20);
StorageLive(_23);
StorageLive(_13);
StorageLive(_22);
StorageLive(_25);
_11 = copy _6;
_12 = copy _9;
switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb8];
@ -224,16 +227,23 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
}
bb10: {
StorageDead(_22);
StorageDead(_25);
StorageDead(_13);
StorageDead(_20);
StorageDead(_23);
StorageDead(_19);
StorageDead(_12);
StorageDead(_11);
StorageDead(_23);
StorageDead(_26);
StorageDead(_25);
StorageLive(_20);
StorageLive(_22);
_20 = discriminant(_21);
_22 = Eq(copy _20, const 0_isize);
assume(move _22);
StorageDead(_22);
StorageDead(_20);
StorageDead(_29);
StorageDead(_28);
StorageDead(_31);
StorageDead(_10);
drop(_2) -> [return: bb11, unwind unreachable];
}
@ -243,51 +253,51 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
}
bb12: {
_20 = SubUnchecked(copy _19, const 1_usize);
_9 = copy _20 as *const T (Transmute);
_23 = SubUnchecked(copy _19, const 1_usize);
_9 = copy _23 as *const T (Transmute);
goto -> bb13;
}
bb13: {
StorageLive(_21);
_21 = copy _11 as *const T (Transmute);
_22 = &(*_21);
StorageDead(_21);
_23 = Option::<&T>::Some(copy _22);
StorageDead(_22);
StorageLive(_24);
_24 = copy _11 as *const T (Transmute);
_25 = &(*_24);
StorageDead(_24);
_26 = Option::<&T>::Some(copy _25);
StorageDead(_25);
StorageDead(_13);
StorageDead(_20);
StorageDead(_23);
StorageDead(_19);
StorageDead(_12);
StorageDead(_11);
_24 = copy ((_23 as Some).0: &T);
StorageDead(_23);
_25 = copy _10;
_26 = AddWithOverflow(copy _10, const 1_usize);
assert(!move (_26.1: bool), "attempt to compute `{} + {}`, which would overflow", copy _10, const 1_usize) -> [success: bb14, unwind unreachable];
_27 = copy ((_26 as Some).0: &T);
StorageDead(_26);
_28 = copy _10;
_29 = AddWithOverflow(copy _10, const 1_usize);
assert(!move (_29.1: bool), "attempt to compute `{} + {}`, which would overflow", copy _10, const 1_usize) -> [success: bb14, unwind unreachable];
}
bb14: {
_10 = move (_26.0: usize);
StorageLive(_27);
_27 = (copy _25, copy _24);
_28 = Option::<(usize, &T)>::Some(move _27);
StorageDead(_27);
StorageDead(_26);
StorageDead(_25);
_29 = copy (((_28 as Some).0: (usize, &T)).0: usize);
_30 = copy (((_28 as Some).0: (usize, &T)).1: &T);
StorageLive(_31);
_31 = &_2;
StorageLive(_32);
_32 = (copy _29, copy _30);
_33 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _31, move _32) -> [return: bb15, unwind unreachable];
_10 = move (_29.0: usize);
StorageLive(_30);
_30 = (copy _28, copy _27);
_31 = Option::<(usize, &T)>::Some(move _30);
StorageDead(_30);
StorageDead(_29);
StorageDead(_28);
_32 = copy (((_31 as Some).0: (usize, &T)).0: usize);
_33 = copy (((_31 as Some).0: (usize, &T)).1: &T);
StorageLive(_34);
_34 = &_2;
StorageLive(_35);
_35 = (copy _32, copy _33);
_36 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _34, move _35) -> [return: bb15, unwind unreachable];
}
bb15: {
StorageDead(_32);
StorageDead(_35);
StorageDead(_34);
StorageDead(_31);
StorageDead(_28);
goto -> bb4;
}
}

View file

@ -0,0 +1,12 @@
//@ check-pass
fn main() {
let functions = &vec![
|x: i32| -> i32 { x + 3 },
|x: i32| -> i32 { x + 3 },
];
let string = String::new();
let a = vec![&string, "abc"];
let b = vec!["abc", &string];
}

View file

@ -1,7 +1,7 @@
const fn foo(a: i32) -> Vec<i32> {
vec![1, 2, 3]
//~^ ERROR allocations are not allowed
//~| ERROR cannot call non-const method
//~^ ERROR cannot call non-const
//~| ERROR cannot call non-const
}
fn main() {}

View file

@ -1,10 +1,4 @@
error[E0010]: allocations are not allowed in constant functions
--> $DIR/bad_const_fn_body_ice.rs:2:5
|
LL | vec![1, 2, 3]
| ^^^^^^^^^^^^^ allocation not allowed in constant functions
error[E0015]: cannot call non-const method `slice::<impl [i32]>::into_vec::<std::alloc::Global>` in constant functions
error[E0015]: cannot call non-const associated function `Box::<[i32; 3]>::new_uninit` in constant functions
--> $DIR/bad_const_fn_body_ice.rs:2:5
|
LL | vec![1, 2, 3]
@ -12,7 +6,16 @@ LL | vec![1, 2, 3]
|
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error[E0015]: cannot call non-const function `std::boxed::box_assume_init_into_vec_unsafe::<i32, 3>` in constant functions
--> $DIR/bad_const_fn_body_ice.rs:2:5
|
LL | vec![1, 2, 3]
| ^^^^^^^^^^^^^
|
note: function `box_assume_init_into_vec_unsafe` is not const
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
= note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0010, E0015.
For more information about an error, try `rustc --explain E0010`.
For more information about this error, try `rustc --explain E0015`.

View file

@ -15,11 +15,11 @@ fn main() {
let mut g = #[coroutine]
|| {
// This is desuraged as 4 stages:
// - allocate a `*mut u8` with `exchange_malloc`;
// - create a Box that is ignored for trait computations;
// - `vec!` macro
// - `write_via_move`
// - compute fields (and yields);
// - assign to `t`.
let t = std::boxed::box_new((5, yield));
let t = vec![(5, yield)];
drop(t);
};
@ -30,7 +30,7 @@ fn main() {
// As it is not taken into account for trait computation,
// the coroutine is `Copy`.
let mut h = copy(g);
//~^ ERROR the trait bound `Box<(i32, ())>: Copy` is not satisfied in
//~^ ERROR the trait bound `Box<MaybeUninit<[(i32, ()); 1]>>: Copy` is not satisfied in
// We now have 2 boxes with the same backing allocation:
// one inside `g` and one inside `h`.

View file

@ -1,20 +1,20 @@
error[E0277]: the trait bound `Box<(i32, ())>: Copy` is not satisfied in `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}`
error[E0277]: the trait bound `Box<MaybeUninit<[(i32, ()); 1]>>: Copy` is not satisfied in `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}`
--> $DIR/issue-105084.rs:32:17
|
LL | || {
| -- within this `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}`
...
LL | let mut h = copy(g);
| ^^^^^^^ within `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}`, the trait `Copy` is not implemented for `Box<(i32, ())>`
| ^^^^^^^ within `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}`, the trait `Copy` is not implemented for `Box<MaybeUninit<[(i32, ()); 1]>>`
|
note: coroutine does not implement `Copy` as this value is used across a yield
--> $DIR/issue-105084.rs:22:41
--> $DIR/issue-105084.rs:22:26
|
LL | let t = std::boxed::box_new((5, yield));
| ------------------------^^^^^--
LL | let t = vec![(5, yield)];
| ---------^^^^^--
| | |
| | yield occurs here, with `std::boxed::box_new((5, yield))` maybe used later
| has type `Box<(i32, ())>` which does not implement `Copy`
| | yield occurs here, with the value maybe used later
| has type `Box<MaybeUninit<[(i32, ()); 1]>>` which does not implement `Copy`
note: required by a bound in `copy`
--> $DIR/issue-105084.rs:10:12
|

View file

@ -1,7 +0,0 @@
//@ compile-flags: -Z teach
#![allow(warnings)]
const CON: Vec<i32> = vec![1, 2, 3]; //~ ERROR E0010
//~| ERROR cannot call non-const method
fn main() {}

View file

@ -1,20 +0,0 @@
error[E0010]: allocations are not allowed in constants
--> $DIR/E0010-teach.rs:5:23
|
LL | const CON: Vec<i32> = vec![1, 2, 3];
| ^^^^^^^^^^^^^ allocation not allowed in constants
|
= note: the runtime heap is not yet available at compile-time, so no runtime heap allocations can be created
error[E0015]: cannot call non-const method `slice::<impl [i32]>::into_vec::<std::alloc::Global>` in constants
--> $DIR/E0010-teach.rs:5:23
|
LL | const CON: Vec<i32> = vec![1, 2, 3];
| ^^^^^^^^^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0010, E0015.
For more information about an error, try `rustc --explain E0010`.

View file

@ -1,5 +0,0 @@
#![allow(warnings)]
const CON: Vec<i32> = vec![1, 2, 3]; //~ ERROR E0010
//~| ERROR cannot call non-const method
fn main() {}

View file

@ -1,18 +0,0 @@
error[E0010]: allocations are not allowed in constants
--> $DIR/E0010.rs:3:23
|
LL | const CON: Vec<i32> = vec![1, 2, 3];
| ^^^^^^^^^^^^^ allocation not allowed in constants
error[E0015]: cannot call non-const method `slice::<impl [i32]>::into_vec::<std::alloc::Global>` in constants
--> $DIR/E0010.rs:3:23
|
LL | const CON: Vec<i32> = vec![1, 2, 3];
| ^^^^^^^^^^^^^
|
= note: calls in constants are limited to constant functions, tuple structs and tuple variants
error: aborting due to 2 previous errors
Some errors have detailed explanations: E0010, E0015.
For more information about an error, try `rustc --explain E0010`.

View file

@ -390,14 +390,6 @@ LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { pani
- impl<F, Args> Fn<Args> for Exclusive<F>
where F: Sync, F: Fn<Args>, Args: std::marker::Tuple;
error[E0118]: no nominal type found for inherent implementation
--> $DIR/where-allowed.rs:241:1
|
LL | impl<T = impl Debug> T {}
| ^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type
|
= note: either implement a trait on it or create a newtype to wrap it instead
error: unconstrained opaque type
--> $DIR/where-allowed.rs:122:16
|
@ -414,6 +406,14 @@ LL | type InTypeAlias<R> = impl Debug;
|
= note: `InTypeAlias` must be used in combination with a concrete type within the same crate
error[E0118]: no nominal type found for inherent implementation
--> $DIR/where-allowed.rs:241:1
|
LL | impl<T = impl Debug> T {}
| ^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type
|
= note: either implement a trait on it or create a newtype to wrap it instead
error: aborting due to 48 previous errors
Some errors have detailed explanations: E0053, E0118, E0283, E0562, E0658, E0666.

View file

@ -1,24 +1,19 @@
error[E0080]: values of the type `[&usize; usize::MAX]` are too big for the target architecture
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
= note: evaluation of `<std::mem::MaybeUninit<[&usize; usize::MAX]> as std::mem::SizedTypeProperties>::SIZE` failed here
error[E0080]: values of the type `[&usize; usize::MAX]` are too big for the target architecture
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
= note: evaluation of `<std::mem::MaybeUninit<[&usize; usize::MAX]> as std::mem::SizedTypeProperties>::ALIGN` failed here
note: the above error was encountered while instantiating `fn Box::<[&usize; usize::MAX]>::new_uninit_in`
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
error[E0080]: values of the type `[&usize; usize::MAX]` are too big for the target architecture
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
= note: evaluation of `<[&usize; usize::MAX] as std::mem::SizedTypeProperties>::SIZE` failed here
note: the above error was encountered while instantiating `fn Box::<[&usize; usize::MAX]>::try_new_uninit_in`
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
error[E0080]: values of the type `[&usize; usize::MAX]` are too big for the target architecture
--> $SRC_DIR/core/src/mem/mod.rs:LL:COL
|
= note: evaluation of `<[&usize; usize::MAX] as std::mem::SizedTypeProperties>::ALIGN` failed here
error: aborting due to 3 previous errors
note: the above error was encountered while instantiating `fn Box::<[&usize; usize::MAX]>::new`
--> $DIR/issue-17913.rs:16:21
|
LL | let a: Box<_> = Box::new([&n; SIZE]);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0080`.

View file

@ -6,7 +6,7 @@ fn main() {
match Some(vec![42]) {
Some(vec![43]) => {} //~ ERROR expected a pattern, found a function call
//~| ERROR found associated function
//~| ERROR usage of qualified paths in this context is experimental
//~| ERROR expected a pattern, found a function call
_ => {}
}
}

View file

@ -6,17 +6,15 @@ LL | Some(vec![43]) => {}
|
= note: function calls are not allowed in patterns: <https://doc.rust-lang.org/book/ch19-00-patterns.html>
error[E0658]: usage of qualified paths in this context is experimental
error[E0532]: expected a pattern, found a function call
--> $DIR/vec-macro-in-pattern.rs:7:14
|
LL | Some(vec![43]) => {}
| ^^^^^^^^
| ^^^^^^^^ not a tuple struct or tuple variant
|
= note: see issue #86935 <https://github.com/rust-lang/rust/issues/86935> for more information
= help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: function calls are not allowed in patterns: <https://doc.rust-lang.org/book/ch19-00-patterns.html>
error[E0164]: expected tuple struct or tuple variant, found associated function `<[_]>::into_vec`
error[E0164]: expected tuple struct or tuple variant, found associated function `::alloc::boxed::Box::new_uninit`
--> $DIR/vec-macro-in-pattern.rs:7:14
|
LL | Some(vec![43]) => {}
@ -26,5 +24,5 @@ LL | Some(vec![43]) => {}
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0164, E0532, E0658.
Some errors have detailed explanations: E0164, E0532.
For more information about an error, try `rustc --explain E0164`.

View file

@ -1,5 +0,0 @@
//! regression test for issue <https://github.com/rust-lang/rust/issues/47184>
fn main() {
let _vec: Vec<&'static String> = vec![&String::new()];
//~^ ERROR temporary value dropped while borrowed [E0716]
}

View file

@ -1,12 +0,0 @@
error[E0716]: temporary value dropped while borrowed
--> $DIR/borrowck-annotate-static-lifetime.rs:3:44
|
LL | let _vec: Vec<&'static String> = vec![&String::new()];
| -------------------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
| | |
| | creates a temporary value which is freed while still in use
| type annotation requires that borrow lasts for `'static`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0716`.

View file

@ -70,6 +70,11 @@ fn underscore_with_initializer() {
//~^ ERROR temporary value dropped while borrowed [E0716]
}
fn issue_47184() {
let _vec: Vec<&'static String> = vec![&String::new()];
//~^ ERROR temporary value dropped while borrowed [E0716]
}
fn pair_underscores_with_initializer() {
let x = 22;
let (_, _): (&'static u32, u32) = (&x, 44); //~ ERROR

View file

@ -111,8 +111,17 @@ LL | let (_a, b): (Vec<&'static String>, _) = (vec![&String::new()], 44);
| | creates a temporary value which is freed while still in use
| type annotation requires that borrow lasts for `'static`
error[E0716]: temporary value dropped while borrowed
--> $DIR/patterns.rs:74:44
|
LL | let _vec: Vec<&'static String> = vec![&String::new()];
| -------------------- ^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
| | |
| | creates a temporary value which is freed while still in use
| type annotation requires that borrow lasts for `'static`
error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:75:40
--> $DIR/patterns.rs:80:40
|
LL | let x = 22;
| - binding `x` declared here
@ -124,7 +133,7 @@ LL | }
| - `x` dropped here while still borrowed
error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:80:40
--> $DIR/patterns.rs:85:40
|
LL | let x = 22;
| - binding `x` declared here
@ -136,7 +145,7 @@ LL | }
| - `x` dropped here while still borrowed
error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:85:69
--> $DIR/patterns.rs:90:69
|
LL | let x = 22;
| - binding `x` declared here
@ -148,7 +157,7 @@ LL | }
| - `x` dropped here while still borrowed
error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:90:69
--> $DIR/patterns.rs:95:69
|
LL | let x = 22;
| - binding `x` declared here
@ -160,7 +169,7 @@ LL | }
| - `x` dropped here while still borrowed
error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:98:17
--> $DIR/patterns.rs:103:17
|
LL | let x = 22;
| - binding `x` declared here
@ -173,7 +182,7 @@ LL | }
| - `x` dropped here while still borrowed
error: lifetime may not live long enough
--> $DIR/patterns.rs:111:5
--> $DIR/patterns.rs:116:5
|
LL | fn static_to_a_to_static_through_variable<'a>(x: &'a u32) -> &'static u32 {
| -- lifetime `'a` defined here
@ -182,7 +191,7 @@ LL | y
| ^ returning this value requires that `'a` must outlive `'static`
error: lifetime may not live long enough
--> $DIR/patterns.rs:123:5
--> $DIR/patterns.rs:128:5
|
LL | fn static_to_a_to_static_through_tuple<'a>(x: &'a u32) -> &'static u32 {
| -- lifetime `'a` defined here
@ -191,7 +200,7 @@ LL | y
| ^ returning this value requires that `'a` must outlive `'static`
error: lifetime may not live long enough
--> $DIR/patterns.rs:128:5
--> $DIR/patterns.rs:133:5
|
LL | fn static_to_a_to_static_through_struct<'a>(_x: &'a u32) -> &'static u32 {
| -- lifetime `'a` defined here
@ -200,14 +209,14 @@ LL | y
| ^ returning this value requires that `'a` must outlive `'static`
error: lifetime may not live long enough
--> $DIR/patterns.rs:132:18
--> $DIR/patterns.rs:137:18
|
LL | fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 {
| -- lifetime `'a` defined here
LL | let (y, _z): (&'static u32, u32) = (x, 44);
| ^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
error: aborting due to 19 previous errors
error: aborting due to 20 previous errors
Some errors have detailed explanations: E0597, E0716.
For more information about an error, try `rustc --explain E0597`.

View file

@ -4,7 +4,7 @@
fn main() {
let vec![const { vec![] }]: Vec<usize> = vec![];
//~^ ERROR expected a pattern, found a function call
//~| ERROR usage of qualified paths in this context is experimental
//~| ERROR expected a pattern, found a function call
//~| ERROR expected tuple struct or tuple variant
//~| ERROR arbitrary expressions aren't allowed in patterns
}

View file

@ -6,15 +6,13 @@ LL | let vec![const { vec![] }]: Vec<usize> = vec![];
|
= note: function calls are not allowed in patterns: <https://doc.rust-lang.org/book/ch19-00-patterns.html>
error[E0658]: usage of qualified paths in this context is experimental
error[E0532]: expected a pattern, found a function call
--> $DIR/ice-adjust-mode-unimplemented-for-constblock.rs:5:9
|
LL | let vec![const { vec![] }]: Vec<usize> = vec![];
| ^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^ not a tuple struct or tuple variant
|
= note: see issue #86935 <https://github.com/rust-lang/rust/issues/86935> for more information
= help: add `#![feature(more_qualified_paths)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
= note: function calls are not allowed in patterns: <https://doc.rust-lang.org/book/ch19-00-patterns.html>
error: arbitrary expressions aren't allowed in patterns
--> $DIR/ice-adjust-mode-unimplemented-for-constblock.rs:5:14
@ -24,7 +22,7 @@ LL | let vec![const { vec![] }]: Vec<usize> = vec![];
|
= help: use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead
error[E0164]: expected tuple struct or tuple variant, found associated function `<[_]>::into_vec`
error[E0164]: expected tuple struct or tuple variant, found associated function `::alloc::boxed::Box::new_uninit`
--> $DIR/ice-adjust-mode-unimplemented-for-constblock.rs:5:9
|
LL | let vec![const { vec![] }]: Vec<usize> = vec![];
@ -34,5 +32,5 @@ LL | let vec![const { vec![] }]: Vec<usize> = vec![];
error: aborting due to 4 previous errors
Some errors have detailed explanations: E0164, E0532, E0658.
Some errors have detailed explanations: E0164, E0532.
For more information about an error, try `rustc --explain E0164`.

View file

@ -1,5 +1,5 @@
error[E0716]: temporary value dropped while borrowed
--> $DIR/issue-15480.rs:6:10
--> $DIR/vec-macro-outlives-issue-15480.rs:6:10
|
LL | &id(3)
| ^^^^^ creates a temporary value which is freed while still in use

View file

@ -79,8 +79,8 @@ static STATIC10: UnsafeStruct = UnsafeStruct;
struct MyOwned;
static STATIC11: Vec<MyOwned> = vec![MyOwned];
//~^ ERROR allocations are not allowed in statics
//~^^ ERROR cannot call non-const
//~^ ERROR cannot call non-const function
//~| ERROR cannot call non-const
static mut STATIC12: UnsafeStruct = UnsafeStruct;
@ -93,29 +93,29 @@ static mut STATIC14: SafeStruct = SafeStruct {
};
static STATIC15: &'static [Vec<MyOwned>] = &[
vec![MyOwned], //~ ERROR allocations are not allowed in statics
//~^ ERROR cannot call non-const
vec![MyOwned], //~ ERROR allocations are not allowed in statics
//~^ ERROR cannot call non-const
vec![MyOwned], //~ ERROR cannot call non-const function
//~| ERROR cannot call non-const
vec![MyOwned], //~ ERROR cannot call non-const function
//~| ERROR cannot call non-const
];
static STATIC16: (&'static Vec<MyOwned>, &'static Vec<MyOwned>) = (
&vec![MyOwned], //~ ERROR allocations are not allowed in statics
//~^ ERROR cannot call non-const
&vec![MyOwned], //~ ERROR allocations are not allowed in statics
//~^ ERROR cannot call non-const
&vec![MyOwned], //~ ERROR cannot call non-const function
//~| ERROR cannot call non-const
&vec![MyOwned], //~ ERROR cannot call non-const function
//~| ERROR cannot call non-const
);
static mut STATIC17: SafeEnum = SafeEnum::Variant1;
static STATIC19: Vec<isize> = vec![3];
//~^ ERROR allocations are not allowed in statics
//~^^ ERROR cannot call non-const
//~^ ERROR cannot call non-const function
//~| ERROR cannot call non-const
pub fn main() {
let y = {
static x: Vec<isize> = vec![3]; //~ ERROR allocations are not allowed in statics
//~^ ERROR cannot call non-const
static x: Vec<isize> = vec![3]; //~ ERROR cannot call non-const function
//~| ERROR cannot call non-const
x
//~^ ERROR cannot move out of static
};

View file

@ -11,13 +11,7 @@ LL | | }
LL | };
| - value is dropped here
error[E0010]: allocations are not allowed in statics
--> $DIR/check-values-constraints.rs:81:33
|
LL | static STATIC11: Vec<MyOwned> = vec![MyOwned];
| ^^^^^^^^^^^^^ allocation not allowed in statics
error[E0015]: cannot call non-const method `slice::<impl [MyOwned]>::into_vec::<std::alloc::Global>` in statics
error[E0015]: cannot call non-const associated function `Box::<[MyOwned; 1]>::new_uninit` in statics
--> $DIR/check-values-constraints.rs:81:33
|
LL | static STATIC11: Vec<MyOwned> = vec![MyOwned];
@ -26,6 +20,17 @@ LL | static STATIC11: Vec<MyOwned> = vec![MyOwned];
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
error[E0015]: cannot call non-const function `std::boxed::box_assume_init_into_vec_unsafe::<MyOwned, 1>` in statics
--> $DIR/check-values-constraints.rs:81:33
|
LL | static STATIC11: Vec<MyOwned> = vec![MyOwned];
| ^^^^^^^^^^^^^
|
note: function `box_assume_init_into_vec_unsafe` is not const
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
error[E0015]: cannot call non-const method `<str as ToString>::to_string` in statics
--> $DIR/check-values-constraints.rs:92:38
|
@ -42,13 +47,7 @@ note: method `to_string` is not const because trait `ToString` is not const
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
error[E0010]: allocations are not allowed in statics
--> $DIR/check-values-constraints.rs:96:5
|
LL | vec![MyOwned],
| ^^^^^^^^^^^^^ allocation not allowed in statics
error[E0015]: cannot call non-const method `slice::<impl [MyOwned]>::into_vec::<std::alloc::Global>` in statics
error[E0015]: cannot call non-const associated function `Box::<[MyOwned; 1]>::new_uninit` in statics
--> $DIR/check-values-constraints.rs:96:5
|
LL | vec![MyOwned],
@ -57,13 +56,18 @@ LL | vec![MyOwned],
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
error[E0010]: allocations are not allowed in statics
--> $DIR/check-values-constraints.rs:98:5
error[E0015]: cannot call non-const function `std::boxed::box_assume_init_into_vec_unsafe::<MyOwned, 1>` in statics
--> $DIR/check-values-constraints.rs:96:5
|
LL | vec![MyOwned],
| ^^^^^^^^^^^^^ allocation not allowed in statics
| ^^^^^^^^^^^^^
|
note: function `box_assume_init_into_vec_unsafe` is not const
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
error[E0015]: cannot call non-const method `slice::<impl [MyOwned]>::into_vec::<std::alloc::Global>` in statics
error[E0015]: cannot call non-const associated function `Box::<[MyOwned; 1]>::new_uninit` in statics
--> $DIR/check-values-constraints.rs:98:5
|
LL | vec![MyOwned],
@ -72,13 +76,18 @@ LL | vec![MyOwned],
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
error[E0010]: allocations are not allowed in statics
--> $DIR/check-values-constraints.rs:103:6
error[E0015]: cannot call non-const function `std::boxed::box_assume_init_into_vec_unsafe::<MyOwned, 1>` in statics
--> $DIR/check-values-constraints.rs:98:5
|
LL | &vec![MyOwned],
| ^^^^^^^^^^^^^ allocation not allowed in statics
LL | vec![MyOwned],
| ^^^^^^^^^^^^^
|
note: function `box_assume_init_into_vec_unsafe` is not const
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
error[E0015]: cannot call non-const method `slice::<impl [MyOwned]>::into_vec::<std::alloc::Global>` in statics
error[E0015]: cannot call non-const associated function `Box::<[MyOwned; 1]>::new_uninit` in statics
--> $DIR/check-values-constraints.rs:103:6
|
LL | &vec![MyOwned],
@ -87,13 +96,18 @@ LL | &vec![MyOwned],
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
error[E0010]: allocations are not allowed in statics
--> $DIR/check-values-constraints.rs:105:6
error[E0015]: cannot call non-const function `std::boxed::box_assume_init_into_vec_unsafe::<MyOwned, 1>` in statics
--> $DIR/check-values-constraints.rs:103:6
|
LL | &vec![MyOwned],
| ^^^^^^^^^^^^^ allocation not allowed in statics
| ^^^^^^^^^^^^^
|
note: function `box_assume_init_into_vec_unsafe` is not const
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
error[E0015]: cannot call non-const method `slice::<impl [MyOwned]>::into_vec::<std::alloc::Global>` in statics
error[E0015]: cannot call non-const associated function `Box::<[MyOwned; 1]>::new_uninit` in statics
--> $DIR/check-values-constraints.rs:105:6
|
LL | &vec![MyOwned],
@ -102,13 +116,18 @@ LL | &vec![MyOwned],
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
error[E0010]: allocations are not allowed in statics
--> $DIR/check-values-constraints.rs:111:31
error[E0015]: cannot call non-const function `std::boxed::box_assume_init_into_vec_unsafe::<MyOwned, 1>` in statics
--> $DIR/check-values-constraints.rs:105:6
|
LL | static STATIC19: Vec<isize> = vec![3];
| ^^^^^^^ allocation not allowed in statics
LL | &vec![MyOwned],
| ^^^^^^^^^^^^^
|
note: function `box_assume_init_into_vec_unsafe` is not const
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
error[E0015]: cannot call non-const method `slice::<impl [isize]>::into_vec::<std::alloc::Global>` in statics
error[E0015]: cannot call non-const associated function `Box::<[isize; 1]>::new_uninit` in statics
--> $DIR/check-values-constraints.rs:111:31
|
LL | static STATIC19: Vec<isize> = vec![3];
@ -117,13 +136,18 @@ LL | static STATIC19: Vec<isize> = vec![3];
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
error[E0010]: allocations are not allowed in statics
--> $DIR/check-values-constraints.rs:117:32
error[E0015]: cannot call non-const function `std::boxed::box_assume_init_into_vec_unsafe::<isize, 1>` in statics
--> $DIR/check-values-constraints.rs:111:31
|
LL | static x: Vec<isize> = vec![3];
| ^^^^^^^ allocation not allowed in statics
LL | static STATIC19: Vec<isize> = vec![3];
| ^^^^^^^
|
note: function `box_assume_init_into_vec_unsafe` is not const
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
error[E0015]: cannot call non-const method `slice::<impl [isize]>::into_vec::<std::alloc::Global>` in statics
error[E0015]: cannot call non-const associated function `Box::<[isize; 1]>::new_uninit` in statics
--> $DIR/check-values-constraints.rs:117:32
|
LL | static x: Vec<isize> = vec![3];
@ -132,6 +156,17 @@ LL | static x: Vec<isize> = vec![3];
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
error[E0015]: cannot call non-const function `std::boxed::box_assume_init_into_vec_unsafe::<isize, 1>` in statics
--> $DIR/check-values-constraints.rs:117:32
|
LL | static x: Vec<isize> = vec![3];
| ^^^^^^^
|
note: function `box_assume_init_into_vec_unsafe` is not const
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL
= note: calls in statics are limited to constant functions, tuple structs and tuple variants
= note: consider wrapping this expression in `std::sync::LazyLock::new(|| ...)`
error[E0507]: cannot move out of static item `x`
--> $DIR/check-values-constraints.rs:119:9
|
@ -149,5 +184,5 @@ LL | x.clone()
error: aborting due to 17 previous errors
Some errors have detailed explanations: E0010, E0015, E0493, E0507.
For more information about an error, try `rustc --explain E0010`.
Some errors have detailed explanations: E0015, E0493, E0507.
For more information about an error, try `rustc --explain E0015`.

View file

@ -1,8 +0,0 @@
//@ compile-flags: -Zunpretty=thir-tree
//@ check-pass
#![feature(liballoc_internals)]
fn main() {
let _ = std::boxed::box_new(1);
}

View file

@ -1,90 +0,0 @@
DefId(0:3 ~ box[efb9]::main):
params: [
]
body:
Expr {
ty: ()
temp_scope_id: 11
span: $DIR/box.rs:6:11: 8:2 (#0)
kind:
Scope {
region_scope: Node(11)
hir_id: HirId(DefId(0:3 ~ box[efb9]::main).11)
value:
Expr {
ty: ()
temp_scope_id: 11
span: $DIR/box.rs:6:11: 8:2 (#0)
kind:
Block {
targeted_by_break: false
span: $DIR/box.rs:6:11: 8:2 (#0)
region_scope: Node(1)
safety_mode: Safe
stmts: [
Stmt {
kind: Let {
remainder_scope: Remainder { block: 1, first_statement_index: 0}
init_scope: Node(2)
pattern:
Pat {
ty: std::boxed::Box<i32, std::alloc::Global>
span: $DIR/box.rs:7:9: 7:10 (#0)
kind: PatKind {
Wild
}
}
,
initializer: Some(
Expr {
ty: std::boxed::Box<i32, std::alloc::Global>
temp_scope_id: 3
span: $DIR/box.rs:7:13: 7:35 (#0)
kind:
Scope {
region_scope: Node(3)
hir_id: HirId(DefId(0:3 ~ box[efb9]::main).3)
value:
Expr {
ty: std::boxed::Box<i32, std::alloc::Global>
temp_scope_id: 3
span: $DIR/box.rs:7:13: 7:35 (#0)
kind:
Box {
Expr {
ty: i32
temp_scope_id: 8
span: $DIR/box.rs:7:33: 7:34 (#0)
kind:
Scope {
region_scope: Node(8)
hir_id: HirId(DefId(0:3 ~ box[efb9]::main).8)
value:
Expr {
ty: i32
temp_scope_id: 8
span: $DIR/box.rs:7:33: 7:34 (#0)
kind:
Literal( lit: Spanned { node: Int(Pu128(1), Unsuffixed), span: $DIR/box.rs:7:33: 7:34 (#0) }, neg: false)
}
}
}
}
}
}
}
)
else_block: None
hir_id: HirId(DefId(0:3 ~ box[efb9]::main).9)
span: $DIR/box.rs:7:5: 7:35 (#0)
}
}
]
expr: []
}
}
}
}