Auto merge of #145513 - beepster4096:erasedereftemps, r=saethlin,cjgillot

Validate CopyForDeref and DerefTemps better and remove them from runtime MIR

(split from my WIP rust-lang/rust#145344)

This PR:
- Removes `Rvalue::CopyForDeref` and `LocalInfo::DerefTemp` from runtime MIR
    - Using a new mir pass `EraseDerefTemps`
    - `CopyForDeref(x)` is turned into `Use(Copy(x))`
    - `DerefTemp` is turned into `Boring`
        - Not sure if this part is actually necessary, it made more sense in rust-lang/rust#145344 with `DerefTemp` storing actual data that I wanted to keep from having to be kept in sync with the rest of the body in runtime MIR
- Checks in validation that `CopyForDeref` and `DerefTemp` are only used together
- Removes special handling for `CopyForDeref` from many places
- Removes `CopyForDeref` from `custom_mir` reverting rust-lang/rust#111587
    - In runtime MIR simple copies can be used instead
    - In post cleanup analysis MIR it was already wrong to use due to the lack of support for creating `DerefTemp` locals
    - Possibly this should be its own PR?
 - Adds an argument to `deref_finder` to avoid creating new `DerefTemp`s and `CopyForDeref` in runtime MIR.
     - Ideally we would just avoid making intermediate derefs instead of fixing it at the end of a pass / during shim building
 - Removes some usages of `deref_finder` that I found out don't actually do anything

r? oli-obk
This commit is contained in:
bors 2025-10-12 02:34:20 +00:00
commit 3be68033b6
55 changed files with 418 additions and 407 deletions

View file

@ -1538,24 +1538,6 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
self.consume_operand(location, (operand, span), state)
}
&Rvalue::CopyForDeref(place) => {
self.access_place(
location,
(place, span),
(Deep, Read(ReadKind::Copy)),
LocalMutationIsAllowed::No,
state,
);
// Finally, check if path was already moved.
self.check_if_path_or_subpath_is_moved(
location,
InitializationRequiringAction::Use,
(place.as_ref(), span),
state,
);
}
&Rvalue::Discriminant(place) => {
let af = match *rvalue {
Rvalue::Discriminant(..) => None,
@ -1617,6 +1599,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
Rvalue::WrapUnsafeBinder(op, _) => {
self.consume_operand(location, (op, span), state);
}
Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in borrowck"),
}
}

View file

@ -300,11 +300,6 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> {
| Rvalue::Cast(_ /*cast_kind*/, operand, _ /*ty*/)
| Rvalue::ShallowInitBox(operand, _ /*ty*/) => self.consume_operand(location, operand),
&Rvalue::CopyForDeref(place) => {
let op = &Operand::Copy(place);
self.consume_operand(location, op);
}
&Rvalue::Discriminant(place) => {
self.access_place(
location,
@ -330,6 +325,8 @@ impl<'a, 'tcx> LoanInvalidationsGenerator<'a, 'tcx> {
Rvalue::WrapUnsafeBinder(op, _) => {
self.consume_operand(location, op);
}
Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in borrowck"),
}
}

View file

@ -600,11 +600,6 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
let val = codegen_operand(fx, operand);
lval.write_cvalue(fx, val);
}
Rvalue::CopyForDeref(place) => {
let cplace = codegen_place(fx, place);
let val = cplace.to_cvalue(fx);
lval.write_cvalue(fx, val)
}
Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => {
let place = codegen_place(fx, place);
let ref_ = place.place_ref(fx, lval.layout());
@ -928,6 +923,7 @@ fn codegen_stmt<'tcx>(fx: &mut FunctionCx<'_, '_, 'tcx>, cur_block: Block, stmt:
let operand = codegen_operand(fx, operand);
lval.write_cvalue_transmute(fx, operand);
}
Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in codegen"),
}
}
StatementKind::StorageLive(_)

View file

@ -504,9 +504,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
self.codegen_place_to_pointer(bx, place, mk_ref)
}
mir::Rvalue::CopyForDeref(place) => {
self.codegen_operand(bx, &mir::Operand::Copy(place))
}
mir::Rvalue::RawPtr(kind, place) => {
let mk_ptr = move |tcx: TyCtxt<'tcx>, ty: Ty<'tcx>| {
Ty::new_ptr(tcx, ty, kind.to_mutbl_lossy())
@ -742,6 +739,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
let layout = bx.cx().layout_of(binder_ty);
OperandRef { val: operand.val, layout }
}
mir::Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in codegen"),
}
}

View file

@ -234,7 +234,7 @@ where
Rvalue::Discriminant(place) => in_place::<Q, _>(cx, in_local, place.as_ref()),
Rvalue::CopyForDeref(place) => in_place::<Q, _>(cx, in_local, place.as_ref()),
Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in runtime MIR"),
Rvalue::Use(operand)
| Rvalue::Repeat(operand, _)

View file

@ -183,10 +183,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
self.copy_op(&op, &dest)?;
}
CopyForDeref(place) => {
let op = self.eval_place_to_op(place, Some(dest.layout))?;
self.copy_op(&op, &dest)?;
}
CopyForDeref(_) => bug!("`CopyForDeref` in runtime MIR"),
BinaryOp(bin_op, box (ref left, ref right)) => {
let layout = util::binop_left_homogeneous(bin_op).then_some(dest.layout);

View file

@ -1065,7 +1065,11 @@ pub enum LocalInfo<'tcx> {
/// A temporary created during evaluating `if` predicate, possibly for pattern matching for `let`s,
/// and subject to Edition 2024 temporary lifetime rules
IfThenRescopeTemp { if_then: HirId },
/// A temporary created during the pass `Derefer` to avoid it's retagging
/// A temporary created during the pass `Derefer` treated as a transparent alias
/// for the place its copied from by analysis passes such as `AddRetag` and `ElaborateDrops`.
///
/// It may only be written to by a `CopyForDeref` and otherwise only accessed through a deref.
/// In runtime MIR, it is replaced with a normal `Boring` local.
DerefTemp,
/// A temporary created for borrow checking.
FakeBorrow,

View file

@ -130,7 +130,9 @@ pub enum RuntimePhase {
/// * [`TerminatorKind::Yield`]
/// * [`TerminatorKind::CoroutineDrop`]
/// * [`Rvalue::Aggregate`] for any `AggregateKind` except `Array`
/// * [`Rvalue::CopyForDeref`]
/// * [`PlaceElem::OpaqueCast`]
/// * [`LocalInfo::DerefTemp`](super::LocalInfo::DerefTemp)
///
/// And the following variants are allowed:
/// * [`StatementKind::Retag`]
@ -1454,11 +1456,13 @@ pub enum Rvalue<'tcx> {
/// A CopyForDeref is equivalent to a read from a place at the
/// codegen level, but is treated specially by drop elaboration. When such a read happens, it
/// is guaranteed (via nature of the mir_opt `Derefer` in rustc_mir_transform/src/deref_separator)
/// that the only use of the returned value is a deref operation, immediately
/// followed by one or more projections. Drop elaboration treats this rvalue as if the
/// that the returned value is written into a `DerefTemp` local and that its only use is a deref operation,
/// immediately followed by one or more projections. Drop elaboration treats this rvalue as if the
/// read never happened and just projects further. This allows simplifying various MIR
/// optimizations and codegen backends that previously had to handle deref operations anywhere
/// in a place.
///
/// Disallowed in runtime MIR and is replaced by normal copies.
CopyForDeref(Place<'tcx>),
/// Wraps a value in an unsafe binder.

View file

@ -250,7 +250,6 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> {
Ok(Rvalue::BinaryOp(BinOp::Offset, Box::new((ptr, offset))))
},
@call(mir_ptr_metadata, args) => Ok(Rvalue::UnaryOp(UnOp::PtrMetadata, self.parse_operand(args[0])?)),
@call(mir_copy_for_deref, args) => Ok(Rvalue::CopyForDeref(self.parse_place(args[0])?)),
ExprKind::Borrow { borrow_kind, arg } => Ok(
Rvalue::Ref(self.tcx.lifetimes.re_erased, *borrow_kind, self.parse_place(*arg)?)
),

View file

@ -74,9 +74,7 @@ fn fully_moved_locals(ssa: &SsaLocals, body: &Body<'_>) -> DenseBitSet<Local> {
let mut fully_moved = DenseBitSet::new_filled(body.local_decls.len());
for (_, rvalue, _) in ssa.assignments(body) {
let (Rvalue::Use(Operand::Copy(place) | Operand::Move(place))
| Rvalue::CopyForDeref(place)) = rvalue
else {
let Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) = rvalue else {
continue;
};
@ -85,7 +83,7 @@ fn fully_moved_locals(ssa: &SsaLocals, body: &Body<'_>) -> DenseBitSet<Local> {
continue;
}
if let Rvalue::Use(Operand::Copy(_)) | Rvalue::CopyForDeref(_) = rvalue {
if let Rvalue::Use(Operand::Copy(_)) = rvalue {
fully_moved.remove(rhs);
}
}
@ -146,8 +144,7 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
// Do not leave tautological assignments around.
if let StatementKind::Assign(box (lhs, ref rhs)) = stmt.kind
&& let Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)) | Rvalue::CopyForDeref(rhs) =
*rhs
&& let Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)) = *rhs
&& lhs == rhs
{
stmt.make_nop(true);

View file

@ -1625,19 +1625,19 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
let mut drop_shim =
create_coroutine_drop_shim_async(tcx, &transform, body, drop_clean, can_unwind);
// Run derefer to fix Derefs that are not in the first place
deref_finder(tcx, &mut drop_shim);
deref_finder(tcx, &mut drop_shim, false);
body.coroutine.as_mut().unwrap().coroutine_drop_async = Some(drop_shim);
} else {
// If coroutine has no async drops, generating sync drop shim
let mut drop_shim =
create_coroutine_drop_shim(tcx, &transform, coroutine_ty, body, drop_clean);
// Run derefer to fix Derefs that are not in the first place
deref_finder(tcx, &mut drop_shim);
deref_finder(tcx, &mut drop_shim, false);
body.coroutine.as_mut().unwrap().coroutine_drop = Some(drop_shim);
// For coroutine with sync drop, generating async proxy for `future_drop_poll` call
let mut proxy_shim = create_coroutine_drop_shim_proxy_async(tcx, body);
deref_finder(tcx, &mut proxy_shim);
deref_finder(tcx, &mut proxy_shim, false);
body.coroutine.as_mut().unwrap().coroutine_drop_proxy_async = Some(proxy_shim);
}
@ -1645,7 +1645,7 @@ impl<'tcx> crate::MirPass<'tcx> for StateTransform {
create_coroutine_resume_function(tcx, transform, body, can_return, can_unwind);
// Run derefer to fix Derefs that are not in the first place
deref_finder(tcx, body);
deref_finder(tcx, body, false);
}
fn is_required(&self) -> bool {

View file

@ -305,12 +305,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
self.assign_operand(state, target, operand);
}
}
Rvalue::CopyForDeref(rhs) => {
state.flood(target.as_ref(), &self.map);
if let Some(target) = self.map.find(target.as_ref()) {
self.assign_operand(state, target, &Operand::Copy(*rhs));
}
}
Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in runtime MIR"),
Rvalue::Aggregate(kind, operands) => {
// If we assign `target = Enum::Variant#0(operand)`,
// we must make sure that all `target as Variant#i` are `Top`.
@ -484,9 +479,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
}
Rvalue::Discriminant(place) => state.get_discr(place.as_ref(), &self.map),
Rvalue::Use(operand) => return self.handle_operand(operand, state),
Rvalue::CopyForDeref(place) => {
return self.handle_operand(&Operand::Copy(*place), state);
}
Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in runtime MIR"),
Rvalue::Ref(..) | Rvalue::RawPtr(..) => {
// We don't track such places.
return ValueOrPlace::TOP;

View file

@ -11,6 +11,7 @@ struct DerefChecker<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
patcher: MirPatch<'tcx>,
local_decls: &'a LocalDecls<'tcx>,
add_deref_metadata: bool,
}
impl<'a, 'tcx> MutVisitor<'tcx> for DerefChecker<'a, 'tcx> {
@ -39,7 +40,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for DerefChecker<'a, 'tcx> {
let temp = self.patcher.new_local_with_info(
ty,
self.local_decls[p_ref.local].source_info.span,
LocalInfo::DerefTemp,
if self.add_deref_metadata {
LocalInfo::DerefTemp
} else {
LocalInfo::Boring
},
);
// We are adding current p_ref's projections to our
@ -50,7 +55,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for DerefChecker<'a, 'tcx> {
self.patcher.add_assign(
loc,
Place::from(temp),
Rvalue::CopyForDeref(deref_place),
if self.add_deref_metadata {
Rvalue::CopyForDeref(deref_place)
} else {
Rvalue::Use(Operand::Copy(deref_place))
},
);
place_local = temp;
last_len = p_ref.projection.len();
@ -67,9 +76,14 @@ impl<'a, 'tcx> MutVisitor<'tcx> for DerefChecker<'a, 'tcx> {
}
}
pub(super) fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
pub(super) fn deref_finder<'tcx>(
tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>,
add_deref_metadata: bool,
) {
let patch = MirPatch::new(body);
let mut checker = DerefChecker { tcx, patcher: patch, local_decls: &body.local_decls };
let mut checker =
DerefChecker { tcx, patcher: patch, local_decls: &body.local_decls, add_deref_metadata };
for (bb, data) in body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
checker.visit_basic_block_data(bb, data);
@ -80,7 +94,7 @@ pub(super) fn deref_finder<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
impl<'tcx> crate::MirPass<'tcx> for Derefer {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
deref_finder(tcx, body);
deref_finder(tcx, body, true);
}
fn is_required(&self) -> bool {

View file

@ -284,8 +284,7 @@ impl<'tcx> MutVisitor<'tcx> for Merger<'tcx> {
match &statement.kind {
StatementKind::Assign(box (dest, rvalue)) => {
match rvalue {
Rvalue::CopyForDeref(place)
| Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) => {
Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) => {
// These might've been turned into self-assignments by the replacement
// (this includes the original statement we wanted to eliminate).
if dest == place {
@ -399,7 +398,7 @@ impl<'tcx> Visitor<'tcx> for FindAssignments<'_, 'tcx> {
fn visit_statement(&mut self, statement: &Statement<'tcx>, _: Location) {
if let StatementKind::Assign(box (
lhs,
Rvalue::CopyForDeref(rhs) | Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)),
Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs)),
)) = &statement.kind
&& let Some(src) = lhs.as_local()
&& let Some(dest) = rhs.as_local()

View file

@ -14,7 +14,6 @@ use rustc_mir_dataflow::{
use rustc_span::Span;
use tracing::{debug, instrument};
use crate::deref_separator::deref_finder;
use crate::elaborate_drop::{DropElaborator, DropFlagMode, DropStyle, Unwind, elaborate_drop};
use crate::patch::MirPatch;
@ -87,7 +86,6 @@ impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops {
.elaborate()
};
elaborate_patch.apply(body);
deref_finder(tcx, body);
}
fn is_required(&self) -> bool {

View file

@ -0,0 +1,41 @@
//! This pass converts all `DerefTemp` locals into normal temporaries
//! and turns their `CopyForDeref` rvalues into normal copies.
use rustc_middle::mir::visit::MutVisitor;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
struct EraseDerefTempsVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for EraseDerefTempsVisitor<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, _: Location) {
if let &mut Rvalue::CopyForDeref(place) = rvalue {
*rvalue = Rvalue::Use(Operand::Copy(place))
}
}
fn visit_local_decl(&mut self, _: Local, local_decl: &mut LocalDecl<'tcx>) {
if local_decl.is_deref_temp() {
let info = local_decl.local_info.as_mut().unwrap_crate_local();
**info = LocalInfo::Boring;
}
}
}
pub(super) struct EraseDerefTemps;
impl<'tcx> crate::MirPass<'tcx> for EraseDerefTemps {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
EraseDerefTempsVisitor { tcx }.visit_body_preserves_cfg(body);
}
fn is_required(&self) -> bool {
true
}
}

View file

@ -1027,12 +1027,6 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
let value = match *rvalue {
// Forward values.
Rvalue::Use(ref mut operand) => return self.simplify_operand(operand, location),
Rvalue::CopyForDeref(place) => {
let mut operand = Operand::Copy(place);
let val = self.simplify_operand(&mut operand, location);
*rvalue = Rvalue::Use(operand);
return val;
}
// Roots.
Rvalue::Repeat(ref mut op, amount) => {
@ -1074,6 +1068,7 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
// Unsupported values.
Rvalue::ThreadLocalRef(..) | Rvalue::ShallowInitBox(..) => return None,
Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in runtime MIR"),
};
let ty = rvalue.ty(self.local_decls, self.tcx);
Some(self.insert(ty, value))

View file

@ -20,7 +20,6 @@ use rustc_span::source_map::Spanned;
use tracing::{debug, instrument, trace, trace_span};
use crate::cost_checker::{CostChecker, is_call_like};
use crate::deref_separator::deref_finder;
use crate::simplify::{UsedInStmtLocals, simplify_cfg};
use crate::validate::validate_types;
use crate::{check_inline, util};
@ -64,7 +63,6 @@ impl<'tcx> crate::MirPass<'tcx> for Inline {
if inline::<NormalInliner<'tcx>>(tcx, body) {
debug!("running simplify cfg on {:?}", body.source);
simplify_cfg(tcx, body);
deref_finder(tcx, body);
}
}
@ -100,7 +98,6 @@ impl<'tcx> crate::MirPass<'tcx> for ForceInline {
if inline::<ForceInliner<'tcx>>(tcx, body) {
debug!("running simplify cfg on {:?}", body.source);
simplify_cfg(tcx, body);
deref_finder(tcx, body);
}
}
}

View file

