Auto merge of #148190 - RalfJung:box_new, r=RalfJung
replace box_new with lower-level intrinsics The `box_new` intrinsic is super special: during THIR construction it turns into an `ExprKind::Box` (formerly known as the `box` keyword), which then during MIR building turns into a special instruction sequence that invokes the exchange_malloc lang item (which has a name from a different time) and a special MIR statement to represent a shallowly-initialized `Box` (which raises [interesting opsem questions](https://github.com/rust-lang/rust/issues/97270)). This PR is the n-th attempt to get rid of `box_new`. That's non-trivial because it usually causes a perf regression: replacing `box_new` by naive unsafe code will incur extra copies in debug builds, making the resulting binaries a lot slower, and will generate a lot more MIR, making compilation measurably slower. Furthermore, `vec!` is a macro, so the exact code it expands to is highly relevant for borrow checking, type inference, and temporary scopes. To avoid those problems, this PR does its best to make the MIR almost exactly the same as what it was before. `box_new` is used in two places, `Box::new` and `vec!`: - For `Box::new` that is fairly easy: the `move_by_value` intrinsic is basically all we need. However, to avoid the extra copy that would usually be generated for the argument of a function call, we need to special-case this intrinsic during MIR building. That's what the first commit does. - `vec!` is a lot more tricky. As a macro, its details leak to stable code, so almost every variant I tried broke either type inference or the lifetimes of temporaries in some ui test or ended up accepting unsound code due to the borrow checker not enforcing all the constraints I hoped it would enforce. I ended up with a variant that involves a new intrinsic, `fn write_box_via_move<T>(b: Box<MaybeUninit<T>>, x: T) -> Box<MaybeUninit<T>>`, that writes a value into a `Box<MaybeUninit<T>>` and returns that box again. In exchange we can get rid of somewhat similar code in the lowering for `ExprKind::Box`, and the `exchange_malloc` lang item. (We can also get rid of `Rvalue::ShallowInitBox`; I didn't include that in this PR -- I think @cjgillot has a commit for this somewhere [around here](https://github.com/rust-lang/rust/pull/147862/commits).) See [here](https://github.com/rust-lang/rust/pull/148190#issuecomment-3457454814) for the latest perf numbers. Most of the regressions are in deep-vector which consists entirely of an invocation of `vec!`, so any change to that macro affects this benchmark disproportionally. This is my first time even looking at MIR building code, so I am very low confidence in that part of the patch, in particular when it comes to scopes and drops and things like that. I also had do nerf some clippy tests because clippy gets confused by the new expansion of `vec!` so it makes fewer suggestions when `vec!` is involved. ### `vec!` FAQ - Why does `write_box_via_move` return the `Box` again? Because we need to expand `vec!` to a bunch of method invocations without any blocks or let-statements, or else the temporary scopes (and type inference) don't work out. - Why is `box_assume_init_into_vec_unsafe` (unsoundly!) a safe function? Because we can't use an unsafe block in `vec!` as that would necessarily also include the `$x` (due to it all being one big method invocation) and therefore interpret the user's code as being inside `unsafe`, which would be bad (and 10 years later, we still don't have safe blocks for macros like this). - Why does `write_box_via_move` use `Box` as input/output type, and not, say, raw pointers? Because that is the only way to get the correct behavior when `$x` panics or has control effects: we need the `Box` to be dropped in that case. (As a nice side-effect this also makes the intrinsic safe, which is imported as explained in the previous bullet.) - Can't we make it safe by having `write_box_via_move` return `Box<T>`? Yes we could, but there's no easy way for the intrinsic to convert its `Box<MaybeUninit<T>>` to a `Box<T>`. Transmuting would be unsound as the borrow checker would no longer properly enforce that lifetimes involved in a `vec!` invocation behave correctly. - Is this macro truly cursed? Yes, yes it is.
This commit is contained in:
commit
3c9faa0d03
100 changed files with 1256 additions and 1508 deletions
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -850,13 +850,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) {
|
||||||
|
|
|
||||||
|
|
@ -561,18 +561,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 {
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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];
|
||||||
```
|
```
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 => {
|
||||||
|
|
|
||||||
|
|
@ -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) =
|
||||||
|
|
|
||||||
|
|
@ -432,6 +432,22 @@ impl<'tcx> Place<'tcx> {
|
||||||
self.as_ref().project_deeper(more_projections, tcx)
|
self.as_ref().project_deeper(more_projections, tcx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return a place that projects to a field of the current place.
|
||||||
|
///
|
||||||
|
/// The type of the current place must be an ADT.
|
||||||
|
pub fn project_to_field(
|
||||||
|
self,
|
||||||
|
idx: FieldIdx,
|
||||||
|
local_decls: &impl HasLocalDecls<'tcx>,
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
) -> Self {
|
||||||
|
let ty = self.ty(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);
|
||||||
|
self.project_deeper(&[ProjectionElem::Field(idx, field_ty)], tcx)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn ty_from<D>(
|
pub fn ty_from<D>(
|
||||||
local: Local,
|
local: Local,
|
||||||
projection: &[PlaceElem<'tcx>],
|
projection: &[PlaceElem<'tcx>],
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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]);
|
||||||
|
|
|
||||||
|
|
@ -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 { .. }
|
||||||
|
|
|
||||||
|
|
@ -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];
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 { .. }
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
|
@ -9,8 +10,8 @@ use rustc_middle::mir::*;
|
||||||
use rustc_middle::span_bug;
|
use rustc_middle::span_bug;
|
||||||
use rustc_middle::thir::*;
|
use rustc_middle::thir::*;
|
||||||
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty};
|
use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty};
|
||||||
use rustc_span::DUMMY_SP;
|
|
||||||
use rustc_span::source_map::Spanned;
|
use rustc_span::source_map::Spanned;
|
||||||
|
use rustc_span::{DUMMY_SP, sym};
|
||||||
use rustc_trait_selection::infer::InferCtxtExt;
|
use rustc_trait_selection::infer::InferCtxtExt;
|
||||||
use tracing::{debug, instrument};
|
use tracing::{debug, instrument};
|
||||||
|
|
||||||
|
|
@ -366,6 +367,87 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||||
None
|
None
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
// Some intrinsics are handled here because they desperately want to avoid introducing
|
||||||
|
// unnecessary copies.
|
||||||
|
ExprKind::Call { ty, fun, ref args, .. }
|
||||||
|
if let ty::FnDef(def_id, generic_args) = ty.kind()
|
||||||
|
&& let Some(intrinsic) = this.tcx.intrinsic(def_id)
|
||||||
|
&& matches!(intrinsic.name, sym::write_via_move | sym::write_box_via_move) =>
|
||||||
|
{
|
||||||
|
// We still have to evaluate the callee expression as normal (but we don't care
|
||||||
|
// about its result).
|
||||||
|
let _fun = unpack!(block = this.as_local_operand(block, fun));
|
||||||
|
|
||||||
|
match intrinsic.name {
|
||||||
|
sym::write_via_move => {
|
||||||
|
// `write_via_move(ptr, val)` becomes `*ptr = val` but without any dropping.
|
||||||
|
|
||||||
|
// The destination must have unit type (so we don't actually have to store anything
|
||||||
|
// into it).
|
||||||
|
assert!(destination.ty(&this.local_decls, this.tcx).ty.is_unit());
|
||||||
|
|
||||||
|
// Compile this to an assignment of the argument into the destination.
|
||||||
|
let [ptr, val] = **args else {
|
||||||
|
span_bug!(expr_span, "invalid write_via_move call")
|
||||||
|
};
|
||||||
|
let Some(ptr) = unpack!(block = this.as_local_operand(block, ptr)).place()
|
||||||
|
else {
|
||||||
|
span_bug!(expr_span, "invalid write_via_move call")
|
||||||
|
};
|
||||||
|
let ptr_deref = ptr.project_deeper(&[ProjectionElem::Deref], this.tcx);
|
||||||
|
this.expr_into_dest(ptr_deref, block, val)
|
||||||
|
}
|
||||||
|
sym::write_box_via_move => {
|
||||||
|
// The signature is:
|
||||||
|
// `fn write_box_via_move<T>(b: Box<MaybeUninit<T>>, val: T) -> Box<MaybeUninit<T>>`.
|
||||||
|
// `write_box_via_move(b, val)` becomes
|
||||||
|
// ```
|
||||||
|
// (*b).value.value.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.
|
||||||
|
|
||||||
|
// 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")
|
||||||
|
};
|
||||||
|
let tcx = this.tcx;
|
||||||
|
let decls = &this.local_decls;
|
||||||
|
|
||||||
|
// `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_to_field(FieldIdx::from_u32(1), decls, tcx);
|
||||||
|
// Current type: `ManuallyDrop<T>`. Field #0 is `MaybeDangling<T>`.
|
||||||
|
let place = place.project_to_field(FieldIdx::ZERO, decls, tcx);
|
||||||
|
// Current type: `MaybeDangling<T>`. Field #0 is `T`.
|
||||||
|
let place = place.project_to_field(FieldIdx::ZERO, decls, tcx);
|
||||||
|
// Sanity check.
|
||||||
|
assert_eq!(place.ty(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));
|
||||||
let args: Box<[_]> = args
|
let args: Box<[_]> = args
|
||||||
|
|
@ -770,7 +852,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 { .. }
|
||||||
|
|
|
||||||
|
|
@ -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 { .. }
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -342,7 +342,6 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
|
||||||
| Binary { .. }
|
| Binary { .. }
|
||||||
| Block { .. }
|
| Block { .. }
|
||||||
| Borrow { .. }
|
| Borrow { .. }
|
||||||
| Box { .. }
|
|
||||||
| Call { .. }
|
| Call { .. }
|
||||||
| ByUse { .. }
|
| ByUse { .. }
|
||||||
| Closure { .. }
|
| Closure { .. }
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -177,30 +177,7 @@ impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics {
|
||||||
Some(target) => TerminatorKind::Goto { target },
|
Some(target) => TerminatorKind::Goto { target },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
sym::write_via_move => {
|
// `write_via_move` is already lowered during MIR building.
|
||||||
let target = target.unwrap();
|
|
||||||
let Ok([ptr, val]) = take_array(args) else {
|
|
||||||
span_bug!(
|
|
||||||
terminator.source_info.span,
|
|
||||||
"Wrong number of arguments for write_via_move intrinsic",
|
|
||||||
);
|
|
||||||
};
|
|
||||||
let derefed_place = if let Some(place) = ptr.node.place()
|
|
||||||
&& let Some(local) = place.as_local()
|
|
||||||
{
|
|
||||||
tcx.mk_place_deref(local.into())
|
|
||||||
} else {
|
|
||||||
span_bug!(
|
|
||||||
terminator.source_info.span,
|
|
||||||
"Only passing a local is supported"
|
|
||||||
);
|
|
||||||
};
|
|
||||||
block.statements.push(Statement::new(
|
|
||||||
terminator.source_info,
|
|
||||||
StatementKind::Assign(Box::new((derefed_place, Rvalue::Use(val.node)))),
|
|
||||||
));
|
|
||||||
terminator.kind = TerminatorKind::Goto { target };
|
|
||||||
}
|
|
||||||
sym::discriminant_value => {
|
sym::discriminant_value => {
|
||||||
let target = target.unwrap();
|
let target = target.unwrap();
|
||||||
let Ok([arg]) = take_array(args) else {
|
let Ok([arg]) = take_array(args) else {
|
||||||
|
|
|
||||||
|
|
@ -991,7 +991,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,
|
||||||
|
|
@ -2183,7 +2182,6 @@ symbols! {
|
||||||
slice_from_raw_parts_mut,
|
slice_from_raw_parts_mut,
|
||||||
slice_from_ref,
|
slice_from_ref,
|
||||||
slice_get_unchecked,
|
slice_get_unchecked,
|
||||||
slice_into_vec,
|
|
||||||
slice_iter,
|
slice_iter,
|
||||||
slice_len_fn,
|
slice_len_fn,
|
||||||
slice_patterns,
|
slice_patterns,
|
||||||
|
|
@ -2542,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,
|
||||||
|
|
|
||||||
|
|
@ -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 { .. }
|
||||||
|
|
|
||||||
|
|
@ -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")]
|
||||||
|
|
|
||||||
|
|
@ -479,19 +479,6 @@ unsafe impl const Allocator for Global {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The allocator for `Box`.
|
|
||||||
#[cfg(not(no_global_oom_handling))]
|
|
||||||
#[lang = "exchange_malloc"]
|
|
||||||
#[inline]
|
|
||||||
#[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
|
|
||||||
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))]
|
||||||
|
|
|
||||||
|
|
@ -236,14 +236,35 @@ 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))]
|
||||||
|
#[rustc_diagnostic_item = "box_assume_init_into_vec_unsafe"]
|
||||||
|
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,7 +283,16 @@ 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 {
|
||||||
return box_new(x);
|
// 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 {
|
||||||
|
box_new_uninit(<T as SizedTypeProperties>::SIZE, <T as SizedTypeProperties>::ALIGN)
|
||||||
|
} as *mut T;
|
||||||
|
// Nothing below can panic so we do not have to worry about deallocating `ptr`.
|
||||||
|
// SAFETY: we just allocated the box to store `x`.
|
||||||
|
unsafe { core::intrinsics::write_via_move(ptr, x) };
|
||||||
|
// SAFETY: we just initialized `b`.
|
||||||
|
unsafe { mem::transmute(ptr) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a new box with uninitialized contents.
|
/// Constructs a new box with uninitialized contents.
|
||||||
|
|
@ -280,9 +310,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
|
||||||
|
|
@ -1142,10 +1184,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>`.
|
||||||
|
|
|
||||||
15
library/alloc/src/intrinsics.rs
Normal file
15
library/alloc/src/intrinsics.rs
Normal 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>>;
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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),+])
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -477,7 +477,6 @@ impl<T> [T] {
|
||||||
#[rustc_allow_incoherent_impl]
|
#[rustc_allow_incoherent_impl]
|
||||||
#[stable(feature = "rust1", since = "1.0.0")]
|
#[stable(feature = "rust1", since = "1.0.0")]
|
||||||
#[inline]
|
#[inline]
|
||||||
#[rustc_diagnostic_item = "slice_into_vec"]
|
|
||||||
pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> {
|
pub fn into_vec<A: Allocator>(self: Box<Self, A>) -> Vec<T, A> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let len = self.len();
|
let len = self.len();
|
||||||
|
|
|
||||||
|
|
@ -297,12 +297,12 @@ impl<'a> VecArgs<'a> {
|
||||||
// `vec![elem; size]` case
|
// `vec![elem; size]` case
|
||||||
Some(VecArgs::Repeat(elem, size))
|
Some(VecArgs::Repeat(elem, size))
|
||||||
},
|
},
|
||||||
(sym::slice_into_vec, [slice])
|
(sym::box_assume_init_into_vec_unsafe, [write_box_via_move])
|
||||||
if let ExprKind::Call(_, [arg]) = slice.kind
|
if let ExprKind::Call(_, [_box, elems]) = write_box_via_move.kind
|
||||||
&& let ExprKind::Array(args) = arg.kind =>
|
&& let ExprKind::Array(elems) = elems.kind =>
|
||||||
{
|
{
|
||||||
// `vec![a, b, c]` case
|
// `vec![a, b, c]` case
|
||||||
Some(VecArgs::Vec(args))
|
Some(VecArgs::Vec(elems))
|
||||||
},
|
},
|
||||||
(sym::vec_new, []) => Some(VecArgs::Vec(&[])),
|
(sym::vec_new, []) => Some(VecArgs::Vec(&[])),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
|
|
||||||
|
|
@ -91,6 +91,7 @@ generate! {
|
||||||
author,
|
author,
|
||||||
borrow,
|
borrow,
|
||||||
borrow_mut,
|
borrow_mut,
|
||||||
|
box_assume_init_into_vec_unsafe,
|
||||||
build_hasher,
|
build_hasher,
|
||||||
by_ref,
|
by_ref,
|
||||||
bytes,
|
bytes,
|
||||||
|
|
|
||||||
|
|
@ -113,10 +113,7 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// #6811
|
// #6811
|
||||||
match Some(0) {
|
Some(0).map(|x| vec![x]);
|
||||||
Some(x) => Some(vec![x]),
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Don't lint, coercion
|
// Don't lint, coercion
|
||||||
let x: Option<Vec<&[u8]>> = match Some(()) {
|
let x: Option<Vec<&[u8]>> = match Some(()) {
|
||||||
|
|
|
||||||
|
|
@ -183,6 +183,7 @@ fn main() {
|
||||||
|
|
||||||
// #6811
|
// #6811
|
||||||
match Some(0) {
|
match Some(0) {
|
||||||
|
//~^ manual_map
|
||||||
Some(x) => Some(vec![x]),
|
Some(x) => Some(vec![x]),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -173,7 +173,17 @@ LL | | };
|
||||||
| |_____^ help: try: `Some((String::new(), "test")).as_ref().map(|(x, y)| (y, x))`
|
| |_____^ help: try: `Some((String::new(), "test")).as_ref().map(|(x, y)| (y, x))`
|
||||||
|
|
||||||
error: manual implementation of `Option::map`
|
error: manual implementation of `Option::map`
|
||||||
--> tests/ui/manual_map_option.rs:196:5
|
--> tests/ui/manual_map_option.rs:185:5
|
||||||
|
|
|
||||||
|
LL | / match Some(0) {
|
||||||
|
LL | |
|
||||||
|
LL | | Some(x) => Some(vec![x]),
|
||||||
|
LL | | None => None,
|
||||||
|
LL | | };
|
||||||
|
| |_____^ help: try: `Some(0).map(|x| vec![x])`
|
||||||
|
|
||||||
|
error: manual implementation of `Option::map`
|
||||||
|
--> tests/ui/manual_map_option.rs:197:5
|
||||||
|
|
|
|
||||||
LL | / match option_env!("") {
|
LL | / match option_env!("") {
|
||||||
LL | |
|
LL | |
|
||||||
|
|
@ -183,7 +193,7 @@ LL | | };
|
||||||
| |_____^ help: try: `option_env!("").map(String::from)`
|
| |_____^ help: try: `option_env!("").map(String::from)`
|
||||||
|
|
||||||
error: manual implementation of `Option::map`
|
error: manual implementation of `Option::map`
|
||||||
--> tests/ui/manual_map_option.rs:217:12
|
--> tests/ui/manual_map_option.rs:218:12
|
||||||
|
|
|
|
||||||
LL | } else if let Some(x) = Some(0) {
|
LL | } else if let Some(x) = Some(0) {
|
||||||
| ____________^
|
| ____________^
|
||||||
|
|
@ -195,7 +205,7 @@ LL | | };
|
||||||
| |_____^ help: try: `{ Some(0).map(|x| x + 1) }`
|
| |_____^ help: try: `{ Some(0).map(|x| x + 1) }`
|
||||||
|
|
||||||
error: manual implementation of `Option::map`
|
error: manual implementation of `Option::map`
|
||||||
--> tests/ui/manual_map_option.rs:226:12
|
--> tests/ui/manual_map_option.rs:227:12
|
||||||
|
|
|
|
||||||
LL | } else if let Some(x) = Some(0) {
|
LL | } else if let Some(x) = Some(0) {
|
||||||
| ____________^
|
| ____________^
|
||||||
|
|
@ -206,5 +216,5 @@ LL | | None
|
||||||
LL | | };
|
LL | | };
|
||||||
| |_____^ help: try: `{ Some(0).map(|x| x + 1) }`
|
| |_____^ help: try: `{ Some(0).map(|x| x + 1) }`
|
||||||
|
|
||||||
error: aborting due to 20 previous errors
|
error: aborting due to 21 previous errors
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ fn or_fun_call() {
|
||||||
with_constructor.unwrap_or_else(make);
|
with_constructor.unwrap_or_else(make);
|
||||||
//~^ or_fun_call
|
//~^ or_fun_call
|
||||||
|
|
||||||
let with_new = Some(vec![1]);
|
let with_new: Option<Vec<i32>> = Some(vec![1]);
|
||||||
with_new.unwrap_or_default();
|
with_new.unwrap_or_default();
|
||||||
//~^ unwrap_or_default
|
//~^ unwrap_or_default
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@ fn or_fun_call() {
|
||||||
real_default.unwrap_or_default();
|
real_default.unwrap_or_default();
|
||||||
//~^ unwrap_or_default
|
//~^ unwrap_or_default
|
||||||
|
|
||||||
let with_vec = Some(vec![1]);
|
let with_vec: Option<Vec<i32>> = Some(vec![1]);
|
||||||
with_vec.unwrap_or_default();
|
with_vec.unwrap_or_default();
|
||||||
//~^ unwrap_or_default
|
//~^ unwrap_or_default
|
||||||
|
|
||||||
|
|
@ -329,7 +329,7 @@ mod lazy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let with_new = Some(vec![1]);
|
let with_new: Option<Vec<i32>> = Some(vec![1]);
|
||||||
with_new.unwrap_or_default();
|
with_new.unwrap_or_default();
|
||||||
//~^ unwrap_or_default
|
//~^ unwrap_or_default
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -53,7 +53,7 @@ fn or_fun_call() {
|
||||||
with_constructor.unwrap_or(make());
|
with_constructor.unwrap_or(make());
|
||||||
//~^ or_fun_call
|
//~^ or_fun_call
|
||||||
|
|
||||||
let with_new = Some(vec![1]);
|
let with_new: Option<Vec<i32>> = Some(vec![1]);
|
||||||
with_new.unwrap_or(Vec::new());
|
with_new.unwrap_or(Vec::new());
|
||||||
//~^ unwrap_or_default
|
//~^ unwrap_or_default
|
||||||
|
|
||||||
|
|
@ -101,7 +101,7 @@ fn or_fun_call() {
|
||||||
real_default.unwrap_or(<FakeDefault as Default>::default());
|
real_default.unwrap_or(<FakeDefault as Default>::default());
|
||||||
//~^ unwrap_or_default
|
//~^ unwrap_or_default
|
||||||
|
|
||||||
let with_vec = Some(vec![1]);
|
let with_vec: Option<Vec<i32>> = Some(vec![1]);
|
||||||
with_vec.unwrap_or(Vec::new());
|
with_vec.unwrap_or(Vec::new());
|
||||||
//~^ unwrap_or_default
|
//~^ unwrap_or_default
|
||||||
|
|
||||||
|
|
@ -329,7 +329,7 @@ mod lazy {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let with_new = Some(vec![1]);
|
let with_new: Option<Vec<i32>> = Some(vec![1]);
|
||||||
with_new.unwrap_or_else(Vec::new);
|
with_new.unwrap_or_else(Vec::new);
|
||||||
//~^ unwrap_or_default
|
//~^ unwrap_or_default
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,8 +43,7 @@ fn unwrap_or_else_default() {
|
||||||
with_enum.unwrap_or_else(Enum::A);
|
with_enum.unwrap_or_else(Enum::A);
|
||||||
|
|
||||||
let with_new = Some(vec![1]);
|
let with_new = Some(vec![1]);
|
||||||
with_new.unwrap_or_default();
|
with_new.unwrap_or_else(Vec::new);
|
||||||
//~^ unwrap_or_default
|
|
||||||
|
|
||||||
let with_err: Result<_, ()> = Ok(vec![1]);
|
let with_err: Result<_, ()> = Ok(vec![1]);
|
||||||
with_err.unwrap_or_else(make);
|
with_err.unwrap_or_else(make);
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@ fn unwrap_or_else_default() {
|
||||||
|
|
||||||
let with_new = Some(vec![1]);
|
let with_new = Some(vec![1]);
|
||||||
with_new.unwrap_or_else(Vec::new);
|
with_new.unwrap_or_else(Vec::new);
|
||||||
//~^ unwrap_or_default
|
|
||||||
|
|
||||||
let with_err: Result<_, ()> = Ok(vec![1]);
|
let with_err: Result<_, ()> = Ok(vec![1]);
|
||||||
with_err.unwrap_or_else(make);
|
with_err.unwrap_or_else(make);
|
||||||
|
|
|
||||||
|
|
@ -1,101 +1,95 @@
|
||||||
error: use of `unwrap_or_else` to construct default value
|
error: use of `unwrap_or_else` to construct default value
|
||||||
--> tests/ui/unwrap_or_else_default.rs:46:14
|
--> tests/ui/unwrap_or_else_default.rs:60:23
|
||||||
|
|
|
|
||||||
LL | with_new.unwrap_or_else(Vec::new);
|
LL | with_real_default.unwrap_or_else(<HasDefaultAndDuplicate as Default>::default);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
||||||
|
|
|
|
||||||
= note: `-D clippy::unwrap-or-default` implied by `-D warnings`
|
= note: `-D clippy::unwrap-or-default` implied by `-D warnings`
|
||||||
= help: to override `-D warnings` add `#[allow(clippy::unwrap_or_default)]`
|
= help: to override `-D warnings` add `#[allow(clippy::unwrap_or_default)]`
|
||||||
|
|
||||||
error: use of `unwrap_or_else` to construct default value
|
error: use of `unwrap_or_else` to construct default value
|
||||||
--> tests/ui/unwrap_or_else_default.rs:61:23
|
--> tests/ui/unwrap_or_else_default.rs:64:24
|
||||||
|
|
|
||||||
LL | with_real_default.unwrap_or_else(<HasDefaultAndDuplicate as Default>::default);
|
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
|
||||||
|
|
||||||
error: use of `unwrap_or_else` to construct default value
|
|
||||||
--> tests/ui/unwrap_or_else_default.rs:65:24
|
|
||||||
|
|
|
|
||||||
LL | with_default_trait.unwrap_or_else(Default::default);
|
LL | with_default_trait.unwrap_or_else(Default::default);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
||||||
|
|
||||||
error: use of `unwrap_or_else` to construct default value
|
error: use of `unwrap_or_else` to construct default value
|
||||||
--> tests/ui/unwrap_or_else_default.rs:69:23
|
--> tests/ui/unwrap_or_else_default.rs:68:23
|
||||||
|
|
|
|
||||||
LL | with_default_type.unwrap_or_else(u64::default);
|
LL | with_default_type.unwrap_or_else(u64::default);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
||||||
|
|
||||||
error: use of `unwrap_or_else` to construct default value
|
error: use of `unwrap_or_else` to construct default value
|
||||||
--> tests/ui/unwrap_or_else_default.rs:73:23
|
--> tests/ui/unwrap_or_else_default.rs:72:23
|
||||||
|
|
|
|
||||||
LL | with_default_type.unwrap_or_else(Vec::new);
|
LL | with_default_type.unwrap_or_else(Vec::new);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
||||||
|
|
||||||
error: use of `unwrap_or_else` to construct default value
|
error: use of `unwrap_or_else` to construct default value
|
||||||
--> tests/ui/unwrap_or_else_default.rs:77:18
|
--> tests/ui/unwrap_or_else_default.rs:76:18
|
||||||
|
|
|
|
||||||
LL | empty_string.unwrap_or_else(|| "".to_string());
|
LL | empty_string.unwrap_or_else(|| "".to_string());
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
||||||
|
|
||||||
error: use of `unwrap_or_else` to construct default value
|
error: use of `unwrap_or_else` to construct default value
|
||||||
--> tests/ui/unwrap_or_else_default.rs:82:12
|
--> tests/ui/unwrap_or_else_default.rs:81:12
|
||||||
|
|
|
|
||||||
LL | option.unwrap_or_else(Vec::new).push(1);
|
LL | option.unwrap_or_else(Vec::new).push(1);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
||||||
|
|
||||||
error: use of `unwrap_or_else` to construct default value
|
error: use of `unwrap_or_else` to construct default value
|
||||||
--> tests/ui/unwrap_or_else_default.rs:86:12
|
--> tests/ui/unwrap_or_else_default.rs:85:12
|
||||||
|
|
|
|
||||||
LL | option.unwrap_or_else(Vec::new).push(1);
|
LL | option.unwrap_or_else(Vec::new).push(1);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
||||||
|
|
||||||
error: use of `unwrap_or_else` to construct default value
|
error: use of `unwrap_or_else` to construct default value
|
||||||
--> tests/ui/unwrap_or_else_default.rs:90:12
|
--> tests/ui/unwrap_or_else_default.rs:89:12
|
||||||
|
|
|
|
||||||
LL | option.unwrap_or_else(Vec::new).push(1);
|
LL | option.unwrap_or_else(Vec::new).push(1);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
||||||
|
|
||||||
error: use of `unwrap_or_else` to construct default value
|
error: use of `unwrap_or_else` to construct default value
|
||||||
--> tests/ui/unwrap_or_else_default.rs:94:12
|
--> tests/ui/unwrap_or_else_default.rs:93:12
|
||||||
|
|
|
|
||||||
LL | option.unwrap_or_else(Vec::new).push(1);
|
LL | option.unwrap_or_else(Vec::new).push(1);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
||||||
|
|
||||||
error: use of `unwrap_or_else` to construct default value
|
error: use of `unwrap_or_else` to construct default value
|
||||||
--> tests/ui/unwrap_or_else_default.rs:98:12
|
--> tests/ui/unwrap_or_else_default.rs:97:12
|
||||||
|
|
|
|
||||||
LL | option.unwrap_or_else(Vec::new).push(1);
|
LL | option.unwrap_or_else(Vec::new).push(1);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
||||||
|
|
||||||
error: use of `unwrap_or_else` to construct default value
|
error: use of `unwrap_or_else` to construct default value
|
||||||
--> tests/ui/unwrap_or_else_default.rs:102:12
|
--> tests/ui/unwrap_or_else_default.rs:101:12
|
||||||
|
|
|
|
||||||
LL | option.unwrap_or_else(Vec::new).push(1);
|
LL | option.unwrap_or_else(Vec::new).push(1);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
||||||
|
|
||||||
error: use of `unwrap_or_else` to construct default value
|
error: use of `unwrap_or_else` to construct default value
|
||||||
--> tests/ui/unwrap_or_else_default.rs:106:12
|
--> tests/ui/unwrap_or_else_default.rs:105:12
|
||||||
|
|
|
|
||||||
LL | option.unwrap_or_else(Vec::new).push(1);
|
LL | option.unwrap_or_else(Vec::new).push(1);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
||||||
|
|
||||||
error: use of `unwrap_or_else` to construct default value
|
error: use of `unwrap_or_else` to construct default value
|
||||||
--> tests/ui/unwrap_or_else_default.rs:110:12
|
--> tests/ui/unwrap_or_else_default.rs:109:12
|
||||||
|
|
|
|
||||||
LL | option.unwrap_or_else(Vec::new).push(1);
|
LL | option.unwrap_or_else(Vec::new).push(1);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
||||||
|
|
||||||
error: use of `unwrap_or_else` to construct default value
|
error: use of `unwrap_or_else` to construct default value
|
||||||
--> tests/ui/unwrap_or_else_default.rs:127:12
|
--> tests/ui/unwrap_or_else_default.rs:126:12
|
||||||
|
|
|
|
||||||
LL | option.unwrap_or_else(Vec::new).push(1);
|
LL | option.unwrap_or_else(Vec::new).push(1);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `unwrap_or_default()`
|
||||||
|
|
||||||
error: use of `or_insert_with` to construct default value
|
error: use of `or_insert_with` to construct default value
|
||||||
--> tests/ui/unwrap_or_else_default.rs:145:32
|
--> tests/ui/unwrap_or_else_default.rs:144:32
|
||||||
|
|
|
|
||||||
LL | let _ = inner_map.entry(0).or_insert_with(Default::default);
|
LL | let _ = inner_map.entry(0).or_insert_with(Default::default);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()`
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `or_default()`
|
||||||
|
|
||||||
error: aborting due to 16 previous errors
|
error: aborting due to 15 previous errors
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ error: Undefined Behavior: write access through <TAG> at ALLOC[0x0] is forbidden
|
||||||
--> RUSTLIB/core/src/mem/mod.rs:LL:CC
|
--> RUSTLIB/core/src/mem/mod.rs:LL:CC
|
||||||
|
|
|
|
||||||
LL | crate::intrinsics::write_via_move(dest, src);
|
LL | crate::intrinsics::write_via_move(dest, src);
|
||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here
|
| ^^^ Undefined Behavior occurred here
|
||||||
|
|
|
|
||||||
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
|
= help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
|
||||||
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information
|
= help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information
|
||||||
|
|
|
||||||
|
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
5
src/tools/miri/tests/pass/vec.stack.stderr
Normal file
5
src/tools/miri/tests/pass/vec.stack.stderr
Normal 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
|
||||||
5
src/tools/miri/tests/pass/vec.tree.stderr
Normal file
5
src/tools/miri/tests/pass/vec.tree.stderr
Normal 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
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
29
tests/mir-opt/building/write_box_via_move.rs
Normal file
29
tests/mir-opt/building/write_box_via_move.rs
Normal 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();
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
// 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 _4: &mut std::mem::MaybeUninit<[T; 1024]>;
|
||||||
|
let mut _5: &mut std::mem::MaybeUninit<[T; 1024]>;
|
||||||
|
let _6: ();
|
||||||
|
let mut _7: *mut [T; 1024];
|
||||||
|
let mut _8: T;
|
||||||
|
let mut _9: std::boxed::Box<std::mem::MaybeUninit<[T; 1024]>>;
|
||||||
|
scope 1 {
|
||||||
|
debug b => _2;
|
||||||
|
let _3: *mut [T; 1024];
|
||||||
|
scope 2 {
|
||||||
|
debug ptr => _3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bb0: {
|
||||||
|
StorageLive(_2);
|
||||||
|
_2 = Box::<[T; 1024]>::new_uninit() -> [return: bb1, unwind: bb7];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb1: {
|
||||||
|
nop;
|
||||||
|
StorageLive(_3);
|
||||||
|
StorageLive(_4);
|
||||||
|
StorageLive(_5);
|
||||||
|
_5 = &mut (*_2);
|
||||||
|
_4 = &mut (*_5);
|
||||||
|
_3 = MaybeUninit::<[T; 1024]>::as_mut_ptr(move _4) -> [return: bb2, unwind: bb6];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb2: {
|
||||||
|
StorageDead(_4);
|
||||||
|
nop;
|
||||||
|
StorageDead(_5);
|
||||||
|
StorageLive(_6);
|
||||||
|
StorageLive(_7);
|
||||||
|
_7 = copy _3;
|
||||||
|
StorageLive(_8);
|
||||||
|
_8 = copy _1;
|
||||||
|
(*_7) = [move _8; 1024];
|
||||||
|
StorageDead(_8);
|
||||||
|
StorageDead(_7);
|
||||||
|
StorageDead(_6);
|
||||||
|
StorageLive(_9);
|
||||||
|
_9 = move _2;
|
||||||
|
_0 = Box::<MaybeUninit<[T; 1024]>>::assume_init(move _9) -> [return: bb3, unwind: bb5];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb3: {
|
||||||
|
StorageDead(_9);
|
||||||
|
StorageDead(_3);
|
||||||
|
drop(_2) -> [return: bb4, unwind: bb7];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb4: {
|
||||||
|
StorageDead(_2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bb5 (cleanup): {
|
||||||
|
drop(_9) -> [return: bb6, unwind terminate(cleanup)];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb6 (cleanup): {
|
||||||
|
drop(_2) -> [return: bb7, unwind terminate(cleanup)];
|
||||||
|
}
|
||||||
|
|
||||||
|
bb7 (cleanup): {
|
||||||
|
resume;
|
||||||
|
}
|
||||||
|
}
|
||||||
23
tests/mir-opt/building/write_via_move.rs
Normal file
23
tests/mir-opt/building/write_via_move.rs
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
//! Ensure we don't generate unnecessary copys for `write_via_move`.
|
||||||
|
//@ compile-flags: -Zmir-opt-level=0
|
||||||
|
#![feature(core_intrinsics)]
|
||||||
|
|
||||||
|
use std::mem;
|
||||||
|
|
||||||
|
// Can't emit `built.after` here as that contains user type annotations which contain DefId that
|
||||||
|
// change all the time.
|
||||||
|
// EMIT_MIR write_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();
|
||||||
|
let ptr = mem::MaybeUninit::as_mut_ptr(&mut *b);
|
||||||
|
// Ensure the array gets constructed directly into the deref'd pointer.
|
||||||
|
// CHECK: (*[[TEMP1:_.+]]) = [{{(move|copy) _.+}}; 1024];
|
||||||
|
unsafe { std::intrinsics::write_via_move(ptr, [x; 1024]) };
|
||||||
|
unsafe { b.assume_init() }
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
box_new(0);
|
||||||
|
}
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
|
|
@ -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];
|
||||||
}
|
}
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
|
|
|
||||||
|
|
@ -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];
|
||||||
}
|
}
|
||||||
+ }
|
+ }
|
||||||
+
|
+
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -213,7 +213,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);
|
||||||
|
|
|
||||||
|
|
@ -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() {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -197,17 +197,6 @@ pub fn read_via_copy_uninhabited(r: &Never) -> Never {
|
||||||
unsafe { core::intrinsics::read_via_copy(r) }
|
unsafe { core::intrinsics::read_via_copy(r) }
|
||||||
}
|
}
|
||||||
|
|
||||||
// EMIT_MIR lower_intrinsics.write_via_move_string.LowerIntrinsics.diff
|
|
||||||
pub fn write_via_move_string(r: &mut String, v: String) {
|
|
||||||
// CHECK-LABEL: fn write_via_move_string(
|
|
||||||
// CHECK: [[ptr:_.*]] = &raw mut (*_1);
|
|
||||||
// CHECK: [[tmp:_.*]] = move _2;
|
|
||||||
// CHECK: (*[[ptr]]) = move [[tmp]];
|
|
||||||
// CHECK: return;
|
|
||||||
|
|
||||||
unsafe { core::intrinsics::write_via_move(r, v) }
|
|
||||||
}
|
|
||||||
|
|
||||||
pub enum Never {}
|
pub enum Never {}
|
||||||
|
|
||||||
// EMIT_MIR lower_intrinsics.ptr_offset.LowerIntrinsics.diff
|
// EMIT_MIR lower_intrinsics.ptr_offset.LowerIntrinsics.diff
|
||||||
|
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
- // MIR for `write_via_move_string` before LowerIntrinsics
|
|
||||||
+ // MIR for `write_via_move_string` after LowerIntrinsics
|
|
||||||
|
|
||||||
fn write_via_move_string(_1: &mut String, _2: String) -> () {
|
|
||||||
debug r => _1;
|
|
||||||
debug v => _2;
|
|
||||||
let mut _0: ();
|
|
||||||
let mut _3: *mut std::string::String;
|
|
||||||
let mut _4: std::string::String;
|
|
||||||
|
|
||||||
bb0: {
|
|
||||||
StorageLive(_3);
|
|
||||||
_3 = &raw mut (*_1);
|
|
||||||
StorageLive(_4);
|
|
||||||
_4 = move _2;
|
|
||||||
- _0 = write_via_move::<String>(move _3, move _4) -> [return: bb1, unwind unreachable];
|
|
||||||
+ (*_3) = move _4;
|
|
||||||
+ goto -> bb1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
StorageDead(_4);
|
|
||||||
StorageDead(_3);
|
|
||||||
goto -> bb2;
|
|
||||||
}
|
|
||||||
|
|
||||||
bb2: {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -1,31 +0,0 @@
|
||||||
- // MIR for `write_via_move_string` before LowerIntrinsics
|
|
||||||
+ // MIR for `write_via_move_string` after LowerIntrinsics
|
|
||||||
|
|
||||||
fn write_via_move_string(_1: &mut String, _2: String) -> () {
|
|
||||||
debug r => _1;
|
|
||||||
debug v => _2;
|
|
||||||
let mut _0: ();
|
|
||||||
let mut _3: *mut std::string::String;
|
|
||||||
let mut _4: std::string::String;
|
|
||||||
|
|
||||||
bb0: {
|
|
||||||
StorageLive(_3);
|
|
||||||
_3 = &raw mut (*_1);
|
|
||||||
StorageLive(_4);
|
|
||||||
_4 = move _2;
|
|
||||||
- _0 = write_via_move::<String>(move _3, move _4) -> [return: bb1, unwind unreachable];
|
|
||||||
+ (*_3) = move _4;
|
|
||||||
+ goto -> bb1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bb1: {
|
|
||||||
StorageDead(_4);
|
|
||||||
StorageDead(_3);
|
|
||||||
goto -> bb2;
|
|
||||||
}
|
|
||||||
|
|
||||||
bb2: {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
tests/ui/coercion/vec-macro-coercions.rs
Normal file
12
tests/ui/coercion/vec-macro-coercions.rs
Normal 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];
|
||||||
|
}
|
||||||
|
|
@ -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() {}
|
||||||
|
|
|
||||||
|
|
@ -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`.
|
|
||||||
|
|
|
||||||
|
|
@ -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`.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
|
||||||
|
|
|
||||||
|
|
@ -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() {}
|
|
||||||
|
|
@ -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`.
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
||||||
#![allow(warnings)]
|
|
||||||
|
|
||||||
const CON: Vec<i32> = vec![1, 2, 3]; //~ ERROR E0010
|
|
||||||
//~| ERROR cannot call non-const method
|
|
||||||
fn main() {}
|
|
||||||
|
|
@ -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`.
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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`.
|
||||||
|
|
|
||||||
|
|
@ -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]
|
|
||||||
}
|
|
||||||
|
|
@ -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`.
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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`.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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`.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -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`.
|
||||||
|
|
|
||||||
|
|
@ -1,8 +0,0 @@
|
||||||
//@ compile-flags: -Zunpretty=thir-tree
|
|
||||||
//@ check-pass
|
|
||||||
|
|
||||||
#![feature(liballoc_internals)]
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
let _ = std::boxed::box_new(1);
|
|
||||||
}
|
|
||||||
|
|
@ -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: []
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue