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"] #[lang = "drop"]
pub trait Drop { pub trait Drop {
fn drop(&mut self); 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"] #[lang = "drop"]
pub trait Drop { pub trait Drop {
fn drop(&mut self); fn drop(&mut self);

View file

@ -845,13 +845,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
return; 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. // Intrinsics are language primitives, not regular calls, so treat them separately.
if let Some(intrinsic) = tcx.intrinsic(callee) { if let Some(intrinsic) = tcx.intrinsic(callee) {
if !tcx.is_const_fn(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)] #[derive(Debug)]
pub(crate) struct InlineAsm; pub(crate) struct InlineAsm;
impl<'tcx> NonConstOp<'tcx> for InlineAsm { impl<'tcx> NonConstOp<'tcx> for InlineAsm {

View file

@ -289,31 +289,6 @@ pub(crate) struct UnallowedOpInConstContext {
pub msg: String, 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)] #[derive(Diagnostic)]
#[diag(r#"inline assembly is not allowed in {$kind -> #[diag(r#"inline assembly is not allowed in {$kind ->
[const] constant [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 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 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. the heap at runtime, and therefore cannot be done at compile time.
Erroneous code example: Erroneous code example:
```compile_fail,E0010 ```ignore (no longer emitted)
const CON : Vec<i32> = vec![1, 2, 3]; 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 // 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 // file saying that this error is not emitted by the compiler any more (see E0001.md for an
// example), and remove all code examples that do not build any more. // example), and remove all code examples that do not build any more by marking them
// with `ignore (no longer emitted)`.
#[macro_export] #[macro_export]
#[rustfmt::skip] #[rustfmt::skip]
macro_rules! error_codes { macro_rules! error_codes {

View file

@ -320,7 +320,6 @@ language_item_table! {
FormatArgument, sym::format_argument, format_argument, Target::Struct, GenericRequirement::None; FormatArgument, sym::format_argument, format_argument, Target::Struct, GenericRequirement::None;
FormatArguments, sym::format_arguments, format_arguments, 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); DropInPlace, sym::drop_in_place, drop_in_place_fn, Target::Fn, GenericRequirement::Minimum(1);
AllocLayout, sym::alloc_layout, alloc_layout, Target::Struct, GenericRequirement::None; 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::autodiff
| sym::bitreverse | sym::bitreverse
| sym::black_box | sym::black_box
| sym::box_new
| sym::breakpoint | sym::breakpoint
| sym::bswap | sym::bswap
| sym::caller_location | sym::caller_location
@ -223,6 +222,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi
| sym::wrapping_add | sym::wrapping_add
| sym::wrapping_mul | sym::wrapping_mul
| sym::wrapping_sub | sym::wrapping_sub
| sym::write_box_via_move
// tidy-alphabetical-end // tidy-alphabetical-end
=> hir::Safety::Safe, => hir::Safety::Safe,
_ => hir::Safety::Unsafe, _ => hir::Safety::Unsafe,
@ -584,6 +584,13 @@ pub(crate) fn check_intrinsic_type(
sym::write_via_move => { sym::write_via_move => {
(1, 0, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit) (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 => { sym::typed_swap_nonoverlapping => {
(1, 0, vec![Ty::new_mut_ptr(tcx, param(0)); 2], tcx.types.unit) (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::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 // 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_requires => (1, 0, vec![param(0)], tcx.types.unit),
sym::contract_check_ensures => { sym::contract_check_ensures => {

View file

@ -3110,6 +3110,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
{ {
let deref_kind = if checked_ty.is_box() { let deref_kind = if checked_ty.is_box() {
// detect Box::new(..) // detect Box::new(..)
// FIXME: use `box_new` diagnostic item instead?
if let ExprKind::Call(box_new, [_]) = expr.kind if let ExprKind::Call(box_new, [_]) = expr.kind
&& let ExprKind::Path(qpath) = &box_new.kind && let ExprKind::Path(qpath) = &box_new.kind
&& let Res::Def(DefKind::AssocFn, fn_id) = && let Res::Def(DefKind::AssocFn, fn_id) =

View file

@ -268,10 +268,6 @@ pub enum ExprKind<'tcx> {
hir_id: HirId, hir_id: HirId,
value: ExprId, value: ExprId,
}, },
/// A `box <value>` expression.
Box {
value: ExprId,
},
/// An `if` expression. /// An `if` expression.
If { If {
if_then_scope: region::Scope, 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; let Expr { kind, ty: _, temp_scope_id: _, span: _ } = expr;
match *kind { match *kind {
Scope { value, region_scope: _, hir_id: _ } => visitor.visit_expr(&visitor.thir()[value]), 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: _ } => { If { cond, then, else_opt, if_then_scope: _ } => {
visitor.visit_expr(&visitor.thir()[cond]); visitor.visit_expr(&visitor.thir()[cond]);
visitor.visit_expr(&visitor.thir()[then]); visitor.visit_expr(&visitor.thir()[then]);

View file

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

View file

@ -1,7 +1,6 @@
//! See docs in `build/expr/mod.rs`. //! See docs in `build/expr/mod.rs`.
use rustc_abi::FieldIdx; use rustc_abi::FieldIdx;
use rustc_hir::lang_items::LangItem;
use rustc_index::{Idx, IndexVec}; use rustc_index::{Idx, IndexVec};
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::middle::region::{self, TempLifetime}; use rustc_middle::middle::region::{self, TempLifetime};
@ -124,65 +123,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
} }
block.and(Rvalue::UnaryOp(op, arg)) 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 } => { ExprKind::Cast { source } => {
let source_expr = &this.thir[source]; let source_expr = &this.thir[source];

View file

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

View file

@ -1,5 +1,6 @@
//! See docs in build/expr/mod.rs //! See docs in build/expr/mod.rs
use rustc_abi::FieldIdx;
use rustc_ast::{AsmMacro, InlineAsmOptions}; use rustc_ast::{AsmMacro, InlineAsmOptions};
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::stack::ensure_sufficient_stack;
@ -366,30 +367,96 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
None None
}) })
} }
// The `write_via_move` intrinsic needs to be special-cased very early to avoid // Some intrinsics are handled here because they desperately want to avoid introducing
// introducing unnecessary copies that can be hard to remove again later: // unnecessary copies.
// `write_via_move(ptr, val)` becomes `*ptr = val` but without any dropping.
ExprKind::Call { ty, fun, ref args, .. } 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) && 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 // We still have to evaluate the callee expression as normal (but we don't care
// about its result). // about its result).
let _fun = unpack!(block = this.as_local_operand(block, fun)); let _fun = unpack!(block = this.as_local_operand(block, fun));
// The destination must have unit type (so we don't actually have to store anything
// into it).
assert!(destination.ty(&this.local_decls, this.tcx).ty.is_unit());
// Compile this to an assignment of the argument into the destination. match intrinsic.name {
let [ptr, val] = **args else { sym::write_via_move => {
span_bug!(expr_span, "invalid write_via_move call") // `write_via_move(ptr, val)` becomes `*ptr = val` but without any dropping.
};
let Some(ptr) = unpack!(block = this.as_local_operand(block, ptr)).place() else { // The destination must have unit type (so we don't actually have to store anything
span_bug!(expr_span, "invalid write_via_move call") // into it).
}; assert!(destination.ty(&this.local_decls, this.tcx).ty.is_unit());
let ptr_deref = ptr.project_deeper(&[ProjectionElem::Deref], this.tcx);
this.expr_into_dest(ptr_deref, block, val) // Compile this to an assignment of the argument into the destination.
let [ptr, val] = **args else {
span_bug!(expr_span, "invalid write_via_move call")
};
let Some(ptr) = unpack!(block = this.as_local_operand(block, ptr)).place()
else {
span_bug!(expr_span, "invalid write_via_move call")
};
let ptr_deref = ptr.project_deeper(&[ProjectionElem::Deref], this.tcx);
this.expr_into_dest(ptr_deref, block, val)
}
sym::write_box_via_move => {
// The signature is:
// `fn write_box_via_move<T>(b: Box<MaybeUninit<T>>, val: T) -> Box<MaybeUninit<T>>`.
// `write_box_via_move(b, val)` becomes
// ```
// (*b).value.value.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 } => { ExprKind::Call { ty: _, fun, ref args, from_hir_call, fn_span } => {
let fun = unpack!(block = this.as_local_operand(block, fun)); let fun = unpack!(block = this.as_local_operand(block, fun));
@ -795,7 +862,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
// these are the cases that are more naturally handled by some other mode // these are the cases that are more naturally handled by some other mode
ExprKind::Unary { .. } ExprKind::Unary { .. }
| ExprKind::Binary { .. } | ExprKind::Binary { .. }
| ExprKind::Box { .. }
| ExprKind::Cast { .. } | ExprKind::Cast { .. }
| ExprKind::PointerCoercion { .. } | ExprKind::PointerCoercion { .. }
| ExprKind::Repeat { .. } | ExprKind::Repeat { .. }

View file

@ -449,7 +449,6 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
| ExprKind::LoopMatch { .. } | ExprKind::LoopMatch { .. }
| ExprKind::Let { .. } | ExprKind::Let { .. }
| ExprKind::Match { .. } | ExprKind::Match { .. }
| ExprKind::Box { .. }
| ExprKind::If { .. } | ExprKind::If { .. }
| ExprKind::InlineAsm { .. } | ExprKind::InlineAsm { .. }
| ExprKind::LogicalOp { .. } | ExprKind::LogicalOp { .. }

View file

@ -20,7 +20,7 @@ use rustc_middle::ty::{
self, AdtKind, GenericArgs, InlineConstArgs, InlineConstArgsParts, ScalarInt, Ty, UpvarArgs, self, AdtKind, GenericArgs, InlineConstArgs, InlineConstArgsParts, ScalarInt, Ty, UpvarArgs,
}; };
use rustc_middle::{bug, span_bug}; use rustc_middle::{bug, span_bug};
use rustc_span::{Span, sym}; use rustc_span::Span;
use tracing::{debug, info, instrument, trace}; use tracing::{debug, info, instrument, trace};
use crate::errors::*; use crate::errors::*;
@ -385,24 +385,6 @@ impl<'tcx> ThirBuildCx<'tcx> {
from_hir_call: true, from_hir_call: true,
fn_span: expr.span, 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 { } else {
// Tuple-like ADTs are represented as ExprKind::Call. We convert them here. // Tuple-like ADTs are represented as ExprKind::Call. We convert them here.
let adt_data = if let hir::ExprKind::Path(ref qpath) = fun.kind 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 { .. } | Binary { .. }
| Block { .. } | Block { .. }
| Borrow { .. } | Borrow { .. }
| Box { .. }
| Call { .. } | Call { .. }
| ByUse { .. } | ByUse { .. }
| Closure { .. } | Closure { .. }

View file

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

View file

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

View file

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

View file

@ -51,8 +51,6 @@ pub(crate) enum GenericConstantTooComplexSub {
YieldNotSupported(#[primary_span] Span), YieldNotSupported(#[primary_span] Span),
#[label("loops and loop control flow are not supported in generic constants")] #[label("loops and loop control flow are not supported in generic constants")]
LoopNotSupported(#[primary_span] Span), LoopNotSupported(#[primary_span] Span),
#[label("allocations are not allowed in generic constants")]
BoxNotSupported(#[primary_span] Span),
#[label("unsupported binary operation in generic constants")] #[label("unsupported binary operation in generic constants")]
BinaryNotSupported(#[primary_span] Span), BinaryNotSupported(#[primary_span] Span),
#[label(".use is not allowed in generic constants")] #[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 // # Allocation error handler
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]

View file

@ -206,7 +206,7 @@ use core::task::{Context, Poll};
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
use crate::alloc::handle_alloc_error; 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; use crate::raw_vec::RawVec;
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
use crate::str::from_boxed_utf8_unchecked; use crate::str::from_boxed_utf8_unchecked;
@ -236,14 +236,34 @@ pub struct Box<
#[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global,
>(Unique<T>, A); >(Unique<T>, A);
/// Constructs a `Box<T>` by calling the `exchange_malloc` lang item and moving the argument into /// Monomorphic function for allocating an uninit `Box`.
/// the newly allocated memory. This is an intrinsic to avoid unnecessary copies.
/// ///
/// 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)] #[doc(hidden)]
#[rustc_intrinsic]
#[unstable(feature = "liballoc_internals", issue = "none")] #[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> { impl<T> Box<T> {
/// Allocates memory on the heap and then places `x` into it. /// Allocates memory on the heap and then places `x` into it.
@ -262,9 +282,10 @@ impl<T> Box<T> {
#[rustc_diagnostic_item = "box_new"] #[rustc_diagnostic_item = "box_new"]
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
pub fn new(x: T) -> Self { 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 { 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; } as *mut T;
// Nothing below can panic so we do not have to worry about deallocating `ptr`. // Nothing below can panic so we do not have to worry about deallocating `ptr`.
// SAFETY: we just allocated the box to store `x`. // SAFETY: we just allocated the box to store `x`.
@ -288,9 +309,21 @@ impl<T> Box<T> {
#[cfg(not(no_global_oom_handling))] #[cfg(not(no_global_oom_handling))]
#[stable(feature = "new_uninit", since = "1.82.0")] #[stable(feature = "new_uninit", since = "1.82.0")]
#[must_use] #[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>> { 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 /// 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) /// assert_eq!(*five, 5)
/// ``` /// ```
#[stable(feature = "new_uninit", since = "1.82.0")] #[stable(feature = "new_uninit", since = "1.82.0")]
#[inline] #[inline(always)]
pub unsafe fn assume_init(self) -> Box<T, A> { pub unsafe fn assume_init(self) -> Box<T, A> {
let (raw, alloc) = Box::into_raw_with_allocator(self); // This is used in the `vec!` macro, so we optimize for minimal IR generation
unsafe { Box::from_raw_in(raw as *mut T, alloc) } // 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>`. /// 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)))] #[cfg(all(not(no_rc), not(no_sync), not(no_global_oom_handling)))]
pub mod ffi; pub mod ffi;
pub mod fmt; pub mod fmt;
pub mod intrinsics;
#[cfg(not(no_rc))] #[cfg(not(no_rc))]
pub mod rc; pub mod rc;
pub mod slice; pub mod slice;

View file

@ -47,10 +47,16 @@ macro_rules! vec {
$crate::vec::from_elem($elem, $n) $crate::vec::from_elem($elem, $n)
); );
($($x:expr),+ $(,)?) => ( ($($x:expr),+ $(,)?) => (
<[_]>::into_vec( // Using `write_box_via_move` produces a dramatic improvement in stack usage for unoptimized
// Using the intrinsic produces a dramatic improvement in stack usage for // programs using this code path to construct large Vecs. We can't use `write_via_move`
// unoptimized programs using this code path to construct large Vecs. // because this entire invocation has to remain a call chain without `let` bindings, or else
$crate::boxed::box_new([$($x),+]) // 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() { fn main() {
assert_eq!(vec_reallocate().len(), 5); assert_eq!(vec_reallocate().len(), 5);
@ -209,4 +227,5 @@ fn main() {
reverse(); reverse();
miri_issue_2759(); miri_issue_2759();
extract_if(); 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/single-use-lifetime/issue-117965.rs
ui/span/issue-107353.rs ui/span/issue-107353.rs
ui/span/issue-11925.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-23338-locals-die-before-temps-of-body.rs
ui/span/issue-23729.rs ui/span/issue-23729.rs
ui/span/issue-23827.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 <TestStruct2 as TestTrait2>::test_func2
//~ MONO_ITEM fn alloc::alloc::exchange_malloc
//~ MONO_ITEM fn foo2 //~ MONO_ITEM fn foo2
//~ MONO_ITEM fn std::alloc::Global::alloc_impl_runtime //~ MONO_ITEM fn std::alloc::Global::alloc_impl_runtime
//~ MONO_ITEM fn std::boxed::Box::<TestStruct2>::new //~ 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 //@ compile-flags: -Zmir-opt-level=0
// skip-filecheck // 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() { 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; 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() { 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; 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 _9: *const [()];
let mut _10: std::boxed::Box<()>; let mut _10: std::boxed::Box<()>;
let mut _11: *const (); let mut _11: *const ();
let mut _16: usize; let mut _14: usize;
let mut _17: usize; let mut _15: usize;
let mut _26: usize; let mut _24: usize;
scope 1 { scope 1 {
debug vp_ctx => _1; debug vp_ctx => _1;
let _5: *const (); let _5: *const ();
@ -26,49 +26,49 @@
scope 4 { scope 4 {
debug _x => _8; debug _x => _8;
} }
scope 19 (inlined foo) { scope 20 (inlined foo) {
let mut _27: *const [()]; let mut _25: *const [()];
} }
} }
scope 17 (inlined slice_from_raw_parts::<()>) { scope 18 (inlined slice_from_raw_parts::<()>) {
scope 18 (inlined std::ptr::from_raw_parts::<[()], ()>) { scope 19 (inlined std::ptr::from_raw_parts::<[()], ()>) {
} }
} }
} }
} }
scope 5 (inlined Box::<()>::new) { scope 5 (inlined Box::<()>::new) {
let mut _12: *mut u8; let mut _12: *mut ();
let mut _13: *const (); let mut _13: *mut u8;
let mut _14: std::ptr::NonNull<()>; scope 6 {
let mut _15: std::ptr::Unique<()>; }
scope 6 (inlined alloc::alloc::exchange_malloc) { scope 7 (inlined boxed::box_new_uninit) {
let _18: std::alloc::Layout; let _16: std::alloc::Layout;
let mut _19: std::result::Result<std::ptr::NonNull<[u8]>, std::alloc::AllocError>; let mut _17: std::result::Result<std::ptr::NonNull<[u8]>, std::alloc::AllocError>;
let mut _20: isize; let mut _18: isize;
let mut _22: !; let mut _20: !;
scope 7 { scope 8 {
let _21: std::ptr::NonNull<[u8]>; let _19: std::ptr::NonNull<[u8]>;
scope 8 { scope 9 {
scope 12 (inlined NonNull::<[u8]>::as_mut_ptr) { scope 13 (inlined NonNull::<[u8]>::as_mut_ptr) {
scope 13 (inlined NonNull::<[u8]>::as_non_null_ptr) { scope 14 (inlined NonNull::<[u8]>::as_non_null_ptr) {
scope 14 (inlined NonNull::<[u8]>::cast::<u8>) { scope 15 (inlined NonNull::<[u8]>::cast::<u8>) {
let mut _25: *mut [u8]; let mut _23: *mut [u8];
scope 15 (inlined NonNull::<[u8]>::as_ptr) { 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 as Allocator>::allocate) {
scope 11 (inlined std::alloc::Global::alloc_impl) { scope 12 (inlined std::alloc::Global::alloc_impl) {
} }
} }
} }
scope 9 (inlined #[track_caller] Layout::from_size_align_unchecked) { scope 10 (inlined #[track_caller] Layout::from_size_align_unchecked) {
let _23: (); let _21: ();
let mut _24: std::ptr::Alignment; let mut _22: std::ptr::Alignment;
} }
} }
} }
@ -83,18 +83,16 @@
StorageLive(_12); StorageLive(_12);
StorageLive(_13); StorageLive(_13);
StorageLive(_14); StorageLive(_14);
- _14 = const <() as std::mem::SizedTypeProperties>::SIZE;
+ _14 = const 0_usize;
StorageLive(_15); StorageLive(_15);
- _15 = const <() as std::mem::SizedTypeProperties>::ALIGN;
+ _15 = const 1_usize;
StorageLive(_16); 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(_18);
StorageLive(_19);
StorageLive(_20); StorageLive(_20);
StorageLive(_21); StorageLive(_21);
StorageLive(_22);
StorageLive(_23);
switchInt(UbChecks) -> [0: bb6, otherwise: bb5]; switchInt(UbChecks) -> [0: bb6, otherwise: bb5];
} }
@ -109,35 +107,31 @@
} }
bb3: { bb3: {
- _22 = handle_alloc_error(move _18) -> unwind unreachable; - _20 = handle_alloc_error(move _16) -> 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(const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }}) -> unwind unreachable;
} }
bb4: { bb4: {
_21 = copy ((_19 as Ok).0: std::ptr::NonNull<[u8]>); _19 = copy ((_17 as Ok).0: std::ptr::NonNull<[u8]>);
- StorageLive(_25); - StorageLive(_23);
+ nop; + nop;
_25 = copy _21 as *mut [u8] (Transmute); _23 = copy _19 as *mut [u8] (Transmute);
_12 = copy _25 as *mut u8 (PtrToPtr); _13 = copy _23 as *mut u8 (PtrToPtr);
- StorageDead(_25); - StorageDead(_23);
+ nop; + nop;
StorageDead(_19); StorageDead(_17);
StorageDead(_23);
StorageDead(_22);
StorageDead(_21); StorageDead(_21);
StorageDead(_20); StorageDead(_20);
StorageDead(_19);
StorageDead(_18); StorageDead(_18);
StorageDead(_17);
StorageDead(_16); 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(_15);
StorageDead(_14); 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(_13);
StorageDead(_12); StorageDead(_12);
StorageDead(_4); StorageDead(_4);
@ -153,21 +147,21 @@
+ nop; + nop;
StorageLive(_7); StorageLive(_7);
_7 = copy _5; _7 = copy _5;
StorageLive(_26); StorageLive(_24);
_26 = const 1_usize; _24 = const 1_usize;
- _6 = *const [()] from (copy _7, copy _26); - _6 = *const [()] from (copy _7, copy _24);
+ _6 = *const [()] from (copy _5, const 1_usize); + _6 = *const [()] from (copy _5, const 1_usize);
StorageDead(_26); StorageDead(_24);
StorageDead(_7); StorageDead(_7);
StorageLive(_8); StorageLive(_8);
StorageLive(_9); StorageLive(_9);
_9 = copy _6; _9 = copy _6;
StorageLive(_27); StorageLive(_25);
- _27 = copy _9; - _25 = copy _9;
- _8 = copy _9 as *mut () (PtrToPtr); - _8 = copy _9 as *mut () (PtrToPtr);
+ _27 = copy _6; + _25 = copy _6;
+ _8 = copy _5 as *mut () (PtrToPtr); + _8 = copy _5 as *mut () (PtrToPtr);
StorageDead(_27); StorageDead(_25);
StorageDead(_9); StorageDead(_9);
_0 = const (); _0 = const ();
StorageDead(_8); StorageDead(_8);
@ -179,25 +173,25 @@
} }
bb5: { bb5: {
- _23 = Layout::from_size_align_unchecked::precondition_check(copy _16, copy _17) -> [return: bb6, unwind unreachable]; - _21 = Layout::from_size_align_unchecked::precondition_check(copy _14, copy _15) -> [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(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable];
} }
bb6: { bb6: {
StorageLive(_24); StorageLive(_22);
- _24 = copy _17 as std::ptr::Alignment (Transmute); - _22 = copy _15 as std::ptr::Alignment (Transmute);
- _18 = Layout { size: copy _16, align: move _24 }; - _16 = Layout { size: copy _14, align: move _22 };
+ _24 = const std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }}; + _22 = 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 }} }}; + _16 = const Layout {{ size: 0_usize, align: std::ptr::Alignment {{ _inner_repr_trick: std::ptr::alignment::AlignmentEnum::_Align1Shl0 }} }};
StorageDead(_24); StorageDead(_22);
StorageLive(_19); StorageLive(_17);
- _19 = std::alloc::Global::alloc_impl_runtime(copy _18, const false) -> [return: bb7, unwind unreachable]; - _17 = std::alloc::Global::alloc_impl_runtime(copy _16, 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]; + _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: { bb7: {
_20 = discriminant(_19); _18 = discriminant(_17);
switchInt(move _20) -> [0: bb4, 1: bb3, otherwise: bb2]; switchInt(move _18) -> [0: bb4, 1: bb3, otherwise: bb2];
} }
+ } + }
+ +

View file

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

View file

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

View file

@ -5,9 +5,9 @@
#![feature(rustc_attrs, liballoc_internals)] #![feature(rustc_attrs, liballoc_internals)]
// EMIT_MIR issue_62289.test.ElaborateDrops.before.mir // EMIT_MIR issue_62289.test.ElaborateDrops.after.mir
fn test() -> Option<Box<u32>> { fn test() -> Option<Vec<u32>> {
Some(std::boxed::box_new(None?)) Some(vec![None?])
} }
fn main() { 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; debug f => _2;
let mut _0: (); let mut _0: ();
let mut _10: usize; let mut _10: usize;
let mut _28: std::option::Option<(usize, &T)>; let mut _31: std::option::Option<(usize, &T)>;
let mut _31: &impl Fn(usize, &T); let mut _34: &impl Fn(usize, &T);
let mut _32: (usize, &T); let mut _35: (usize, &T);
let _33: (); let _36: ();
scope 1 { 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>).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>).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>>).0: std::slice::Iter<'_, T>).2: std::marker::PhantomData<&T>) => const ZeroSized: PhantomData<&T>;
debug ((iter: Enumerate<std::slice::Iter<'_, T>>).1: usize) => _10; debug ((iter: Enumerate<std::slice::Iter<'_, T>>).1: usize) => _10;
let _29: usize; let _32: usize;
let _30: &T; let _33: &T;
scope 2 { scope 2 {
debug i => _29; debug i => _32;
debug x => _30; debug x => _33;
} }
scope 18 (inlined <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next) { scope 18 (inlined <Enumerate<std::slice::Iter<'_, T>> as Iterator>::next) {
let mut _23: std::option::Option<&T>; let mut _21: std::option::Option<std::convert::Infallible>;
let mut _26: (usize, bool); let mut _26: std::option::Option<&T>;
let mut _27: (usize, &T); let mut _29: (usize, bool);
let mut _30: (usize, &T);
scope 19 { scope 19 {
let _25: usize; let _28: usize;
scope 24 { scope 24 {
} }
} }
scope 20 { scope 20 {
scope 21 { scope 21 {
scope 27 (inlined <Option<(usize, &T)> as FromResidual<Option<Infallible>>>::from_residual) { 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) { scope 25 (inlined <Option<&T> as Try>::branch) {
let _24: &T; let _27: &T;
scope 26 { scope 26 {
} }
} }
@ -49,8 +52,8 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
let _11: std::ptr::NonNull<T>; let _11: std::ptr::NonNull<T>;
let _13: std::ptr::NonNull<T>; let _13: std::ptr::NonNull<T>;
let mut _16: bool; let mut _16: bool;
let mut _20: usize; let mut _23: usize;
let _22: &T; let _25: &T;
scope 29 { scope 29 {
let _12: *const T; let _12: *const T;
scope 30 { scope 30 {
@ -84,7 +87,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
} }
} }
scope 43 (inlined NonNull::<T>::as_ref::<'_>) { scope 43 (inlined NonNull::<T>::as_ref::<'_>) {
let _21: *const T; let _24: *const T;
scope 44 (inlined NonNull::<T>::as_ptr) { scope 44 (inlined NonNull::<T>::as_ptr) {
} }
scope 45 (inlined std::ptr::mut_ptr::<impl *mut T>::cast_const) { 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: { bb4: {
StorageLive(_31);
StorageLive(_28); StorageLive(_28);
StorageLive(_25); StorageLive(_29);
StorageLive(_26); StorageLive(_26);
StorageLive(_23);
StorageLive(_11); StorageLive(_11);
StorageLive(_12); StorageLive(_12);
StorageLive(_19); StorageLive(_19);
StorageLive(_20); StorageLive(_23);
StorageLive(_13); StorageLive(_13);
StorageLive(_22); StorageLive(_25);
_11 = copy _6; _11 = copy _6;
_12 = copy _9; _12 = copy _9;
switchInt(const <T as std::mem::SizedTypeProperties>::IS_ZST) -> [0: bb5, otherwise: bb8]; 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: { bb10: {
StorageDead(_22); StorageDead(_25);
StorageDead(_13); StorageDead(_13);
StorageDead(_20); StorageDead(_23);
StorageDead(_19); StorageDead(_19);
StorageDead(_12); StorageDead(_12);
StorageDead(_11); StorageDead(_11);
StorageDead(_23);
StorageDead(_26); 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(_28);
StorageDead(_31);
StorageDead(_10); StorageDead(_10);
drop(_2) -> [return: bb11, unwind unreachable]; drop(_2) -> [return: bb11, unwind unreachable];
} }
@ -243,51 +253,51 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
} }
bb12: { bb12: {
_20 = SubUnchecked(copy _19, const 1_usize); _23 = SubUnchecked(copy _19, const 1_usize);
_9 = copy _20 as *const T (Transmute); _9 = copy _23 as *const T (Transmute);
goto -> bb13; goto -> bb13;
} }
bb13: { bb13: {
StorageLive(_21); StorageLive(_24);
_21 = copy _11 as *const T (Transmute); _24 = copy _11 as *const T (Transmute);
_22 = &(*_21); _25 = &(*_24);
StorageDead(_21); StorageDead(_24);
_23 = Option::<&T>::Some(copy _22); _26 = Option::<&T>::Some(copy _25);
StorageDead(_22); StorageDead(_25);
StorageDead(_13); StorageDead(_13);
StorageDead(_20); StorageDead(_23);
StorageDead(_19); StorageDead(_19);
StorageDead(_12); StorageDead(_12);
StorageDead(_11); StorageDead(_11);
_24 = copy ((_23 as Some).0: &T); _27 = copy ((_26 as Some).0: &T);
StorageDead(_23); StorageDead(_26);
_25 = copy _10; _28 = copy _10;
_26 = AddWithOverflow(copy _10, const 1_usize); _29 = 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]; assert(!move (_29.1: bool), "attempt to compute `{} + {}`, which would overflow", copy _10, const 1_usize) -> [success: bb14, unwind unreachable];
} }
bb14: { bb14: {
_10 = move (_26.0: usize); _10 = move (_29.0: usize);
StorageLive(_27); StorageLive(_30);
_27 = (copy _25, copy _24); _30 = (copy _28, copy _27);
_28 = Option::<(usize, &T)>::Some(move _27); _31 = Option::<(usize, &T)>::Some(move _30);
StorageDead(_27); StorageDead(_30);
StorageDead(_26); StorageDead(_29);
StorageDead(_25); StorageDead(_28);
_29 = copy (((_28 as Some).0: (usize, &T)).0: usize); _32 = copy (((_31 as Some).0: (usize, &T)).0: usize);
_30 = copy (((_28 as Some).0: (usize, &T)).1: &T); _33 = copy (((_31 as Some).0: (usize, &T)).1: &T);
StorageLive(_31); StorageLive(_34);
_31 = &_2; _34 = &_2;
StorageLive(_32); StorageLive(_35);
_32 = (copy _29, copy _30); _35 = (copy _32, copy _33);
_33 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _31, move _32) -> [return: bb15, unwind unreachable]; _36 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _34, move _35) -> [return: bb15, unwind unreachable];
} }
bb15: { bb15: {
StorageDead(_32); StorageDead(_35);
StorageDead(_34);
StorageDead(_31); StorageDead(_31);
StorageDead(_28);
goto -> bb4; 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> { const fn foo(a: i32) -> Vec<i32> {
vec![1, 2, 3] vec![1, 2, 3]
//~^ ERROR allocations are not allowed //~^ ERROR cannot call non-const
//~| ERROR cannot call non-const method //~| ERROR cannot call non-const
} }
fn main() {} fn main() {}

View file

@ -1,10 +1,4 @@
error[E0010]: allocations are not allowed 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]
| ^^^^^^^^^^^^^ allocation not allowed in constant functions
error[E0015]: cannot call non-const method `slice::<impl [i32]>::into_vec::<std::alloc::Global>` in constant functions
--> $DIR/bad_const_fn_body_ice.rs:2:5 --> $DIR/bad_const_fn_body_ice.rs:2:5
| |
LL | vec![1, 2, 3] 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 = 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 error: aborting due to 2 previous errors
Some errors have detailed explanations: E0010, E0015. For more information about this error, try `rustc --explain E0015`.
For more information about an error, try `rustc --explain E0010`.

View file

@ -15,11 +15,11 @@ fn main() {
let mut g = #[coroutine] let mut g = #[coroutine]
|| { || {
// This is desuraged as 4 stages: // This is desuraged as 4 stages:
// - allocate a `*mut u8` with `exchange_malloc`; // - `vec!` macro
// - create a Box that is ignored for trait computations; // - `write_via_move`
// - compute fields (and yields); // - compute fields (and yields);
// - assign to `t`. // - assign to `t`.
let t = std::boxed::box_new((5, yield)); let t = vec![(5, yield)];
drop(t); drop(t);
}; };
@ -30,7 +30,7 @@ fn main() {
// As it is not taken into account for trait computation, // As it is not taken into account for trait computation,
// the coroutine is `Copy`. // the coroutine is `Copy`.
let mut h = copy(g); 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: // We now have 2 boxes with the same backing allocation:
// one inside `g` and one inside `h`. // 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 --> $DIR/issue-105084.rs:32:17
| |
LL | || { LL | || {
| -- within this `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}` | -- within this `{coroutine@$DIR/issue-105084.rs:16:5: 16:7}`
... ...
LL | let mut h = copy(g); 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 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 | | yield occurs here, with the value maybe used later
| has type `Box<(i32, ())>` which does not implement `Copy` | has type `Box<MaybeUninit<[(i32, ()); 1]>>` which does not implement `Copy`
note: required by a bound in `copy` note: required by a bound in `copy`
--> $DIR/issue-105084.rs:10:12 --> $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> - impl<F, Args> Fn<Args> for Exclusive<F>
where F: Sync, F: Fn<Args>, Args: std::marker::Tuple; 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 error: unconstrained opaque type
--> $DIR/where-allowed.rs:122:16 --> $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 = 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 error: aborting due to 48 previous errors
Some errors have detailed explanations: E0053, E0118, E0283, E0562, E0658, E0666. 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 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 --> $SRC_DIR/core/src/mem/mod.rs:LL:COL
| |
= note: evaluation of `<[&usize; usize::MAX] as std::mem::SizedTypeProperties>::SIZE` failed here = 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` error[E0080]: values of the type `[&usize; usize::MAX]` are too big for the target architecture
--> $SRC_DIR/alloc/src/boxed.rs:LL:COL --> $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`. For more information about this error, try `rustc --explain E0080`.

View file

@ -6,7 +6,7 @@ fn main() {
match Some(vec![42]) { match Some(vec![42]) {
Some(vec![43]) => {} //~ ERROR expected a pattern, found a function call Some(vec![43]) => {} //~ ERROR expected a pattern, found a function call
//~| ERROR found associated function //~| 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> = 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 --> $DIR/vec-macro-in-pattern.rs:7:14
| |
LL | Some(vec![43]) => {} 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 = note: function calls are not allowed in patterns: <https://doc.rust-lang.org/book/ch19-00-patterns.html>
= 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
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 --> $DIR/vec-macro-in-pattern.rs:7:14
| |
LL | Some(vec![43]) => {} LL | Some(vec![43]) => {}
@ -26,5 +24,5 @@ LL | Some(vec![43]) => {}
error: aborting due to 3 previous errors 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`. 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] //~^ 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() { fn pair_underscores_with_initializer() {
let x = 22; let x = 22;
let (_, _): (&'static u32, u32) = (&x, 44); //~ ERROR 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 | | creates a temporary value which is freed while still in use
| type annotation requires that borrow lasts for `'static` | 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 error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:75:40 --> $DIR/patterns.rs:80:40
| |
LL | let x = 22; LL | let x = 22;
| - binding `x` declared here | - binding `x` declared here
@ -124,7 +133,7 @@ LL | }
| - `x` dropped here while still borrowed | - `x` dropped here while still borrowed
error[E0597]: `x` does not live long enough error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:80:40 --> $DIR/patterns.rs:85:40
| |
LL | let x = 22; LL | let x = 22;
| - binding `x` declared here | - binding `x` declared here
@ -136,7 +145,7 @@ LL | }
| - `x` dropped here while still borrowed | - `x` dropped here while still borrowed
error[E0597]: `x` does not live long enough error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:85:69 --> $DIR/patterns.rs:90:69
| |
LL | let x = 22; LL | let x = 22;
| - binding `x` declared here | - binding `x` declared here
@ -148,7 +157,7 @@ LL | }
| - `x` dropped here while still borrowed | - `x` dropped here while still borrowed
error[E0597]: `x` does not live long enough error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:90:69 --> $DIR/patterns.rs:95:69
| |
LL | let x = 22; LL | let x = 22;
| - binding `x` declared here | - binding `x` declared here
@ -160,7 +169,7 @@ LL | }
| - `x` dropped here while still borrowed | - `x` dropped here while still borrowed
error[E0597]: `x` does not live long enough error[E0597]: `x` does not live long enough
--> $DIR/patterns.rs:98:17 --> $DIR/patterns.rs:103:17
| |
LL | let x = 22; LL | let x = 22;
| - binding `x` declared here | - binding `x` declared here
@ -173,7 +182,7 @@ LL | }
| - `x` dropped here while still borrowed | - `x` dropped here while still borrowed
error: lifetime may not live long enough 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 { LL | fn static_to_a_to_static_through_variable<'a>(x: &'a u32) -> &'static u32 {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
@ -182,7 +191,7 @@ LL | y
| ^ returning this value requires that `'a` must outlive `'static` | ^ returning this value requires that `'a` must outlive `'static`
error: lifetime may not live long enough 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 { LL | fn static_to_a_to_static_through_tuple<'a>(x: &'a u32) -> &'static u32 {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
@ -191,7 +200,7 @@ LL | y
| ^ returning this value requires that `'a` must outlive `'static` | ^ returning this value requires that `'a` must outlive `'static`
error: lifetime may not live long enough 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 { LL | fn static_to_a_to_static_through_struct<'a>(_x: &'a u32) -> &'static u32 {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
@ -200,14 +209,14 @@ LL | y
| ^ returning this value requires that `'a` must outlive `'static` | ^ returning this value requires that `'a` must outlive `'static`
error: lifetime may not live long enough 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 { LL | fn a_to_static_then_static<'a>(x: &'a u32) -> &'static u32 {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
LL | let (y, _z): (&'static u32, u32) = (x, 44); LL | let (y, _z): (&'static u32, u32) = (x, 44);
| ^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` | ^^^^^^^^^^^^^^^^^^^ 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. Some errors have detailed explanations: E0597, E0716.
For more information about an error, try `rustc --explain E0597`. For more information about an error, try `rustc --explain E0597`.

View file

@ -4,7 +4,7 @@
fn main() { fn main() {
let vec![const { vec![] }]: Vec<usize> = vec![]; let vec![const { vec![] }]: Vec<usize> = vec![];
//~^ ERROR expected a pattern, found a function call //~^ 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 expected tuple struct or tuple variant
//~| ERROR arbitrary expressions aren't allowed in patterns //~| 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> = 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 --> $DIR/ice-adjust-mode-unimplemented-for-constblock.rs:5:9
| |
LL | let vec![const { vec![] }]: Vec<usize> = vec![]; 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 = note: function calls are not allowed in patterns: <https://doc.rust-lang.org/book/ch19-00-patterns.html>
= 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
error: arbitrary expressions aren't allowed in patterns error: arbitrary expressions aren't allowed in patterns
--> $DIR/ice-adjust-mode-unimplemented-for-constblock.rs:5:14 --> $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 = 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 --> $DIR/ice-adjust-mode-unimplemented-for-constblock.rs:5:9
| |
LL | let vec![const { vec![] }]: Vec<usize> = vec![]; 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 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`. For more information about an error, try `rustc --explain E0164`.

View file

@ -1,5 +1,5 @@
error[E0716]: temporary value dropped while borrowed 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) LL | &id(3)
| ^^^^^ creates a temporary value which is freed while still in use | ^^^^^ creates a temporary value which is freed while still in use

View file

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

View file

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