@ -454,7 +454,6 @@ impl<'a, 'tcx> TOFinder<'a, 'tcx> {
match rhs {
Rvalue::Use(operand) => self.process_operand(bb, lhs, operand, state),
// Transfer the conditions on the copy rhs.
Rvalue::CopyForDeref(rhs) => self.process_operand(bb, lhs, &Operand::Copy(*rhs), state),
Rvalue::Discriminant(rhs) => {
let Some(rhs) = self.map.find_discr(rhs.as_ref()) else { return };
state.insert_place_idx(rhs, lhs, &self.map);

View file

@ -139,6 +139,7 @@ declare_passes! {
mod dest_prop : DestinationPropagation;
pub mod dump_mir : Marker;
mod early_otherwise_branch : EarlyOtherwiseBranch;
mod erase_deref_temps : EraseDerefTemps;
mod elaborate_box_derefs : ElaborateBoxDerefs;
mod elaborate_drops : ElaborateDrops;
mod function_item_references : FunctionItemReferences;
@ -619,6 +620,7 @@ fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
// `AddRetag` needs to run after `ElaborateDrops` but before `ElaborateBoxDerefs`.
// Otherwise it should run fairly late, but before optimizations begin.
&add_retag::AddRetag,
&erase_deref_temps::EraseDerefTemps,
&elaborate_box_derefs::ElaborateBoxDerefs,
&coroutine::StateTransform,
&Lint(known_panics_lint::KnownPanicsLint),

View file

@ -247,8 +247,7 @@ fn compute_replacement<'tcx>(
// This is a copy, just use the value we have in store for the previous one.
// As we are visiting in `assignment_order`, ie. reverse postorder, `rhs` should
// have been visited before.
Rvalue::Use(Operand::Copy(place) | Operand::Move(place))
| Rvalue::CopyForDeref(place) => {
Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) => {
if let Some(rhs) = place.as_local()
&& ssa.is_ssa(rhs)
{

View file

@ -17,12 +17,13 @@ use rustc_span::source_map::{Spanned, dummy_spanned};
use rustc_span::{DUMMY_SP, Span};
use tracing::{debug, instrument};
use crate::deref_separator::deref_finder;
use crate::elaborate_drop::{DropElaborator, DropFlagMode, DropStyle, Unwind, elaborate_drop};
use crate::patch::MirPatch;
use crate::{
abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, deref_separator, inline,
instsimplify, mentioned_items, pass_manager as pm, remove_noop_landing_pads,
run_optimization_passes, simplify,
abort_unwinding_calls, add_call_guards, add_moves_for_packed_drops, inline, instsimplify,
mentioned_items, pass_manager as pm, remove_noop_landing_pads, run_optimization_passes,
simplify,
};
mod async_destructor_ctor;
@ -222,6 +223,8 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<
};
debug!("make_shim({:?}) = untransformed {:?}", instance, result);
deref_finder(tcx, &mut result, false);
// We don't validate MIR here because the shims may generate code that's
// only valid in a `PostAnalysis` param-env. However, since we do initial
// validation with the MirBuilt phase, which uses a user-facing param-env.
@ -232,7 +235,6 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceKind<'tcx>) -> Body<
&[
&mentioned_items::MentionedItems,
&add_moves_for_packed_drops::AddMovesForPackedDrops,
&deref_separator::Derefer,
&remove_noop_landing_pads::RemoveNoopLandingPads,
&simplify::SimplifyCfg::MakeShim,
&instsimplify::InstSimplify::BeforeInline,

View file

@ -240,7 +240,7 @@ fn build_adrop_for_coroutine_shim<'tcx>(
source_info,
StatementKind::Assign(Box::new((
Place::from(proxy_ref_local),
Rvalue::CopyForDeref(proxy_ref_place),
Rvalue::Use(Operand::Copy(proxy_ref_place)),
))),
),
);
@ -261,7 +261,7 @@ fn build_adrop_for_coroutine_shim<'tcx>(
source_info,
StatementKind::Assign(Box::new((
Place::from(cor_ptr_local),
Rvalue::CopyForDeref(impl_ptr_place),
Rvalue::Use(Operand::Copy(impl_ptr_place)),
))),
),
);
@ -334,7 +334,7 @@ fn build_adrop_for_adrop_shim<'tcx>(
source_info,
StatementKind::Assign(Box::new((
Place::from(proxy_ref_local),
Rvalue::CopyForDeref(proxy_ref_place),
Rvalue::Use(Operand::Copy(proxy_ref_place)),
))),
));
@ -350,7 +350,7 @@ fn build_adrop_for_adrop_shim<'tcx>(
source_info,
StatementKind::Assign(Box::new((
Place::from(cor_ptr_local),
Rvalue::CopyForDeref(impl_ptr_place),
Rvalue::Use(Operand::Copy(impl_ptr_place)),
))),
));
}

View file

@ -297,9 +297,7 @@ fn compute_copy_classes(ssa: &mut SsaLocals, body: &Body<'_>) {
let mut copies = IndexVec::from_fn_n(|l| l, body.local_decls.len());
for (local, rvalue, _) in ssa.assignments(body) {
let (Rvalue::Use(Operand::Copy(place) | Operand::Move(place))
| Rvalue::CopyForDeref(place)) = rvalue
else {
let Rvalue::Use(Operand::Copy(place) | Operand::Move(place)) = rvalue else {
continue;
};

View file

@ -9,7 +9,7 @@ use rustc_index::bit_set::DenseBitSet;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{Obligation, ObligationCause};
use rustc_middle::mir::coverage::CoverageKind;
use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor};
use rustc_middle::mir::visit::{MutatingUseContext, NonUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::print::with_no_trimmed_paths;
@ -907,6 +907,20 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
}
}
if let ClearCrossCrate::Set(box LocalInfo::DerefTemp) =
self.body.local_decls[place.local].local_info
&& !place.is_indirect_first_projection()
{
if cntxt != PlaceContext::MutatingUse(MutatingUseContext::Store)
|| place.as_local().is_none()
{
self.fail(
location,
format!("`DerefTemp` locals must only be dereferenced or directly assigned to"),
);
}
}
self.super_place(place, cntxt, location);
}
@ -919,7 +933,12 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
};
}
match rvalue {
Rvalue::Use(_) | Rvalue::CopyForDeref(_) => {}
Rvalue::Use(_) => {}
Rvalue::CopyForDeref(_) => {
if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(location, "`CopyForDeref` should have been removed in runtime MIR");
}
}
Rvalue::Aggregate(kind, fields) => match **kind {
AggregateKind::Tuple => {}
AggregateKind::Array(dest) => {
@ -1417,13 +1436,13 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
),
);
}
if let Rvalue::CopyForDeref(place) = rvalue {
if place.ty(&self.body.local_decls, self.tcx).ty.builtin_deref(true).is_none() {
self.fail(
location,
"`CopyForDeref` should only be used for dereferenceable types",
)
}
if let Some(local) = dest.as_local()
&& let ClearCrossCrate::Set(box LocalInfo::DerefTemp) =
self.body.local_decls[local].local_info
&& !matches!(rvalue, Rvalue::CopyForDeref(_))
{
self.fail(location, "assignment to a `DerefTemp` must use `CopyForDeref`")
}
}
StatementKind::AscribeUserType(..) => {
@ -1590,6 +1609,24 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
self.super_terminator(terminator, location);
}
fn visit_local_decl(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
if let ClearCrossCrate::Set(box LocalInfo::DerefTemp) = local_decl.local_info {
if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(
START_BLOCK.start_location(),
"`DerefTemp` should have been removed in runtime MIR",
);
} else if local_decl.ty.builtin_deref(true).is_none() {
self.fail(
START_BLOCK.start_location(),
"`DerefTemp` should only be used for dereferenceable types",
)
}
}
self.super_local_decl(local, local_decl);
}
}
pub(super) fn validate_debuginfos<'tcx>(body: &Body<'tcx>) -> Vec<(Location, String)> {

View file

@ -1428,7 +1428,6 @@ symbols! {
mir_cast_transmute,
mir_cast_unsize,
mir_checked,
mir_copy_for_deref,
mir_debuginfo,
mir_deinit,
mir_discriminant,

View file

@ -233,7 +233,7 @@
//!
//! - Operands implicitly convert to `Use` rvalues.
//! - `&`, `&mut`, `addr_of!`, and `addr_of_mut!` all work to create their associated rvalue.
//! - [`CopyForDeref`], [`CastTransmute`], [`CastPtrToPtr`], [`CastUnsize`], and [`Discriminant`]
//! - [`CastTransmute`], [`CastPtrToPtr`], [`CastUnsize`], and [`Discriminant`]
//! have associated functions.
//! - Unary and binary operations use their normal Rust syntax - `a * b`, `!c`, etc.
//! - The binary operation `Offset` can be created via [`Offset`].
@ -405,7 +405,6 @@ define!(
"mir_ptr_metadata",
fn PtrMetadata<P: ?Sized>(place: *const P) -> <P as ::core::ptr::Pointee>::Metadata
);
define!("mir_copy_for_deref", fn CopyForDeref<T>(place: T) -> T);
define!("mir_retag", fn Retag<T>(place: T));
define!("mir_move", fn Move<T>(place: T) -> T);
define!("mir_static", fn Static<T>(s: T) -> &'static T);

View file

@ -50,19 +50,19 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2
let mut _25: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18};
bb0: {
_18 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
_18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
_17 = discriminant((*_18));
switchInt(move _17) -> [0: bb1, 1: bb19, 3: bb17, 4: bb18, otherwise: bb20];
}
bb1: {
_19 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
_19 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
(((*_19) as variant#4).0: std::string::String) = move _2;
StorageLive(_3);
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
_20 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
_20 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
_6 = &(((*_20) as variant#4).0: std::string::String);
_5 = <String as Clone>::clone(move _6) -> [return: bb2, unwind unreachable];
}
@ -84,7 +84,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2
_0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _4);
StorageDead(_3);
StorageDead(_4);
_21 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
_21 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
discriminant((*_21)) = 3;
return;
}
@ -108,7 +108,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2
_10 = &(*_11);
StorageLive(_12);
StorageLive(_13);
_22 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
_22 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
_13 = &(((*_22) as variant#4).0: std::string::String);
_12 = <String as Clone>::clone(move _13) -> [return: bb8, unwind unreachable];
}
@ -135,7 +135,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2
StorageDead(_9);
StorageDead(_11);
StorageDead(_15);
_23 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
_23 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
discriminant((*_23)) = 4;
return;
}
@ -154,7 +154,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2
StorageDead(_11);
StorageDead(_8);
_16 = const ();
_24 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
_24 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
drop((((*_24) as variant#4).0: std::string::String)) -> [return: bb14, unwind unreachable];
}
@ -164,7 +164,7 @@ fn main::{closure#0}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:18:5: 18:18}>, _2
bb15: {
_0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16);
_25 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
_25 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:18:5: 18:18});
discriminant((*_25)) = 1;
return;
}

View file

@ -50,19 +50,19 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2
let mut _25: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18};
bb0: {
_18 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
_18 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
_17 = discriminant((*_18));
switchInt(move _17) -> [0: bb1, 1: bb19, 3: bb17, 4: bb18, otherwise: bb20];
}
bb1: {
_19 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
_19 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
(((*_19) as variant#4).0: std::string::String) = move _2;
StorageLive(_3);
StorageLive(_4);
StorageLive(_5);
StorageLive(_6);
_20 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
_20 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
_6 = &(((*_20) as variant#4).0: std::string::String);
_5 = <String as Clone>::clone(move _6) -> [return: bb2, unwind unreachable];
}
@ -84,7 +84,7 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2
_0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Yielded(move _4);
StorageDead(_3);
StorageDead(_4);
_21 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
_21 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
discriminant((*_21)) = 3;
return;
}
@ -108,7 +108,7 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2
_10 = &(*_11);
StorageLive(_12);
StorageLive(_13);
_22 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
_22 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
_13 = &(((*_22) as variant#4).0: std::string::String);
_12 = <String as Clone>::clone(move _13) -> [return: bb8, unwind unreachable];
}
@ -135,7 +135,7 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2
StorageDead(_9);
StorageDead(_11);
StorageDead(_15);
_23 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
_23 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
discriminant((*_23)) = 4;
return;
}
@ -154,7 +154,7 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2
StorageDead(_11);
StorageDead(_8);
_16 = const ();
_24 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
_24 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
drop((((*_24) as variant#4).0: std::string::String)) -> [return: bb14, unwind unreachable];
}
@ -164,7 +164,7 @@ fn main::{closure#1}(_1: Pin<&mut {coroutine@$DIR/coroutine.rs:25:5: 25:18}>, _2
bb15: {
_0 = CoroutineState::<(&str, String, &Location<'_>), ()>::Complete(move _16);
_25 = deref_copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
_25 = copy (_1.0: &mut {coroutine@$DIR/coroutine.rs:25:5: 25:18});
discriminant((*_25)) = 1;
return;
}

View file

@ -1,12 +0,0 @@
// MIR for `copy_for_deref` after built
fn copy_for_deref(_1: (&i32, i32)) -> i32 {
let mut _0: i32;
let mut _2: &i32;
bb0: {
_2 = deref_copy (_1.0: &i32);
_0 = copy (*_2);
return;
}
}

View file

@ -79,19 +79,6 @@ fn simple_index(a: [i32; 10], b: &[i32]) -> i32 {
}
}
// EMIT_MIR projections.copy_for_deref.built.after.mir
#[custom_mir(dialect = "runtime", phase = "initial")]
fn copy_for_deref(x: (&i32, i32)) -> i32 {
mir! {
let temp: &i32;
{
temp = CopyForDeref(x.0);
RET = *temp;
Return()
}
}
}
fn main() {
assert_eq!(unions(U { a: 5 }), 5);
assert_eq!(tuples((5, 6)), (5, 6));
@ -103,7 +90,4 @@ fn main() {
assert_eq!(o, Some(10));
assert_eq!(simple_index([0; 10], &[0; 10]), 0);
let one = 1;
assert_eq!(copy_for_deref((&one, one)), 1);
}

View file

@ -112,16 +112,16 @@
StorageDead(_10);
StorageLive(_14);
_14 = const {ALLOC0: &&SmallStruct};
_31 = deref_copy (*_14);
_31 = copy (*_14);
StorageLive(_11);
_32 = deref_copy (*_14);
_32 = copy (*_14);
- _11 = copy ((*_32).0: f32);
+ _11 = const 9f32;
StorageLive(_12);
_33 = deref_copy (*_14);
_33 = copy (*_14);
_12 = copy ((*_33).1: std::option::Option<S>);
StorageLive(_13);
_34 = deref_copy (*_14);
_34 = copy (*_14);
_13 = copy ((*_34).2: &[f32]);
StorageDead(_14);
StorageLive(_15);
@ -149,16 +149,16 @@
StorageDead(_22);
StorageLive(_26);
_26 = const {ALLOC1: &&BigStruct};
_35 = deref_copy (*_26);
_35 = copy (*_26);
StorageLive(_23);
_36 = deref_copy (*_26);
_36 = copy (*_26);
- _23 = copy ((*_36).0: f32);
+ _23 = const 82f32;
StorageLive(_24);
_37 = deref_copy (*_26);
_37 = copy (*_26);
_24 = copy ((*_37).1: std::option::Option<S>);
StorageLive(_25);
_38 = deref_copy (*_26);
_38 = copy (*_26);
_25 = copy ((*_38).2: &[f32]);
StorageDead(_26);
StorageLive(_27);

View file

@ -112,16 +112,16 @@
StorageDead(_10);
StorageLive(_14);
_14 = const {ALLOC0: &&SmallStruct};
_31 = deref_copy (*_14);
_31 = copy (*_14);
StorageLive(_11);
_32 = deref_copy (*_14);
_32 = copy (*_14);
- _11 = copy ((*_32).0: f32);
+ _11 = const 9f32;
StorageLive(_12);
_33 = deref_copy (*_14);
_33 = copy (*_14);
_12 = copy ((*_33).1: std::option::Option<S>);
StorageLive(_13);
_34 = deref_copy (*_14);
_34 = copy (*_14);
_13 = copy ((*_34).2: &[f32]);
StorageDead(_14);
StorageLive(_15);
@ -149,16 +149,16 @@
StorageDead(_22);
StorageLive(_26);
_26 = const {ALLOC1: &&BigStruct};
_35 = deref_copy (*_26);
_35 = copy (*_26);
StorageLive(_23);
_36 = deref_copy (*_26);
_36 = copy (*_26);
- _23 = copy ((*_36).0: f32);
+ _23 = const 82f32;
StorageLive(_24);
_37 = deref_copy (*_26);
_37 = copy (*_26);
_24 = copy ((*_37).1: std::option::Option<S>);
StorageLive(_25);
_38 = deref_copy (*_26);
_38 = copy (*_26);
_25 = copy ((*_38).2: &[f32]);
StorageDead(_26);
StorageLive(_27);

View file

@ -13,10 +13,10 @@
bb0: {
- StorageLive(_2);
- _3 = deref_copy (_1.1: &Foo);
- _3 = copy (_1.1: &Foo);
- _2 = &((*_3).2: i32);
+ // DBG: _2 = &((*_3).2: i32);
_4 = deref_copy (_1.1: &Foo);
_4 = copy (_1.1: &Foo);
_0 = copy ((*_4).0: i32);
- StorageDead(_2);
return;

View file

@ -8,14 +8,14 @@
let _3: std::boxed::Box<()>;
let mut _6: *const ();
let mut _8: *const [()];
let mut _9: std::boxed::Box<()>;
let mut _10: *const ();
let mut _23: usize;
let mut _9: *const ();
let mut _22: usize;
let mut _23: std::ptr::NonNull<()>;
scope 1 {
debug vp_ctx => _1;
let _4: *const ();
scope 2 {
debug slf => _10;
debug slf => _9;
let _5: *const [()];
scope 3 {
debug bytes => _5;
@ -33,21 +33,21 @@
}
}
scope 5 (inlined Box::<()>::new) {
let mut _10: usize;
let mut _11: usize;
let mut _12: usize;
let mut _13: *mut u8;
let mut _12: *mut u8;
scope 6 (inlined alloc::alloc::exchange_malloc) {
let _14: std::alloc::Layout;
let mut _15: std::result::Result<std::ptr::NonNull<[u8]>, std::alloc::AllocError>;
let mut _16: isize;
let mut _18: !;
let _13: std::alloc::Layout;
let mut _14: std::result::Result<std::ptr::NonNull<[u8]>, std::alloc::AllocError>;
let mut _15: isize;
let mut _17: !;
scope 7 {
let _17: std::ptr::NonNull<[u8]>;
let _16: std::ptr::NonNull<[u8]>;
scope 8 {
scope 11 (inlined NonNull::<[u8]>::as_mut_ptr) {
scope 12 (inlined NonNull::<[u8]>::as_non_null_ptr) {
scope 13 (inlined NonNull::<[u8]>::cast::<u8>) {
let mut _22: *mut [u8];
let mut _21: *mut [u8];
scope 14 (inlined NonNull::<[u8]>::as_ptr) {
}
}
@ -60,9 +60,9 @@
}
}
scope 9 (inlined #[track_caller] Layout::from_size_align_unchecked) {
let mut _19: bool;
let _20: ();
let mut _21: std::ptr::Alignment;
let mut _18: bool;
let _19: ();
let mut _20: std::ptr::Alignment;
}
}
}
@ -71,19 +71,19 @@
StorageLive(_1);
StorageLive(_2);
StorageLive(_3);
StorageLive(_10);
StorageLive(_11);
StorageLive(_12);
- _10 = SizeOf(());
- _11 = AlignOf(());
+ _10 = const 0_usize;
+ _11 = const 1_usize;
StorageLive(_13);
- _11 = SizeOf(());
- _12 = AlignOf(());
+ _11 = const 0_usize;
+ _12 = const 1_usize;
StorageLive(_14);
StorageLive(_15);
StorageLive(_16);
StorageLive(_17);
StorageLive(_19);
_19 = const false;
- switchInt(move _19) -> [0: bb6, otherwise: bb5];
StorageLive(_18);
_18 = const false;
- switchInt(move _18) -> [0: bb6, otherwise: bb5];
+ switchInt(const false) -> [0: bb6, otherwise: bb5];
}
@ -98,48 +98,47 @@
}
bb3: {
- _18 = handle_alloc_error(move _14) -> unwind unreachable;
+ _18 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}) -> unwind unreachable;
- _17 = handle_alloc_error(move _13) -> unwind unreachable;
+ _17 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}) -> unwind unreachable;
}
bb4: {
_17 = copy ((_15 as Ok).0: std::ptr::NonNull<[u8]>);
StorageLive(_22);
_22 = copy _17 as *mut [u8] (Transmute);
_13 = copy _22 as *mut u8 (PtrToPtr);
StorageDead(_22);
StorageDead(_15);
StorageDead(_17);
StorageDead(_16);
_16 = copy ((_14 as Ok).0: std::ptr::NonNull<[u8]>);
StorageLive(_21);
_21 = copy _16 as *mut [u8] (Transmute);
_12 = copy _21 as *mut u8 (PtrToPtr);
StorageDead(_21);
StorageDead(_14);
_3 = ShallowInitBox(copy _13, ());
StorageDead(_16);
StorageDead(_15);
StorageDead(_13);
_3 = ShallowInitBox(copy _12, ());
StorageDead(_12);
StorageDead(_11);
StorageDead(_10);
_2 = &_3;
_1 = copy _2;
StorageDead(_2);
StorageLive(_4);
- _9 = deref_copy _3;
+ _9 = copy _3;
_10 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
_4 = copy _10;
_23 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>);
_9 = copy _23 as *const () (Transmute);
_4 = copy _9;
- StorageLive(_5);
+ nop;
StorageLive(_6);
- _6 = copy _4;
+ _6 = copy _10;
StorageLive(_23);
_23 = const 1_usize;
- _5 = *const [()] from (copy _6, copy _23);
+ _5 = *const [()] from (copy _10, const 1_usize);
StorageDead(_23);
+ _6 = copy _9;
StorageLive(_22);
_22 = const 1_usize;
- _5 = *const [()] from (copy _6, copy _22);
+ _5 = *const [()] from (copy _9, const 1_usize);
StorageDead(_22);
StorageDead(_6);
StorageLive(_7);
StorageLive(_8);
_8 = copy _5;
- _7 = copy _8 as *mut () (PtrToPtr);
+ _7 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute);
+ _7 = copy _23 as *mut () (Transmute);
StorageDead(_8);
StorageDead(_7);
- StorageDead(_5);
@ -149,26 +148,26 @@
}
bb5: {
- _20 = Layout::from_size_align_unchecked::precondition_check(copy _11, copy _12) -> [return: bb6, unwind unreachable];
+ _20 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable];
- _19 = Layout::from_size_align_unchecked::precondition_check(copy _10, copy _11) -> [return: bb6, unwind unreachable];
+ _19 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable];
}
bb6: {
StorageDead(_19);
StorageLive(_21);
- _21 = copy _12 as std::ptr::Alignment (Transmute);
- _14 = Layout { size: copy _11, align: move _21 };
+ _21 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0);
+ _14 = const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }};
StorageDead(_21);
StorageLive(_15);
- _15 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], copy _14, const false) -> [return: bb7, unwind unreachable];
+ _15 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb7, unwind unreachable];
StorageDead(_18);
StorageLive(_20);
- _20 = copy _11 as std::ptr::Alignment (Transmute);
- _13 = Layout { size: copy _10, align: move _20 };
+ _20 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0);
+ _13 = const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }};
StorageDead(_20);
StorageLive(_14);
- _14 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], copy _13, const false) -> [return: bb7, unwind unreachable];
+ _14 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb7, unwind unreachable];
}
bb7: {
_16 = discriminant(_15);
switchInt(move _16) -> [0: bb4, 1: bb3, otherwise: bb2];
_15 = discriminant(_14);
switchInt(move _15) -> [0: bb4, 1: bb3, otherwise: bb2];
}
+ }
+

View file

@ -8,14 +8,14 @@
let _3: std::boxed::Box<()>;
let mut _6: *const ();
let mut _8: *const [()];
let mut _9: std::boxed::Box<()>;
let mut _10: *const ();
let mut _11: usize;
let mut _9: *const ();
let mut _10: usize;
let mut _11: std::ptr::NonNull<()>;
scope 1 {
debug vp_ctx => _1;
let _4: *const ();
scope 2 {
debug slf => _10;
debug slf => _9;
let _5: *const [()];
scope 3 {
debug bytes => _5;
@ -45,26 +45,25 @@
_1 = copy _2;
StorageDead(_2);
StorageLive(_4);
- _9 = deref_copy _3;
+ _9 = copy _3;
_10 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
_4 = copy _10;
_11 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>);
_9 = copy _11 as *const () (Transmute);
_4 = copy _9;
- StorageLive(_5);
+ nop;
StorageLive(_6);
- _6 = copy _4;
+ _6 = copy _10;
StorageLive(_11);
_11 = const 1_usize;
- _5 = *const [()] from (copy _6, copy _11);
+ _5 = *const [()] from (copy _10, const 1_usize);
StorageDead(_11);
+ _6 = copy _9;
StorageLive(_10);
_10 = const 1_usize;
- _5 = *const [()] from (copy _6, copy _10);
+ _5 = *const [()] from (copy _9, const 1_usize);
StorageDead(_10);
StorageDead(_6);
StorageLive(_7);
StorageLive(_8);
_8 = copy _5;
- _7 = copy _8 as *mut () (PtrToPtr);
+ _7 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute);
+ _7 = copy _11 as *mut () (Transmute);
StorageDead(_8);
StorageDead(_7);
- StorageDead(_5);

View file

@ -8,14 +8,14 @@
let _3: std::boxed::Box<()>;
let mut _6: *const ();
let mut _8: *const [()];
let mut _9: std::boxed::Box<()>;
let mut _10: *const ();
let mut _23: usize;
let mut _9: *const ();
let mut _22: usize;
let mut _23: std::ptr::NonNull<()>;
scope 1 {
debug vp_ctx => _1;
let _4: *const ();
scope 2 {
debug slf => _10;
debug slf => _9;
let _5: *const [()];
scope 3 {
debug bytes => _5;
@ -33,21 +33,21 @@
}
}
scope 5 (inlined Box::<()>::new) {
let mut _10: usize;
let mut _11: usize;
let mut _12: usize;
let mut _13: *mut u8;
let mut _12: *mut u8;
scope 6 (inlined alloc::alloc::exchange_malloc) {
let _14: std::alloc::Layout;
let mut _15: std::result::Result<std::ptr::NonNull<[u8]>, std::alloc::AllocError>;
let mut _16: isize;
let mut _18: !;
let _13: std::alloc::Layout;
let mut _14: std::result::Result<std::ptr::NonNull<[u8]>, std::alloc::AllocError>;
let mut _15: isize;
let mut _17: !;
scope 7 {
let _17: std::ptr::NonNull<[u8]>;
let _16: std::ptr::NonNull<[u8]>;
scope 8 {
scope 11 (inlined NonNull::<[u8]>::as_mut_ptr) {
scope 12 (inlined NonNull::<[u8]>::as_non_null_ptr) {
scope 13 (inlined NonNull::<[u8]>::cast::<u8>) {
let mut _22: *mut [u8];
let mut _21: *mut [u8];
scope 14 (inlined NonNull::<[u8]>::as_ptr) {
}
}
@ -60,9 +60,9 @@
}
}
scope 9 (inlined #[track_caller] Layout::from_size_align_unchecked) {
let mut _19: bool;
let _20: ();
let mut _21: std::ptr::Alignment;
let mut _18: bool;
let _19: ();
let mut _20: std::ptr::Alignment;
}
}
}
@ -71,19 +71,19 @@
StorageLive(_1);
StorageLive(_2);
StorageLive(_3);
StorageLive(_10);
StorageLive(_11);
StorageLive(_12);
- _10 = SizeOf(());
- _11 = AlignOf(());
+ _10 = const 0_usize;
+ _11 = const 1_usize;
StorageLive(_13);
- _11 = SizeOf(());
- _12 = AlignOf(());
+ _11 = const 0_usize;
+ _12 = const 1_usize;
StorageLive(_14);
StorageLive(_15);
StorageLive(_16);
StorageLive(_17);
StorageLive(_19);
_19 = const false;
- switchInt(move _19) -> [0: bb6, otherwise: bb5];
StorageLive(_18);
_18 = const false;
- switchInt(move _18) -> [0: bb6, otherwise: bb5];
+ switchInt(const false) -> [0: bb6, otherwise: bb5];
}
@ -98,48 +98,47 @@
}
bb3: {
- _18 = handle_alloc_error(move _14) -> unwind unreachable;
+ _18 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}) -> unwind unreachable;
- _17 = handle_alloc_error(move _13) -> unwind unreachable;
+ _17 = handle_alloc_error(const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}) -> unwind unreachable;
}
bb4: {
_17 = copy ((_15 as Ok).0: std::ptr::NonNull<[u8]>);
StorageLive(_22);
_22 = copy _17 as *mut [u8] (Transmute);
_13 = copy _22 as *mut u8 (PtrToPtr);
StorageDead(_22);
StorageDead(_15);
StorageDead(_17);
StorageDead(_16);
_16 = copy ((_14 as Ok).0: std::ptr::NonNull<[u8]>);
StorageLive(_21);
_21 = copy _16 as *mut [u8] (Transmute);
_12 = copy _21 as *mut u8 (PtrToPtr);
StorageDead(_21);
StorageDead(_14);
_3 = ShallowInitBox(copy _13, ());
StorageDead(_16);
StorageDead(_15);
StorageDead(_13);
_3 = ShallowInitBox(copy _12, ());
StorageDead(_12);
StorageDead(_11);
StorageDead(_10);
_2 = &_3;
_1 = copy _2;
StorageDead(_2);
StorageLive(_4);
- _9 = deref_copy _3;
+ _9 = copy _3;
_10 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
_4 = copy _10;
_23 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>);
_9 = copy _23 as *const () (Transmute);
_4 = copy _9;
- StorageLive(_5);
+ nop;
StorageLive(_6);
- _6 = copy _4;
+ _6 = copy _10;
StorageLive(_23);
_23 = const 1_usize;
- _5 = *const [()] from (copy _6, copy _23);
+ _5 = *const [()] from (copy _10, const 1_usize);
StorageDead(_23);
+ _6 = copy _9;
StorageLive(_22);
_22 = const 1_usize;
- _5 = *const [()] from (copy _6, copy _22);
+ _5 = *const [()] from (copy _9, const 1_usize);
StorageDead(_22);
StorageDead(_6);
StorageLive(_7);
StorageLive(_8);
_8 = copy _5;
- _7 = copy _8 as *mut () (PtrToPtr);
+ _7 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute);
+ _7 = copy _23 as *mut () (Transmute);
StorageDead(_8);
StorageDead(_7);
- StorageDead(_5);
@ -149,26 +148,26 @@
}
bb5: {
- _20 = Layout::from_size_align_unchecked::precondition_check(copy _11, copy _12) -> [return: bb6, unwind unreachable];
+ _20 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable];
- _19 = Layout::from_size_align_unchecked::precondition_check(copy _10, copy _11) -> [return: bb6, unwind unreachable];
+ _19 = Layout::from_size_align_unchecked::precondition_check(const 0_usize, const 1_usize) -> [return: bb6, unwind unreachable];
}
bb6: {
StorageDead(_19);
StorageLive(_21);
- _21 = copy _12 as std::ptr::Alignment (Transmute);
- _14 = Layout { size: copy _11, align: move _21 };
+ _21 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0);
+ _14 = const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }};
StorageDead(_21);
StorageLive(_15);
- _15 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], copy _14, const false) -> [return: bb7, unwind unreachable];
+ _15 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb7, unwind unreachable];
StorageDead(_18);
StorageLive(_20);
- _20 = copy _11 as std::ptr::Alignment (Transmute);
- _13 = Layout { size: copy _10, align: move _20 };
+ _20 = const std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0);
+ _13 = const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }};
StorageDead(_20);
StorageLive(_14);
- _14 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], copy _13, const false) -> [return: bb7, unwind unreachable];
+ _14 = std::alloc::Global::alloc_impl(const alloc::alloc::exchange_malloc::promoted[0], const Layout {{ size: 0_usize, align: std::ptr::Alignment(std::ptr::alignment::AlignmentEnum::_Align1Shl0) }}, const false) -> [return: bb7, unwind unreachable];
}
bb7: {
_16 = discriminant(_15);
switchInt(move _16) -> [0: bb4, 1: bb3, otherwise: bb2];
_15 = discriminant(_14);
switchInt(move _15) -> [0: bb4, 1: bb3, otherwise: bb2];
}
+ }
+

View file

@ -8,14 +8,14 @@
let _3: std::boxed::Box<()>;
let mut _6: *const ();
let mut _8: *const [()];
let mut _9: std::boxed::Box<()>;
let mut _10: *const ();
let mut _11: usize;
let mut _9: *const ();
let mut _10: usize;
let mut _11: std::ptr::NonNull<()>;
scope 1 {
debug vp_ctx => _1;
let _4: *const ();
scope 2 {
debug slf => _10;
debug slf => _9;
let _5: *const [()];
scope 3 {
debug bytes => _5;
@ -45,26 +45,25 @@
_1 = copy _2;
StorageDead(_2);
StorageLive(_4);
- _9 = deref_copy _3;
+ _9 = copy _3;
_10 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *const () (Transmute);
_4 = copy _10;
_11 = copy ((_3.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>);
_9 = copy _11 as *const () (Transmute);
_4 = copy _9;
- StorageLive(_5);
+ nop;
StorageLive(_6);
- _6 = copy _4;
+ _6 = copy _10;
StorageLive(_11);
_11 = const 1_usize;
- _5 = *const [()] from (copy _6, copy _11);
+ _5 = *const [()] from (copy _10, const 1_usize);
StorageDead(_11);
+ _6 = copy _9;
StorageLive(_10);
_10 = const 1_usize;
- _5 = *const [()] from (copy _6, copy _10);
+ _5 = *const [()] from (copy _9, const 1_usize);
StorageDead(_10);
StorageDead(_6);
StorageLive(_7);
StorageLive(_8);
_8 = copy _5;
- _7 = copy _8 as *mut () (PtrToPtr);
+ _7 = copy ((_9.0: std::ptr::Unique<()>).0: std::ptr::NonNull<()>) as *mut () (Transmute);
+ _7 = copy _11 as *mut () (Transmute);
StorageDead(_8);
StorageDead(_7);
- StorageDead(_5);

View file

@ -76,7 +76,7 @@
_4 = (move _5, move _6);
StorageDead(_6);
StorageDead(_5);
_34 = deref_copy (_4.0: &ViewportPercentageLength);
_34 = copy (_4.0: &ViewportPercentageLength);
_11 = discriminant((*_34));
switchInt(move _11) -> [0: bb2, 1: bb3, 2: bb4, 3: bb5, otherwise: bb12];
}
@ -92,35 +92,35 @@
}
bb2: {
_35 = deref_copy (_4.1: &ViewportPercentageLength);
_35 = copy (_4.1: &ViewportPercentageLength);
_7 = discriminant((*_35));
switchInt(move _7) -> [0: bb9, otherwise: bb1];
}
bb3: {
_36 = deref_copy (_4.1: &ViewportPercentageLength);
_36 = copy (_4.1: &ViewportPercentageLength);
_8 = discriminant((*_36));
switchInt(move _8) -> [1: bb8, otherwise: bb1];
}
bb4: {
_37 = deref_copy (_4.1: &ViewportPercentageLength);
_37 = copy (_4.1: &ViewportPercentageLength);
_9 = discriminant((*_37));
switchInt(move _9) -> [2: bb7, otherwise: bb1];
}
bb5: {
_38 = deref_copy (_4.1: &ViewportPercentageLength);
_38 = copy (_4.1: &ViewportPercentageLength);
_10 = discriminant((*_38));
switchInt(move _10) -> [3: bb6, otherwise: bb1];
}
bb6: {
StorageLive(_27);
_39 = deref_copy (_4.0: &ViewportPercentageLength);
_39 = copy (_4.0: &ViewportPercentageLength);
_27 = copy (((*_39) as Vmax).0: f32);
StorageLive(_28);
_40 = deref_copy (_4.1: &ViewportPercentageLength);
_40 = copy (_4.1: &ViewportPercentageLength);
_28 = copy (((*_40) as Vmax).0: f32);
StorageLive(_29);
StorageLive(_30);
@ -139,10 +139,10 @@
bb7: {
StorageLive(_22);
_41 = deref_copy (_4.0: &ViewportPercentageLength);
_41 = copy (_4.0: &ViewportPercentageLength);
_22 = copy (((*_41) as Vmin).0: f32);
StorageLive(_23);
_42 = deref_copy (_4.1: &ViewportPercentageLength);
_42 = copy (_4.1: &ViewportPercentageLength);
_23 = copy (((*_42) as Vmin).0: f32);
StorageLive(_24);
StorageLive(_25);
@ -161,10 +161,10 @@
bb8: {
StorageLive(_17);
_43 = deref_copy (_4.0: &ViewportPercentageLength);
_43 = copy (_4.0: &ViewportPercentageLength);
_17 = copy (((*_43) as Vh).0: f32);
StorageLive(_18);
_44 = deref_copy (_4.1: &ViewportPercentageLength);
_44 = copy (_4.1: &ViewportPercentageLength);
_18 = copy (((*_44) as Vh).0: f32);
StorageLive(_19);
StorageLive(_20);
@ -183,10 +183,10 @@
bb9: {
StorageLive(_12);
_45 = deref_copy (_4.0: &ViewportPercentageLength);
_45 = copy (_4.0: &ViewportPercentageLength);
_12 = copy (((*_45) as Vw).0: f32);
StorageLive(_13);
_46 = deref_copy (_4.1: &ViewportPercentageLength);
_46 = copy (_4.1: &ViewportPercentageLength);
_13 = copy (((*_46) as Vw).0: f32);
StorageLive(_14);
StorageLive(_15);

View file

@ -16,7 +16,7 @@
}
bb1: {
_4 = deref_copy (((*_1) as Some).0: &E<'_>);
_4 = copy (((*_1) as Some).0: &E<'_>);
_2 = discriminant((*_4));
switchInt(move _2) -> [1: bb2, 0: bb3, otherwise: bb5];
}

View file

@ -25,15 +25,14 @@
bb0: {
- StorageLive(_2);
- _8 = deref_copy (*_1);
+ nop;
+ _8 = copy (*_1);
_8 = copy (*_1);
_2 = copy ((*_8).0: i32);
- StorageLive(_3);
- _9 = deref_copy (*_1);
- _9 = copy (*_1);
- _3 = copy ((*_9).1: u64);
- StorageLive(_4);
- _10 = deref_copy (*_1);
- _10 = copy (*_1);
- _4 = copy ((*_10).2: [i8; 3]);
+ nop;
+ _9 = copy _8;

View file

@ -9,8 +9,8 @@
let mut _4: I;
+ scope 1 (inlined <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut) {
+ let mut _5: &mut dyn std::ops::FnMut<I, Output = ()>;
+ let mut _6: std::boxed::Box<dyn std::ops::FnMut<I, Output = ()>>;
+ let mut _7: *const dyn std::ops::FnMut<I, Output = ()>;
+ let mut _6: *const dyn std::ops::FnMut<I, Output = ()>;
+ let mut _7: std::ptr::NonNull<dyn std::ops::FnMut<I, Output = ()>>;
+ }
bb0: {
@ -22,9 +22,9 @@
+ StorageLive(_6);
+ StorageLive(_7);
+ StorageLive(_5);
+ _6 = copy (*_3);
+ _7 = copy ((_6.0: std::ptr::Unique<dyn std::ops::FnMut<I, Output = ()>>).0: std::ptr::NonNull<dyn std::ops::FnMut<I, Output = ()>>) as *const dyn std::ops::FnMut<I, Output = ()> (Transmute);
+ _5 = &mut (*_7);
+ _7 = copy (((*_3).0: std::ptr::Unique<dyn std::ops::FnMut<I, Output = ()>>).0: std::ptr::NonNull<dyn std::ops::FnMut<I, Output = ()>>);
+ _6 = copy _7 as *const dyn std::ops::FnMut<I, Output = ()> (Transmute);
+ _5 = &mut (*_6);
+ _0 = <dyn FnMut<I, Output = ()> as FnMut<I>>::call_mut(move _5, move _4) -> [return: bb2, unwind unreachable];
}

View file

@ -9,8 +9,8 @@
let mut _4: I;
+ scope 1 (inlined <Box<dyn FnMut<I, Output = ()>> as FnMut<I>>::call_mut) {
+ let mut _5: &mut dyn std::ops::FnMut<I, Output = ()>;
+ let mut _6: std::boxed::Box<dyn std::ops::FnMut<I, Output = ()>>;
+ let mut _7: *const dyn std::ops::FnMut<I, Output = ()>;
+ let mut _6: *const dyn std::ops::FnMut<I, Output = ()>;
+ let mut _7: std::ptr::NonNull<dyn std::ops::FnMut<I, Output = ()>>;
+ }
bb0: {
@ -22,9 +22,9 @@
+ StorageLive(_6);
+ StorageLive(_7);
+ StorageLive(_5);
+ _6 = copy (*_3);
+ _7 = copy ((_6.0: std::ptr::Unique<dyn std::ops::FnMut<I, Output = ()>>).0: std::ptr::NonNull<dyn std::ops::FnMut<I, Output = ()>>) as *const dyn std::ops::FnMut<I, Output = ()> (Transmute);
+ _5 = &mut (*_7);
+ _7 = copy (((*_3).0: std::ptr::Unique<dyn std::ops::FnMut<I, Output = ()>>).0: std::ptr::NonNull<dyn std::ops::FnMut<I, Output = ()>>);
+ _6 = copy _7 as *const dyn std::ops::FnMut<I, Output = ()> (Transmute);
+ _5 = &mut (*_6);
+ _0 = <dyn FnMut<I, Output = ()> as FnMut<I>>::call_mut(move _5, move _4) -> [return: bb4, unwind: bb2];
}

View file

@ -9,8 +9,8 @@
let mut _4: (i32,);
+ scope 1 (inlined <Box<dyn Fn(i32)> as Fn<(i32,)>>::call) {
+ let mut _5: &dyn std::ops::Fn(i32);
+ let mut _6: std::boxed::Box<dyn std::ops::Fn(i32)>;
+ let mut _7: *const dyn std::ops::Fn(i32);
+ let mut _6: *const dyn std::ops::Fn(i32);
+ let mut _7: std::ptr::NonNull<dyn std::ops::Fn(i32)>;
+ }
bb0: {
@ -23,9 +23,9 @@
+ StorageLive(_6);
+ StorageLive(_7);
+ StorageLive(_5);
+ _6 = copy (*_3);
+ _7 = copy ((_6.0: std::ptr::Unique<dyn std::ops::Fn(i32)>).0: std::ptr::NonNull<dyn std::ops::Fn(i32)>) as *const dyn std::ops::Fn(i32) (Transmute);
+ _5 = &(*_7);
+ _7 = copy (((*_3).0: std::ptr::Unique<dyn std::ops::Fn(i32)>).0: std::ptr::NonNull<dyn std::ops::Fn(i32)>);
+ _6 = copy _7 as *const dyn std::ops::Fn(i32) (Transmute);
+ _5 = &(*_6);
+ _2 = <dyn Fn(i32) as Fn<(i32,)>>::call(move _5, move _4) -> [return: bb2, unwind unreachable];
}

View file

@ -9,8 +9,8 @@
let mut _4: (i32,);
+ scope 1 (inlined <Box<dyn Fn(i32)> as Fn<(i32,)>>::call) {
+ let mut _5: &dyn std::ops::Fn(i32);
+ let mut _6: std::boxed::Box<dyn std::ops::Fn(i32)>;
+ let mut _7: *const dyn std::ops::Fn(i32);
+ let mut _6: *const dyn std::ops::Fn(i32);
+ let mut _7: std::ptr::NonNull<dyn std::ops::Fn(i32)>;
+ }
bb0: {
@ -23,9 +23,9 @@
+ StorageLive(_6);
+ StorageLive(_7);
+ StorageLive(_5);
+ _6 = copy (*_3);
+ _7 = copy ((_6.0: std::ptr::Unique<dyn std::ops::Fn(i32)>).0: std::ptr::NonNull<dyn std::ops::Fn(i32)>) as *const dyn std::ops::Fn(i32) (Transmute);
+ _5 = &(*_7);
+ _7 = copy (((*_3).0: std::ptr::Unique<dyn std::ops::Fn(i32)>).0: std::ptr::NonNull<dyn std::ops::Fn(i32)>);
+ _6 = copy _7 as *const dyn std::ops::Fn(i32) (Transmute);
+ _5 = &(*_6);
+ _2 = <dyn Fn(i32) as Fn<(i32,)>>::call(move _5, move _4) -> [return: bb4, unwind: bb2];
}

View file

@ -8,8 +8,8 @@ fn b(_1: &mut Box<T>) -> &mut T {
let mut _4: &mut std::boxed::Box<T>;
scope 1 (inlined <Box<T> as AsMut<T>>::as_mut) {
debug self => _4;
let mut _5: std::boxed::Box<T>;
let mut _6: *const T;
let mut _5: *const T;
let mut _6: std::ptr::NonNull<T>;
}
bb0: {
@ -19,9 +19,9 @@ fn b(_1: &mut Box<T>) -> &mut T {
_4 = copy _1;
StorageLive(_5);
StorageLive(_6);
_5 = copy (*_4);
_6 = copy ((_5.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>) as *const T (Transmute);
_3 = &mut (*_6);
_6 = copy (((*_4).0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>);
_5 = copy _6 as *const T (Transmute);
_3 = &mut (*_5);
StorageDead(_6);
StorageDead(_5);
_2 = copy _3;

View file

@ -7,8 +7,8 @@ fn d(_1: &Box<T>) -> &T {
let mut _3: &std::boxed::Box<T>;
scope 1 (inlined <Box<T> as AsRef<T>>::as_ref) {
debug self => _3;
let mut _4: std::boxed::Box<T>;
let mut _5: *const T;
let mut _4: *const T;
let mut _5: std::ptr::NonNull<T>;
}
bb0: {
@ -17,9 +17,9 @@ fn d(_1: &Box<T>) -> &T {
_3 = copy _1;
StorageLive(_4);
StorageLive(_5);
_4 = copy (*_3);
_5 = copy ((_4.0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>) as *const T (Transmute);
_2 = &(*_5);
_5 = copy (((*_3).0: std::ptr::Unique<T>).0: std::ptr::NonNull<T>);
_4 = copy _5 as *const T (Transmute);
_2 = &(*_4);
StorageDead(_5);
StorageDead(_4);
_0 = copy _2;

View file

@ -124,7 +124,7 @@
StorageLive(_8);
_8 = move _4;
StorageLive(_9);
_10 = deref_copy (_1.1: &mut std::task::Context<'_>);
_10 = copy (_1.1: &mut std::task::Context<'_>);
_9 = &mut (*_10);
- _7 = <{async fn body of ActionPermit<'_, T>::perform()} as Future>::poll(move _8, move _9) -> [return: bb3, unwind unreachable];
+ StorageLive(_16);
@ -139,7 +139,7 @@
+ StorageLive(_37);
+ StorageLive(_38);
+ StorageLive(_39);
+ _32 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _32 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _31 = discriminant((*_32));
+ switchInt(move _31) -> [0: bb3, 1: bb10, 3: bb9, otherwise: bb5];
}
@ -175,8 +175,8 @@
}
+ bb3: {
+ _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _34 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _33 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _34 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ (((*_33) as variant#3).0: ActionPermit<'_, T>) = move ((*_34).0: ActionPermit<'_, T>);
+ StorageLive(_12);
+ StorageLive(_13);
@ -189,7 +189,7 @@
+ StorageDead(_14);
+ _12 = move _13;
+ StorageDead(_13);
+ _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _35 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ (((*_35) as variant#3).1: std::future::Ready<()>) = move _12;
+ goto -> bb4;
+ }
@ -202,7 +202,7 @@
+ StorageLive(_19);
+ StorageLive(_20);
+ StorageLive(_21);
+ _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _36 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _21 = &mut (((*_36) as variant#3).1: std::future::Ready<()>);
+ _20 = &mut (*_21);
+ _19 = Pin::<&mut std::future::Ready<()>> { pointer: copy _20 };
@ -251,7 +251,7 @@
+ StorageDead(_12);
+ StorageDead(_28);
+ StorageDead(_29);
+ _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _37 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ discriminant((*_37)) = 3;
+ goto -> bb2;
+ }
@ -266,13 +266,13 @@
+ StorageDead(_18);
+ StorageDead(_17);
+ StorageDead(_12);
+ _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _38 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ drop((((*_38) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb8, unwind unreachable];
+ }
+
+ bb8: {
+ _7 = Poll::<()>::Ready(move _30);
+ _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _39 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ discriminant((*_39)) = 1;
+ goto -> bb2;
+ }

View file

@ -126,7 +126,7 @@
StorageLive(_8);
_8 = move _4;
StorageLive(_9);
_10 = deref_copy (_1.1: &mut std::task::Context<'_>);
_10 = copy (_1.1: &mut std::task::Context<'_>);
_9 = &mut (*_10);
- _7 = <{async fn body of ActionPermit<'_, T>::perform()} as Future>::poll(move _8, move _9) -> [return: bb3, unwind: bb5];
+ StorageLive(_16);
@ -143,7 +143,7 @@
+ StorageLive(_39);
+ StorageLive(_40);
+ StorageLive(_41);
+ _32 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _32 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _31 = discriminant((*_32));
+ switchInt(move _31) -> [0: bb5, 1: bb15, 2: bb14, 3: bb13, otherwise: bb7];
}
@ -192,8 +192,8 @@
- StorageDead(_2);
- return;
+ bb5: {
+ _33 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _34 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _33 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _34 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ (((*_33) as variant#3).0: ActionPermit<'_, T>) = move ((*_34).0: ActionPermit<'_, T>);
+ StorageLive(_12);
+ StorageLive(_13);
@ -206,7 +206,7 @@
+ StorageDead(_14);
+ _12 = move _13;
+ StorageDead(_13);
+ _35 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _35 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ (((*_35) as variant#3).1: std::future::Ready<()>) = move _12;
+ goto -> bb6;
}
@ -219,7 +219,7 @@
+ StorageLive(_19);
+ StorageLive(_20);
+ StorageLive(_21);
+ _36 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _36 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _21 = &mut (((*_36) as variant#3).1: std::future::Ready<()>);
+ _20 = &mut (*_21);
+ _19 = Pin::<&mut std::future::Ready<()>> { pointer: copy _20 };
@ -270,7 +270,7 @@
+ StorageDead(_12);
+ StorageDead(_28);
+ StorageDead(_29);
+ _37 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _37 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ discriminant((*_37)) = 3;
+ goto -> bb4;
+ }
@ -285,13 +285,13 @@
+ StorageDead(_18);
+ StorageDead(_17);
+ StorageDead(_12);
+ _38 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _38 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ drop((((*_38) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb10, unwind: bb12];
+ }
+
+ bb10: {
+ _7 = Poll::<()>::Ready(move _30);
+ _39 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _39 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ discriminant((*_39)) = 1;
+ goto -> bb4;
+ }
@ -304,12 +304,12 @@
+ StorageDead(_18);
+ StorageDead(_17);
+ StorageDead(_12);
+ _40 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _40 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ drop((((*_40) as variant#3).0: ActionPermit<'_, T>)) -> [return: bb12, unwind terminate(cleanup)];
+ }
+
+ bb12 (cleanup): {
+ _41 = deref_copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ _41 = copy (_8.0: &mut {async fn body of ActionPermit<'_, T>::perform()});
+ discriminant((*_41)) = 2;
+ goto -> bb2;
+ }

View file

@ -16,17 +16,15 @@
bb0: {
- StorageLive(_2);
- _6 = deref_copy (*_1);
+ nop;
+ _6 = copy (*_1);
_6 = copy (*_1);
_2 = copy (*_6);
_3 = unknown() -> [return: bb1, unwind unreachable];
}
bb1: {
StorageLive(_4);
- _7 = deref_copy (*_1);
+ _7 = copy (*_1);
_7 = copy (*_1);
_4 = copy (*_7);
StorageLive(_5);
_5 = copy _2;

View file

@ -16,17 +16,15 @@
bb0: {
- StorageLive(_2);
- _6 = deref_copy (*_1);
+ nop;
+ _6 = copy (*_1);
_6 = copy (*_1);
_2 = copy (*_6);
_3 = unknown() -> [return: bb1, unwind continue];
}
bb1: {
StorageLive(_4);
- _7 = deref_copy (*_1);
+ _7 = copy (*_1);
_7 = copy (*_1);
_4 = copy (*_7);
StorageLive(_5);
_5 = copy _2;

View file

@ -8,7 +8,7 @@ fn box_to_raw_mut(_1: &mut Box<i32>) -> *mut i32 {
bb0: {
Retag([fn entry] _1);
_2 = deref_copy (*_1);
_2 = copy (*_1);
_3 = copy ((_2.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
_0 = &raw mut (*_3);
Retag([raw] _0);

View file

@ -8,7 +8,7 @@ fn box_to_raw_mut(_1: &mut Box<i32>) -> *mut i32 {
bb0: {
Retag([fn entry] _1);
_2 = deref_copy (*_1);
_2 = copy (*_1);
_3 = copy ((_2.0: std::ptr::Unique<i32>).0: std::ptr::NonNull<i32>) as *const i32 (Transmute);
_0 = &raw mut (*_3);
Retag([raw] _0);

View file

@ -117,8 +117,8 @@
StorageLive(_15);
StorageLive(_16);
StorageLive(_17);
- _26 = deref_copy (_12.0: &std::boxed::Box<dyn std::fmt::Display>);
+ _26 = deref_copy _34;
- _26 = copy (_12.0: &std::boxed::Box<dyn std::fmt::Display>);
+ _26 = copy _34;
_17 = &(*_26);
_16 = core::fmt::rt::Argument::<'_>::new_display::<Box<dyn std::fmt::Display>>(move _17) -> [return: bb3, unwind unreachable];
}
@ -127,8 +127,8 @@
StorageDead(_17);
StorageLive(_18);
StorageLive(_19);
- _27 = deref_copy (_12.1: &u32);
+ _27 = deref_copy _35;
- _27 = copy (_12.1: &u32);
+ _27 = copy _35;
_19 = &(*_27);
_18 = core::fmt::rt::Argument::<'_>::new_display::<u32>(move _19) -> [return: bb4, unwind unreachable];
}

View file

@ -28,7 +28,7 @@ fn foo::{closure#0}(_1: &{async closure@$DIR/async-closure.rs:9:13: 9:21}) -> {a
debug y => (*((*_1).0: &i32));
bb0: {
StorageLive(_2);
_3 = CopyForDeref(((*_1).0: &i32));
_3 = ((*_1).0: &i32);
_2 = &(*_3);
_0 = {coroutine@$DIR/async-closure.rs:9:22: 11:6}(move _2);
StorageDead(_2);
@ -48,19 +48,19 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo
debug y => (*((*(_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})).0: &i32));
debug y => _3;
bb0: {
_7 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
_7 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6});
_6 = discriminant((*_7));
switchInt(move _6) -> [0: bb1, 1: bb2, otherwise: bb3];
}
bb1: {
StorageLive(_3);
_8 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
_4 = CopyForDeref(((*_8).0: &i32));
_8 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6});
_4 = ((*_8).0: &i32);
_3 = (*_4);
_5 = ();
StorageDead(_3);
_0 = std::task::Poll::Ready(move _5);
_9 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
_9 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6});
discriminant((*_9)) = 1;
return;
}
@ -84,19 +84,19 @@ fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-c
debug y => (*((*(_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6})).0: &i32));
debug y => _3;
bb0: {
_7 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
_7 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6});
_6 = discriminant((*_7));
switchInt(move _6) -> [0: bb1, 1: bb2, otherwise: bb3];
}
bb1: {
StorageLive(_3);
_8 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
_4 = CopyForDeref(((*_8).0: &i32));
_8 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6});
_4 = ((*_8).0: &i32);
_3 = (*_4);
_5 = ();
StorageDead(_3);
_0 = std::task::Poll::Ready(move _5);
_9 = CopyForDeref((_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}));
_9 = (_1.0: &mut {async closure body@$DIR/async-closure.rs:9:22: 11:6});
discriminant((*_9)) = 1;
return;
}