1#![feature(const_type_name)]
3#![feature(cow_is_borrowed)]
4#![feature(deref_patterns)]
5#![feature(impl_trait_in_assoc_type)]
6#![feature(iterator_try_collect)]
7#![feature(option_into_flat_iter)]
8#![feature(try_blocks)]
9#![feature(yeet_expr)]
10use hir::ConstContext;
13use required_consts::RequiredConstsVisitor;
14use rustc_const_eval::check_consts::{self, ConstCx};
15use rustc_const_eval::util;
16use rustc_data_structures::fx::FxIndexSet;
17use rustc_data_structures::steal::Steal;
18use rustc_hir as hir;
19use rustc_hir::def::{CtorKind, DefKind};
20use rustc_hir::def_id::LocalDefId;
21use rustc_index::IndexVec;
22use rustc_middle::mir::{
23 AnalysisPhase, Body, CallSource, ClearCrossCrate, ConstOperand, ConstQualifs, LocalDecl,
24 MirPhase, Operand, Place, ProjectionElem, Promoted, RuntimePhase, Rvalue, START_BLOCK,
25 SourceInfo, Statement, StatementKind, TerminatorKind, WithRetag,
26};
27use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt};
28use rustc_middle::util::Providers;
29use rustc_middle::{bug, query, span_bug};
30use rustc_span::{DUMMY_SP, Spanned, sym};
31use tracing::debug;
32
33#[macro_use]
34mod pass_manager;
35
36use std::sync::LazyLock;
37
38use pass_manager::{self as pm, Lint, MirLint, MirPass, PassCtx, PassPolicy, WithMinOptLevel};
39
40mod check_pointers;
41mod cost_checker;
42mod cross_crate_inline;
43mod deduce_param_attrs;
44mod diagnostics;
45mod elaborate_drop;
46mod ffi_unwind_calls;
47mod lint;
48mod lint_tail_expr_drop_order;
49mod liveness;
50mod patch;
51mod shim;
52mod ssa;
53mod trivial_const;
54
55pub use shim::build_drop_shim;
57
58macro_rules! declare_passes {
81 (
82 $(
83 $vis:vis mod $mod_name:ident : $($pass_name:ident $( { $($ident:ident),* } )?),+ $(,)?;
84 )*
85 ) => {
86 $(
87 $vis mod $mod_name;
88 $(
89 #[allow(unused_imports)]
91 use $mod_name::$pass_name as _;
92 )+
93 )*
94
95 static PASS_NAMES: LazyLock<FxIndexSet<&str>> = LazyLock::new(|| {
96 let mut set = FxIndexSet::default();
97 $(
98 $(
99 set.extend(pass_names!($mod_name : $pass_name $( { $($ident),* } )? ));
100 )+
101 )*
102 set
103 });
104 };
105}
106
107macro_rules! pass_names {
108 ($mod_name:ident : $pass_group:ident { $($pass_name:ident),* $(,)? }) => {
110 [
111 $(
112 $mod_name::$pass_group::$pass_name.name(),
113 )*
114 ]
115 };
116 ($mod_name:ident : $pass_name:ident) => {
118 [stringify!($pass_name)]
119 };
120}
121
122mod abort_unwinding_calls {
use rustc_abi::ExternAbi;
use rustc_ast::InlineAsmOptions;
use rustc_middle::mir::*;
use rustc_middle::span_bug;
use rustc_middle::ty::{self, TyCtxt, layout};
use rustc_span::sym;
use rustc_target::spec::PanicStrategy;
use crate::PassPolicy;
pub(super) struct AbortUnwindingCalls;
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for AbortUnwindingCalls { }
#[automatically_derived]
impl ::core::cmp::PartialEq for AbortUnwindingCalls {
#[inline]
fn eq(&self, other: &AbortUnwindingCalls) -> bool { true }
}
impl<'tcx> crate::MirPass<'tcx> for AbortUnwindingCalls {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let def_id = body.source.def_id();
let kind = tcx.def_kind(def_id);
if !kind.is_fn_like() { return; }
let target_supports_unwinding =
!(tcx.sess.target.is_like_wasm &&
tcx.sess.panic_strategy() == PanicStrategy::Abort &&
!tcx.asm_target_features(def_id).contains(&sym::exception_handling));
let body_ty = tcx.type_of(def_id).skip_binder();
let body_abi =
match body_ty.kind() {
ty::FnDef(..) => body_ty.fn_sig(tcx).abi(),
ty::Closure(..) => ExternAbi::RustCall,
ty::CoroutineClosure(..) => ExternAbi::RustCall,
ty::Coroutine(..) => ExternAbi::Rust,
ty::Error(_) => return,
_ =>
::rustc_middle::util::bug::span_bug_fmt(body.span,
format_args!("unexpected body ty: {0:?}", body_ty)),
};
let body_can_unwind =
layout::fn_can_unwind(tcx, Some(def_id), body_abi);
for block in body.basic_blocks.as_mut() {
let Some(terminator) =
&mut block.terminator else { continue };
let span = terminator.source_info.span;
if let TerminatorKind::UnwindResume = &terminator.kind {
if !target_supports_unwinding {
terminator.kind = TerminatorKind::Unreachable;
} else if !body_can_unwind {
terminator.kind =
TerminatorKind::UnwindTerminate(UnwindTerminateReason::Abi);
}
}
if block.is_cleanup { continue; }
let call_can_unwind =
match &terminator.kind {
TerminatorKind::Call { func, .. } => {
let ty = func.ty(&body.local_decls, tcx);
let sig = ty.fn_sig(tcx);
let fn_def_id =
match ty.kind() {
ty::FnPtr(..) => None,
&ty::FnDef(def_id, _) => Some(def_id),
_ =>
::rustc_middle::util::bug::span_bug_fmt(span,
format_args!("invalid callee of type {0:?}", ty)),
};
layout::fn_can_unwind(tcx, fn_def_id, sig.abi())
}
TerminatorKind::Drop { .. } => {
tcx.sess.opts.unstable_opts.panic_in_drop ==
PanicStrategy::Unwind &&
layout::fn_can_unwind(tcx, None, ExternAbi::Rust)
}
TerminatorKind::Assert { .. } |
TerminatorKind::FalseUnwind { .. } => {
layout::fn_can_unwind(tcx, None, ExternAbi::Rust)
}
TerminatorKind::InlineAsm { options, .. } => {
options.contains(InlineAsmOptions::MAY_UNWIND)
}
_ if terminator.unwind().is_some() => {
::rustc_middle::util::bug::span_bug_fmt(span,
format_args!("unexpected terminator that may unwind {0:?}",
terminator))
}
_ => continue,
};
if !call_can_unwind || !target_supports_unwinding {
let cleanup = block.terminator_mut().unwind_mut().unwrap();
*cleanup = UnwindAction::Unreachable;
} else if !body_can_unwind &&
#[allow(non_exhaustive_omitted_patterns)] match terminator.unwind()
{
Some(UnwindAction::Continue) => true,
_ => false,
} {
let cleanup = block.terminator_mut().unwind_mut().unwrap();
*cleanup =
UnwindAction::Terminate(UnwindTerminateReason::Abi);
}
}
super::simplify::remove_dead_blocks(body);
}
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::Required
}
}
}
#[allow(unused_imports)]
use abort_unwinding_calls::AbortUnwindingCalls as _;
mod add_call_guards {
use rustc_data_structures::thin_vec::ThinVec;
use rustc_index::{Idx, IndexVec};
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use tracing::debug;
use crate::PassPolicy;
pub(super) enum AddCallGuards { AllCallEdges, CriticalCallEdges, }
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for AddCallGuards { }
#[automatically_derived]
impl ::core::cmp::PartialEq for AddCallGuards {
#[inline]
fn eq(&self, other: &AddCallGuards) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}
pub(super) use self::AddCallGuards::*;
impl<'tcx> crate::MirPass<'tcx> for AddCallGuards {
fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let mut pred_count = IndexVec::from_elem(0u8, &body.basic_blocks);
for (_, data) in body.basic_blocks.iter_enumerated() {
for succ in data.terminator().successors() {
pred_count[succ] = pred_count[succ].saturating_add(1);
}
}
enum Action {
Call,
Asm {
target_index: usize,
},
}
let mut work = Vec::with_capacity(body.basic_blocks.len());
for (bb, block) in body.basic_blocks.iter_enumerated() {
let term = block.terminator();
match term.kind {
TerminatorKind::Call { target: Some(destination), unwind, ..
} if
pred_count[destination] > 1 &&
(generates_invoke(unwind) || self == &AllCallEdges) => {
work.push((bb, Action::Call));
}
TerminatorKind::InlineAsm {
asm_macro: InlineAsmMacro::Asm,
ref targets,
ref operands,
unwind, .. } if self == &CriticalCallEdges => {
let has_outputs =
operands.iter().any(|op|
{
#[allow(non_exhaustive_omitted_patterns)]
match op {
InlineAsmOperand::InOut { .. } | InlineAsmOperand::Out { ..
} => true,
_ => false,
}
});
let has_labels =
operands.iter().any(|op|
#[allow(non_exhaustive_omitted_patterns)] match op {
InlineAsmOperand::Label { .. } => true,
_ => false,
});
if has_outputs && (has_labels || generates_invoke(unwind)) {
for (target_index, target) in targets.iter().enumerate() {
if pred_count[*target] > 1 {
work.push((bb, Action::Asm { target_index }));
}
}
}
}
_ => {}
}
}
if work.is_empty() { return; }
let mut new_blocks = Vec::with_capacity(work.len());
let cur_len = body.basic_blocks.len();
let mut new_block =
|source_info: SourceInfo, is_cleanup: bool,
target: BasicBlock|
{
let block =
BasicBlockData::new(Some(Terminator {
source_info,
kind: TerminatorKind::Goto { target },
attributes: ThinVec::new(),
}), is_cleanup);
let idx = cur_len + new_blocks.len();
new_blocks.push(block);
BasicBlock::new(idx)
};
let basic_blocks = body.basic_blocks.as_mut();
for (source, action) in work {
let block = &mut basic_blocks[source];
let is_cleanup = block.is_cleanup;
let term = block.terminator_mut();
let source_info = term.source_info;
let destination =
match action {
Action::Call => {
let TerminatorKind::Call {
target: Some(ref mut destination), .. } =
term.kind else {
::core::panicking::panic("internal error: entered unreachable code")
};
destination
}
Action::Asm { target_index } => {
let TerminatorKind::InlineAsm { ref mut targets, .. } =
term.kind else {
::core::panicking::panic("internal error: entered unreachable code")
};
&mut targets[target_index]
}
};
*destination =
new_block(source_info, is_cleanup, *destination);
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/add_call_guards.rs:128",
"rustc_mir_transform::add_call_guards",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/add_call_guards.rs"),
::tracing_core::__macro_support::Option::Some(128u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::add_call_guards"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Broke {0} N edges",
new_blocks.len()) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
basic_blocks.extend(new_blocks);
}
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::Required
}
}
fn generates_invoke(unwind: UnwindAction) -> bool {
match unwind {
UnwindAction::Continue | UnwindAction::Unreachable => false,
UnwindAction::Cleanup(_) | UnwindAction::Terminate(_) => true,
}
}
}
#[allow(unused_imports)]
use add_call_guards::AddCallGuards as _;
mod add_moves_for_packed_drops {
use rustc_data_structures::thin_vec::ThinVec;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, TyCtxt};
use tracing::debug;
use crate::patch::MirPatch;
use crate::{PassPolicy, util};
pub(super) struct AddMovesForPackedDrops;
impl<'tcx> crate::MirPass<'tcx> for AddMovesForPackedDrops {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs:43",
"rustc_mir_transform::add_moves_for_packed_drops",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs"),
::tracing_core::__macro_support::Option::Some(43u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::add_moves_for_packed_drops"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("add_moves_for_packed_drops({0:?} @ {1:?})",
body.source, body.span) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let mut patch = MirPatch::new(body);
let typing_env =
ty::TypingEnv::post_analysis(tcx, body.source.def_id());
for (bb, data) in body.basic_blocks.iter_enumerated() {
let loc =
Location {
block: bb,
statement_index: data.statements.len(),
};
let terminator = data.terminator();
match terminator.kind {
TerminatorKind::Drop { place, .. } if
util::place_unalignment(tcx, body, typing_env,
place).is_some() => {
add_move_for_packed_drop(tcx, body, &mut patch, terminator,
loc, data.is_cleanup);
}
_ => {}
}
}
patch.apply(body);
}
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::Required
}
}
fn add_move_for_packed_drop<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>,
patch: &mut MirPatch<'tcx>, terminator: &Terminator<'tcx>,
loc: Location, is_cleanup: bool) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs:87",
"rustc_mir_transform::add_moves_for_packed_drops",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs"),
::tracing_core::__macro_support::Option::Some(87u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::add_moves_for_packed_drops"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("add_move_for_packed_drop({0:?} @ {1:?})",
terminator, loc) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let TerminatorKind::Drop { ref place, target, unwind, replace, drop
} =
terminator.kind else {
::core::panicking::panic("internal error: entered unreachable code");
};
let source_info = terminator.source_info;
let ty = place.ty(body, tcx).ty;
let temp = patch.new_temp(ty, source_info.span);
let storage_dead_block =
patch.new_block(BasicBlockData::new_stmts(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[Statement::new(source_info,
StatementKind::StorageDead(temp))])),
Some(Terminator {
source_info,
kind: TerminatorKind::Goto { target },
attributes: ThinVec::new(),
}), is_cleanup));
patch.add_statement(loc, StatementKind::StorageLive(temp));
patch.add_assign(loc, Place::from(temp),
Rvalue::Use(Operand::Move(*place), WithRetag::Yes));
patch.patch_terminator(loc.block,
TerminatorKind::Drop {
place: Place::from(temp),
target: storage_dead_block,
unwind,
replace,
drop,
});
}
}
#[allow(unused_imports)]
use add_moves_for_packed_drops::AddMovesForPackedDrops as _;
mod add_subtyping_projections {
use rustc_middle::mir::visit::MutVisitor;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use crate::PassPolicy;
use crate::patch::MirPatch;
pub(super) struct Subtyper;
struct SubTypeChecker<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
patcher: MirPatch<'tcx>,
local_decls: &'a LocalDecls<'tcx>,
}
impl<'a, 'tcx> MutVisitor<'tcx> for SubTypeChecker<'a, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_assign(&mut self, place: &mut Place<'tcx>,
rvalue: &mut Rvalue<'tcx>, location: Location) {
if rvalue.is_generic_reborrow() { return; }
if self.local_decls[place.local].is_deref_temp() { return; }
let mut place_ty = place.ty(self.local_decls, self.tcx).ty;
let mut rval_ty = rvalue.ty(self.local_decls, self.tcx);
rval_ty = self.tcx.erase_and_anonymize_regions(rval_ty);
place_ty = self.tcx.erase_and_anonymize_regions(place_ty);
if place_ty != rval_ty {
let temp =
self.patcher.new_temp(rval_ty,
self.local_decls[place.as_ref().local].source_info.span);
let new_place = Place::from(temp);
self.patcher.add_assign(location, new_place, rvalue.clone());
*rvalue =
Rvalue::Cast(CastKind::Subtype, Operand::Move(new_place),
place_ty);
}
}
}
impl<'tcx> crate::MirPass<'tcx> for Subtyper {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let patch = MirPatch::new(body);
let mut checker =
SubTypeChecker {
tcx,
patcher: patch,
local_decls: &body.local_decls,
};
for (bb, data) in
body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut()
{
checker.visit_basic_block_data(bb, data);
}
checker.patcher.apply(body);
}
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::Required
}
}
}
#[allow(unused_imports)]
use add_subtyping_projections::Subtyper as _;
mod check_inline {
use rustc_hir::attrs::InlineAttr;
use rustc_hir::def_id::DefId;
use rustc_hir::find_attr;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::{Body, TerminatorKind};
use rustc_middle::ty;
use rustc_middle::ty::TyCtxt;
use crate::pass_manager::MirLint;
pub(super) struct CheckForceInline;
impl<'tcx> MirLint<'tcx> for CheckForceInline {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
let def_id = body.source.def_id();
if !tcx.hir_body_owner_kind(def_id).is_fn_or_closure() ||
!def_id.is_local() {
return;
}
let InlineAttr::Force { attr_span, .. } =
tcx.codegen_fn_attrs(def_id).inline else { return; };
if let Err(reason) =
is_inline_valid_on_fn(tcx,
def_id).and_then(|_| is_inline_valid_on_body(tcx, body)) {
tcx.dcx().emit_err(crate::diagnostics::InvalidForceInline {
attr_span,
callee_span: tcx.def_span(def_id),
callee: tcx.def_path_str(def_id),
reason,
});
}
}
}
pub(super) fn is_inline_valid_on_fn<'tcx>(tcx: TyCtxt<'tcx>,
def_id: DefId) -> Result<(), &'static str> {
let codegen_attrs = tcx.codegen_fn_attrs(def_id);
if {
{
'done:
{
for i in ::rustc_attr_ir::HasAttrs::get_attrs(def_id, &tcx)
{
#[allow(unused_imports)]
use ::rustc_attr_ir::AttributeKind::*;
let i: &::rustc_attr_ir::Attribute = i;
match i {
::rustc_attr_ir::Attribute::Parsed(RustcNoMirInline) => {
break 'done Some(());
}
::rustc_attr_ir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}.is_some() {
return Err("#[rustc_no_mir_inline]");
}
let ty = tcx.type_of(def_id);
if match ty.instantiate_identity().skip_norm_wip().kind() {
ty::FnDef(..) =>
tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip().c_variadic(),
ty::Closure(_, args) => args.as_closure().sig().c_variadic(),
_ => false,
} {
return Err("C variadic");
}
if codegen_attrs.flags.contains(CodegenFnAttrFlags::COLD) {
return Err("cold");
}
if let Some(intrinsic) = tcx.intrinsic(def_id) &&
intrinsic.must_be_overridden {
return Err("callee is an intrinsic without fallback body");
}
Ok(())
}
pub(super) fn is_inline_valid_on_body<'tcx>(_: TyCtxt<'tcx>,
body: &Body<'tcx>) -> Result<(), &'static str> {
if body.basic_blocks.iter().any(|bb|
#[allow(non_exhaustive_omitted_patterns)] match bb.terminator().kind
{
TerminatorKind::TailCall { .. } => true,
_ => false,
}) {
return Err("can't inline functions with tail calls");
}
Ok(())
}
}
#[allow(unused_imports)]
use check_inline::CheckForceInline as _;
mod check_call_recursion {
use std::ops::ControlFlow;
use rustc_data_structures::graph::iterate::{
NodeStatus, TriColorDepthFirstSearch, TriColorVisitor,
};
use rustc_hir::attrs::lang_items::LangItem;
use rustc_hir::def::DefKind;
use rustc_lint_defs::builtin::UNCONDITIONAL_RECURSION;
use rustc_middle::mir::{
self, BasicBlock, BasicBlocks, Body, Terminator, TerminatorKind,
};
use rustc_middle::ty::{
self, GenericArg, GenericArgs, Instance, Ty, TyCtxt, Unnormalized,
};
use rustc_span::Span;
use crate::diagnostics::UnconditionalRecursion;
use crate::pass_manager::MirLint;
pub(super) struct CheckCallRecursion;
impl<'tcx> MirLint<'tcx> for CheckCallRecursion {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
let def_id = body.source.def_id().expect_local();
if let DefKind::Fn | DefKind::AssocFn = tcx.def_kind(def_id) {
let trait_args =
match tcx.trait_of_assoc(def_id.to_def_id()) {
Some(trait_def_id) => {
let trait_args_count =
tcx.generics_of(trait_def_id).count();
&GenericArgs::identity_for_item(tcx,
def_id)[..trait_args_count]
}
_ => &[],
};
check_recursion(tcx, body, CallRecursion { trait_args })
}
}
}
pub(super) struct CheckDropRecursion;
impl<'tcx> MirLint<'tcx> for CheckDropRecursion {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
let def_id = body.source.def_id().expect_local();
if let DefKind::AssocFn = tcx.def_kind(def_id) &&
let Some(impl_id) =
tcx.trait_impl_of_assoc(def_id.to_def_id()) &&
let trait_ref = tcx.impl_trait_ref(impl_id) &&
tcx.is_lang_item(trait_ref.def_id(), LangItem::Drop) &&
let sig =
tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip() &&
sig.inputs().skip_binder().len() == 1 {
if let ty::Ref(_, dropped_ty, _) =
tcx.liberate_late_bound_regions(def_id.to_def_id(),
sig.input(0)).kind() {
check_recursion(tcx, body,
RecursiveDrop { drop_for: *dropped_ty });
}
}
}
}
fn check_recursion<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>,
classifier: impl TerminatorClassifier<'tcx>) {
let def_id = body.source.def_id().expect_local();
if let DefKind::Fn | DefKind::AssocFn = tcx.def_kind(def_id) {
let mut vis =
Search {
tcx,
body,
classifier,
reachable_recursive_calls: ::alloc::vec::Vec::new(),
};
if let Some(NonRecursive) =
TriColorDepthFirstSearch::new(&body.basic_blocks).run_from_start(&mut vis)
{
return;
}
if vis.reachable_recursive_calls.is_empty() { return; }
vis.reachable_recursive_calls.sort();
let sp = tcx.def_span(def_id);
let hir_id = tcx.local_def_id_to_hir_id(def_id);
tcx.emit_node_span_lint(UNCONDITIONAL_RECURSION, hir_id, sp,
UnconditionalRecursion {
span: sp,
call_sites: vis.reachable_recursive_calls,
});
}
}
trait TerminatorClassifier<'tcx> {
fn is_recursive_terminator(&self, tcx: TyCtxt<'tcx>,
body: &Body<'tcx>, terminator: &Terminator<'tcx>)
-> bool;
}
struct NonRecursive;
struct Search<'mir, 'tcx, C: TerminatorClassifier<'tcx>> {
tcx: TyCtxt<'tcx>,
body: &'mir Body<'tcx>,
classifier: C,
reachable_recursive_calls: Vec<Span>,
}
struct CallRecursion<'tcx> {
trait_args: &'tcx [GenericArg<'tcx>],
}
struct RecursiveDrop<'tcx> {
drop_for: Ty<'tcx>,
}
impl<'tcx> TerminatorClassifier<'tcx> for CallRecursion<'tcx> {
fn is_recursive_terminator(&self, tcx: TyCtxt<'tcx>,
body: &Body<'tcx>, terminator: &Terminator<'tcx>) -> bool {
let TerminatorKind::Call { func, args, .. } =
&terminator.kind else { return false; };
if args.len() != body.arg_count { return false; }
let caller = body.source.def_id();
let typing_env = body.typing_env(tcx);
let func_ty = func.ty(body, tcx);
if let ty::FnDef(callee, args) = *func_ty.kind() {
let args = args.no_bound_vars().unwrap();
let Ok(normalized_args) =
tcx.try_normalize_erasing_regions(typing_env,
Unnormalized::new_wip(args)) else { return false; };
let (callee, call_args) =
if let Ok(Some(instance)) =
Instance::try_resolve(tcx, typing_env, callee,
normalized_args) {
(instance.def_id(), instance.args)
} else { (callee, normalized_args) };
return callee == caller &&
&call_args[..self.trait_args.len()] == self.trait_args;
}
false
}
}
impl<'tcx> TerminatorClassifier<'tcx> for RecursiveDrop<'tcx> {
fn is_recursive_terminator(&self, tcx: TyCtxt<'tcx>,
body: &Body<'tcx>, terminator: &Terminator<'tcx>) -> bool {
let TerminatorKind::Drop { place, .. } =
&terminator.kind else { return false };
let dropped_ty = place.ty(body, tcx).ty;
dropped_ty == self.drop_for
}
}
impl<'mir, 'tcx, C: TerminatorClassifier<'tcx>>
TriColorVisitor<BasicBlocks<'tcx>> for Search<'mir, 'tcx, C> {
type BreakVal = NonRecursive;
fn node_examined(&mut self, bb: BasicBlock,
prior_status: Option<NodeStatus>) -> ControlFlow<Self::BreakVal> {
if let Some(NodeStatus::Visited) = prior_status {
return ControlFlow::Break(NonRecursive);
}
match self.body[bb].terminator().kind {
TerminatorKind::UnwindTerminate(_) |
TerminatorKind::CoroutineDrop | TerminatorKind::UnwindResume
| TerminatorKind::Return | TerminatorKind::Unreachable |
TerminatorKind::Yield { .. } =>
ControlFlow::Break(NonRecursive),
TerminatorKind::InlineAsm { ref targets, .. } => {
if !targets.is_empty() {
ControlFlow::Continue(())
} else { ControlFlow::Break(NonRecursive) }
}
TerminatorKind::Assert { .. } | TerminatorKind::Call { .. } |
TerminatorKind::Drop { .. } | TerminatorKind::FalseEdge { ..
} | TerminatorKind::FalseUnwind { .. } |
TerminatorKind::Goto { .. } | TerminatorKind::SwitchInt { ..
} => ControlFlow::Continue(()),
TerminatorKind::TailCall { .. } => ControlFlow::Continue(()),
}
}
fn node_settled(&mut self, bb: BasicBlock)
-> ControlFlow<Self::BreakVal> {
let terminator = self.body[bb].terminator();
if self.classifier.is_recursive_terminator(self.tcx, self.body,
terminator) {
self.reachable_recursive_calls.push(terminator.source_info.span);
}
ControlFlow::Continue(())
}
fn ignore_edge(&mut self, bb: BasicBlock, target: BasicBlock)
-> bool {
let terminator = self.body[bb].terminator();
let ignore_unwind =
terminator.unwind() ==
Some(&mir::UnwindAction::Cleanup(target)) &&
terminator.successors().count() > 1;
if ignore_unwind ||
self.classifier.is_recursive_terminator(self.tcx, self.body,
terminator) {
return true;
}
match &terminator.kind {
TerminatorKind::FalseEdge { imaginary_target, .. } =>
imaginary_target == &target,
_ => false,
}
}
}
}
#[allow(unused_imports)]
use check_call_recursion::CheckCallRecursion as _;
#[allow(unused_imports)]
use check_call_recursion::CheckDropRecursion as _;
mod check_alignment {
use rustc_abi::Align;
use rustc_hir::attrs::lang_items::LangItem;
use rustc_index::IndexVec;
use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::visit::PlaceContext;
use rustc_middle::mir::*;
use rustc_middle::ty::{Ty, TyCtxt};
use crate::PassPolicy;
use crate::check_pointers::{
BorrowedFieldProjectionMode, PointerCheck, check_pointers,
};
pub(super) struct CheckAlignment;
impl<'tcx> crate::MirPass<'tcx> for CheckAlignment {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.ub_checks())
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let excluded_pointees =
[tcx.types.bool, tcx.types.i8, tcx.types.u8];
check_pointers(tcx, body, &excluded_pointees,
insert_alignment_check,
BorrowedFieldProjectionMode::FollowProjections);
}
}
fn insert_alignment_check<'tcx>(tcx: TyCtxt<'tcx>, pointer: Place<'tcx>,
pointee_ty: Ty<'tcx>, _context: PlaceContext,
local_decls: &mut IndexVec<Local, LocalDecl<'tcx>>,
stmts: &mut Vec<Statement<'tcx>>, source_info: SourceInfo)
-> PointerCheck<'tcx> {
let const_raw_ptr = Ty::new_imm_ptr(tcx, tcx.types.unit);
let rvalue =
Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(pointer),
const_raw_ptr);
let thin_ptr =
local_decls.push(LocalDecl::with_source_info(const_raw_ptr,
source_info)).into();
stmts.push(Statement::new(source_info,
StatementKind::Assign(Box::new((thin_ptr, rvalue)))));
let rvalue =
Rvalue::Cast(CastKind::Transmute, Operand::Copy(thin_ptr),
tcx.types.usize);
let addr =
local_decls.push(LocalDecl::with_source_info(tcx.types.usize,
source_info)).into();
stmts.push(Statement::new(source_info,
StatementKind::Assign(Box::new((addr, rvalue)))));
let align_def_id =
tcx.require_lang_item(LangItem::AlignOf, source_info.span);
let alignment =
Operand::unevaluated_constant(tcx, align_def_id,
&[pointee_ty.into()], source_info.span);
let alignment_mask =
local_decls.push(LocalDecl::with_source_info(tcx.types.usize,
source_info)).into();
let one =
Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
user_ty: None,
const_: Const::Val(ConstValue::Scalar(Scalar::from_target_usize(1,
&tcx)), tcx.types.usize),
}));
stmts.push(Statement::new(source_info,
StatementKind::Assign(Box::new((alignment_mask,
Rvalue::BinaryOp(BinOp::Sub,
Box::new((alignment.clone(), one))))))));
if let max_align = tcx.sess.target.max_reliable_alignment() &&
max_align < Align::MAX {
let max_mask = max_align.bytes() - 1;
let max_mask =
Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
user_ty: None,
const_: Const::Val(ConstValue::Scalar(Scalar::from_target_usize(max_mask,
&tcx)), tcx.types.usize),
}));
stmts.push(Statement::new(source_info,
StatementKind::Assign(Box::new((alignment_mask,
Rvalue::BinaryOp(BinOp::BitAnd,
Box::new((Operand::Copy(alignment_mask), max_mask))))))));
}
let alignment_bits =
local_decls.push(LocalDecl::with_source_info(tcx.types.usize,
source_info)).into();
stmts.push(Statement::new(source_info,
StatementKind::Assign(Box::new((alignment_bits,
Rvalue::BinaryOp(BinOp::BitAnd,
Box::new((Operand::Copy(addr),
Operand::Copy(alignment_mask)))))))));
let is_ok =
local_decls.push(LocalDecl::with_source_info(tcx.types.bool,
source_info)).into();
let zero =
Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
user_ty: None,
const_: Const::Val(ConstValue::Scalar(Scalar::from_target_usize(0,
&tcx)), tcx.types.usize),
}));
stmts.push(Statement::new(source_info,
StatementKind::Assign(Box::new((is_ok,
Rvalue::BinaryOp(BinOp::Eq,
Box::new((Operand::Copy(alignment_bits),
zero.clone()))))))));
PointerCheck {
cond: Operand::Copy(is_ok),
assert_kind: Box::new(AssertKind::MisalignedPointerDereference {
required: alignment,
found: Operand::Copy(addr),
}),
}
}
}
#[allow(unused_imports)]
use check_alignment::CheckAlignment as _;
mod check_enums {
use rustc_abi::{Scalar, Size, TagEncoding, Variants, WrappingRange};
use rustc_data_structures::thin_vec::ThinVec;
use rustc_hir::attrs::lang_items::LangItem;
use rustc_index::IndexVec;
use rustc_middle::bug;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
use rustc_middle::ty::layout::PrimitiveExt;
use rustc_middle::ty::{self, Ty, TyCtxt, TypingEnv};
use tracing::debug;
use crate::PassPolicy;
pub(super) struct CheckEnums;
impl<'tcx> crate::MirPass<'tcx> for CheckEnums {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.ub_checks())
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
if tcx.lang_items().get(LangItem::PanicImpl).is_none() { return; }
let typing_env = body.typing_env(tcx);
let basic_blocks = body.basic_blocks.as_mut();
let local_decls = &mut body.local_decls;
for block in basic_blocks.indices().rev() {
for statement_index in
(0..basic_blocks[block].statements.len()).rev() {
let location = Location { block, statement_index };
let statement =
&basic_blocks[block].statements[statement_index];
let source_info = statement.source_info;
let mut finder =
EnumFinder::new(tcx, local_decls, typing_env);
finder.visit_statement(statement, location);
for check in finder.into_found_enums() {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/check_enums.rs:50",
"rustc_mir_transform::check_enums", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/check_enums.rs"),
::tracing_core::__macro_support::Option::Some(50u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::check_enums"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Inserting enum check")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let new_block = split_block(basic_blocks, location);
match check {
EnumCheckType::Direct { op_size, .. } |
EnumCheckType::WithNiche { op_size, .. } if
op_size.bytes() == 0 => {
tcx.dcx().span_delayed_bug(source_info.span,
"cannot build enum discriminant from zero-sized type");
basic_blocks[block].terminator =
Some(Terminator {
source_info,
kind: TerminatorKind::Goto { target: new_block },
attributes: ThinVec::new(),
});
}
EnumCheckType::Direct {
source_op, discr, op_size, valid_discrs } => {
insert_direct_enum_check(tcx, local_decls, basic_blocks,
block, source_op, discr, op_size, valid_discrs, source_info,
new_block)
}
EnumCheckType::Uninhabited =>
insert_uninhabited_enum_check(tcx, local_decls,
&mut basic_blocks[block], source_info, new_block),
EnumCheckType::WithNiche {
source_op, discr, op_size, offset, valid_range } =>
insert_niche_check(tcx, local_decls,
&mut basic_blocks[block], source_op, valid_range, discr,
op_size, offset, source_info, new_block),
}
}
}
}
}
}
enum EnumCheckType<'tcx> {
Uninhabited,
Direct {
source_op: Operand<'tcx>,
discr: TyAndSize<'tcx>,
op_size: Size,
valid_discrs: Vec<u128>,
},
WithNiche {
source_op: Operand<'tcx>,
discr: TyAndSize<'tcx>,
op_size: Size,
offset: Size,
valid_range: WrappingRange,
},
}
struct TyAndSize<'tcx> {
pub ty: Ty<'tcx>,
pub size: Size,
}
#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for TyAndSize<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f, "TyAndSize",
"ty", &self.ty, "size", &&self.size)
}
}
#[automatically_derived]
impl<'tcx> ::core::marker::Copy for TyAndSize<'tcx> { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl<'tcx> ::core::clone::TrivialClone for TyAndSize<'tcx> { }
#[automatically_derived]
impl<'tcx> ::core::clone::Clone for TyAndSize<'tcx> {
#[inline]
fn clone(&self) -> TyAndSize<'tcx> {
let _: ::core::clone::AssertParamIsClone<Ty<'tcx>>;
let _: ::core::clone::AssertParamIsClone<Size>;
*self
}
}
struct EnumFinder<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
local_decls: &'a mut LocalDecls<'tcx>,
typing_env: TypingEnv<'tcx>,
enums: Vec<EnumCheckType<'tcx>>,
}
impl<'a, 'tcx> EnumFinder<'a, 'tcx> {
fn new(tcx: TyCtxt<'tcx>, local_decls: &'a mut LocalDecls<'tcx>,
typing_env: TypingEnv<'tcx>) -> Self {
EnumFinder { tcx, local_decls, typing_env, enums: Vec::new() }
}
fn into_found_enums(self) -> Vec<EnumCheckType<'tcx>> { self.enums }
}
impl<'a, 'tcx> Visitor<'tcx> for EnumFinder<'a, 'tcx> {
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>,
location: Location) {
if let Rvalue::Cast(CastKind::Transmute, op, ty) = rvalue {
let ty::Adt(adt_def, _) = ty.kind() else { return; };
if !adt_def.is_enum() { return; }
let Ok(enum_layout) =
self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else {
return;
};
let Ok(op_layout) =
self.tcx.layout_of(self.typing_env.as_query_input(op.ty(self.local_decls,
self.tcx))) else { return; };
match enum_layout.variants {
Variants::Empty if op_layout.is_uninhabited() => return,
Variants::Empty => {
self.enums.push(EnumCheckType::Uninhabited);
}
Variants::Single { .. } => {}
Variants::Multiple {
tag_encoding: TagEncoding::Direct,
tag: Scalar::Initialized { value, .. }, .. } => {
let valid_discrs =
adt_def.discriminants(self.tcx).map(|(_, discr)|
discr.val).collect();
let discr =
TyAndSize {
ty: value.to_int_ty(self.tcx),
size: value.size(&self.tcx),
};
self.enums.push(EnumCheckType::Direct {
source_op: op.to_copy(),
discr,
op_size: op_layout.size,
valid_discrs,
});
}
Variants::Multiple {
tag_encoding: TagEncoding::Niche { .. },
tag: Scalar::Initialized { value, valid_range, .. },
tag_field, .. } => {
let discr =
TyAndSize {
ty: value.to_int_ty(self.tcx),
size: value.size(&self.tcx),
};
self.enums.push(EnumCheckType::WithNiche {
source_op: op.to_copy(),
discr,
op_size: op_layout.size,
offset: enum_layout.fields.offset(tag_field.as_usize()),
valid_range,
});
}
_ => return,
}
self.super_rvalue(rvalue, location);
}
}
}
fn split_block(basic_blocks:
&mut IndexVec<BasicBlock, BasicBlockData<'_>>, location: Location)
-> BasicBlock {
let block_data = &mut basic_blocks[location.block];
let new_block =
BasicBlockData::new_stmts(block_data.statements.split_off(location.statement_index),
block_data.terminator.take(), block_data.is_cleanup);
basic_blocks.push(new_block)
}
fn insert_discr_cast_to_u128<'tcx>(tcx: TyCtxt<'tcx>,
local_decls: &mut IndexVec<Local, LocalDecl<'tcx>>,
block_data: &mut BasicBlockData<'tcx>, source_op: Operand<'tcx>,
discr: TyAndSize<'tcx>, op_size: Size, offset: Option<Size>,
source_info: SourceInfo) -> Place<'tcx> {
let get_ty_for_size =
|tcx: TyCtxt<'tcx>, size: Size| -> Ty<'tcx>
{
match size.bytes() {
1 => tcx.types.u8,
2 => tcx.types.u16,
4 => tcx.types.u32,
8 => tcx.types.u64,
16 => tcx.types.u128,
invalid =>
::rustc_middle::util::bug::bug_fmt(format_args!("Found discriminant with invalid size, has {0} bytes",
invalid)),
}
};
let (cast_kind, discr_ty_bits) =
if discr.size.bytes() < op_size.bytes() {
let mu = Ty::new_maybe_uninit(tcx, tcx.types.u8);
let array_len = op_size.bytes();
let mu_array_ty = Ty::new_array(tcx, mu, array_len);
let mu_array =
local_decls.push(LocalDecl::with_source_info(mu_array_ty,
source_info)).into();
let rvalue =
Rvalue::Cast(CastKind::Transmute, source_op, mu_array_ty);
block_data.statements.push(Statement::new(source_info,
StatementKind::Assign(Box::new((mu_array, rvalue)))));
let offset = offset.unwrap_or(Size::ZERO);
let smaller_mu_array =
mu_array.project_deeper(&[ProjectionElem::Subslice {
from: offset.bytes(),
to: offset.bytes() + discr.size.bytes(),
from_end: false,
}], tcx);
(CastKind::Transmute, Operand::Copy(smaller_mu_array))
} else {
let operand_int_ty = get_ty_for_size(tcx, op_size);
let op_as_int =
local_decls.push(LocalDecl::with_source_info(operand_int_ty,
source_info)).into();
let rvalue =
Rvalue::Cast(CastKind::Transmute, source_op,
operand_int_ty);
block_data.statements.push(Statement::new(source_info,
StatementKind::Assign(Box::new((op_as_int, rvalue)))));
(CastKind::IntToInt, Operand::Copy(op_as_int))
};
let rvalue = Rvalue::Cast(cast_kind, discr_ty_bits, discr.ty);
let discr_in_discr_ty =
local_decls.push(LocalDecl::with_source_info(discr.ty,
source_info)).into();
block_data.statements.push(Statement::new(source_info,
StatementKind::Assign(Box::new((discr_in_discr_ty,
rvalue)))));
let const_u128 = Ty::new_uint(tcx, ty::UintTy::U128);
let rvalue =
Rvalue::Cast(CastKind::IntToInt, Operand::Copy(discr_in_discr_ty),
const_u128);
let discr =
local_decls.push(LocalDecl::with_source_info(const_u128,
source_info)).into();
block_data.statements.push(Statement::new(source_info,
StatementKind::Assign(Box::new((discr, rvalue)))));
discr
}
fn insert_direct_enum_check<'tcx>(tcx: TyCtxt<'tcx>,
local_decls: &mut IndexVec<Local, LocalDecl<'tcx>>,
basic_blocks: &mut IndexVec<BasicBlock, BasicBlockData<'tcx>>,
current_block: BasicBlock, source_op: Operand<'tcx>,
discr: TyAndSize<'tcx>, op_size: Size, discriminants: Vec<u128>,
source_info: SourceInfo, new_block: BasicBlock) {
let invalid_discr_block_data = BasicBlockData::new(None, false);
let invalid_discr_block = basic_blocks.push(invalid_discr_block_data);
let block_data = &mut basic_blocks[current_block];
let discr_place =
insert_discr_cast_to_u128(tcx, local_decls, block_data, source_op,
discr, op_size, None, source_info);
let mask = discr.size.unsigned_int_max();
let discr_masked =
local_decls.push(LocalDecl::with_source_info(tcx.types.u128,
source_info)).into();
let rvalue =
Rvalue::BinaryOp(BinOp::BitAnd,
Box::new((Operand::Copy(discr_place),
Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
user_ty: None,
const_: Const::Val(ConstValue::from_u128(mask),
tcx.types.u128),
})))));
block_data.statements.push(Statement::new(source_info,
StatementKind::Assign(Box::new((discr_masked, rvalue)))));
block_data.terminator =
Some(Terminator {
source_info,
kind: TerminatorKind::SwitchInt {
discr: Operand::Copy(discr_masked),
targets: SwitchTargets::new(discriminants.into_iter().map(|discr_val|
(discr.size.truncate(discr_val), new_block)),
invalid_discr_block),
},
attributes: ThinVec::new(),
});
basic_blocks[invalid_discr_block].terminator =
Some(Terminator {
source_info,
kind: TerminatorKind::Assert {
cond: Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
user_ty: None,
const_: Const::Val(ConstValue::from_bool(false),
tcx.types.bool),
})),
expected: true,
target: new_block,
msg: Box::new(AssertKind::InvalidEnumConstruction(Operand::Copy(discr_masked))),
unwind: UnwindAction::Unreachable,
},
attributes: ThinVec::new(),
});
}
fn insert_uninhabited_enum_check<'tcx>(tcx: TyCtxt<'tcx>,
local_decls: &mut IndexVec<Local, LocalDecl<'tcx>>,
block_data: &mut BasicBlockData<'tcx>, source_info: SourceInfo,
new_block: BasicBlock) {
let is_ok: Place<'_> =
local_decls.push(LocalDecl::with_source_info(tcx.types.bool,
source_info)).into();
block_data.statements.push(Statement::new(source_info,
StatementKind::Assign(Box::new((is_ok,
Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
user_ty: None,
const_: Const::Val(ConstValue::from_bool(false),
tcx.types.bool),
})), WithRetag::Yes))))));
block_data.terminator =
Some(Terminator {
source_info,
kind: TerminatorKind::Assert {
cond: Operand::Copy(is_ok),
expected: true,
target: new_block,
msg: Box::new(AssertKind::InvalidEnumConstruction(Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
user_ty: None,
const_: Const::Val(ConstValue::from_u128(0), tcx.types.u128),
})))),
unwind: UnwindAction::Unreachable,
},
attributes: ThinVec::new(),
});
}
fn insert_niche_check<'tcx>(tcx: TyCtxt<'tcx>,
local_decls: &mut IndexVec<Local, LocalDecl<'tcx>>,
block_data: &mut BasicBlockData<'tcx>, source_op: Operand<'tcx>,
valid_range: WrappingRange, discr: TyAndSize<'tcx>, op_size: Size,
offset: Size, source_info: SourceInfo, new_block: BasicBlock) {
let discr =
insert_discr_cast_to_u128(tcx, local_decls, block_data, source_op,
discr, op_size, Some(offset), source_info);
let start_const =
Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
user_ty: None,
const_: Const::Val(ConstValue::from_u128(valid_range.start),
tcx.types.u128),
}));
let end_start_diff_const =
Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
user_ty: None,
const_: Const::Val(ConstValue::from_u128(u128::wrapping_sub(valid_range.end,
valid_range.start)), tcx.types.u128),
}));
let discr_diff: Place<'_> =
local_decls.push(LocalDecl::with_source_info(tcx.types.u128,
source_info)).into();
block_data.statements.push(Statement::new(source_info,
StatementKind::Assign(Box::new((discr_diff,
Rvalue::BinaryOp(BinOp::Sub,
Box::new((Operand::Copy(discr), start_const))))))));
let is_ok: Place<'_> =
local_decls.push(LocalDecl::with_source_info(tcx.types.bool,
source_info)).into();
block_data.statements.push(Statement::new(source_info,
StatementKind::Assign(Box::new((is_ok,
Rvalue::BinaryOp(BinOp::Le,
Box::new((Operand::Copy(discr_diff),
end_start_diff_const))))))));
block_data.terminator =
Some(Terminator {
source_info,
kind: TerminatorKind::Assert {
cond: Operand::Copy(is_ok),
expected: true,
target: new_block,
msg: Box::new(AssertKind::InvalidEnumConstruction(Operand::Copy(discr))),
unwind: UnwindAction::Unreachable,
},
attributes: ThinVec::new(),
});
}
}
#[allow(unused_imports)]
use check_enums::CheckEnums as _;
mod check_const_item_mutation {
use rustc_hir::HirId;
use rustc_lint_defs::builtin::CONST_ITEM_MUTATION;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use rustc_span::Span;
use rustc_span::def_id::DefId;
use crate::diagnostics;
pub(super) struct CheckConstItemMutation;
impl<'tcx> crate::MirLint<'tcx> for CheckConstItemMutation {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
let mut checker =
ConstMutationChecker { body, tcx, target_local: None };
checker.visit_body(body);
}
}
struct ConstMutationChecker<'a, 'tcx> {
body: &'a Body<'tcx>,
tcx: TyCtxt<'tcx>,
target_local: Option<Local>,
}
impl<'tcx> ConstMutationChecker<'_, 'tcx> {
fn is_const_item(&self, local: Local) -> Option<DefId> {
if let LocalInfo::ConstRef { def_id } =
*self.body.local_decls[local].local_info() {
Some(def_id)
} else { None }
}
fn is_const_item_without_destructor(&self, local: Local)
-> Option<DefId> {
let def_id = self.is_const_item(local)?;
match self.tcx.type_of(def_id).skip_binder().ty_adt_def().map(|adt|
adt.has_dtor(self.tcx)) {
Some(true) => None,
Some(false) | None => Some(def_id),
}
}
fn should_lint_const_item_usage(&self, place: &Place<'tcx>,
const_item: DefId, location: Location)
-> Option<(HirId, Span, Span)> {
if !place.projection.iter().any(|p|
#[allow(non_exhaustive_omitted_patterns)] match p {
PlaceElem::Deref => true,
_ => false,
}) {
let source_info = self.body.source_info(location);
let lint_root =
self.body.source_scopes[source_info.scope].local_data.as_ref().unwrap_crate_local().lint_root;
Some((lint_root, source_info.span,
self.tcx.def_span(const_item)))
} else { None }
}
}
impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> {
fn visit_statement(&mut self, stmt: &Statement<'tcx>, loc: Location) {
if let StatementKind::Assign((lhs, _)) = &stmt.kind {
if !lhs.projection.is_empty() &&
let Some(def_id) =
self.is_const_item_without_destructor(lhs.local) &&
let Some((lint_root, span, item)) =
self.should_lint_const_item_usage(lhs, def_id, loc) {
self.tcx.emit_node_span_lint(CONST_ITEM_MUTATION, lint_root,
span, diagnostics::ConstMutate::Modify { konst: item });
}
self.target_local = lhs.as_local();
}
self.super_statement(stmt, loc);
self.target_local = None;
}
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>, loc: Location) {
if let Rvalue::Ref(_, BorrowKind::Mut { .. }, place) = rvalue {
let local = place.local;
if let Some(def_id) = self.is_const_item(local) {
let method_did =
self.target_local.and_then(|target_local|
{
find_self_call(self.tcx, self.body, target_local, loc.block)
});
let lint_loc =
if method_did.is_some() {
self.body.terminator_loc(loc.block)
} else { loc };
let method_call =
if let Some((method_did, _)) = method_did {
Some(self.tcx.def_span(method_did))
} else { None };
if let Some((lint_root, span, item)) =
self.should_lint_const_item_usage(place, def_id, lint_loc) {
self.tcx.emit_node_span_lint(CONST_ITEM_MUTATION, lint_root,
span,
diagnostics::ConstMutate::MutBorrow {
method_call,
konst: item,
});
}
}
}
self.super_rvalue(rvalue, loc);
}
}
}
#[allow(unused_imports)]
use check_const_item_mutation::CheckConstItemMutation as _;
mod check_null {
use rustc_hir::attrs::lang_items::LangItem;
use rustc_index::IndexVec;
use rustc_middle::mir::visit::{
MutatingUseContext, NonMutatingUseContext, PlaceContext,
};
use rustc_middle::mir::*;
use rustc_middle::ty::{Ty, TyCtxt};
use crate::PassPolicy;
use crate::check_pointers::{
BorrowedFieldProjectionMode, PointerCheck, check_pointers,
};
pub(super) struct CheckNull;
impl<'tcx> crate::MirPass<'tcx> for CheckNull {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.ub_checks())
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
check_pointers(tcx, body, &[], insert_null_check,
BorrowedFieldProjectionMode::NoFollowProjections);
}
}
fn insert_null_check<'tcx>(tcx: TyCtxt<'tcx>, pointer: Place<'tcx>,
pointee_ty: Ty<'tcx>, context: PlaceContext,
local_decls: &mut IndexVec<Local, LocalDecl<'tcx>>,
stmts: &mut Vec<Statement<'tcx>>, source_info: SourceInfo)
-> PointerCheck<'tcx> {
let const_raw_ptr = Ty::new_imm_ptr(tcx, tcx.types.unit);
let rvalue =
Rvalue::Cast(CastKind::PtrToPtr, Operand::Copy(pointer),
const_raw_ptr);
let thin_ptr =
local_decls.push(LocalDecl::with_source_info(const_raw_ptr,
source_info)).into();
stmts.push(Statement::new(source_info,
StatementKind::Assign(Box::new((thin_ptr, rvalue)))));
let rvalue =
Rvalue::Cast(CastKind::Transmute, Operand::Copy(thin_ptr),
tcx.types.usize);
let addr =
local_decls.push(LocalDecl::with_source_info(tcx.types.usize,
source_info)).into();
stmts.push(Statement::new(source_info,
StatementKind::Assign(Box::new((addr, rvalue)))));
let zero =
Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
user_ty: None,
const_: Const::Val(ConstValue::from_target_usize(0, &tcx),
tcx.types.usize),
}));
let (pointee_should_be_checked, assert_kind) =
match context {
PlaceContext::NonMutatingUse(NonMutatingUseContext::SharedBorrow)
| PlaceContext::MutatingUse(MutatingUseContext::Borrow) => {
(Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
user_ty: None,
const_: Const::from_bool(tcx, true),
})), AssertKind::NullReferenceConstructed)
}
_ => {
let size_of =
tcx.require_lang_item(LangItem::SizeOf, source_info.span);
let size_of =
Operand::unevaluated_constant(tcx, size_of,
&[pointee_ty.into()], source_info.span);
let pointee_should_be_checked =
local_decls.push(LocalDecl::with_source_info(tcx.types.bool,
source_info)).into();
let rvalue =
Rvalue::BinaryOp(BinOp::Ne,
Box::new((size_of, zero.clone())));
stmts.push(Statement::new(source_info,
StatementKind::Assign(Box::new((pointee_should_be_checked,
rvalue)))));
(Operand::Copy(pointee_should_be_checked),
AssertKind::NullPointerDereference)
}
};
let is_null =
local_decls.push(LocalDecl::with_source_info(tcx.types.bool,
source_info)).into();
stmts.push(Statement::new(source_info,
StatementKind::Assign(Box::new((is_null,
Rvalue::BinaryOp(BinOp::Eq,
Box::new((Operand::Copy(addr), zero))))))));
let should_throw_exception =
local_decls.push(LocalDecl::with_source_info(tcx.types.bool,
source_info)).into();
stmts.push(Statement::new(source_info,
StatementKind::Assign(Box::new((should_throw_exception,
Rvalue::BinaryOp(BinOp::BitAnd,
Box::new((Operand::Copy(is_null),
pointee_should_be_checked))))))));
let is_ok =
local_decls.push(LocalDecl::with_source_info(tcx.types.bool,
source_info)).into();
stmts.push(Statement::new(source_info,
StatementKind::Assign(Box::new((is_ok,
Rvalue::UnaryOp(UnOp::Not,
Operand::Copy(should_throw_exception)))))));
PointerCheck {
cond: Operand::Copy(is_ok),
assert_kind: Box::new(assert_kind),
}
}
}
#[allow(unused_imports)]
use check_null::CheckNull as _;
mod check_packed_ref {
use rustc_middle::mir::visit::{PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::span_bug;
use rustc_middle::ty::{self, TyCtxt};
use crate::{diagnostics, util};
pub(super) struct CheckPackedRef;
impl<'tcx> crate::MirLint<'tcx> for CheckPackedRef {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
let typing_env = body.typing_env(tcx);
let source_info = SourceInfo::outermost(body.span);
let mut checker =
PackedRefChecker { body, tcx, typing_env, source_info };
checker.visit_body(body);
}
}
struct PackedRefChecker<'a, 'tcx> {
body: &'a Body<'tcx>,
tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
source_info: SourceInfo,
}
impl<'tcx> Visitor<'tcx> for PackedRefChecker<'_, 'tcx> {
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>,
location: Location) {
self.source_info = terminator.source_info;
self.super_terminator(terminator, location);
}
fn visit_statement(&mut self, statement: &Statement<'tcx>,
location: Location) {
self.source_info = statement.source_info;
self.super_statement(statement, location);
}
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext,
_location: Location) {
if context.is_borrow() &&
let Some((adt, pack)) =
util::place_unalignment(self.tcx, self.body,
self.typing_env, *place) {
let def_id = self.body.source.instance.def_id();
if let Some(impl_def_id) =
self.tcx.trait_impl_of_assoc(def_id) &&
self.tcx.is_builtin_derived(impl_def_id) {
::rustc_middle::util::bug::span_bug_fmt(self.source_info.span,
format_args!("builtin derive created an unaligned reference"));
} else {
self.tcx.dcx().emit_err(diagnostics::UnalignedPackedRef {
span: self.source_info.span,
ty_descr: adt.descr(),
align: pack.bytes(),
});
}
}
}
}
}
#[allow(unused_imports)]
use check_packed_ref::CheckPackedRef as _;
mod check_mut_restriction {
use rustc_hir::def::{CtorOf, DefKind};
use rustc_middle::mir::visit::{PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::Span;
use crate::diagnostics;
pub(super) struct CheckMutRestriction;
impl<'tcx> crate::MirLint<'tcx> for CheckMutRestriction {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
if body.tainted_by_errors.is_some() { return; }
let mut checker =
MutRestrictionChecker { body, tcx, mutating_span: body.span };
checker.visit_body(body);
}
}
struct MutRestrictionChecker<'a, 'tcx> {
body: &'a Body<'tcx>,
tcx: TyCtxt<'tcx>,
mutating_span: Span,
}
impl<'tcx> Visitor<'tcx> for MutRestrictionChecker<'_, 'tcx> {
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>,
location: Location) {
self.mutating_span = terminator.source_info.span;
self.super_terminator(terminator, location);
}
fn visit_statement(&mut self, statement: &Statement<'tcx>,
location: Location) {
self.mutating_span = statement.source_info.span;
self.super_statement(statement, location);
}
fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>,
location: Location) {
if let ty::FnDef(def_id, _) = *constant.const_.ty().kind() &&
let DefKind::Ctor(ctor_of, _) = self.tcx.def_kind(def_id) {
let body_did = self.body.source.instance.def_id();
let adt_did =
match ctor_of {
CtorOf::Struct => self.tcx.parent(def_id),
CtorOf::Variant => self.tcx.parent(self.tcx.parent(def_id)),
};
let adt = self.tcx.adt_def(adt_did);
let variant =
match ctor_of {
CtorOf::Struct => adt.non_enum_variant(),
CtorOf::Variant => adt.variant_with_ctor_id(def_id),
};
let mut_restriction =
variant.fields.iter().fold(ty::RestrictionKind::Unrestricted,
|acc, field|
{ acc.stricter_of(field.mut_restriction, self.tcx) });
if !mut_restriction.is_allowed_in(body_did, self.tcx) {
self.tcx.dcx().emit_err(diagnostics::ConstructionOfTyWithMutRestrictedField {
construction_span: constant.span,
restriction_span: mut_restriction.expect_span(),
name: variant.name,
descr: adt.variant_descr(),
restriction_path: mut_restriction.restriction_path(self.tcx),
});
}
}
self.super_const_operand(constant, location);
}
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext,
location: Location) {
if context.is_mutating_use() {
let body_did = self.body.source.instance.def_id();
for (place_base, elem) in place.iter_projections() {
let ProjectionElem::Field(field_idx, _field_ty) =
elem else { continue; };
let base_ty = place_base.ty(self.body, self.tcx);
let ty::Adt(adt_def, _args) =
*base_ty.ty.kind() else { continue; };
let variant_def =
if let Some(idx) = base_ty.variant_index {
if !adt_def.is_enum() {
::core::panicking::panic("assertion failed: adt_def.is_enum()")
};
adt_def.variant(idx)
} else { adt_def.non_enum_variant() };
let field_def: &ty::FieldDef =
&variant_def.fields[field_idx];
let mut_restriction = field_def.mut_restriction;
if !mut_restriction.is_allowed_in(body_did, self.tcx) {
self.tcx.dcx().emit_err(diagnostics::MutOfRestrictedField {
mut_span: self.mutating_span,
restriction_span: mut_restriction.expect_span(),
name: field_def.name,
restriction_path: mut_restriction.restriction_path(self.tcx),
});
}
}
}
self.super_place(place, context, location);
}
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>,
location: Location) {
if let Rvalue::Aggregate(aggr, _) = rvalue &&
let AggregateKind::Adt(adt_did, variant_idx, _args,
_user_ty, active_field) = &**aggr {
let body_did = self.body.source.instance.def_id();
let adt = self.tcx.adt_def(*adt_did);
let variant = &adt.variants()[*variant_idx];
if let Some(field_idx) = active_field {
let field_def = &variant.fields[*field_idx];
let mut_restriction = field_def.mut_restriction;
if !mut_restriction.is_allowed_in(body_did, self.tcx) {
self.tcx.dcx().emit_err(diagnostics::ConstructionOfTyWithMutRestrictedField {
construction_span: self.mutating_span,
restriction_span: mut_restriction.expect_span(),
name: variant.name,
descr: adt.variant_descr(),
restriction_path: mut_restriction.restriction_path(self.tcx),
});
}
} else {
let mut_restriction =
variant.fields.iter().fold(ty::RestrictionKind::Unrestricted,
|acc, field|
{ acc.stricter_of(field.mut_restriction, self.tcx) });
if !mut_restriction.is_allowed_in(body_did, self.tcx) {
self.tcx.dcx().emit_err(diagnostics::ConstructionOfTyWithMutRestrictedField {
construction_span: self.mutating_span,
restriction_span: mut_restriction.expect_span(),
name: variant.name,
descr: adt.variant_descr(),
restriction_path: mut_restriction.restriction_path(self.tcx),
});
}
}
}
self.super_rvalue(rvalue, location);
}
}
}
#[allow(unused_imports)]
use check_mut_restriction::CheckMutRestriction as _;
pub mod cleanup_post_borrowck {
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use rustc_middle::ty::adjustment::PointerCoercion;
use crate::PassPolicy;
pub(super) struct CleanupPostBorrowck;
impl<'tcx> crate::MirPass<'tcx> for CleanupPostBorrowck {
fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let mut invalidate_cfg = false;
for basic_block in
body.basic_blocks.as_mut_preserves_cfg().iter_mut() {
for statement in basic_block.statements.iter_mut() {
match statement.kind {
StatementKind::AscribeUserType(..) |
StatementKind::Assign((_,
Rvalue::Ref(_, BorrowKind::Fake(_), _))) |
StatementKind::FakeRead(..) |
StatementKind::BackwardIncompatibleDropHint { .. } => {
statement.make_nop(true)
}
StatementKind::Coverage(ref kind) if
kind.is_removed_after_analysis() => {
statement.make_nop(true)
}
StatementKind::Assign((_,
Rvalue::Cast(ref mut cast_kind @
CastKind::PointerCoercion(PointerCoercion::ArrayToPointer |
PointerCoercion::MutToConstPointer, _), ..))) => {
*cast_kind = CastKind::PtrToPtr;
}
_ => (),
}
}
let terminator = basic_block.terminator_mut();
match terminator.kind {
TerminatorKind::FalseEdge { real_target, .. } |
TerminatorKind::FalseUnwind { real_target, .. } => {
invalidate_cfg = true;
terminator.kind =
TerminatorKind::Goto { target: real_target };
}
_ => {}
}
}
if invalidate_cfg { body.basic_blocks.invalidate_cfg_cache(); }
body.user_type_annotations.raw.clear();
for decl in &mut body.local_decls { decl.user_ty = None; }
}
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::Required
}
}
}
#[allow(unused_imports)]
use cleanup_post_borrowck::CleanupPostBorrowck as _;
mod copy_prop {
use rustc_index::IndexSlice;
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use rustc_mir_dataflow::{Analysis, ResultsCursor};
use tracing::{debug, instrument};
use crate::PassPolicy;
use crate::ssa::{MaybeUninitializedLocals, SsaLocals};
pub(super) struct CopyProp;
impl<'tcx> crate::MirPass<'tcx> for CopyProp {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 1)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("run_pass",
"rustc_mir_transform::copy_prop", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/copy_prop.rs"),
::tracing_core::__macro_support::Option::Some(29u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::copy_prop"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/copy_prop.rs:31",
"rustc_mir_transform::copy_prop", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/copy_prop.rs"),
::tracing_core::__macro_support::Option::Some(31u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::copy_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&body.source.def_id())
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let typing_env = body.typing_env(tcx);
let ssa = SsaLocals::new(tcx, body, typing_env);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/copy_prop.rs:36",
"rustc_mir_transform::copy_prop", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/copy_prop.rs"),
::tracing_core::__macro_support::Option::Some(36u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::copy_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("borrowed_locals")
}> =
::tracing::__macro_support::FieldName::new("borrowed_locals");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ssa.borrowed_locals())
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/copy_prop.rs:37",
"rustc_mir_transform::copy_prop", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/copy_prop.rs"),
::tracing_core::__macro_support::Option::Some(37u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::copy_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("copy_classes")
}> =
::tracing::__macro_support::FieldName::new("copy_classes");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ssa.copy_classes())
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let mut any_replacement = false;
let mut unified =
DenseBitSet::new_empty(body.local_decls.len());
for (local, &head) in ssa.copy_classes().iter_enumerated() {
if local != head {
any_replacement = true;
unified.insert(head);
unified.insert(local);
}
}
if !any_replacement { return; }
let storage_to_remove =
if tcx.sess.emit_lifetime_markers() {
let mut storage_to_remove =
DenseBitSet::new_empty(body.local_decls.len());
let borrowed_locals = ssa.borrowed_locals();
for (local, &head) in ssa.copy_classes().iter_enumerated() {
if local != head && borrowed_locals.contains(local) {
storage_to_remove.insert(head);
}
}
let maybe_uninit =
MaybeUninitializedLocals.iterate_to_fixpoint(tcx, body,
Some("mir_opt::copy_prop")).into_results_cursor(body);
let mut storage_checker =
StorageChecker {
maybe_uninit,
copy_classes: ssa.copy_classes(),
storage_to_remove,
};
for (bb, data) in traversal::reachable(body) {
storage_checker.visit_basic_block_data(bb, data);
}
Some(storage_checker.storage_to_remove)
} else { None };
let storage_to_remove =
storage_to_remove.as_ref().unwrap_or(&unified);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/copy_prop.rs:92",
"rustc_mir_transform::copy_prop", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/copy_prop.rs"),
::tracing_core::__macro_support::Option::Some(92u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::copy_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("storage_to_remove")
}> =
::tracing::__macro_support::FieldName::new("storage_to_remove");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&storage_to_remove)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
Replacer {
tcx,
copy_classes: ssa.copy_classes(),
unified: &unified,
storage_to_remove,
}.visit_body_preserves_cfg(body);
crate::simplify::remove_unused_definitions(body);
}
}
}
}
}
struct Replacer<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
unified: &'a DenseBitSet<Local>,
storage_to_remove: &'a DenseBitSet<Local>,
copy_classes: &'a IndexSlice<Local, Local>,
}
impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_local(&mut self, local: &mut Local, ctxt: PlaceContext,
_: Location) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("visit_local",
"rustc_mir_transform::copy_prop", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/copy_prop.rs"),
::tracing_core::__macro_support::Option::Some(115u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::copy_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("local")
}> =
::tracing::__macro_support::FieldName::new("local");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("ctxt")
}> =
::tracing::__macro_support::FieldName::new("ctxt");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&local)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ctxt)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let new_local = self.copy_classes[*local];
match ctxt {
PlaceContext::NonUse(NonUseContext::StorageLive |
NonUseContext::StorageDead) => {}
_ => *local = new_local,
}
}
}
}
}
fn visit_operand(&mut self, operand: &mut Operand<'tcx>,
loc: Location) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("visit_operand",
"rustc_mir_transform::copy_prop", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/copy_prop.rs"),
::tracing_core::__macro_support::Option::Some(126u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::copy_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("operand")
}> =
::tracing::__macro_support::FieldName::new("operand");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("loc")
}> =
::tracing::__macro_support::FieldName::new("loc");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&operand)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&loc)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
if let Operand::Move(place) = *operand &&
!place.is_indirect_first_projection() &&
self.unified.contains(place.local) {
*operand = Operand::Copy(place);
}
self.super_operand(operand, loc);
}
}
}
}
fn visit_statement(&mut self, stmt: &mut Statement<'tcx>,
loc: Location) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("visit_statement",
"rustc_mir_transform::copy_prop", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/copy_prop.rs"),
::tracing_core::__macro_support::Option::Some(139u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::copy_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("stmt")
}> =
::tracing::__macro_support::FieldName::new("stmt");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("loc")
}> =
::tracing::__macro_support::FieldName::new("loc");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&stmt)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&loc)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
if let StatementKind::StorageLive(l) |
StatementKind::StorageDead(l) = stmt.kind &&
self.storage_to_remove.contains(l) {
stmt.make_nop(true);
}
self.super_statement(stmt, loc);
if let StatementKind::Assign((lhs, ref rhs)) = stmt.kind &&
let Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs), _)
= *rhs && lhs == rhs {
stmt.make_nop(true);
}
}
}
}
}
}
struct StorageChecker<'a, 'tcx> {
maybe_uninit: ResultsCursor<'a, 'tcx, MaybeUninitializedLocals>,
copy_classes: &'a IndexSlice<Local, Local>,
storage_to_remove: DenseBitSet<Local>,
}
impl<'a, 'tcx> Visitor<'tcx> for StorageChecker<'a, 'tcx> {
fn visit_local(&mut self, local: Local, context: PlaceContext,
loc: Location) {
if !context.is_use() { return; }
let head = self.copy_classes[local];
if head == local || self.storage_to_remove.contains(head) {
return;
}
self.maybe_uninit.seek_before_primary_effect(loc);
if self.maybe_uninit.get().contains(head) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/copy_prop.rs:184",
"rustc_mir_transform::copy_prop", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/copy_prop.rs"),
::tracing_core::__macro_support::Option::Some(184u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::copy_prop"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("loc")
}> =
::tracing::__macro_support::FieldName::new("loc");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("context")
}> =
::tracing::__macro_support::FieldName::new("context");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("local")
}> =
::tracing::__macro_support::FieldName::new("local");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("head")
}> =
::tracing::__macro_support::FieldName::new("head");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("local\'s head is maybe uninit at this location, marking head for storage statement removal")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&loc)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&context)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&local)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&head)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
self.storage_to_remove.insert(head);
}
}
}
}
#[allow(unused_imports)]
use copy_prop::CopyProp as _;
mod coroutine {
mod by_move_body {
use rustc_abi::{FieldIdx, VariantIdx};
use rustc_data_structures::steal::Steal;
use rustc_data_structures::unord::UnordMap;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_hir::definitions::PerParentDisambiguatorState;
use rustc_middle::bug;
use rustc_middle::hir::place::{Projection, ProjectionKind};
use rustc_middle::mir::visit::MutVisitor;
use rustc_middle::mir::{self, MirDumper};
use rustc_middle::ty::{
self, InstanceKind, Ty, TyCtxt, TypeVisitableExt,
};
pub(crate) fn coroutine_by_move_body_def_id<'tcx>(tcx: TyCtxt<'tcx>,
coroutine_def_id: LocalDefId) -> DefId {
let body = tcx.mir_built(coroutine_def_id).borrow();
if body.tainted_by_errors.is_some() {
return coroutine_def_id.to_def_id();
}
let Some(hir::CoroutineKind::Desugared(_,
hir::CoroutineSource::Closure)) =
tcx.coroutine_kind(coroutine_def_id) else {
::rustc_middle::util::bug::bug_fmt(format_args!("should only be invoked on coroutine-closures"));
};
let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty;
let ty::Coroutine(_, args) =
*coroutine_ty.kind() else {
::rustc_middle::util::bug::bug_fmt(format_args!("tried to create by-move body of non-coroutine receiver"));
};
let args = args.as_coroutine();
let coroutine_kind =
args.kind_ty().to_opt_closure_kind().unwrap();
let parent_def_id = tcx.local_parent(coroutine_def_id);
let ty::CoroutineClosure(_, parent_args) =
*tcx.type_of(parent_def_id).instantiate_identity().skip_norm_wip().kind() else {
::rustc_middle::util::bug::bug_fmt(format_args!("coroutine\'s parent was not a coroutine-closure"));
};
if parent_args.references_error() {
return coroutine_def_id.to_def_id();
}
let parent_closure_args = parent_args.as_coroutine_closure();
let num_args =
parent_closure_args.coroutine_closure_sig().skip_binder().tupled_inputs_ty.tuple_fields().len();
let field_remapping: UnordMap<_, _> =
ty::analyze_coroutine_closure_captures(tcx.closure_captures(parent_def_id).iter().copied(),
tcx.closure_captures(coroutine_def_id).iter().skip(num_args).copied(),
|(parent_field_idx, parent_capture),
(child_field_idx, child_capture)|
{
let mut child_precise_captures =
child_capture.place.projections[parent_capture.place.projections.len()..].to_vec();
if parent_capture.is_by_ref() {
child_precise_captures.insert(0,
Projection {
ty: parent_capture.place.ty(),
kind: ProjectionKind::Deref,
});
}
let peel_deref =
if child_capture.is_by_ref() {
if !(parent_capture.is_by_ref() ||
coroutine_kind != ty::ClosureKind::FnOnce) {
{
::core::panicking::panic_fmt(format_args!("`FnOnce` coroutine-closures return coroutines that capture from their body; it will always result in a borrowck error!"));
}
};
true
} else { false };
let mut parent_capture_ty = parent_capture.place.ty();
parent_capture_ty =
match parent_capture.info.capture_kind {
ty::UpvarCapture::ByValue | ty::UpvarCapture::ByUse =>
parent_capture_ty,
ty::UpvarCapture::ByRef(kind) =>
Ty::new_ref(tcx, tcx.lifetimes.re_erased, parent_capture_ty,
kind.to_mutbl_lossy()),
};
Some((FieldIdx::from_usize(child_field_idx + num_args),
(FieldIdx::from_usize(parent_field_idx + num_args),
parent_capture_ty, peel_deref, child_precise_captures)))
}).flatten().collect();
if coroutine_kind == ty::ClosureKind::FnOnce {
{
match (&field_remapping.len(),
&tcx.closure_captures(parent_def_id).len()) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
return coroutine_def_id.to_def_id();
}
let by_move_coroutine_ty =
tcx.instantiate_bound_regions_with_erased(parent_closure_args.coroutine_closure_sig()).to_coroutine_given_kind_and_upvars(tcx,
parent_closure_args.parent_args(),
coroutine_def_id.to_def_id(), ty::ClosureKind::FnOnce,
tcx.lifetimes.re_erased,
parent_closure_args.tupled_upvars_ty(),
parent_closure_args.coroutine_captures_by_ref_ty());
let mut by_move_body = body.clone();
MakeByMoveBody {
tcx,
field_remapping,
by_move_coroutine_ty,
}.visit_body(&mut by_move_body);
let body_def =
tcx.create_def(parent_def_id, None,
DefKind::SyntheticCoroutineBody, None,
&mut PerParentDisambiguatorState::new(parent_def_id));
by_move_body.source =
mir::MirSource {
instance: InstanceKind::Item(body_def.def_id().to_def_id()),
promoted: None,
};
if let Some(dumper) = MirDumper::new(tcx, "built", &by_move_body)
{
dumper.set_disambiguator(&"after").dump_mir(&by_move_body);
}
body_def.feed_hir();
body_def.codegen_fn_attrs(tcx.codegen_fn_attrs(coroutine_def_id).clone());
body_def.coverage_attr_on(tcx.coverage_attr_on(coroutine_def_id));
body_def.constness(tcx.constness(coroutine_def_id));
body_def.coroutine_kind(tcx.coroutine_kind(coroutine_def_id));
body_def.def_ident_span(tcx.def_ident_span(coroutine_def_id));
body_def.def_span(tcx.def_span(coroutine_def_id));
body_def.explicit_clauses_of(tcx.explicit_clauses_of(coroutine_def_id));
body_def.generics_of(tcx.generics_of(coroutine_def_id).clone());
body_def.param_env(tcx.param_env(coroutine_def_id));
body_def.explicit_clauses_of(tcx.explicit_clauses_of(coroutine_def_id));
body_def.type_of(ty::EarlyBinder::bind(tcx,
by_move_coroutine_ty));
body_def.mir_built(tcx.arena.alloc(Steal::new(by_move_body)));
body_def.def_id().to_def_id()
}
struct MakeByMoveBody<'tcx> {
tcx: TyCtxt<'tcx>,
field_remapping: UnordMap<FieldIdx,
(FieldIdx, Ty<'tcx>, bool, Vec<Projection<'tcx>>)>,
by_move_coroutine_ty: Ty<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for MakeByMoveBody<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_place(&mut self, place: &mut mir::Place<'tcx>,
context: mir::visit::PlaceContext, location: mir::Location) {
if place.local == ty::CAPTURE_STRUCT_LOCAL &&
let Some((&mir::ProjectionElem::Field(idx, _), projection))
= place.projection.split_first() &&
let Some(&(remapped_idx, remapped_ty, peel_deref,
ref bridging_projections)) = self.field_remapping.get(&idx)
{
let final_projections =
if peel_deref {
let Some((mir::ProjectionElem::Deref, projection)) =
projection.split_first() else {
::rustc_middle::util::bug::bug_fmt(format_args!("There should be at least a single deref for an upvar local initialization, found {0:#?}",
projection));
};
projection
} else { projection };
let bridging_projections =
bridging_projections.iter().map(|elem|
match elem.kind {
ProjectionKind::Deref => mir::ProjectionElem::Deref,
ProjectionKind::Field(idx, VariantIdx::ZERO) => {
mir::ProjectionElem::Field(idx, elem.ty)
}
_ => {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("precise captures only through fields and derefs")));
}
});
*place =
mir::Place {
local: place.local,
projection: self.tcx.mk_place_elems_from_iter([mir::ProjectionElem::Field(remapped_idx,
remapped_ty)].into_iter().chain(bridging_projections).chain(final_projections.iter().copied())),
};
}
self.super_place(place, context, location);
}
fn visit_statement(&mut self,
statement: &mut mir::Statement<'tcx>,
location: mir::Location) {
if let mir::StatementKind::Assign((_, rvalue)) =
&statement.kind &&
let mir::Rvalue::Ref(_,
mir::BorrowKind::Fake(mir::FakeBorrowKind::Shallow), place)
= rvalue &&
let mir::PlaceRef {
local: ty::CAPTURE_STRUCT_LOCAL,
projection: [mir::ProjectionElem::Field(idx, _)] } =
place.as_ref() &&
let Some(&(_, _, true, _)) = self.field_remapping.get(&idx)
{
statement.kind = mir::StatementKind::Nop;
}
self.super_statement(statement, location);
}
fn visit_local_decl(&mut self, local: mir::Local,
local_decl: &mut mir::LocalDecl<'tcx>) {
if local == ty::CAPTURE_STRUCT_LOCAL {
local_decl.ty = self.by_move_coroutine_ty;
}
self.super_local_decl(local, local_decl);
}
}
}
mod drop {
use super::*;
struct FixReturnPendingVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for FixReturnPendingVisitor<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_assign(&mut self, place: &mut Place<'tcx>,
rvalue: &mut Rvalue<'tcx>, _location: Location) {
if place.local != RETURN_PLACE { return; }
if let Rvalue::Aggregate(kind, _) = rvalue &&
let AggregateKind::Adt(_, _, ref mut args, _, _) = **kind {
*args = self.tcx.mk_args(&[self.tcx.types.unit.into()]);
} else if let Rvalue::Use(Operand::Constant(constant), _) =
rvalue {
if let Some(async_gen_pending_def_id) =
self.tcx.lang_items().async_gen_pending() &&
let Const::Unevaluated(unevaluated, _) = constant.const_ &&
unevaluated.def == async_gen_pending_def_id {
let poll_def_id = self.tcx.lang_items().poll().unwrap();
*rvalue =
Rvalue::Aggregate(Box::new(AggregateKind::Adt(poll_def_id,
VariantIdx::from_u32(1),
self.tcx.mk_args(&[self.tcx.types.unit.into()]), None,
None)), IndexVec::new());
}
}
}
}
#[doc =
" Drop elaboration has transformed all async drops into `yield` loops."]
#[doc =
" The resulting coroutine needs `async drop` if it yields on a path"]
#[doc = " reachable through \'drop\' targets of a Yield terminator."]
pub(super) fn has_async_drops<'tcx>(body: &mut Body<'tcx>) -> bool {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("has_async_drops",
"rustc_mir_transform::coroutine::drop",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/drop.rs"),
::tracing_core::__macro_support::Option::Some(54u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::drop"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: bool = loop {};
return __tracing_attr_fake_return;
}
{
let mut has_async_drops = false;
let mut dropline: DenseBitSet<BasicBlock> =
DenseBitSet::new_empty(body.basic_blocks.len());
for (bb, data) in traversal::reverse_postorder(body) {
if data.is_cleanup { continue; }
if let TerminatorKind::Yield { drop, .. } =
data.terminator().kind {
if dropline.contains(bb) { has_async_drops = true }
if let Some(v) = drop { dropline.insert(v); }
}
if dropline.contains(bb) {
data.terminator().successors().for_each(|v|
{ dropline.insert(v); });
}
}
has_async_drops
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/drop.rs:54",
"rustc_mir_transform::coroutine::drop",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/drop.rs"),
::tracing_core::__macro_support::Option::Some(54u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::drop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
pub(super) fn elaborate_coroutine_drops<'tcx>(tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("elaborate_coroutine_drops",
"rustc_mir_transform::coroutine::drop",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/drop.rs"),
::tracing_core::__macro_support::Option::Some(84u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::drop"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
use crate::elaborate_drop::{Unwind, elaborate_drop};
use crate::patch::MirPatch;
use crate::shim::DropShimElaborator;
let typing_env = body.typing_env(tcx);
let mut elaborator =
DropShimElaborator {
body,
patch: MirPatch::new(body),
tcx,
typing_env,
produce_async_drops: false,
};
for (block, block_data) in
body.basic_blocks.iter_enumerated() {
let (target, unwind, source_info, dropline) =
match block_data.terminator() {
Terminator {
source_info,
kind: TerminatorKind::Drop {
place, target, unwind, replace: _, drop
}, .. } => {
if let Some(local) = place.as_local() && local == SELF_ARG {
(target, unwind, source_info, *drop)
} else { continue; }
}
_ => continue,
};
let unwind =
if block_data.is_cleanup {
Unwind::InCleanup
} else {
Unwind::To(match *unwind {
UnwindAction::Cleanup(tgt) => tgt,
UnwindAction::Continue => elaborator.patch.resume_block(),
UnwindAction::Unreachable =>
elaborator.patch.unreachable_cleanup_block(),
UnwindAction::Terminate(reason) =>
elaborator.patch.terminate_block(reason),
})
};
elaborate_drop(&mut elaborator, *source_info,
Place::from(SELF_ARG), (), *target, unwind, block,
dropline);
}
elaborator.patch.apply(body);
}
}
}
}
pub(super) fn insert_clean_drop<'tcx>(tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>, has_async_drops: bool) -> BasicBlock {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("insert_clean_drop",
"rustc_mir_transform::coroutine::drop",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/drop.rs"),
::tracing_core::__macro_support::Option::Some(147u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::drop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("has_async_drops")
}> =
::tracing::__macro_support::FieldName::new("has_async_drops");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&has_async_drops
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: BasicBlock = loop {};
return __tracing_attr_fake_return;
}
{
let return_block =
if has_async_drops {
insert_poll_ready_block(tcx, body)
} else { insert_term_block(body, TerminatorKind::Return) };
let dropline = None;
let term =
TerminatorKind::Drop {
place: Place::from(SELF_ARG),
target: return_block,
unwind: UnwindAction::Continue,
replace: false,
drop: dropline,
};
insert_term_block(body, term)
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/drop.rs:147",
"rustc_mir_transform::coroutine::drop",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/drop.rs"),
::tracing_core::__macro_support::Option::Some(147u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::drop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
pub(super) fn create_coroutine_drop_shim<'tcx>(tcx: TyCtxt<'tcx>,
transform: &TransformVisitor<'tcx>, coroutine_ty: Ty<'tcx>,
body: &Body<'tcx>, drop_clean: BasicBlock) -> Body<'tcx> {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("create_coroutine_drop_shim",
"rustc_mir_transform::coroutine::drop",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/drop.rs"),
::tracing_core::__macro_support::Option::Some(176u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::drop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("coroutine_ty")
}> =
::tracing::__macro_support::FieldName::new("coroutine_ty");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("drop_clean")
}> =
::tracing::__macro_support::FieldName::new("drop_clean");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&coroutine_ty)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&drop_clean)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Body<'tcx> = loop {};
return __tracing_attr_fake_return;
}
{
let mut body = body.clone();
let _ = body.coroutine.take();
body.arg_count = 1;
let source_info = SourceInfo::outermost(body.span);
let mut cases =
create_cases(&mut body, transform, Operation::Drop);
cases.insert(0, (CoroutineArgs::UNRESUMED, drop_clean));
let default_block =
insert_term_block(&mut body, TerminatorKind::Return);
insert_switch(&mut body, cases, transform, default_block);
for block in body.basic_blocks_mut() {
let kind = &mut block.terminator_mut().kind;
if let TerminatorKind::CoroutineDrop = *kind {
*kind = TerminatorKind::Return;
}
}
body.local_decls[RETURN_PLACE] =
LocalDecl::with_source_info(tcx.types.unit, source_info);
make_coroutine_state_argument_indirect(tcx, &mut body);
simplify::remove_dead_blocks(&mut body);
deref_finder(tcx, &mut body, false);
let coroutine_instance = body.source.instance;
let drop_glue =
tcx.require_lang_item(LangItem::DropGlue, body.span);
let drop_instance =
InstanceKind::Shim(ShimKind::DropGlue(drop_glue,
Some(coroutine_ty)));
body.source.instance = coroutine_instance;
if let Some(dumper) =
MirDumper::new(tcx, "coroutine_drop", &body) {
dumper.dump_mir(&body);
}
body.source.instance = drop_instance;
body.phase = MirPhase::Runtime(RuntimePhase::Initial);
body
}
}
}
}
pub(super) fn create_coroutine_drop_shim_async<'tcx>(tcx:
TyCtxt<'tcx>, transform: &TransformVisitor<'tcx>,
body: &Body<'tcx>, drop_clean: BasicBlock, can_unwind: bool)
-> Body<'tcx> {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("create_coroutine_drop_shim_async",
"rustc_mir_transform::coroutine::drop",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/drop.rs"),
::tracing_core::__macro_support::Option::Some(247u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::drop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("drop_clean")
}> =
::tracing::__macro_support::FieldName::new("drop_clean");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("can_unwind")
}> =
::tracing::__macro_support::FieldName::new("can_unwind");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&drop_clean)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&can_unwind as
&dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Body<'tcx> = loop {};
return __tracing_attr_fake_return;
}
{
let mut body = body.clone();
let _ = body.coroutine.take();
FixReturnPendingVisitor { tcx }.visit_body(&mut body);
if can_unwind {
generate_poison_block_and_redirect_unwinds_there(transform,
&mut body);
}
let source_info = SourceInfo::outermost(body.span);
let mut cases =
create_cases(&mut body, transform, Operation::AsyncDrop);
cases.insert(0, (CoroutineArgs::UNRESUMED, drop_clean));
use rustc_middle::mir::AssertKind::ResumedAfterPanic;
if can_unwind {
cases.insert(1,
(CoroutineArgs::POISONED,
insert_panic_block(tcx, &mut body,
ResumedAfterPanic(transform.coroutine_kind))));
}
let default_block = insert_poll_ready_block(tcx, &mut body);
insert_switch(&mut body, cases, transform, default_block);
for block in body.basic_blocks_mut() {
let kind = &mut block.terminator_mut().kind;
if let TerminatorKind::CoroutineDrop = *kind {
*kind = TerminatorKind::Return;
block.statements.push(return_poll_ready_assign(tcx,
source_info));
}
}
let poll_adt_ref =
tcx.adt_def(tcx.require_lang_item(LangItem::Poll,
body.span));
let poll_enum =
Ty::new_adt(tcx, poll_adt_ref,
tcx.mk_args(&[tcx.types.unit.into()]));
body.local_decls[RETURN_PLACE] =
LocalDecl::with_source_info(poll_enum, source_info);
match transform.coroutine_kind {
CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => {
make_coroutine_state_argument_indirect(tcx, &mut body);
}
_ => {
make_coroutine_state_argument_pinned(tcx, &mut body);
}
}
simplify::remove_dead_blocks(&mut body);
pm::run_passes_no_validate(tcx, &mut body,
&[&abort_unwinding_calls::AbortUnwindingCalls], None);
deref_finder(tcx, &mut body, false);
if transform.coroutine_kind.is_async_desugaring() {
transform_async_context(tcx, &mut body);
}
if let Some(dumper) =
MirDumper::new(tcx, "coroutine_drop_async", &body) {
dumper.dump_mir(&body);
}
body
}
}
}
}
pub(super) fn create_coroutine_drop_shim_proxy_async<'tcx>(tcx:
TyCtxt<'tcx>, body: &Body<'tcx>,
coroutine_kind: CoroutineKind) -> Body<'tcx> {
let mut body = body.clone();
let _ = body.coroutine.take();
let basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>> =
IndexVec::new();
body.basic_blocks = BasicBlocks::new(basic_blocks);
body.var_debug_info.clear();
body.local_decls.truncate(1 + body.arg_count);
let source_info = SourceInfo::outermost(body.span);
let poll_adt_ref =
tcx.adt_def(tcx.require_lang_item(LangItem::Poll, body.span));
let poll_enum =
Ty::new_adt(tcx, poll_adt_ref,
tcx.mk_args(&[tcx.types.unit.into()]));
body.local_decls[RETURN_PLACE] =
LocalDecl::with_source_info(poll_enum, source_info);
let call_bb =
body.basic_blocks_mut().push(BasicBlockData::new(None,
false));
let ret_bb = insert_poll_ready_block(tcx, &mut body);
let kind =
TerminatorKind::Drop {
place: Place::from(SELF_ARG),
target: ret_bb,
unwind: UnwindAction::Continue,
replace: false,
drop: None,
};
body.basic_blocks_mut()[call_bb].terminator =
Some(Terminator {
source_info,
kind,
attributes: ThinVec::new(),
});
deref_finder(tcx, &mut body, false);
if coroutine_kind.is_async_desugaring() {
transform_async_context(tcx, &mut body);
}
if let Some(dumper) =
MirDumper::new(tcx, "coroutine_drop_proxy_async", &body) {
dumper.dump_mir(&body);
}
body
}
}
mod layout {
use std::ops;
use itertools::izip;
use rustc_abi::{FieldIdx, VariantIdx};
use rustc_data_structures::fx::FxHashSet;
use rustc_errors::pluralize;
use rustc_hir::attrs::lang_items::LangItem;
use rustc_hir::{self as hir, find_attr};
use rustc_index::bit_set::{BitMatrix, DenseBitSet};
use rustc_index::{Idx, IndexVec};
use rustc_infer::traits::TraitErrors;
use rustc_lint_defs::builtin::MUST_NOT_SUSPEND;
use rustc_middle::mir::*;
use rustc_middle::span_bug;
use rustc_middle::ty::{
self, CoroutineArgs, CoroutineArgsExt, Ty, TyCtxt, TypingMode,
};
use rustc_mir_dataflow::impls::{
MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage,
MaybeStorageLive, always_storage_live_locals,
};
use rustc_mir_dataflow::{
Analysis, Results, ResultsCursor, ResultsVisitor, visit_results,
};
use rustc_span::Span;
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
use rustc_trait_selection::infer::TyCtxtInferExt as _;
use rustc_trait_selection::traits::{
ObligationCause, ObligationCauseCode, ObligationCtxt,
};
use tracing::{debug, instrument};
use crate::diagnostics::{MustNotSupend, MustNotSuspendReason};
const SELF_ARG: Local = Local::arg(0);
pub(super) struct LivenessInfo {
pub(super) saved_locals: CoroutineSavedLocals,
live_locals_at_suspension_points: Vec<DenseBitSet<CoroutineSavedLocal>>,
source_info_at_suspension_points: Vec<SourceInfo>,
pub(super) storage_conflicts: BitMatrix<CoroutineSavedLocal,
CoroutineSavedLocal>,
storage_liveness: IndexVec<BasicBlock,
Option<DenseBitSet<Local>>>,
}
#[doc =
" Computes which locals have to be stored in the state-machine for the"]
#[doc = " given coroutine."]
#[doc = ""]
#[doc = " The basic idea is as follows:"]
#[doc =
" - a local is live until we encounter a `StorageDead` statement. In"]
#[doc =
" case none exist, the local is considered to be always live."]
#[doc =
" - a local has to be stored if it is either directly used after the"]
#[doc =
" the suspend point, or if it is live and has been previously borrowed."]
pub(super) fn locals_live_across_suspend_points<'tcx>(tcx:
TyCtxt<'tcx>, body: &Body<'tcx>,
always_live_locals: &DenseBitSet<Local>, movable: bool)
-> LivenessInfo {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("locals_live_across_suspend_points",
"rustc_mir_transform::coroutine::layout",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs"),
::tracing_core::__macro_support::Option::Some(82u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::layout"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("always_live_locals")
}> =
::tracing::__macro_support::FieldName::new("always_live_locals");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("movable")
}> =
::tracing::__macro_support::FieldName::new("movable");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&always_live_locals)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&movable as
&dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: LivenessInfo = loop {};
return __tracing_attr_fake_return;
}
{
let mut storage_live =
MaybeStorageLive::new(std::borrow::Cow::Borrowed(always_live_locals)).iterate_to_fixpoint(tcx,
body, None).into_results_cursor(body);
let borrowed_locals =
MaybeBorrowedLocals.iterate_to_fixpoint(tcx, body,
Some("coroutine"));
let requires_storage =
MaybeRequiresStorage::new(body,
&borrowed_locals).iterate_to_fixpoint(tcx, body, None);
let mut requires_storage_cursor =
ResultsCursor::new_borrowing(body, &requires_storage);
let mut liveness =
MaybeLiveLocals.iterate_to_fixpoint(tcx, body,
Some("coroutine")).into_results_cursor(body);
let mut storage_liveness_map =
IndexVec::from_elem(None, &body.basic_blocks);
let mut live_locals_at_suspension_points = Vec::new();
let mut source_info_at_suspension_points = Vec::new();
let mut live_locals_at_any_suspension_point =
DenseBitSet::new_empty(body.local_decls.len());
let mut borrowed_locals_cursor =
ResultsCursor::new_owning(body, borrowed_locals);
for (block, data) in body.basic_blocks.iter_enumerated() {
let TerminatorKind::Yield { .. } =
data.terminator().kind else { continue };
let loc =
Location { block, statement_index: data.statements.len() };
liveness.seek_to_block_end(block);
let mut live_locals = liveness.get().clone();
if !movable {
borrowed_locals_cursor.seek_before_primary_effect(loc);
live_locals.union(borrowed_locals_cursor.get());
}
storage_live.seek_before_primary_effect(loc);
storage_liveness_map[block] =
Some(storage_live.get().clone());
requires_storage_cursor.seek_before_primary_effect(loc);
live_locals.intersect(requires_storage_cursor.get());
live_locals.remove(SELF_ARG);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs:150",
"rustc_mir_transform::coroutine::layout",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs"),
::tracing_core::__macro_support::Option::Some(150u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::layout"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("loc")
}> =
::tracing::__macro_support::FieldName::new("loc");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("live_locals")
}> =
::tracing::__macro_support::FieldName::new("live_locals");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&loc)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&live_locals)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
live_locals_at_any_suspension_point.union(&live_locals);
live_locals_at_suspension_points.push(live_locals);
source_info_at_suspension_points.push(data.terminator().source_info);
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs:160",
"rustc_mir_transform::coroutine::layout",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs"),
::tracing_core::__macro_support::Option::Some(160u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::layout"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("live_locals_at_any_suspension_point")
}> =
::tracing::__macro_support::FieldName::new("live_locals_at_any_suspension_point");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&live_locals_at_any_suspension_point)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let saved_locals =
CoroutineSavedLocals(live_locals_at_any_suspension_point);
let live_locals_at_suspension_points =
live_locals_at_suspension_points.iter().map(|live_here|
saved_locals.renumber_bitset(live_here)).collect();
let storage_conflicts =
compute_storage_conflicts(body, &saved_locals,
always_live_locals.clone(), &requires_storage);
LivenessInfo {
saved_locals,
live_locals_at_suspension_points,
source_info_at_suspension_points,
storage_conflicts,
storage_liveness: storage_liveness_map,
}
}
}
}
}
pub(super) struct CoroutineSavedLocals(DenseBitSet<Local>);
impl CoroutineSavedLocals {
fn iter_enumerated(&self)
-> impl '_ + Iterator<Item = (CoroutineSavedLocal, Local)> {
self.iter().enumerate().map(|(i, l)|
(CoroutineSavedLocal::from(i), l))
}
fn renumber_bitset(&self, input: &DenseBitSet<Local>)
-> DenseBitSet<CoroutineSavedLocal> {
if !self.superset(input) {
{
::core::panicking::panic_fmt(format_args!("{0:?} not a superset of {1:?}",
self.0, input));
}
};
let mut out = DenseBitSet::new_empty(self.count());
for (saved_local, local) in self.iter_enumerated() {
if input.contains(local) { out.insert(saved_local); }
}
out
}
pub(super) fn get(&self, local: Local)
-> Option<CoroutineSavedLocal> {
if !self.contains(local) { return None; }
let idx = self.iter().take_while(|&l| l < local).count();
Some(CoroutineSavedLocal::new(idx))
}
}
impl ops::Deref for CoroutineSavedLocals {
type Target = DenseBitSet<Local>;
fn deref(&self) -> &Self::Target { &self.0 }
}
fn compute_storage_conflicts<'mir,
'tcx>(body: &'mir Body<'tcx>,
saved_locals: &'mir CoroutineSavedLocals,
always_live_locals: DenseBitSet<Local>,
results: &Results<'tcx, MaybeRequiresStorage>)
-> BitMatrix<CoroutineSavedLocal, CoroutineSavedLocal> {
{
match (&body.local_decls.len(), &saved_locals.domain_size()) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs:243",
"rustc_mir_transform::coroutine::layout",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs"),
::tracing_core::__macro_support::Option::Some(243u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::layout"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("compute_storage_conflicts({0:?})",
body.span) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs:244",
"rustc_mir_transform::coroutine::layout",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs"),
::tracing_core::__macro_support::Option::Some(244u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::layout"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("always_live = {0:?}",
always_live_locals) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let mut ineligible_locals = always_live_locals;
ineligible_locals.intersect(&**saved_locals);
let mut visitor =
StorageConflictVisitor {
saved_locals,
local_conflicts: BitMatrix::from_row_n(&ineligible_locals,
body.local_decls.len()),
eligible_storage_live: DenseBitSet::new_empty(body.local_decls.len()),
};
let blocks =
traversal::reachable(body).filter_map(|(bb, data)|
{
(!#[allow(non_exhaustive_omitted_patterns)] match data.terminator().kind
{
TerminatorKind::Unreachable => true,
_ => false,
}).then_some(bb)
});
visit_results(body, blocks, results, &mut visitor);
let local_conflicts = visitor.local_conflicts;
let mut storage_conflicts =
BitMatrix::new(saved_locals.count(), saved_locals.count());
for (saved_local_a, local_a) in saved_locals.iter_enumerated() {
if ineligible_locals.contains(local_a) {
storage_conflicts.insert_all_into_row(saved_local_a);
} else {
for (saved_local_b, local_b) in
saved_locals.iter_enumerated() {
if local_conflicts.contains(local_a, local_b) {
storage_conflicts.insert(saved_local_a, saved_local_b);
}
}
}
}
storage_conflicts
}
struct StorageConflictVisitor<'a> {
saved_locals: &'a CoroutineSavedLocals,
local_conflicts: BitMatrix<Local, Local>,
eligible_storage_live: DenseBitSet<Local>,
}
impl<'a, 'tcx> ResultsVisitor<'tcx, MaybeRequiresStorage> for
StorageConflictVisitor<'a> {
fn visit_after_early_statement_effect(&mut self,
state: &DenseBitSet<Local>, _statement: &Statement<'tcx>,
_loc: Location) {
self.apply_state(state);
}
fn visit_after_early_terminator_effect(&mut self,
state: &DenseBitSet<Local>, _terminator: &Terminator<'tcx>,
_loc: Location) {
self.apply_state(state);
}
}
impl StorageConflictVisitor<'_> {
fn apply_state(&mut self, state: &DenseBitSet<Local>) {
self.eligible_storage_live.clone_from(state);
self.eligible_storage_live.intersect(&**self.saved_locals);
for local in self.eligible_storage_live.iter() {
self.local_conflicts.union_row_with(&self.eligible_storage_live,
local);
}
}
}
pub(super) fn compute_layout<'tcx>(liveness: LivenessInfo,
body: &Body<'tcx>)
->
(IndexVec<Local, Option<(Ty<'tcx>, VariantIdx, FieldIdx)>>,
CoroutineLayout<'tcx>,
IndexVec<BasicBlock, Option<DenseBitSet<Local>>>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("compute_layout",
"rustc_mir_transform::coroutine::layout",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs"),
::tracing_core::__macro_support::Option::Some(333u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::layout"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
(IndexVec<Local, Option<(Ty<'tcx>, VariantIdx, FieldIdx)>>,
CoroutineLayout<'tcx>,
IndexVec<BasicBlock, Option<DenseBitSet<Local>>>) = loop {};
return __tracing_attr_fake_return;
}
{
let LivenessInfo {
saved_locals,
live_locals_at_suspension_points,
source_info_at_suspension_points,
storage_conflicts,
storage_liveness } = liveness;
let mut tys:
IndexVec<CoroutineSavedLocal, CoroutineSavedTy<'_>> =
saved_locals.iter_enumerated().map(|(saved_local, local)|
{
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs:354",
"rustc_mir_transform::coroutine::layout",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs"),
::tracing_core::__macro_support::Option::Some(354u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::layout"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("coroutine saved local {0:?} => {1:?}",
saved_local, local) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let decl = &body.local_decls[local];
let ignore_for_traits =
match decl.local_info {
ClearCrossCrate::Set(LocalInfo::StaticRef { is_thread_local,
.. }) => {
!is_thread_local
}
ClearCrossCrate::Set(LocalInfo::FakeBorrow) => true,
_ => false,
};
CoroutineSavedTy {
ty: decl.ty,
source_info: decl.source_info,
ignore_for_traits,
debuginfo_name: None,
}
}).collect();
let body_span =
body.source_scopes[OUTERMOST_SOURCE_SCOPE].span;
let mut variant_source_info:
IndexVec<VariantIdx, SourceInfo> =
IndexVec::with_capacity(CoroutineArgs::RESERVED_VARIANTS +
live_locals_at_suspension_points.len());
variant_source_info.extend([SourceInfo::outermost(body_span.shrink_to_lo()),
SourceInfo::outermost(body_span.shrink_to_hi()),
SourceInfo::outermost(body_span.shrink_to_hi())]);
let reverse_local_map:
IndexVec<CoroutineSavedLocal, Local> =
saved_locals.iter().collect();
let mut variant_fields: IndexVec<VariantIdx, _> =
IndexVec::from_elem_n(IndexVec::new(),
CoroutineArgs::RESERVED_VARIANTS +
live_locals_at_suspension_points.len());
let mut remap =
IndexVec::from_elem_n(None, saved_locals.domain_size());
for (live_locals, &source_info_at_suspension_point,
(variant_index, fields)) in
::itertools::__std_iter::Iterator::map(::itertools::__std_iter::Iterator::zip(::itertools::__std_iter::IntoIterator::into_iter(&live_locals_at_suspension_points),
::itertools::__std_iter::Iterator::zip(::itertools::__std_iter::IntoIterator::into_iter(&source_info_at_suspension_points),
::itertools::__std_iter::IntoIterator::into_iter(variant_fields.iter_enumerated_mut().skip(CoroutineArgs::RESERVED_VARIANTS)))),
|(b, (b, a))| (b, b, a)) {
*fields = live_locals.iter().collect();
for (idx, &saved_local) in fields.iter_enumerated() {
remap[reverse_local_map[saved_local]] =
Some((tys[saved_local].ty, variant_index, idx));
}
variant_source_info.push(source_info_at_suspension_point);
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs:422",
"rustc_mir_transform::coroutine::layout",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs"),
::tracing_core::__macro_support::Option::Some(422u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::layout"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("variant_fields")
}> =
::tracing::__macro_support::FieldName::new("variant_fields");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&variant_fields)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs:423",
"rustc_mir_transform::coroutine::layout",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs"),
::tracing_core::__macro_support::Option::Some(423u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::layout"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("storage_conflicts")
}> =
::tracing::__macro_support::FieldName::new("storage_conflicts");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&storage_conflicts)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
for var in &body.var_debug_info {
let VarDebugInfoContents::Place(place) =
&var.value else { continue };
let Some(local) = place.as_local() else { continue };
let Some(&Some((_, variant, field))) =
remap.get(local) else { continue; };
let saved_local: CoroutineSavedLocal =
variant_fields[variant][field];
tys[saved_local].debuginfo_name.get_or_insert(var.name);
}
let layout =
CoroutineLayout {
field_tys: tys,
variant_fields,
variant_source_info,
storage_conflicts,
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs:438",
"rustc_mir_transform::coroutine::layout",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs"),
::tracing_core::__macro_support::Option::Some(438u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::layout"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("remap")
}> =
::tracing::__macro_support::FieldName::new("remap");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&remap)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs:439",
"rustc_mir_transform::coroutine::layout",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs"),
::tracing_core::__macro_support::Option::Some(439u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::layout"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("layout")
}> =
::tracing::__macro_support::FieldName::new("layout");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&layout)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs:440",
"rustc_mir_transform::coroutine::layout",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs"),
::tracing_core::__macro_support::Option::Some(440u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::layout"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("storage_liveness")
}> =
::tracing::__macro_support::FieldName::new("storage_liveness");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&storage_liveness)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
(remap, layout, storage_liveness)
}
}
}
}
pub(crate) fn mir_coroutine_witnesses<'tcx>(tcx: TyCtxt<'tcx>,
def_id: LocalDefId) -> Option<CoroutineLayout<'tcx>> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("mir_coroutine_witnesses",
"rustc_mir_transform::coroutine::layout",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs"),
::tracing_core::__macro_support::Option::Some(445u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::layout"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<CoroutineLayout<'tcx>> = loop {};
return __tracing_attr_fake_return;
}
{
let (body, _) = tcx.mir_promoted(def_id);
let body = body.borrow();
let body = &*body;
let coroutine_ty =
body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty;
let movable =
match *coroutine_ty.kind() {
ty::Coroutine(def_id, _) =>
tcx.coroutine_movability(def_id) ==
hir::Movability::Movable,
ty::Error(_) => return None,
_ =>
::rustc_middle::util::bug::span_bug_fmt(body.span,
format_args!("unexpected coroutine type {0}",
coroutine_ty)),
};
let always_live_locals = always_storage_live_locals(body);
let liveness_info =
locals_live_across_suspend_points(tcx, body,
&always_live_locals, movable);
let (_, coroutine_layout, _) =
compute_layout(liveness_info, body);
check_suspend_tys(tcx, &coroutine_layout, body);
check_field_tys_sized(tcx, &coroutine_layout, def_id);
Some(coroutine_layout)
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs:445",
"rustc_mir_transform::coroutine::layout",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs"),
::tracing_core::__macro_support::Option::Some(445u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::layout"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn check_field_tys_sized<'tcx>(tcx: TyCtxt<'tcx>,
coroutine_layout: &CoroutineLayout<'tcx>, def_id: LocalDefId) {
if !tcx.features().unsized_fn_params() { return; }
let infcx =
tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis());
let param_env = tcx.param_env(def_id);
let ocx = ObligationCtxt::new_with_diagnostics(&infcx);
for field_ty in &coroutine_layout.field_tys {
ocx.register_bound(ObligationCause::new(field_ty.source_info.span,
def_id,
ObligationCauseCode::SizedCoroutineInterior(def_id)),
param_env, field_ty.ty,
tcx.require_lang_item(LangItem::Sized,
field_ty.source_info.span));
}
let errors = ocx.evaluate_obligations_error_on_ambiguity();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs:512",
"rustc_mir_transform::coroutine::layout",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs"),
::tracing_core::__macro_support::Option::Some(512u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::layout"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("errors")
}> =
::tracing::__macro_support::FieldName::new("errors");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&errors)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if let TraitErrors::HasErrors(errors) = errors {
infcx.err_ctxt().report_fulfillment_errors(errors);
}
}
fn check_suspend_tys<'tcx>(tcx: TyCtxt<'tcx>,
layout: &CoroutineLayout<'tcx>, body: &Body<'tcx>) {
let mut linted_tys = FxHashSet::default();
for (variant, yield_source_info) in
layout.variant_fields.iter().zip(&layout.variant_source_info)
{
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs:524",
"rustc_mir_transform::coroutine::layout",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs"),
::tracing_core::__macro_support::Option::Some(524u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::layout"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("variant")
}> =
::tracing::__macro_support::FieldName::new("variant");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&variant)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
for &local in variant {
let decl = &layout.field_tys[local];
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs:527",
"rustc_mir_transform::coroutine::layout",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs"),
::tracing_core::__macro_support::Option::Some(527u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::layout"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("decl")
}> =
::tracing::__macro_support::FieldName::new("decl");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&decl)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if !decl.ignore_for_traits && linted_tys.insert(decl.ty) {
let Some(hir_id) =
decl.source_info.scope.lint_root(&body.source_scopes) else {
continue;
};
check_must_not_suspend_ty(tcx, decl.ty, hir_id,
SuspendCheckData {
source_span: decl.source_info.span,
yield_span: yield_source_info.span,
plural_len: 1,
..Default::default()
});
}
}
}
}
struct SuspendCheckData<'a> {
source_span: Span,
yield_span: Span,
descr_pre: &'a str,
descr_post: &'a str,
plural_len: usize,
}
#[automatically_derived]
impl<'a> ::core::default::Default for SuspendCheckData<'a> {
#[inline]
fn default() -> SuspendCheckData<'a> {
SuspendCheckData {
source_span: ::core::default::Default::default(),
yield_span: ::core::default::Default::default(),
descr_pre: ::core::default::Default::default(),
descr_post: ::core::default::Default::default(),
plural_len: ::core::default::Default::default(),
}
}
}
fn check_must_not_suspend_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>,
hir_id: hir::HirId, data: SuspendCheckData<'_>) -> bool {
if ty.is_unit() { return false; }
let plural_suffix = if data.plural_len == 1 { "" } else { "s" };
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs:577",
"rustc_mir_transform::coroutine::layout",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/layout.rs"),
::tracing_core::__macro_support::Option::Some(577u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine::layout"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Checking must_not_suspend for {0}",
ty) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
match *ty.kind() {
ty::Adt(_, args) if ty.is_box() => {
let boxed_ty = args.type_at(0);
let allocator_ty = args.type_at(1);
check_must_not_suspend_ty(tcx, boxed_ty, hir_id,
SuspendCheckData {
descr_pre: &::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}boxed ",
data.descr_pre))
}),
..data
}) ||
check_must_not_suspend_ty(tcx, allocator_ty, hir_id,
SuspendCheckData {
descr_pre: &::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}allocator ",
data.descr_pre))
}),
..data
})
}
ty::Adt(def, _) if def.repr().scalable() => {
tcx.dcx().span_err(data.source_span,
"scalable vectors cannot be held over await points");
true
}
ty::Adt(def, _) =>
check_must_not_suspend_def(tcx, def.did(), hir_id, data),
ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: def },
.. }) => {
let mut has_emitted = false;
for &(predicate, _) in
tcx.explicit_item_bounds(def).skip_binder() {
if let ty::ClauseKind::Trait(ref poly_trait_predicate) =
predicate.kind().skip_binder() {
let def_id = poly_trait_predicate.trait_ref.def_id;
let descr_pre =
&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}implementer{1} of ",
data.descr_pre, plural_suffix))
});
if check_must_not_suspend_def(tcx, def_id, hir_id,
SuspendCheckData { descr_pre, ..data }) {
has_emitted = true;
break;
}
}
}
has_emitted
}
ty::Dynamic(binder, _) => {
let mut has_emitted = false;
for predicate in binder.iter() {
if let ty::ExistentialPredicate::Trait(ref trait_ref) =
predicate.skip_binder() {
let def_id = trait_ref.def_id;
let descr_post =
&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" trait object{0}{1}",
plural_suffix, data.descr_post))
});
if check_must_not_suspend_def(tcx, def_id, hir_id,
SuspendCheckData { descr_post, ..data }) {
has_emitted = true;
break;
}
}
}
has_emitted
}
ty::Tuple(fields) => {
let mut has_emitted = false;
for (i, ty) in fields.iter().enumerate() {
let descr_post =
&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" in tuple element {0}",
i))
});
if check_must_not_suspend_ty(tcx, ty, hir_id,
SuspendCheckData { descr_post, ..data }) {
has_emitted = true;
}
}
has_emitted
}
ty::Array(ty, len) => {
let descr_pre =
&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}array{1} of ",
data.descr_pre, plural_suffix))
});
check_must_not_suspend_ty(tcx, ty, hir_id,
SuspendCheckData {
descr_pre,
plural_len: len.try_to_target_usize(tcx).unwrap_or(0) as
usize + 1,
..data
})
}
ty::Ref(_region, ty, _mutability) => {
let descr_pre =
&::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}reference{1} to ",
data.descr_pre, plural_suffix))
});
check_must_not_suspend_ty(tcx, ty, hir_id,
SuspendCheckData { descr_pre, ..data })
}
_ => false,
}
}
fn check_must_not_suspend_def(tcx: TyCtxt<'_>, def_id: DefId,
hir_id: hir::HirId, data: SuspendCheckData<'_>) -> bool {
if let Some(reason_str) =
{
{
'done:
{
for i in ::rustc_attr_ir::HasAttrs::get_attrs(def_id, &tcx)
{
#[allow(unused_imports)]
use ::rustc_attr_ir::AttributeKind::*;
let i: &::rustc_attr_ir::Attribute = i;
match i {
::rustc_attr_ir::Attribute::Parsed(MustNotSupend { reason })
=> {
break 'done Some(reason);
}
::rustc_attr_ir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
} {
let reason =
reason_str.map(|s|
MustNotSuspendReason { span: data.source_span, reason: s });
tcx.emit_node_span_lint(MUST_NOT_SUSPEND, hir_id,
data.source_span,
MustNotSupend {
tcx,
yield_sp: data.yield_span,
reason,
src_sp: data.source_span,
pre: data.descr_pre,
def_id,
post: data.descr_post,
});
true
} else { false }
}
}
pub(super) use by_move_body::coroutine_by_move_body_def_id;
use drop::{
create_coroutine_drop_shim, create_coroutine_drop_shim_async,
create_coroutine_drop_shim_proxy_async, elaborate_coroutine_drops,
has_async_drops, insert_clean_drop,
};
pub(super) use layout::mir_coroutine_witnesses;
use layout::{
CoroutineSavedLocals, compute_layout,
locals_live_across_suspend_points,
};
use rustc_abi::{FieldIdx, VariantIdx};
use rustc_data_structures::thin_vec::ThinVec;
use rustc_hir::attrs::lang_items::LangItem;
use rustc_hir::{self as hir, CoroutineDesugaring, CoroutineKind};
use rustc_index::bit_set::{BitMatrix, DenseBitSet, GrowableBitSet};
use rustc_index::{Idx, IndexVec, indexvec};
use rustc_middle::mir::visit::{
MutVisitor, MutatingUseContext, PlaceContext, Visitor,
};
use rustc_middle::mir::*;
use rustc_middle::ty::{
self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind,
ShimKind, Ty, TyCtxt,
};
use rustc_middle::{bug, span_bug};
use rustc_mir_dataflow::impls::always_storage_live_locals;
use rustc_span::def_id::DefId;
use tracing::{debug, instrument};
use crate::deref_separator::deref_finder;
use crate::patch::MirPatch;
use crate::{
PassPolicy, abort_unwinding_calls, pass_manager as pm, simplify,
};
pub(super) struct StateTransform;
struct RenameLocalVisitor<'tcx> {
from: Local,
to: Local,
tcx: TyCtxt<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for RenameLocalVisitor<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_local(&mut self, local: &mut Local, _: PlaceContext,
_: Location) {
if *local == self.from {
*local = self.to;
} else if *local == self.to { *local = self.from; }
}
fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>,
location: Location) {
match terminator.kind {
TerminatorKind::Return => {}
_ => self.super_terminator(terminator, location),
}
}
}
struct SelfArgVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
new_base: Place<'tcx>,
}
impl<'tcx> SelfArgVisitor<'tcx> {
fn new(tcx: TyCtxt<'tcx>, new_base: Place<'tcx>) -> Self {
Self { tcx, new_base }
}
}
impl<'tcx> MutVisitor<'tcx> for SelfArgVisitor<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_local(&mut self, local: &mut Local, _: PlaceContext,
_: Location) {
{
match (&*local, &SELF_ARG) {
(left_val, right_val) => {
if *left_val == *right_val {
let kind = ::core::panicking::AssertKind::Ne;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
}
fn visit_place(&mut self, place: &mut Place<'tcx>, _: PlaceContext,
_: Location) {
if place.local == SELF_ARG {
replace_base(place, self.new_base, self.tcx);
}
for elem in place.projection.iter() {
if let PlaceElem::Index(local) = elem {
{
match (&local, &SELF_ARG) {
(left_val, right_val) => {
if *left_val == *right_val {
let kind = ::core::panicking::AssertKind::Ne;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
}
}
}
}
fn replace_base<'tcx>(place: &mut Place<'tcx>, new_base: Place<'tcx>,
tcx: TyCtxt<'tcx>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("replace_base",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(150u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("place")
}> =
::tracing::__macro_support::FieldName::new("place");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("new_base")
}> =
::tracing::__macro_support::FieldName::new("new_base");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&new_base)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
place.local = new_base.local;
let mut new_projection = new_base.projection.to_vec();
new_projection.append(&mut place.projection.to_vec());
place.projection = tcx.mk_place_elems(&new_projection);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs:158",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(158u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("place")
}> =
::tracing::__macro_support::FieldName::new("place");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
}
}
}
}
const SELF_ARG: Local = Local::arg(0);
pub(crate) const CTX_ARG: Local = Local::arg(1);
struct SuspensionPoint<'tcx> {
state: usize,
resume: BasicBlock,
resume_arg: Place<'tcx>,
drop: Option<BasicBlock>,
storage_liveness: GrowableBitSet<Local>,
}
struct TransformVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
coroutine_kind: hir::CoroutineKind,
discr_ty: Ty<'tcx>,
remap: IndexVec<Local, Option<(Ty<'tcx>, VariantIdx, FieldIdx)>>,
storage_liveness: IndexVec<BasicBlock, Option<DenseBitSet<Local>>>,
suspension_points: Vec<SuspensionPoint<'tcx>>,
always_live_locals: DenseBitSet<Local>,
new_ret_local: Local,
old_yield_ty: Ty<'tcx>,
old_ret_ty: Ty<'tcx>,
patch: Option<MirPatch<'tcx>>,
}
impl<'tcx> TransformVisitor<'tcx> {
fn insert_none_ret_block(&self, body: &mut Body<'tcx>) -> BasicBlock {
let block = body.basic_blocks.next_index();
let source_info = SourceInfo::outermost(body.span);
let none_value =
match self.coroutine_kind {
CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => {
::rustc_middle::util::bug::span_bug_fmt(body.span,
format_args!("`Future`s are not fused inherently"))
}
CoroutineKind::Coroutine(_) =>
::rustc_middle::util::bug::span_bug_fmt(body.span,
format_args!("`Coroutine`s cannot be fused")),
CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => {
let option_def_id =
self.tcx.require_lang_item(LangItem::Option, body.span);
make_aggregate_adt(option_def_id, VariantIdx::ZERO,
self.tcx.mk_args(&[self.old_yield_ty.into()]),
IndexVec::new())
}
CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)
=> {
let ty::Adt(_poll_adt, args) =
*self.old_yield_ty.kind() else {
::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))
};
let ty::Adt(_option_adt, args) =
*args.type_at(0).kind() else {
::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))
};
let yield_ty = args.type_at(0);
Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
const_: Const::Unevaluated(UnevaluatedConst::new(self.tcx.require_lang_item(LangItem::AsyncGenFinished,
body.span), self.tcx.mk_args(&[yield_ty.into()])),
self.old_yield_ty),
user_ty: None,
})), WithRetag::Yes)
}
};
let statements =
::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[Statement::new(source_info,
StatementKind::Assign(Box::new((Place::return_place(),
none_value))))]));
body.basic_blocks_mut().push(BasicBlockData::new_stmts(statements,
Some(Terminator {
source_info,
kind: TerminatorKind::Return,
attributes: ThinVec::new(),
}), false));
block
}
fn make_state(&self, val: Operand<'tcx>, source_info: SourceInfo,
is_return: bool, statements: &mut Vec<Statement<'tcx>>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("make_state",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(272u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("val")
}> =
::tracing::__macro_support::FieldName::new("val");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("source_info")
}> =
::tracing::__macro_support::FieldName::new("source_info");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("is_return")
}> =
::tracing::__macro_support::FieldName::new("is_return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&val)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&source_info)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&is_return as
&dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
const ZERO: VariantIdx = VariantIdx::ZERO;
const ONE: VariantIdx = VariantIdx::from_usize(1);
let rvalue =
match self.coroutine_kind {
CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => {
let poll_def_id =
self.tcx.require_lang_item(LangItem::Poll,
source_info.span);
let args = self.tcx.mk_args(&[self.old_ret_ty.into()]);
let (variant_idx, operands) =
if is_return {
(ZERO,
IndexVec::from_raw(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[val]))))
} else { (ONE, IndexVec::new()) };
make_aggregate_adt(poll_def_id, variant_idx, args, operands)
}
CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => {
let option_def_id =
self.tcx.require_lang_item(LangItem::Option,
source_info.span);
let args = self.tcx.mk_args(&[self.old_yield_ty.into()]);
let (variant_idx, operands) =
if is_return {
(ZERO, IndexVec::new())
} else {
(ONE,
IndexVec::from_raw(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[val]))))
};
make_aggregate_adt(option_def_id, variant_idx, args,
operands)
}
CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)
=> {
if is_return {
let ty::Adt(_poll_adt, args) =
*self.old_yield_ty.kind() else {
::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))
};
let ty::Adt(_option_adt, args) =
*args.type_at(0).kind() else {
::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))
};
let yield_ty = args.type_at(0);
Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
const_: Const::Unevaluated(UnevaluatedConst::new(self.tcx.require_lang_item(LangItem::AsyncGenFinished,
source_info.span), self.tcx.mk_args(&[yield_ty.into()])),
self.old_yield_ty),
user_ty: None,
})), WithRetag::Yes)
} else { Rvalue::Use(val, WithRetag::Yes) }
}
CoroutineKind::Coroutine(_) => {
let coroutine_state_def_id =
self.tcx.require_lang_item(LangItem::CoroutineState,
source_info.span);
let args =
self.tcx.mk_args(&[self.old_yield_ty.into(),
self.old_ret_ty.into()]);
let variant_idx = if is_return { ONE } else { ZERO };
make_aggregate_adt(coroutine_state_def_id, variant_idx,
args,
IndexVec::from_raw(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[val]))))
}
};
statements.push(Statement::new(source_info,
StatementKind::Assign(Box::new((self.new_ret_local.into(),
rvalue)))));
}
}
}
}
fn make_field(&self, variant_index: VariantIdx, idx: FieldIdx,
ty: Ty<'tcx>) -> Place<'tcx> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("make_field",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(350u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("variant_index")
}> =
::tracing::__macro_support::FieldName::new("variant_index");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("idx")
}> =
::tracing::__macro_support::FieldName::new("idx");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("ty")
}> =
::tracing::__macro_support::FieldName::new("ty");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&variant_index)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&idx)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Place<'tcx> = loop {};
return __tracing_attr_fake_return;
}
{
let self_place = Place::from(SELF_ARG);
let base =
self.tcx.mk_place_downcast_unnamed(self_place,
variant_index);
let mut projection = base.projection.to_vec();
projection.push(ProjectionElem::Field(idx, ty));
Place {
local: base.local,
projection: self.tcx.mk_place_elems(&projection),
}
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs:350",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(350u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn set_discr(&self, state_disc: VariantIdx, source_info: SourceInfo)
-> Statement<'tcx> {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("set_discr",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(361u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("state_disc")
}> =
::tracing::__macro_support::FieldName::new("state_disc");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("source_info")
}> =
::tracing::__macro_support::FieldName::new("source_info");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&state_disc)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&source_info)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Statement<'tcx> = loop {};
return __tracing_attr_fake_return;
}
{
let self_place = Place::from(SELF_ARG);
Statement::new(source_info,
StatementKind::SetDiscriminant {
place: Box::new(self_place),
variant_index: state_disc,
})
}
}
}
}
fn get_discr(&self, body: &mut Body<'tcx>)
-> (Statement<'tcx>, Place<'tcx>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("get_discr",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(374u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
(Statement<'tcx>, Place<'tcx>) = loop {};
return __tracing_attr_fake_return;
}
{
let temp_decl = LocalDecl::new(self.discr_ty, body.span);
let local_decls_len = body.local_decls.push(temp_decl);
let temp = Place::from(local_decls_len);
let self_place = Place::from(SELF_ARG);
let assign =
Statement::new(SourceInfo::outermost(body.span),
StatementKind::Assign(Box::new((temp,
Rvalue::Discriminant(self_place)))));
(assign, temp)
}
}
}
}
#[doc = " Swaps all references of `old_local` and `new_local`."]
fn replace_local(&mut self, old_local: Local, new_local: Local,
body: &mut Body<'tcx>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("replace_local",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(389u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("old_local")
}> =
::tracing::__macro_support::FieldName::new("old_local");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("new_local")
}> =
::tracing::__macro_support::FieldName::new("new_local");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&old_local)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&new_local)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
body.local_decls.swap(old_local, new_local);
let mut visitor =
RenameLocalVisitor {
from: old_local,
to: new_local,
tcx: self.tcx,
};
visitor.visit_body(body);
for suspension in &mut self.suspension_points {
let ctxt =
PlaceContext::MutatingUse(MutatingUseContext::Yield);
let location =
Location { block: START_BLOCK, statement_index: 0 };
visitor.visit_place(&mut suspension.resume_arg, ctxt,
location);
}
}
}
}
}
}
impl<'tcx> MutVisitor<'tcx> for TransformVisitor<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_local(&mut self, local: &mut Local, _: PlaceContext,
_location: Location) {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("visit_local",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(408u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("local")
}> =
::tracing::__macro_support::FieldName::new("local");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("_location")
}> =
::tracing::__macro_support::FieldName::new("_location");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&local)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&_location)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
if !!self.remap.contains(*local) {
::core::panicking::panic("assertion failed: !self.remap.contains(*local)")
};
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs:408",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(408u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn visit_place(&mut self, place: &mut Place<'tcx>, _: PlaceContext,
location: Location) {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("visit_place",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(413u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("place")
}> =
::tracing::__macro_support::FieldName::new("place");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("location")
}> =
::tracing::__macro_support::FieldName::new("location");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&location)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
if let Some(&Some((ty, variant_index, idx))) =
self.remap.get(place.local) {
replace_base(place, self.make_field(variant_index, idx, ty),
self.tcx);
}
if let Some(new_projection) =
self.process_projection(&place.projection, location) {
place.projection = self.tcx.mk_place_elems(&new_projection);
}
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs:413",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(413u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn process_projection_elem(&mut self, elem: PlaceElem<'tcx>,
location: Location) -> Option<PlaceElem<'tcx>> {
match elem {
PlaceElem::Index(local) => {
if let Some(&Some((ty, variant, idx))) =
self.remap.get(local) {
let field = self.make_field(variant, idx, ty);
self.patch.as_mut().unwrap().add_assign(location,
Place::from(local),
Rvalue::Use(Operand::Copy(field), WithRetag::No));
}
None
}
PlaceElem::Field(..) | PlaceElem::OpaqueCast(..) |
PlaceElem::UnwrapUnsafeBinder(..) | PlaceElem::Deref |
PlaceElem::ConstantIndex { .. } | PlaceElem::Subslice { .. }
| PlaceElem::Downcast(..) | PlaceElem::PhantomDeref => None,
}
}
fn visit_statement(&mut self, stmt: &mut Statement<'tcx>,
location: Location) {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("visit_statement",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(462u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("location")
}> =
::tracing::__macro_support::FieldName::new("location");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&location)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
if let StatementKind::StorageLive(l) |
StatementKind::StorageDead(l) = stmt.kind &&
self.remap.contains(l) {
stmt.make_nop(true);
}
self.super_statement(stmt, location);
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs:462",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(462u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn visit_terminator(&mut self, term: &mut Terminator<'tcx>,
location: Location) {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("visit_terminator",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(473u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("location")
}> =
::tracing::__macro_support::FieldName::new("location");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&location)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
if let TerminatorKind::Return = term.kind { return; }
self.super_terminator(term, location);
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs:473",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(473u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn visit_basic_block_data(&mut self, block: BasicBlock,
data: &mut BasicBlockData<'tcx>) {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("visit_basic_block_data",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(483u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("block")
}> =
::tracing::__macro_support::FieldName::new("block");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&block)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
match data.terminator().kind {
TerminatorKind::Return => {
let source_info = data.terminator().source_info;
self.make_state(Operand::Move(Place::return_place()),
source_info, true, &mut data.statements);
let state = VariantIdx::new(CoroutineArgs::RETURNED);
data.statements.push(self.set_discr(state, source_info));
data.terminator_mut().kind = TerminatorKind::Return;
}
TerminatorKind::Yield {
ref value, resume, mut resume_arg, drop } => {
let source_info = data.terminator().source_info;
self.make_state(value.clone(), source_info, false,
&mut data.statements);
let state =
CoroutineArgs::RESERVED_VARIANTS +
self.suspension_points.len();
if let Some(&Some((ty, variant, idx))) =
self.remap.get(resume_arg.local) {
replace_base(&mut resume_arg,
self.make_field(variant, idx, ty), self.tcx);
}
let storage_liveness: GrowableBitSet<Local> =
self.storage_liveness[block].clone().unwrap().into();
for i in 0..self.always_live_locals.domain_size() {
let l = Local::new(i);
let needs_storage_dead =
storage_liveness.contains(l) && !self.remap.contains(l) &&
!self.always_live_locals.contains(l);
if needs_storage_dead {
data.statements.push(Statement::new(source_info,
StatementKind::StorageDead(l)));
}
}
self.suspension_points.push(SuspensionPoint {
state,
resume,
resume_arg,
drop,
storage_liveness,
});
let state = VariantIdx::new(state);
data.statements.push(self.set_discr(state, source_info));
data.terminator_mut().kind = TerminatorKind::Return;
}
_ => {}
}
self.super_basic_block_data(block, data);
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs:483",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(483u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
}
fn make_aggregate_adt<'tcx>(def_id: DefId, variant_idx: VariantIdx,
args: GenericArgsRef<'tcx>,
operands: IndexVec<FieldIdx, Operand<'tcx>>) -> Rvalue<'tcx> {
Rvalue::Aggregate(Box::new(AggregateKind::Adt(def_id, variant_idx,
args, None, None)), operands)
}
fn make_coroutine_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("make_coroutine_state_argument_indirect",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(555u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let coroutine_ty = body.local_decls[SELF_ARG].ty;
let ref_coroutine_ty =
Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty);
body.local_decls[SELF_ARG].ty = ref_coroutine_ty;
SelfArgVisitor::new(tcx,
tcx.mk_place_deref(SELF_ARG.into())).visit_body(body);
}
}
}
}
fn make_coroutine_state_argument_pinned<'tcx>(tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("make_coroutine_state_argument_pinned",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(568u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let coroutine_ty = body.local_decls[SELF_ARG].ty;
let ref_coroutine_ty =
Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, coroutine_ty);
let pin_did =
tcx.require_lang_item(LangItem::Pin, body.span);
let pin_adt_ref = tcx.adt_def(pin_did);
let args = tcx.mk_args(&[ref_coroutine_ty.into()]);
let pin_ref_coroutine_ty =
Ty::new_adt(tcx, pin_adt_ref, args);
body.local_decls[SELF_ARG].ty = pin_ref_coroutine_ty;
let unpinned_local =
body.local_decls.push(LocalDecl::new(ref_coroutine_ty,
body.span));
SelfArgVisitor::new(tcx,
tcx.mk_place_deref(unpinned_local.into())).visit_body(body);
let source_info = SourceInfo::outermost(body.span);
let pin_field =
tcx.mk_place_field(SELF_ARG.into(), FieldIdx::ZERO,
ref_coroutine_ty);
let statements =
&mut body.basic_blocks.as_mut_preserves_cfg()[START_BLOCK].statements;
statements.insert(0,
Statement::new(source_info,
StatementKind::Assign(Box::new((unpinned_local.into(),
Rvalue::Use(Operand::Copy(pin_field), WithRetag::Yes))))));
}
}
}
}
#[doc =
" Async desugaring uses an unsafe binder type `ResumeTy` to circumvert borrow-checking."]
#[doc =
" The `ResumeTy` hides a `&mut Context<\'_>` behind an unsafe raw pointer, and the"]
#[doc =
" `get_context` function is being used to convert that back to a `&mut Context<\'_>`."]
#[doc = ""]
#[doc =
" The actual should be `&mut Context<\'_>`. This performs the substitution:"]
#[doc = " - create a new local `_r` of type `ResumeTy`;"]
#[doc =
" - assign `ResumeTy(transmute::<&mut Context<\'_>, NonNull<Context<\'_>>>(_2))` to that local;"]
#[doc = " - let all the code use `_r` instead of `_2`."]
#[doc = ""]
#[doc =
" Ideally the async lowering would not use the `ResumeTy`/`get_context` indirection,"]
#[doc =
" but rather directly use `&mut Context<\'_>`, however that would currently"]
#[doc = " lead to higher-kinded lifetime errors."]
#[doc = " See <https://github.com/rust-lang/rust/issues/105501>."]
#[doc = ""]
#[doc =
" The async lowering step and the type / lifetime inference / checking are"]
#[doc =
" still using the `ResumeTy` indirection for the time being, and that indirection"]
#[doc =
" is removed here. After this transform, the coroutine body only knows about `&mut Context<\'_>`."]
fn transform_async_context<'tcx>(tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>) {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("transform_async_context",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(620u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let context_mut_ref = Ty::new_task_context(tcx);
let resume_ty_def_id =
tcx.require_lang_item(LangItem::ResumeTy, body.span);
let resume_nonnull_ty =
tcx.instantiate_and_normalize_erasing_regions(ty::GenericArgs::empty(),
body.typing_env(tcx),
tcx.type_of(tcx.adt_def(resume_ty_def_id).non_enum_variant().fields[FieldIdx::ZERO].did));
let resume_local =
body.local_decls.push(LocalDecl::new(context_mut_ref,
body.span));
body.local_decls.swap(CTX_ARG, resume_local);
RenameLocalVisitor {
from: CTX_ARG,
to: resume_local,
tcx,
}.visit_body(body);
let source_info = SourceInfo::outermost(body.span);
let nonnull_local =
body.local_decls.push(LocalDecl::new(resume_nonnull_ty,
body.span));
let nonnull_rhs =
Rvalue::Cast(CastKind::Transmute,
Operand::Move(CTX_ARG.into()), resume_nonnull_ty);
let nonnull_assign =
StatementKind::Assign(Box::new((nonnull_local.into(),
nonnull_rhs)));
let resume_rhs =
Rvalue::Aggregate(Box::new(AggregateKind::Adt(resume_ty_def_id,
VariantIdx::ZERO, ty::GenericArgs::empty(), None, None)),
IndexVec::from_raw(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[Operand::Move(nonnull_local.into())]))));
let resume_assign =
StatementKind::Assign(Box::new((resume_local.into(),
resume_rhs)));
body.basic_blocks.as_mut_preserves_cfg()[START_BLOCK].statements.splice(0..0,
[Statement::new(source_info, nonnull_assign),
Statement::new(source_info, resume_assign)]);
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs:620",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(620u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn eliminate_get_context_calls<'tcx>(tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>) {
let context_mut_ref = Ty::new_task_context(tcx);
let resume_ty_def_id =
tcx.require_lang_item(LangItem::ResumeTy, body.span);
let resume_nonnull_ty =
tcx.instantiate_and_normalize_erasing_regions(ty::GenericArgs::empty(),
body.typing_env(tcx),
tcx.type_of(tcx.adt_def(resume_ty_def_id).non_enum_variant().fields[FieldIdx::ZERO].did));
let get_context_def_id =
tcx.require_lang_item(LangItem::GetContext, body.span);
for bb_data in body.basic_blocks.as_mut().iter_mut() {
if bb_data.is_cleanup { continue; }
let terminator = bb_data.terminator_mut();
if let TerminatorKind::Call { func, args, destination, target, ..
} = &terminator.kind &&
let func_ty = func.ty(&body.local_decls, tcx) &&
let ty::FnDef(def_id, _) = *func_ty.kind() &&
def_id == get_context_def_id && let [arg] = &**args &&
let Some(place) = arg.node.place() {
let arg =
Rvalue::Cast(CastKind::Transmute,
Operand::Copy(place.project_deeper(&[PlaceElem::Field(FieldIdx::ZERO,
resume_nonnull_ty)], tcx)), context_mut_ref);
let assign =
Statement::new(terminator.source_info,
StatementKind::Assign(Box::new((*destination, arg))));
terminator.kind =
TerminatorKind::Goto { target: target.unwrap() };
bb_data.statements.push(assign);
}
}
}
fn insert_switch<'tcx>(body: &mut Body<'tcx>,
cases: Vec<(usize, BasicBlock)>, transform: &TransformVisitor<'tcx>,
default_block: BasicBlock) {
let (assign, discr) = transform.get_discr(body);
for bb in body.basic_blocks.iter() {
for target in bb.terminator().successors() {
{
match (&target, &START_BLOCK) {
(left_val, right_val) => {
if *left_val == *right_val {
let kind = ::core::panicking::AssertKind::Ne;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
}
}
let former_entry =
std::mem::replace(&mut body.basic_blocks_mut()[START_BLOCK],
BasicBlockData::new_stmts(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[assign])), None, false));
let former_entry = body.basic_blocks_mut().push(former_entry);
let mut switch_targets =
SwitchTargets::new(cases.iter().map(|(i, bb)|
((*i) as u128, *bb)), default_block);
for bb in switch_targets.all_targets_mut() {
if *bb == START_BLOCK { *bb = former_entry; }
}
let switch =
TerminatorKind::SwitchInt {
discr: Operand::Move(discr),
targets: switch_targets,
};
body.basic_blocks_mut()[START_BLOCK].terminator =
Some(Terminator {
source_info: SourceInfo::outermost(body.span),
kind: switch,
attributes: ThinVec::new(),
});
}
fn insert_term_block<'tcx>(body: &mut Body<'tcx>,
kind: TerminatorKind<'tcx>) -> BasicBlock {
let source_info = SourceInfo::outermost(body.span);
body.basic_blocks_mut().push(BasicBlockData::new(Some(Terminator {
source_info,
kind,
attributes: ThinVec::new(),
}), false))
}
fn return_poll_ready_assign<'tcx>(tcx: TyCtxt<'tcx>,
source_info: SourceInfo) -> Statement<'tcx> {
let poll_def_id =
tcx.require_lang_item(LangItem::Poll, source_info.span);
let args = tcx.mk_args(&[tcx.types.unit.into()]);
let val =
Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
user_ty: None,
const_: Const::zero_sized(tcx.types.unit),
}));
let ready_val =
Rvalue::Aggregate(Box::new(AggregateKind::Adt(poll_def_id,
VariantIdx::from_usize(0), args, None, None)),
IndexVec::from_raw(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[val]))));
Statement::new(source_info,
StatementKind::Assign(Box::new((Place::return_place(),
ready_val))))
}
fn insert_poll_ready_block<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>)
-> BasicBlock {
let source_info = SourceInfo::outermost(body.span);
body.basic_blocks_mut().push(BasicBlockData::new_stmts([return_poll_ready_assign(tcx,
source_info)].to_vec(),
Some(Terminator {
source_info,
kind: TerminatorKind::Return,
attributes: ThinVec::new(),
}), false))
}
fn insert_panic_block<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>,
message: AssertMessage<'tcx>) -> BasicBlock {
let assert_block = body.basic_blocks.next_index();
let kind =
TerminatorKind::Assert {
cond: Operand::Constant(Box::new(ConstOperand {
span: body.span,
user_ty: None,
const_: Const::from_bool(tcx, false),
})),
expected: true,
msg: Box::new(message),
target: assert_block,
unwind: UnwindAction::Continue,
};
insert_term_block(body, kind)
}
fn can_return<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>,
typing_env: ty::TypingEnv<'tcx>) -> bool {
if body.return_ty().is_privately_uninhabited(tcx, typing_env) {
return false;
}
body.basic_blocks.iter().any(|block|
#[allow(non_exhaustive_omitted_patterns)] match block.terminator().kind
{
TerminatorKind::Return => true,
_ => false,
})
}
fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
if !tcx.sess.panic_strategy().unwinds() { return false; }
body.basic_blocks.iter().any(|block|
block.terminator().unwind().is_some())
}
fn generate_poison_block_and_redirect_unwinds_there<'tcx>(transform:
&TransformVisitor<'tcx>, body: &mut Body<'tcx>) {
let source_info = SourceInfo::outermost(body.span);
let poison_block =
body.basic_blocks_mut().push(BasicBlockData::new_stmts(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[transform.set_discr(VariantIdx::new(CoroutineArgs::POISONED),
source_info)])),
Some(Terminator {
source_info,
kind: TerminatorKind::UnwindResume,
attributes: ThinVec::new(),
}), true));
for (idx, block) in body.basic_blocks_mut().iter_enumerated_mut() {
let source_info = block.terminator().source_info;
if let TerminatorKind::UnwindResume = block.terminator().kind {
if idx != poison_block {
*block.terminator_mut() =
Terminator {
source_info,
kind: TerminatorKind::Goto { target: poison_block },
attributes: ThinVec::new(),
};
}
} else if !block.is_cleanup &&
let Some(unwind @ UnwindAction::Continue) =
block.terminator_mut().unwind_mut() {
*unwind = UnwindAction::Cleanup(poison_block);
}
}
}
fn create_coroutine_resume_function<'tcx>(tcx: TyCtxt<'tcx>,
transform: TransformVisitor<'tcx>, body: &mut Body<'tcx>,
can_return: bool, can_unwind: bool) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("create_coroutine_resume_function",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(867u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("can_return")
}> =
::tracing::__macro_support::FieldName::new("can_return");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("can_unwind")
}> =
::tracing::__macro_support::FieldName::new("can_unwind");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&can_return
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&can_unwind as
&dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
if can_unwind {
generate_poison_block_and_redirect_unwinds_there(&transform,
body);
}
let mut cases =
create_cases(body, &transform, Operation::Resume);
use rustc_middle::mir::AssertKind::{
ResumedAfterPanic, ResumedAfterReturn,
};
cases.insert(0, (CoroutineArgs::UNRESUMED, START_BLOCK));
if can_unwind {
cases.insert(1,
(CoroutineArgs::POISONED,
insert_panic_block(tcx, body,
ResumedAfterPanic(transform.coroutine_kind))));
}
if can_return {
let block =
match transform.coroutine_kind {
CoroutineKind::Desugared(CoroutineDesugaring::Async, _) |
CoroutineKind::Coroutine(_) => {
if tcx.is_async_drop_in_place_coroutine(body.source.def_id())
{
insert_poll_ready_block(tcx, body)
} else {
insert_panic_block(tcx, body,
ResumedAfterReturn(transform.coroutine_kind))
}
}
CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _) |
CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => {
transform.insert_none_ret_block(body)
}
};
cases.insert(1, (CoroutineArgs::RETURNED, block));
}
let default_block =
insert_term_block(body, TerminatorKind::Unreachable);
insert_switch(body, cases, &transform, default_block);
match transform.coroutine_kind {
CoroutineKind::Coroutine(_) |
CoroutineKind::Desugared(CoroutineDesugaring::Async |
CoroutineDesugaring::AsyncGen, _) => {
make_coroutine_state_argument_pinned(tcx, body);
}
CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => {
make_coroutine_state_argument_indirect(tcx, body);
}
}
simplify::remove_dead_blocks(body);
pm::run_passes_no_validate(tcx, body,
&[&abort_unwinding_calls::AbortUnwindingCalls], None);
deref_finder(tcx, body, false);
if transform.coroutine_kind.is_async_desugaring() {
transform_async_context(tcx, body);
}
if let Some(dumper) =
MirDumper::new(tcx, "coroutine_resume", body) {
dumper.dump_mir(body);
}
}
}
}
}
enum Operation { Resume, Drop, AsyncDrop, }
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for Operation { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Operation {
#[inline]
fn eq(&self, other: &Operation) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}
#[automatically_derived]
impl ::core::marker::Copy for Operation { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Operation { }
#[automatically_derived]
impl ::core::clone::Clone for Operation {
#[inline]
fn clone(&self) -> Operation { *self }
}
#[automatically_derived]
impl ::core::fmt::Debug for Operation {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
Operation::Resume => "Resume",
Operation::Drop => "Drop",
Operation::AsyncDrop => "AsyncDrop",
})
}
}
impl Operation {
fn target_block(self, point: &SuspensionPoint<'_>)
-> Option<BasicBlock> {
match self {
Operation::Resume => Some(point.resume),
Operation::Drop | Operation::AsyncDrop => point.drop,
}
}
fn resume_place<'tcx>(self, point: &SuspensionPoint<'tcx>)
-> Option<Place<'tcx>> {
match self {
Operation::Resume | Operation::AsyncDrop =>
Some(point.resume_arg),
Operation::Drop => None,
}
}
}
fn create_cases<'tcx>(body: &mut Body<'tcx>,
transform: &TransformVisitor<'tcx>, operation: Operation)
-> Vec<(usize, BasicBlock)> {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("create_cases",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(976u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("operation")
}> =
::tracing::__macro_support::FieldName::new("operation");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&operation)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Vec<(usize, BasicBlock)> =
loop {};
return __tracing_attr_fake_return;
}
{
let source_info = SourceInfo::outermost(body.span);
transform.suspension_points.iter().filter_map(|point|
{
operation.target_block(point).map(|target|
{
let mut statements = Vec::new();
for l in body.local_decls.indices() {
let needs_storage_live =
point.storage_liveness.contains(l) &&
!transform.remap.contains(l) &&
!transform.always_live_locals.contains(l);
if needs_storage_live {
statements.push(Statement::new(source_info,
StatementKind::StorageLive(l)));
}
}
if let Some(resume_arg) = operation.resume_place(point) &&
resume_arg != CTX_ARG.into() {
statements.push(Statement::new(source_info,
StatementKind::Assign(Box::new((resume_arg,
Rvalue::Use(Operand::Move(CTX_ARG.into()),
WithRetag::Yes))))));
}
let block =
body.basic_blocks_mut().push(BasicBlockData::new_stmts(statements,
Some(Terminator {
source_info,
kind: TerminatorKind::Goto { target },
attributes: ThinVec::new(),
}), false));
(point.state, block)
})
}).collect()
}
}
}
}
impl<'tcx> crate::MirPass<'tcx> for StateTransform {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("run_pass",
"rustc_mir_transform::coroutine", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(1034u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs:1036",
"rustc_mir_transform::coroutine", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(1036u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&body.source.def_id())
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let Some(old_yield_ty) = body.yield_ty() else { return; };
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs:1042",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(1042u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&body.source.def_id())
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let old_ret_ty = body.return_ty();
if !(body.coroutine_drop().is_none() &&
body.coroutine_drop_async().is_none()) {
::core::panicking::panic("assertion failed: body.coroutine_drop().is_none() && body.coroutine_drop_async().is_none()")
};
if let Some(dumper) =
MirDumper::new(tcx, "coroutine_before", body) {
dumper.dump_mir(body);
}
let coroutine_ty = body.local_decls.raw[1].ty;
let coroutine_kind = body.coroutine_kind().unwrap();
let ty::Coroutine(_, args) =
coroutine_ty.kind() else {
tcx.dcx().span_bug(body.span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("unexpected coroutine type {0}",
coroutine_ty))
}));
};
let discr_ty = args.as_coroutine().discr_ty(tcx);
let new_ret_ty =
match coroutine_kind {
CoroutineKind::Desugared(CoroutineDesugaring::Async, _) => {
let poll_did =
tcx.require_lang_item(LangItem::Poll, body.span);
let poll_adt_ref = tcx.adt_def(poll_did);
let poll_args = tcx.mk_args(&[old_ret_ty.into()]);
Ty::new_adt(tcx, poll_adt_ref, poll_args)
}
CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) => {
let option_did =
tcx.require_lang_item(LangItem::Option, body.span);
let option_adt_ref = tcx.adt_def(option_did);
let option_args = tcx.mk_args(&[old_yield_ty.into()]);
Ty::new_adt(tcx, option_adt_ref, option_args)
}
CoroutineKind::Desugared(CoroutineDesugaring::AsyncGen, _)
=> {
old_yield_ty
}
CoroutineKind::Coroutine(_) => {
let state_did =
tcx.require_lang_item(LangItem::CoroutineState, body.span);
let state_adt_ref = tcx.adt_def(state_did);
let state_args =
tcx.mk_args(&[old_yield_ty.into(), old_ret_ty.into()]);
Ty::new_adt(tcx, state_adt_ref, state_args)
}
};
let has_async_drops = has_async_drops(body);
if coroutine_kind.is_async_desugaring() {
eliminate_get_context_calls(tcx, body);
}
let always_live_locals = always_storage_live_locals(body);
let movable =
coroutine_kind.movability() == hir::Movability::Movable;
let liveness_info =
locals_live_across_suspend_points(tcx, body,
&always_live_locals, movable);
if tcx.sess.opts.unstable_opts.validate_mir {
let mut vis =
EnsureCoroutineFieldAssignmentsNeverAlias {
assigned_local: None,
saved_locals: &liveness_info.saved_locals,
storage_conflicts: &liveness_info.storage_conflicts,
};
vis.visit_body(body);
}
let (remap, layout, storage_liveness) =
compute_layout(liveness_info, body);
let can_return =
can_return(tcx, body, body.typing_env(tcx));
let new_ret_local =
body.local_decls.push(LocalDecl::new(new_ret_ty,
body.span));
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs:1125",
"rustc_mir_transform::coroutine", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(1125u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("new_ret_local")
}> =
::tracing::__macro_support::FieldName::new("new_ret_local");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&new_ret_local)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let mut transform =
TransformVisitor {
tcx,
coroutine_kind,
remap,
storage_liveness,
always_live_locals,
suspension_points: Vec::new(),
discr_ty,
new_ret_local,
old_ret_ty,
old_yield_ty,
patch: Some(MirPatch::new(body)),
};
transform.visit_body(body);
transform.replace_local(RETURN_PLACE, new_ret_local, body);
let source_info = SourceInfo::outermost(body.span);
let args_iter = body.args_iter();
body.basic_blocks.as_mut()[START_BLOCK].statements.splice(0..0,
args_iter.filter_map(|local|
{
let (ty, variant_index, idx) = transform.remap[local]?;
let lhs = transform.make_field(variant_index, idx, ty);
let rhs =
Rvalue::Use(Operand::Move(local.into()), WithRetag::Yes);
let assign = StatementKind::Assign(Box::new((lhs, rhs)));
Some(Statement::new(source_info, assign))
}));
transform.patch.take().unwrap().apply(body);
if #[allow(non_exhaustive_omitted_patterns)] match coroutine_kind
{
CoroutineKind::Desugared(CoroutineDesugaring::Gen, _) =>
true,
_ => false,
} {
body.arg_count = 1;
}
for var in &mut body.var_debug_info {
var.argument_index = None;
}
body.coroutine.as_mut().unwrap().yield_ty = None;
body.coroutine.as_mut().unwrap().resume_ty = None;
body.coroutine.as_mut().unwrap().coroutine_layout =
Some(layout);
let drop_clean =
insert_clean_drop(tcx, body, has_async_drops);
if let Some(dumper) =
MirDumper::new(tcx, "coroutine_pre-elab", body) {
dumper.dump_mir(body);
}
elaborate_coroutine_drops(tcx, body);
if let Some(dumper) =
MirDumper::new(tcx, "coroutine_post-transform", body) {
dumper.dump_mir(body);
}
let can_unwind = can_unwind(tcx, body);
if has_async_drops {
let drop_shim =
create_coroutine_drop_shim_async(tcx, &transform, body,
drop_clean, can_unwind);
body.coroutine.as_mut().unwrap().coroutine_drop_async =
Some(drop_shim);
} else {
let drop_shim =
create_coroutine_drop_shim(tcx, &transform, coroutine_ty,
body, drop_clean);
body.coroutine.as_mut().unwrap().coroutine_drop =
Some(drop_shim);
let proxy_shim =
create_coroutine_drop_shim_proxy_async(tcx, body,
coroutine_kind);
body.coroutine.as_mut().unwrap().coroutine_drop_proxy_async
= Some(proxy_shim);
}
create_coroutine_resume_function(tcx, transform, body,
can_return, can_unwind);
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs:1034",
"rustc_mir_transform::coroutine", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coroutine/mod.rs"),
::tracing_core::__macro_support::Option::Some(1034u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coroutine"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::Required
}
}
struct EnsureCoroutineFieldAssignmentsNeverAlias<'a> {
saved_locals: &'a CoroutineSavedLocals,
storage_conflicts: &'a BitMatrix<CoroutineSavedLocal,
CoroutineSavedLocal>,
assigned_local: Option<CoroutineSavedLocal>,
}
impl EnsureCoroutineFieldAssignmentsNeverAlias<'_> {
fn saved_local_for_direct_place(&self, place: Place<'_>)
-> Option<CoroutineSavedLocal> {
if place.is_indirect() { return None; }
self.saved_locals.get(place.local)
}
fn check_assigned_place(&mut self, place: Place<'_>,
f: impl FnOnce(&mut Self)) {
if let Some(assigned_local) =
self.saved_local_for_direct_place(place) {
if !self.assigned_local.is_none() {
{
::core::panicking::panic_fmt(format_args!("`check_assigned_place` must not recurse"));
}
};
self.assigned_local = Some(assigned_local);
f(self);
self.assigned_local = None;
}
}
}
impl<'tcx> Visitor<'tcx> for EnsureCoroutineFieldAssignmentsNeverAlias<'_>
{
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext,
location: Location) {
let Some(lhs) =
self.assigned_local else {
if !!context.is_use() {
::core::panicking::panic("assertion failed: !context.is_use()")
};
return;
};
let Some(rhs) =
self.saved_local_for_direct_place(*place) else { return };
if !self.storage_conflicts.contains(lhs, rhs) {
::rustc_middle::util::bug::bug_fmt(format_args!("Assignment between coroutine saved locals whose storage is not marked as conflicting: {0:?}: {1:?} = {2:?}",
location, lhs, rhs));
}
}
fn visit_statement(&mut self, statement: &Statement<'tcx>,
location: Location) {
match &statement.kind {
StatementKind::Assign((lhs, rhs)) => {
self.check_assigned_place(*lhs,
|this| this.visit_rvalue(rhs, location));
}
StatementKind::FakeRead(..) | StatementKind::SetDiscriminant {
.. } | StatementKind::StorageLive(_) |
StatementKind::StorageDead(_) |
StatementKind::AscribeUserType(..) |
StatementKind::PlaceMention(..) |
StatementKind::Coverage(..) | StatementKind::Intrinsic(..) |
StatementKind::ConstEvalCounter |
StatementKind::BackwardIncompatibleDropHint { .. } |
StatementKind::Nop => {}
}
}
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>,
location: Location) {
match &terminator.kind {
TerminatorKind::Call {
func,
args,
destination,
target: Some(_),
unwind: _,
call_source: _,
fn_span: _ } => {
self.check_assigned_place(*destination,
|this|
{
this.visit_operand(func, location);
for arg in args { this.visit_operand(&arg.node, location); }
});
}
TerminatorKind::Yield { value, resume: _, resume_arg, drop: _
} => {
self.check_assigned_place(*resume_arg,
|this| this.visit_operand(value, location));
}
TerminatorKind::InlineAsm { .. } => {}
TerminatorKind::Call { .. } | TerminatorKind::Goto { .. } |
TerminatorKind::SwitchInt { .. } |
TerminatorKind::UnwindResume |
TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return
| TerminatorKind::TailCall { .. } |
TerminatorKind::Unreachable | TerminatorKind::Drop { .. } |
TerminatorKind::Assert { .. } |
TerminatorKind::CoroutineDrop | TerminatorKind::FalseEdge {
.. } | TerminatorKind::FalseUnwind { .. } => {}
}
}
}
}
#[allow(unused_imports)]
use coroutine::StateTransform as _;
mod coverage {
use rustc_middle::mir::coverage::{CoverageKind, CoverageMirInfo};
use rustc_middle::mir::{
self, BasicBlock, Statement, StatementKind, TerminatorKind,
};
use rustc_middle::ty::TyCtxt;
use tracing::{debug, debug_span, trace};
use crate::PassPolicy;
use crate::coverage::counters::BcbCountersData;
use crate::coverage::graph::CoverageGraph;
use crate::coverage::mappings::ExtractedMappings;
mod counters {
use std::cmp::Ordering;
use either::Either;
use itertools::Itertools;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_data_structures::graph::DirectedGraph;
use rustc_index::IndexVec;
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::mir::coverage::{
CounterId, CovTerm, Expression, ExpressionId, Op,
};
use crate::coverage::counters::balanced_flow::BalancedFlowGraph;
use crate::coverage::counters::node_flow::{
CounterTerm, NodeCounters, NodeFlowData,
node_flow_data_for_balanced_graph,
};
use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
mod balanced_flow {
use rustc_data_structures::graph;
use rustc_data_structures::graph::iterate::DepthFirstSearch;
use rustc_data_structures::graph::reversed::ReversedGraph;
use rustc_index::Idx;
use rustc_index::bit_set::DenseBitSet;
pub(crate) struct BalancedFlowGraph<G: graph::DirectedGraph> {
graph: G,
sink_edge_nodes: DenseBitSet<G::Node>,
pub(crate) sink: G::Node,
}
impl<G: graph::DirectedGraph> BalancedFlowGraph<G> {
pub(crate) fn for_graph(graph: G,
force_sink_edge: impl Fn(G::Node) -> bool) -> Self where
G: graph::ControlFlowGraph {
let mut sink_edge_nodes =
DenseBitSet::new_empty(graph.num_nodes());
let mut dfs =
DepthFirstSearch::new(ReversedGraph::new(&graph));
for node in graph.iter_nodes() {
if force_sink_edge(node) ||
graph.successors(node).next().is_none() {
sink_edge_nodes.insert(node);
dfs.push_start_node(node);
}
}
dfs.complete_search();
sink_edge_nodes.union_not(dfs.visited_set());
let sink = G::Node::new(graph.num_nodes());
BalancedFlowGraph { graph, sink_edge_nodes, sink }
}
}
impl<G> graph::DirectedGraph for BalancedFlowGraph<G> where
G: graph::DirectedGraph {
type Node = G::Node;
fn num_nodes(&self) -> usize { self.sink.index() + 1 }
}
impl<G> graph::StartNode for BalancedFlowGraph<G> where
G: graph::StartNode {
fn start_node(&self) -> Self::Node { self.graph.start_node() }
}
impl<G> graph::Successors for BalancedFlowGraph<G> where
G: graph::StartNode + graph::Successors {
fn successors(&self, node: Self::Node)
-> impl Iterator<Item = Self::Node> {
let real_edges;
let sink_edge;
if node == self.sink {
real_edges = None;
sink_edge = Some(self.graph.start_node());
} else {
real_edges = Some(self.graph.successors(node));
sink_edge =
self.sink_edge_nodes.contains(node).then_some(self.sink);
}
real_edges.into_flat_iter().chain(sink_edge)
}
}
}
pub(crate) mod node_flow {
use rustc_data_structures::graph;
use rustc_data_structures::union_find::UnionFind;
use rustc_index::bit_set::DenseBitSet;
use rustc_index::{Idx, IndexSlice, IndexVec};
pub(crate) use rustc_middle::mir::coverage::NodeFlowData;
use rustc_middle::mir::coverage::Op;
pub(crate) fn node_flow_data_for_balanced_graph<G>(graph: G)
-> NodeFlowData<G::Node> where G: graph::Successors {
let mut supernodes =
UnionFind::<G::Node>::new(graph.num_nodes());
let successors =
graph.iter_nodes().map(|node|
{
graph.successors(node).reduce(|a, b|
supernodes.unify(a,
b)).expect("each node in a balanced graph must have at least one out-edge")
}).collect::<IndexVec<G::Node, G::Node>>();
let supernodes = supernodes.snapshot();
let succ_supernodes =
successors.into_iter().map(|succ|
supernodes[succ]).collect();
NodeFlowData { supernodes, succ_supernodes }
}
pub(crate) fn make_node_counters<Node: Idx>(node_flow_data:
&NodeFlowData<Node>, priority_list: &[Node])
-> NodeCounters<Node> {
let mut builder = SpantreeBuilder::new(node_flow_data);
for &node in priority_list { builder.visit_node(node); }
NodeCounters { counter_terms: builder.finish() }
}
pub(crate) struct NodeCounters<Node: Idx> {
pub(crate) counter_terms: IndexVec<Node,
Vec<CounterTerm<Node>>>,
}
#[automatically_derived]
impl<Node: ::core::fmt::Debug + Idx> ::core::fmt::Debug for
NodeCounters<Node> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"NodeCounters", "counter_terms", &&self.counter_terms)
}
}
struct SpantreeEdge<Node> {
is_reversed: bool,
claiming_node: Node,
span_parent: Node,
}
#[automatically_derived]
impl<Node: ::core::fmt::Debug> ::core::fmt::Debug for
SpantreeEdge<Node> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"SpantreeEdge", "is_reversed", &self.is_reversed,
"claiming_node", &self.claiming_node, "span_parent",
&&self.span_parent)
}
}
pub(crate) struct CounterTerm<Node> {
pub(crate) op: Op,
pub(crate) node: Node,
}
#[automatically_derived]
impl<Node: ::core::fmt::Debug> ::core::fmt::Debug for
CounterTerm<Node> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"CounterTerm", "op", &self.op, "node", &&self.node)
}
}
struct SpantreeBuilder<'a, Node: Idx> {
supernodes: &'a IndexSlice<Node, Node>,
succ_supernodes: &'a IndexSlice<Node, Node>,
is_unvisited: DenseBitSet<Node>,
span_edges: IndexVec<Node, Option<SpantreeEdge<Node>>>,
yank_buffer: Vec<Node>,
counter_terms: IndexVec<Node, Vec<CounterTerm<Node>>>,
}
#[automatically_derived]
impl<'a, Node: ::core::fmt::Debug + Idx> ::core::fmt::Debug for
SpantreeBuilder<'a, Node> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
let names: &'static _ =
&["supernodes", "succ_supernodes", "is_unvisited",
"span_edges", "yank_buffer", "counter_terms"];
let values: &[&dyn ::core::fmt::Debug] =
&[&self.supernodes, &self.succ_supernodes,
&self.is_unvisited, &self.span_edges, &self.yank_buffer,
&&self.counter_terms];
::core::fmt::Formatter::debug_struct_fields_finish(f,
"SpantreeBuilder", names, values)
}
}
impl<'a, Node: Idx> SpantreeBuilder<'a, Node> {
fn new(node_flow_data: &'a NodeFlowData<Node>) -> Self {
let NodeFlowData { supernodes, succ_supernodes } =
node_flow_data;
let num_nodes = supernodes.len();
Self {
supernodes,
succ_supernodes,
is_unvisited: DenseBitSet::new_filled(num_nodes),
span_edges: IndexVec::from_fn_n(|_| None, num_nodes),
yank_buffer: ::alloc::vec::Vec::new(),
counter_terms: IndexVec::from_fn_n(|_|
::alloc::vec::Vec::new(), num_nodes),
}
}
fn is_supernode(&self, node: Node) -> bool {
self.supernodes[node] == node
}
fn spantree_root(&self, this: Node) -> Node {
if true {
if !self.is_supernode(this) {
::core::panicking::panic("assertion failed: self.is_supernode(this)")
};
};
match self.span_edges[this] {
None => this,
Some(SpantreeEdge { span_parent, .. }) =>
self.spantree_root(span_parent),
}
}
fn yank_to_spantree_root(&mut self, this: Node) {
if true {
if !self.is_supernode(this) {
::core::panicking::panic("assertion failed: self.is_supernode(this)")
};
};
let path_buf = &mut self.yank_buffer;
path_buf.clear();
path_buf.push(this);
let mut curr = this;
while let &Some(SpantreeEdge { span_parent, .. }) =
&self.span_edges[curr] {
path_buf.push(span_parent);
curr = span_parent;
}
for &[a, b] in path_buf.array_windows::<2>().rev() {
let SpantreeEdge { is_reversed, claiming_node, span_parent
} =
self.span_edges[a].take().expect("all nodes in the path (except the last) have a `span_parent`");
if true {
{
match (&span_parent, &b) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
if true {
if !self.span_edges[b].is_none() {
::core::panicking::panic("assertion failed: self.span_edges[b].is_none()")
};
};
self.span_edges[b] =
Some(SpantreeEdge {
is_reversed: !is_reversed,
claiming_node,
span_parent: a,
});
}
if true {
if !self.span_edges[this].is_none() {
::core::panicking::panic("assertion failed: self.span_edges[this].is_none()")
};
};
}
fn visit_node(&mut self, this: Node) {
if !self.is_unvisited.remove(this) {
{
::core::panicking::panic_fmt(format_args!("node has already been visited: {0:?}",
this));
}
};
let this_supernode = self.supernodes[this];
self.yank_to_spantree_root(this_supernode);
let succ_supernode = self.succ_supernodes[this];
if true {
if !self.is_supernode(succ_supernode) {
::core::panicking::panic("assertion failed: self.is_supernode(succ_supernode)")
};
};
if this_supernode != self.spantree_root(succ_supernode) {
self.span_edges[this_supernode] =
Some(SpantreeEdge {
is_reversed: false,
claiming_node: this,
span_parent: succ_supernode,
});
} else {
self.counter_terms[this].push(CounterTerm {
node: this,
op: Op::Add,
});
let mut curr = succ_supernode;
while curr != this_supernode {
let &SpantreeEdge { is_reversed, claiming_node, span_parent
} = self.span_edges[curr].as_ref().unwrap();
let op = if is_reversed { Op::Subtract } else { Op::Add };
self.counter_terms[claiming_node].push(CounterTerm {
node: this,
op,
});
curr = span_parent;
}
}
}
fn finish(self) -> IndexVec<Node, Vec<CounterTerm<Node>>> {
let Self {
ref span_edges, ref is_unvisited, ref counter_terms, .. } =
self;
if !is_unvisited.is_empty() {
{
::core::panicking::panic_fmt(format_args!("some nodes were never visited: {0:?}",
is_unvisited));
}
};
if true {
if !span_edges.iter_enumerated().all(|(node, span_edge)|
{ span_edge.is_some() <= self.is_supernode(node) }) {
{
::core::panicking::panic_fmt(format_args!("only supernodes can have a span edge"));
}
};
};
if true {
if !counter_terms.iter().all(|terms| !terms.is_empty()) {
{
::core::panicking::panic_fmt(format_args!("after visiting all nodes, every node should have at least one term"));
}
};
};
self.counter_terms
}
}
}
pub(crate) struct BcbCountersData {
pub(crate) node_flow_data: NodeFlowData<BasicCoverageBlock>,
pub(crate) priority_list: Vec<BasicCoverageBlock>,
}
pub(crate) fn prepare_bcb_counters_data(graph: &CoverageGraph)
-> BcbCountersData {
let balanced_graph =
BalancedFlowGraph::for_graph(graph,
|n| !graph[n].is_out_summable);
let node_flow_data =
node_flow_data_for_balanced_graph(&balanced_graph);
let priority_list =
make_node_flow_priority_list(graph, balanced_graph);
BcbCountersData { node_flow_data, priority_list }
}
fn make_node_flow_priority_list(graph: &CoverageGraph,
balanced_graph: BalancedFlowGraph<&CoverageGraph>)
-> Vec<BasicCoverageBlock> {
let is_reloop_node =
IndexVec::<BasicCoverageBlock,
_>::from_fn_n(|node|
match graph.successors[node].as_slice() {
&[succ] => graph.dominates(succ, node),
_ => false,
}, graph.num_nodes());
let mut nodes =
balanced_graph.iter_nodes().rev().collect::<Vec<_>>();
{
match (&nodes[0], &balanced_graph.sink) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
nodes[1..].sort_by(|&a, &b|
{
Ordering::Equal.then_with(||
Ord::cmp(&graph[a].is_out_summable,
&graph[b].is_out_summable)).then_with(||
Ord::cmp(&is_reloop_node[a],
&is_reloop_node[b]).reverse()).then_with(||
graph.cmp_in_dominator_order(a, b).reverse())
});
nodes
}
pub(crate) fn transcribe_counters(old:
&NodeCounters<BasicCoverageBlock>,
bcb_needs_counter: &DenseBitSet<BasicCoverageBlock>,
bcbs_seen: &DenseBitSet<BasicCoverageBlock>) -> CoverageCounters {
let mut new =
CoverageCounters::with_num_bcbs(bcb_needs_counter.domain_size());
for bcb in bcb_needs_counter.iter() {
if !bcbs_seen.contains(bcb) {
new.set_node_counter(bcb, CovTerm::Zero);
continue;
}
let (mut pos, mut neg): (Vec<_>, Vec<_>) =
old.counter_terms[bcb].iter().filter(|term|
bcbs_seen.contains(term.node)).partition_map(|&CounterTerm {
node, op }|
match op {
Op::Add => Either::Left(node),
Op::Subtract => Either::Right(node),
});
pos.sort();
neg.sort();
let mut new_counters_for_sites =
|sites: Vec<BasicCoverageBlock>|
{
sites.into_iter().map(|node|
new.ensure_phys_counter(node)).collect::<Vec<_>>()
};
let pos = new_counters_for_sites(pos);
let neg = new_counters_for_sites(neg);
let pos_counter = new.make_sum(&pos).unwrap_or(CovTerm::Zero);
let new_counter = new.make_subtracted_sum(pos_counter, &neg);
new.set_node_counter(bcb, new_counter);
}
new
}
pub(super) struct CoverageCounters {
pub(crate) phys_counter_for_node: FxIndexMap<BasicCoverageBlock,
CounterId>,
pub(crate) next_counter_id: CounterId,
pub(crate) node_counters: IndexVec<BasicCoverageBlock,
Option<CovTerm>>,
pub(crate) expressions: IndexVec<ExpressionId, Expression>,
expressions_memo: FxHashMap<Expression, CovTerm>,
}
impl CoverageCounters {
fn with_num_bcbs(num_bcbs: usize) -> Self {
Self {
phys_counter_for_node: FxIndexMap::default(),
next_counter_id: CounterId::ZERO,
node_counters: IndexVec::from_elem_n(None, num_bcbs),
expressions: IndexVec::new(),
expressions_memo: FxHashMap::default(),
}
}
fn ensure_phys_counter(&mut self, bcb: BasicCoverageBlock)
-> CovTerm {
let id =
*self.phys_counter_for_node.entry(bcb).or_insert_with(||
{
let id = self.next_counter_id;
self.next_counter_id = id + 1;
id
});
CovTerm::Counter(id)
}
fn make_expression(&mut self, lhs: CovTerm, op: Op, rhs: CovTerm)
-> CovTerm {
let new_expr = Expression { lhs, op, rhs };
*self.expressions_memo.entry(new_expr.clone()).or_insert_with(||
{
let id = self.expressions.push(new_expr);
CovTerm::Expression(id)
})
}
fn make_sum(&mut self, counters: &[CovTerm]) -> Option<CovTerm> {
counters.iter().copied().reduce(|accum, counter|
self.make_expression(accum, Op::Add, counter))
}
fn make_subtracted_sum(&mut self, lhs: CovTerm, rhs: &[CovTerm])
-> CovTerm {
let Some(rhs_sum) = self.make_sum(rhs) else { return lhs };
self.make_expression(lhs, Op::Subtract, rhs_sum)
}
fn set_node_counter(&mut self, bcb: BasicCoverageBlock,
counter: CovTerm) -> CovTerm {
let existing = self.node_counters[bcb].replace(counter);
if !existing.is_none() {
{
::core::panicking::panic_fmt(format_args!("node {0:?} already has a counter: {1:?} => {2:?}",
bcb, existing, counter));
}
};
counter
}
}
}
mod expansion {
use itertools::Itertools;
use rustc_data_structures::fx::{FxIndexMap, FxIndexSet, IndexEntry};
use rustc_middle::mir;
use rustc_middle::mir::coverage::{BasicCoverageBlock, BranchSpan};
use rustc_span::{ExpnKind, Span, SyntaxContext};
use crate::coverage::from_mir;
use crate::coverage::graph::CoverageGraph;
use crate::coverage::hir_info::ExtractedHirInfo;
use crate::coverage::mappings::MappingsError;
pub(crate) struct SpanWithBcb {
pub(crate) span: Span,
pub(crate) bcb: BasicCoverageBlock,
}
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for SpanWithBcb { }
#[automatically_derived]
impl ::core::clone::Clone for SpanWithBcb {
#[inline]
fn clone(&self) -> SpanWithBcb {
let _: ::core::clone::AssertParamIsClone<Span>;
let _: ::core::clone::AssertParamIsClone<BasicCoverageBlock>;
*self
}
}
#[automatically_derived]
impl ::core::marker::Copy for SpanWithBcb { }
#[automatically_derived]
impl ::core::fmt::Debug for SpanWithBcb {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"SpanWithBcb", "span", &self.span, "bcb", &&self.bcb)
}
}
pub(crate) struct ExpnTree {
nodes: FxIndexMap<SyntaxContext, ExpnNode>,
}
#[automatically_derived]
impl ::core::fmt::Debug for ExpnTree {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"ExpnTree", "nodes", &&self.nodes)
}
}
impl ExpnTree {
pub(crate) fn get(&self, context: SyntaxContext)
-> Option<&ExpnNode> {
self.nodes.get(&context)
}
}
pub(crate) struct ExpnNode {
#[expect(dead_code)]
pub(crate) context: SyntaxContext,
pub(crate) dfs_rank: usize,
pub(crate) expn_kind: ExpnKind,
pub(crate) call_site: Option<Span>,
pub(crate) call_site_context: Option<SyntaxContext>,
pub(crate) fn_sig_span: Option<Span>,
pub(crate) body_span: Option<Span>,
pub(crate) spans: Vec<SpanWithBcb>,
pub(crate) child_contexts: FxIndexSet<SyntaxContext>,
pub(crate) minmax_bcbs: Option<MinMaxBcbs>,
pub(crate) branch_spans: Vec<BranchSpan>,
pub(crate) hole_spans: Vec<Span>,
}
#[automatically_derived]
impl ::core::fmt::Debug for ExpnNode {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
let names: &'static _ =
&["context", "dfs_rank", "expn_kind", "call_site",
"call_site_context", "fn_sig_span", "body_span", "spans",
"child_contexts", "minmax_bcbs", "branch_spans",
"hole_spans"];
let values: &[&dyn ::core::fmt::Debug] =
&[&self.context, &self.dfs_rank, &self.expn_kind,
&self.call_site, &self.call_site_context, &self.fn_sig_span,
&self.body_span, &self.spans, &self.child_contexts,
&self.minmax_bcbs, &self.branch_spans, &&self.hole_spans];
::core::fmt::Formatter::debug_struct_fields_finish(f,
"ExpnNode", names, values)
}
}
impl ExpnNode {
fn for_context(context: SyntaxContext) -> Self {
let expn_data = context.outer_expn_data();
let call_site =
Some(expn_data.call_site).filter(|sp| !sp.is_dummy());
let call_site_context = try { call_site?.ctxt() };
Self {
context,
dfs_rank: usize::MAX,
expn_kind: expn_data.kind,
call_site,
call_site_context,
fn_sig_span: None,
body_span: None,
spans: ::alloc::vec::Vec::new(),
child_contexts: FxIndexSet::default(),
minmax_bcbs: None,
branch_spans: ::alloc::vec::Vec::new(),
hole_spans: ::alloc::vec::Vec::new(),
}
}
}
pub(crate) fn build_expn_tree(mir_body: &mir::Body<'_>,
hir_info: &ExtractedHirInfo, graph: &CoverageGraph)
-> Result<ExpnTree, MappingsError> {
let raw_spans =
from_mir::extract_raw_spans_from_mir(mir_body, hir_info,
graph);
let mut nodes = FxIndexMap::default();
let new_node =
|&context: &SyntaxContext| ExpnNode::for_context(context);
for from_mir::RawSpanFromMir { raw_span, bcb } in raw_spans {
let span_with_bcb = SpanWithBcb { span: raw_span, bcb };
let context = span_with_bcb.span.ctxt();
let node = nodes.entry(context).or_insert_with_key(new_node);
node.spans.push(span_with_bcb);
let mut prev = context;
let mut curr_context = node.call_site_context;
while let Some(context) = curr_context {
let entry = nodes.entry(context);
let node_existed =
#[allow(non_exhaustive_omitted_patterns)] match entry {
IndexEntry::Occupied(_) => true,
_ => false,
};
let node = entry.or_insert_with_key(new_node);
node.child_contexts.insert(prev);
if node_existed { break; }
prev = context;
curr_context = node.call_site_context;
}
}
sort_nodes_depth_first(&mut nodes)?;
for i in (0..nodes.len()).rev() {
let minmax_bcbs =
minmax_bcbs_for_expn_tree_node(graph, &nodes, &nodes[i]);
nodes[i].minmax_bcbs = minmax_bcbs;
}
if let Some(fn_sig_span) = hir_info.fn_sig_span &&
let Some(node) = nodes.get_mut(&fn_sig_span.ctxt()) {
node.fn_sig_span = Some(fn_sig_span);
}
let body_span = hir_info.body_span;
if let Some(node) = nodes.get_mut(&body_span.ctxt()) {
node.body_span = Some(body_span);
}
for &hole_span in &hir_info.hole_spans {
let context = hole_span.ctxt();
let Some(node) = nodes.get_mut(&context) else { continue };
node.hole_spans.push(hole_span);
}
if let Some(early_info) = mir_body.coverage_early_info.as_deref()
{
for branch_span in &early_info.branch_spans {
if let Some(node) = nodes.get_mut(&branch_span.span.ctxt())
{
node.branch_spans.push(BranchSpan::clone(branch_span));
}
}
}
Ok(ExpnTree { nodes })
}
fn sort_nodes_depth_first(nodes:
&mut FxIndexMap<SyntaxContext, ExpnNode>)
-> Result<(), MappingsError> {
let mut dfs_stack =
::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[SyntaxContext::root()]));
let mut next_dfs_rank = 0usize;
while let Some(context) = dfs_stack.pop() {
if let Some(node) = nodes.get_mut(&context) {
node.dfs_rank = next_dfs_rank;
next_dfs_rank += 1;
dfs_stack.extend(node.child_contexts.iter().rev().copied());
}
}
nodes.sort_by_key(|_context, node| node.dfs_rank);
for (i, &ExpnNode { dfs_rank, .. }) in nodes.values().enumerate()
{
if dfs_rank != i {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/expansion.rs:208",
"rustc_mir_transform::coverage::expansion",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/expansion.rs"),
::tracing_core::__macro_support::Option::Some(208u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coverage::expansion"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("dfs_rank")
}> =
::tracing::__macro_support::FieldName::new("dfs_rank");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("i")
}> =
::tracing::__macro_support::FieldName::new("i");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("expansion tree node\'s rank does not match its index")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&dfs_rank as
&dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&i as
&dyn ::tracing::field::Value))])
});
} else { ; }
};
return Err(MappingsError::TreeSortFailure);
}
}
Ok(())
}
pub(crate) struct MinMaxBcbs {
pub(crate) min: BasicCoverageBlock,
pub(crate) max: BasicCoverageBlock,
}
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for MinMaxBcbs { }
#[automatically_derived]
impl ::core::clone::Clone for MinMaxBcbs {
#[inline]
fn clone(&self) -> MinMaxBcbs {
let _: ::core::clone::AssertParamIsClone<BasicCoverageBlock>;
*self
}
}
#[automatically_derived]
impl ::core::marker::Copy for MinMaxBcbs { }
#[automatically_derived]
impl ::core::fmt::Debug for MinMaxBcbs {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"MinMaxBcbs", "min", &self.min, "max", &&self.max)
}
}
fn minmax_bcbs_for_expn_tree_node(graph: &CoverageGraph,
nodes: &FxIndexMap<SyntaxContext, ExpnNode>, node: &ExpnNode)
-> Option<MinMaxBcbs> {
let immediate_span_bcbs =
node.spans.iter().map(|sp: &SpanWithBcb| sp.bcb);
let child_minmax_bcbs =
node.child_contexts.iter().flat_map(|id|
nodes.get(id)).flat_map(|child|
child.minmax_bcbs).flat_map(|MinMaxBcbs { min, max }|
[min, max]);
let (min, max) =
Iterator::chain(immediate_span_bcbs,
child_minmax_bcbs).minmax_by(|&a, &b|
graph.cmp_in_dominator_order(a, b)).into_option()?;
Some(MinMaxBcbs { min, max })
}
}
mod from_mir {
use rustc_middle::mir::coverage::{CoverageKind, PointKind};
use rustc_middle::mir::{self, Statement, StatementKind};
use rustc_span::Span;
use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
use crate::coverage::hir_info::ExtractedHirInfo;
pub(crate) struct RawSpanFromMir {
pub(crate) raw_span: Span,
pub(crate) bcb: BasicCoverageBlock,
}
#[automatically_derived]
impl ::core::fmt::Debug for RawSpanFromMir {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"RawSpanFromMir", "raw_span", &self.raw_span, "bcb",
&&self.bcb)
}
}
pub(crate) fn extract_raw_spans_from_mir<'tcx>(mir_body:
&mir::Body<'tcx>, hir_info: &ExtractedHirInfo,
graph: &CoverageGraph) -> Vec<RawSpanFromMir> {
let mut raw_spans = ::alloc::vec::Vec::new();
for (bcb, bcb_data) in graph.iter_enumerated() {
for &bb in &bcb_data.basic_blocks {
let statements = mir_body[bb].statements.iter();
raw_spans.extend(statements.filter_map(|stmt|
filtered_statement_span(hir_info,
stmt)).map(|raw_span: Span|
RawSpanFromMir { raw_span, bcb }));
}
}
raw_spans
}
fn filtered_statement_span<'tcx>(hir_info: &ExtractedHirInfo,
statement: &Statement<'tcx>) -> Option<Span> {
let StatementKind::Coverage(CoverageKind::Point {
point_kind, hir_id }) =
statement.kind else { return None; };
match point_kind {
PointKind::Expr | PointKind::ImplicitElse |
PointKind::FunctionEnd => {}
}
if hir_info.nodes_to_ignore.contains(&hir_id) { return None; }
Some(statement.source_info.span)
}
}
mod graph {
use std::cmp::Ordering;
use std::ops::{Index, IndexMut};
use std::{mem, slice};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::graph::dominators::Dominators;
use rustc_data_structures::graph::{self, DirectedGraph, StartNode};
use rustc_index::IndexVec;
use rustc_index::bit_set::DenseBitSet;
pub(crate) use rustc_middle::mir::coverage::{
BasicCoverageBlock, START_BCB,
};
use rustc_middle::mir::{self, BasicBlock, Terminator, TerminatorKind};
use tracing::debug;
pub(crate) struct CoverageGraph {
bcbs: IndexVec<BasicCoverageBlock, BasicCoverageBlockData>,
bb_to_bcb: IndexVec<BasicBlock, Option<BasicCoverageBlock>>,
pub(crate) successors: IndexVec<BasicCoverageBlock,
Vec<BasicCoverageBlock>>,
pub(crate) predecessors: IndexVec<BasicCoverageBlock,
Vec<BasicCoverageBlock>>,
dominators: Option<Dominators<BasicCoverageBlock>>,
dominator_order_rank: IndexVec<BasicCoverageBlock, u32>,
is_loop_header: DenseBitSet<BasicCoverageBlock>,
enclosing_loop_header: IndexVec<BasicCoverageBlock,
Option<BasicCoverageBlock>>,
}
#[automatically_derived]
impl ::core::fmt::Debug for CoverageGraph {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
let names: &'static _ =
&["bcbs", "bb_to_bcb", "successors", "predecessors",
"dominators", "dominator_order_rank", "is_loop_header",
"enclosing_loop_header"];
let values: &[&dyn ::core::fmt::Debug] =
&[&self.bcbs, &self.bb_to_bcb, &self.successors,
&self.predecessors, &self.dominators,
&self.dominator_order_rank, &self.is_loop_header,
&&self.enclosing_loop_header];
::core::fmt::Formatter::debug_struct_fields_finish(f,
"CoverageGraph", names, values)
}
}
impl CoverageGraph {
pub(crate) fn from_mir(mir_body: &mir::Body<'_>) -> Self {
let (bcbs, bb_to_bcb) =
Self::compute_basic_coverage_blocks(mir_body);
let successors =
IndexVec::<BasicCoverageBlock,
_>::from_fn_n(|bcb|
{
let mut seen_bcbs = FxHashSet::default();
let terminator = mir_body[bcbs[bcb].last_bb()].terminator();
bcb_filtered_successors(terminator).into_iter().filter_map(|successor_bb|
bb_to_bcb[successor_bb]).filter(|&successor_bcb|
seen_bcbs.insert(successor_bcb)).collect::<Vec<_>>()
}, bcbs.len());
let mut predecessors = IndexVec::from_elem(Vec::new(), &bcbs);
for (bcb, bcb_successors) in successors.iter_enumerated() {
for &successor in bcb_successors {
predecessors[successor].push(bcb);
}
}
let num_nodes = bcbs.len();
let mut this =
Self {
bcbs,
bb_to_bcb,
successors,
predecessors,
dominators: None,
dominator_order_rank: IndexVec::from_elem_n(0, num_nodes),
is_loop_header: DenseBitSet::new_empty(num_nodes),
enclosing_loop_header: IndexVec::from_elem_n(None,
num_nodes),
};
{
match (&num_nodes, &this.num_nodes()) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
this.dominators = Some(graph::dominators::dominators(&this));
let dominator_order =
graph::iterate::reverse_post_order(&this,
this.start_node());
{
match (&dominator_order.len(), &this.num_nodes()) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
for (rank, bcb) in (0u32..).zip(dominator_order) {
this.dominator_order_rank[bcb] = rank;
if this.reloop_predecessors(bcb).next().is_some() {
this.is_loop_header.insert(bcb);
}
if let Some(dom) =
this.dominators().immediate_dominator(bcb) {
this.enclosing_loop_header[bcb] =
this.is_loop_header.contains(dom).then_some(dom).or_else(||
this.enclosing_loop_header[dom]);
}
}
if !(this[START_BCB].leader_bb() == mir::START_BLOCK) {
::core::panicking::panic("assertion failed: this[START_BCB].leader_bb() == mir::START_BLOCK")
};
if !this.predecessors[START_BCB].is_empty() {
::core::panicking::panic("assertion failed: this.predecessors[START_BCB].is_empty()")
};
this
}
fn compute_basic_coverage_blocks(mir_body: &mir::Body<'_>)
->
(IndexVec<BasicCoverageBlock, BasicCoverageBlockData>,
IndexVec<BasicBlock, Option<BasicCoverageBlock>>) {
let num_basic_blocks = mir_body.basic_blocks.len();
let mut bcbs =
IndexVec::<BasicCoverageBlock,
_>::with_capacity(num_basic_blocks);
let mut bb_to_bcb =
IndexVec::from_elem_n(None, num_basic_blocks);
let mut flush_chain_into_new_bcb =
|current_chain: &mut Vec<BasicBlock>|
{
let basic_blocks = mem::take(current_chain);
let bcb = bcbs.next_index();
for &bb in basic_blocks.iter() {
bb_to_bcb[bb] = Some(bcb);
}
let is_out_summable =
basic_blocks.last().is_some_and(|&bb|
{
bcb_filtered_successors(mir_body[bb].terminator()).is_out_summable()
});
let bcb_data =
BasicCoverageBlockData { basic_blocks, is_out_summable };
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/graph.rs:142",
"rustc_mir_transform::coverage::graph",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/graph.rs"),
::tracing_core::__macro_support::Option::Some(142u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coverage::graph"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("adding {0:?}: {1:?}",
bcb, bcb_data) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
bcbs.push(bcb_data);
};
let mut current_chain = ::alloc::vec::Vec::new();
let subgraph =
CoverageRelevantSubgraph::new(&mir_body.basic_blocks);
for bb in
graph::depth_first_search(subgraph,
mir::START_BLOCK).filter(|&bb|
mir_body[bb].terminator().kind !=
TerminatorKind::Unreachable) {
if let Some(&prev) = current_chain.last() {
let can_chain =
subgraph.coverage_successors(prev).is_out_chainable() &&
mir_body.basic_blocks.predecessors()[bb].as_slice() ==
&[prev];
if !can_chain {
flush_chain_into_new_bcb(&mut current_chain);
}
}
current_chain.push(bb);
}
if !current_chain.is_empty() {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/graph.rs:175",
"rustc_mir_transform::coverage::graph",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/graph.rs"),
::tracing_core::__macro_support::Option::Some(175u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coverage::graph"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("flushing accumulated blocks into one last BCB")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
flush_chain_into_new_bcb(&mut current_chain);
}
(bcbs, bb_to_bcb)
}
#[inline(always)]
pub(crate) fn iter_enumerated(&self)
->
impl Iterator<Item =
(BasicCoverageBlock, &BasicCoverageBlockData)> {
self.bcbs.iter_enumerated()
}
#[inline(always)]
pub(crate) fn bcb_from_bb(&self, bb: BasicBlock)
-> Option<BasicCoverageBlock> {
if bb.index() < self.bb_to_bcb.len() {
self.bb_to_bcb[bb]
} else { None }
}
#[inline(always)]
fn dominators(&self) -> &Dominators<BasicCoverageBlock> {
self.dominators.as_ref().unwrap()
}
#[inline(always)]
pub(crate) fn dominates(&self, dom: BasicCoverageBlock,
node: BasicCoverageBlock) -> bool {
self.dominators().dominates(dom, node)
}
#[inline(always)]
pub(crate) fn cmp_in_dominator_order(&self, a: BasicCoverageBlock,
b: BasicCoverageBlock) -> Ordering {
self.dominator_order_rank[a].cmp(&self.dominator_order_rank[b])
}
pub(crate) fn reloop_predecessors(&self,
to_bcb: BasicCoverageBlock)
-> impl Iterator<Item = BasicCoverageBlock> {
self.predecessors[to_bcb].iter().copied().filter(move |&pred|
self.dominates(to_bcb, pred))
}
}
impl Index<BasicCoverageBlock> for CoverageGraph {
type Output = BasicCoverageBlockData;
#[inline]
fn index(&self, index: BasicCoverageBlock)
-> &BasicCoverageBlockData {
&self.bcbs[index]
}
}
impl IndexMut<BasicCoverageBlock> for CoverageGraph {
#[inline]
fn index_mut(&mut self, index: BasicCoverageBlock)
-> &mut BasicCoverageBlockData {
&mut self.bcbs[index]
}
}
impl graph::DirectedGraph for CoverageGraph {
type Node = BasicCoverageBlock;
#[inline]
fn num_nodes(&self) -> usize { self.bcbs.len() }
}
impl graph::StartNode for CoverageGraph {
#[inline]
fn start_node(&self) -> Self::Node {
self.bcb_from_bb(mir::START_BLOCK).expect("mir::START_BLOCK should be in a BasicCoverageBlock")
}
}
impl graph::Successors for CoverageGraph {
#[inline]
fn successors(&self, node: Self::Node)
-> impl Iterator<Item = Self::Node> {
self.successors[node].iter().copied()
}
}
impl graph::Predecessors for CoverageGraph {
#[inline]
fn predecessors(&self, node: Self::Node)
-> impl Iterator<Item = Self::Node> {
self.predecessors[node].iter().copied()
}
}
pub(crate) struct BasicCoverageBlockData {
pub(crate) basic_blocks: Vec<BasicBlock>,
pub(crate) is_out_summable: bool,
}
#[automatically_derived]
impl ::core::fmt::Debug for BasicCoverageBlockData {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"BasicCoverageBlockData", "basic_blocks",
&self.basic_blocks, "is_out_summable",
&&self.is_out_summable)
}
}
#[automatically_derived]
impl ::core::clone::Clone for BasicCoverageBlockData {
#[inline]
fn clone(&self) -> BasicCoverageBlockData {
BasicCoverageBlockData {
basic_blocks: ::core::clone::Clone::clone(&self.basic_blocks),
is_out_summable: ::core::clone::Clone::clone(&self.is_out_summable),
}
}
}
impl BasicCoverageBlockData {
#[inline(always)]
pub(crate) fn leader_bb(&self) -> BasicBlock {
self.basic_blocks[0]
}
#[inline(always)]
pub(crate) fn last_bb(&self) -> BasicBlock {
*self.basic_blocks.last().unwrap()
}
}
struct CoverageSuccessors<'a> {
targets: &'a [BasicBlock],
is_yield: bool,
}
#[automatically_derived]
#[doc(hidden)]
unsafe impl<'a> ::core::clone::TrivialClone for CoverageSuccessors<'a>
{
}
#[automatically_derived]
impl<'a> ::core::clone::Clone for CoverageSuccessors<'a> {
#[inline]
fn clone(&self) -> CoverageSuccessors<'a> {
let _: ::core::clone::AssertParamIsClone<&'a [BasicBlock]>;
let _: ::core::clone::AssertParamIsClone<bool>;
*self
}
}
#[automatically_derived]
impl<'a> ::core::marker::Copy for CoverageSuccessors<'a> { }
#[automatically_derived]
impl<'a> ::core::fmt::Debug for CoverageSuccessors<'a> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"CoverageSuccessors", "targets", &self.targets, "is_yield",
&&self.is_yield)
}
}
impl CoverageSuccessors<'_> {
fn is_out_chainable(&self) -> bool {
self.is_out_summable() && self.targets.len() == 1
}
fn is_out_summable(&self) -> bool {
!self.is_yield && !self.targets.is_empty()
}
}
impl IntoIterator for CoverageSuccessors<'_> {
type Item = BasicBlock;
type IntoIter = impl DoubleEndedIterator<Item = Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.targets.iter().copied()
}
}
fn bcb_filtered_successors<'a, 'tcx>(terminator: &'a Terminator<'tcx>)
-> CoverageSuccessors<'a> {
use TerminatorKind::*;
let mut is_yield = false;
let targets =
match &terminator.kind {
SwitchInt { targets, .. } => targets.all_targets(),
Yield { resume, .. } => {
is_yield = true;
slice::from_ref(resume)
}
Assert { target, .. } | Drop { target, .. } | FalseEdge {
real_target: target, .. } | FalseUnwind {
real_target: target, .. } | Goto { target } =>
slice::from_ref(target),
Call { target: maybe_target, .. } =>
maybe_target.as_slice(),
InlineAsm { targets, .. } => &targets,
CoroutineDrop | Return | TailCall { .. } | Unreachable |
UnwindResume | UnwindTerminate(_) => &[],
};
CoverageSuccessors { targets, is_yield }
}
struct CoverageRelevantSubgraph<'a, 'tcx> {
basic_blocks: &'a mir::BasicBlocks<'tcx>,
}
#[automatically_derived]
#[doc(hidden)]
unsafe impl<'a, 'tcx> ::core::clone::TrivialClone for
CoverageRelevantSubgraph<'a, 'tcx> {
}
#[automatically_derived]
impl<'a, 'tcx> ::core::clone::Clone for
CoverageRelevantSubgraph<'a, 'tcx> {
#[inline]
fn clone(&self) -> CoverageRelevantSubgraph<'a, 'tcx> {
let _:
::core::clone::AssertParamIsClone<&'a mir::BasicBlocks<'tcx>>;
*self
}
}
#[automatically_derived]
impl<'a, 'tcx> ::core::marker::Copy for
CoverageRelevantSubgraph<'a, 'tcx> {
}
impl<'a, 'tcx> CoverageRelevantSubgraph<'a, 'tcx> {
fn new(basic_blocks: &'a mir::BasicBlocks<'tcx>) -> Self {
Self { basic_blocks }
}
fn coverage_successors(&self, bb: BasicBlock)
-> CoverageSuccessors<'_> {
bcb_filtered_successors(self.basic_blocks[bb].terminator())
}
}
impl<'a, 'tcx> graph::DirectedGraph for
CoverageRelevantSubgraph<'a, 'tcx> {
type Node = BasicBlock;
fn num_nodes(&self) -> usize { self.basic_blocks.num_nodes() }
}
impl<'a, 'tcx> graph::Successors for
CoverageRelevantSubgraph<'a, 'tcx> {
fn successors(&self, bb: Self::Node)
-> impl Iterator<Item = Self::Node> {
self.coverage_successors(bb).into_iter()
}
}
}
mod hir_info {
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::intravisit::Visitor;
use rustc_hir::{self as hir, HirId};
use rustc_middle::hir::nested_filter;
use rustc_middle::mir;
use rustc_middle::ty::{self, TyCtxt, TypeckResults};
use rustc_span::def_id::LocalDefId;
use rustc_span::{ExpnKind, MacroKind, Span};
pub(crate) struct ExtractedHirInfo {
pub(crate) function_source_hash: u64,
pub(crate) is_async_fn: bool,
pub(crate) fn_sig_span: Option<Span>,
pub(crate) body_span: Span,
pub(crate) hole_spans: Vec<Span>,
pub(crate) nodes_to_ignore: FxHashSet<HirId>,
}
#[automatically_derived]
impl ::core::fmt::Debug for ExtractedHirInfo {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
let names: &'static _ =
&["function_source_hash", "is_async_fn", "fn_sig_span",
"body_span", "hole_spans", "nodes_to_ignore"];
let values: &[&dyn ::core::fmt::Debug] =
&[&self.function_source_hash, &self.is_async_fn,
&self.fn_sig_span, &self.body_span, &self.hole_spans,
&&self.nodes_to_ignore];
::core::fmt::Formatter::debug_struct_fields_finish(f,
"ExtractedHirInfo", names, values)
}
}
pub(crate) fn extract_hir_info<'tcx>(tcx: TyCtxt<'tcx>,
mir_body: &mir::Body<'tcx>) -> ExtractedHirInfo {
let def_id: LocalDefId =
{
let mut def_id = mir_body.source.def_id().expect_local();
if tcx.is_synthetic_mir(def_id) {
match *tcx.type_of(def_id).instantiate_identity().skip_normalization().kind()
{
ty::Coroutine(coroutine_def_id, _) =>
def_id = coroutine_def_id.expect_local(),
_ => def_id = tcx.local_parent(def_id),
}
}
def_id
};
let hir_node = tcx.hir_node_by_def_id(def_id);
let fn_body_id =
hir_node.body_id().expect("HIR node is a function with body");
let hir_body = tcx.hir_body(fn_body_id);
let maybe_fn_sig = hir_node.fn_sig();
let is_async_fn =
maybe_fn_sig.is_some_and(|fn_sig| fn_sig.header.is_async());
let mut body_span = hir_body.value.span;
if let hir::Node::Expr(expr) = hir_node &&
let hir::ExprKind::Closure(closure) = expr.kind &&
let Some(effective_body_span) =
body_span.find_ancestor_in_same_ctxt(closure.fn_decl_span) {
body_span = effective_body_span;
}
let fn_sig_span =
maybe_fn_sig.map(|fn_sig|
fn_sig.span).filter(|&fn_sig_span|
{
let source_map = tcx.sess.source_map();
let file_idx =
|span: Span| source_map.lookup_source_file_idx(span.lo());
fn_sig_span.eq_ctxt(body_span) &&
fn_sig_span.hi() <= body_span.lo() &&
file_idx(fn_sig_span) == file_idx(body_span)
});
let function_source_hash = hash_mir_source(tcx, hir_body);
let hole_spans = extract_hole_spans_from_hir(tcx, hir_body);
let nodes_to_ignore = find_nodes_to_ignore(tcx, def_id, hir_body);
ExtractedHirInfo {
function_source_hash,
is_async_fn,
fn_sig_span,
body_span,
hole_spans,
nodes_to_ignore,
}
}
fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>,
hir_body: &'tcx hir::Body<'tcx>) -> u64 {
let owner = hir_body.id().hir_id.owner;
tcx.hir_owner_nodes(owner).opt_hash.expect("hash should be present when coverage instrumentation is enabled").to_smaller_hash().as_u64()
}
fn extract_hole_spans_from_hir<'tcx>(tcx: TyCtxt<'tcx>,
hir_body: &hir::Body<'tcx>) -> Vec<Span> {
struct HolesVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
hole_spans: Vec<Span>,
}
impl<'tcx> Visitor<'tcx> for HolesVisitor<'tcx> {
type NestedFilter = nested_filter::OnlyBodies;
fn maybe_tcx(&mut self) -> TyCtxt<'tcx> { self.tcx }
fn visit_nested_item(&mut self, id: hir::ItemId)
-> Self::Result {
let span = self.tcx.def_span(id.owner_id.def_id);
self.visit_hole_span(span);
}
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
match expr.kind {
hir::ExprKind::Closure(_) | hir::ExprKind::ConstBlock(_) =>
{
self.visit_hole_span(expr.span);
}
_ => hir::intravisit::walk_expr(self, expr),
}
}
}
impl HolesVisitor<'_> {
fn visit_hole_span(&mut self, hole_span: Span) {
self.hole_spans.push(hole_span);
}
}
let mut visitor =
HolesVisitor { tcx, hole_spans: ::alloc::vec::Vec::new() };
visitor.visit_body(hir_body);
visitor.hole_spans
}
fn find_nodes_to_ignore<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId,
hir_body: &hir::Body<'tcx>) -> FxHashSet<HirId> {
struct FindNodesToIgnoreVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
typeck_results: &'tcx TypeckResults<'tcx>,
nodes_to_ignore: FxHashSet<HirId>,
}
struct IgnoreAllSubexprsVisitor<'a, 'tcx> {
inner: &'a mut FindNodesToIgnoreVisitor<'tcx>,
}
impl<'tcx> Visitor<'tcx> for FindNodesToIgnoreVisitor<'tcx> {
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
if let hir::ExprKind::Call(callee, args) = expr.kind &&
let callee_ty = self.typeck_results.node_type(callee.hir_id)
&& callee_ty.is_fn() &&
let Some(output) =
callee_ty.fn_sig(self.tcx).output().no_bound_vars() &&
output.is_never() &&
let ExpnKind::Macro(MacroKind::Bang, _) =
expr.span.ctxt().outer_expn_data().kind {
for arg in args {
(IgnoreAllSubexprsVisitor { inner: self }).visit_expr(arg)
}
}
if let hir::ExprKind::Block(block, _) = expr.kind &&
let is_empty =
(block.stmts.is_empty() && block.expr.is_none()) &&
!is_empty {
self.nodes_to_ignore.insert(expr.hir_id);
}
hir::intravisit::walk_expr(self, expr);
}
}
impl<'tcx> Visitor<'tcx> for IgnoreAllSubexprsVisitor<'_, 'tcx> {
fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) {
self.inner.nodes_to_ignore.insert(expr.hir_id);
hir::intravisit::walk_expr(self, expr);
}
}
let mut visitor =
FindNodesToIgnoreVisitor {
tcx,
typeck_results: tcx.typeck(def_id),
nodes_to_ignore: FxHashSet::default(),
};
visitor.visit_body(hir_body);
visitor.nodes_to_ignore
}
}
mod mappings {
use rustc_index::IndexVec;
use rustc_middle::mir::coverage::{
BlockMarkerId, BranchSpan, CoverageEarlyInfo, CoverageKind,
Mapping, MappingKind,
};
use rustc_middle::mir::{self, BasicBlock, StatementKind};
use rustc_middle::ty::TyCtxt;
use rustc_span::ExpnKind;
use crate::coverage::expansion::{self, ExpnTree};
use crate::coverage::graph::CoverageGraph;
use crate::coverage::hir_info::ExtractedHirInfo;
use crate::coverage::spans::extract_refined_covspans;
pub(crate) enum MappingsError { NoMappings, TreeSortFailure, }
#[automatically_derived]
impl ::core::fmt::Debug for MappingsError {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
MappingsError::NoMappings => "NoMappings",
MappingsError::TreeSortFailure => "TreeSortFailure",
})
}
}
pub(crate) struct ExtractedMappings {
pub(crate) mappings: Vec<Mapping>,
}
#[automatically_derived]
impl ::core::default::Default for ExtractedMappings {
#[inline]
fn default() -> ExtractedMappings {
ExtractedMappings {
mappings: ::core::default::Default::default(),
}
}
}
pub(crate) fn extract_mappings_from_mir<'tcx>(tcx: TyCtxt<'tcx>,
mir_body: &mir::Body<'tcx>, hir_info: &ExtractedHirInfo,
graph: &CoverageGraph)
-> Result<ExtractedMappings, MappingsError> {
let expn_tree =
expansion::build_expn_tree(mir_body, hir_info, graph)?;
let mut mappings = ::alloc::vec::Vec::new();
extract_refined_covspans(tcx, hir_info, graph, &expn_tree,
&mut mappings);
extract_branch_mappings(mir_body, hir_info, graph, &expn_tree,
&mut mappings);
if mappings.is_empty() {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/mappings.rs:44",
"rustc_mir_transform::coverage::mappings",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/mappings.rs"),
::tracing_core::__macro_support::Option::Some(44u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coverage::mappings"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("no mappings were extracted")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return Err(MappingsError::NoMappings);
}
Ok(ExtractedMappings { mappings })
}
fn resolve_block_markers(early_info: &CoverageEarlyInfo,
mir_body: &mir::Body<'_>)
-> IndexVec<BlockMarkerId, Option<BasicBlock>> {
let mut block_markers =
IndexVec::<BlockMarkerId,
Option<BasicBlock>>::from_elem_n(None,
early_info.num_block_markers);
for (bb, data) in mir_body.basic_blocks.iter_enumerated() {
for statement in &data.statements {
if let StatementKind::Coverage(CoverageKind::BlockMarker {
id }) = statement.kind {
block_markers[id] = Some(bb);
}
}
}
block_markers
}
fn extract_branch_mappings(mir_body: &mir::Body<'_>,
hir_info: &ExtractedHirInfo, graph: &CoverageGraph,
expn_tree: &ExpnTree, mappings: &mut Vec<Mapping>) {
let Some(early_info) =
mir_body.coverage_early_info.as_deref() else { return };
let block_markers = resolve_block_markers(early_info, mir_body);
let Some(node) =
expn_tree.get(hir_info.body_span.ctxt()) else { return };
if node.expn_kind != ExpnKind::Root { return; }
mappings.extend(node.branch_spans.iter().filter_map(|&BranchSpan {
span, true_marker, false_marker }|
try {
let bcb_from_marker =
|marker: BlockMarkerId|
graph.bcb_from_bb(block_markers[marker]?);
let true_bcb = bcb_from_marker(true_marker)?;
let false_bcb = bcb_from_marker(false_marker)?;
Mapping {
span,
kind: MappingKind::Branch { true_bcb, false_bcb },
}
}));
}
}
pub(super) mod query {
use rustc_hir::attrs::CoverageAttrKind;
use rustc_hir::def::DefKind;
use rustc_hir::{self as hir, find_attr};
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
use rustc_middle::mir::coverage::{
BasicCoverageBlock, CoverageCodegenInfo, CoverageKind, MappingKind,
};
use rustc_middle::mir::{Body, Statement, StatementKind};
use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::util::Providers;
use rustc_span::def_id::LocalDefId;
use tracing::trace;
use crate::coverage::counters::node_flow::make_node_counters;
use crate::coverage::counters::{
CoverageCounters, transcribe_counters,
};
pub(crate) fn provide(providers: &mut Providers) {
providers.queries.is_eligible_for_coverage =
is_eligible_for_coverage;
providers.queries.coverage_attr_on = coverage_attr_on;
providers.queries.coverage_codegen_info = coverage_codegen_info;
}
fn is_eligible_for_coverage(tcx: TyCtxt<'_>, def_id: LocalDefId)
-> bool {
let def_kind = tcx.def_kind(def_id);
if !def_kind.is_fn_like() {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/query.rs:36",
"rustc_mir_transform::coverage::query",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/query.rs"),
::tracing_core::__macro_support::Option::Some(36u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coverage::query"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("InstrumentCoverage skipped for {0:?} (not an fn-like)",
def_id) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return false;
}
if #[allow(non_exhaustive_omitted_patterns)] match def_kind {
DefKind::Fn | DefKind::AssocFn => true,
_ => false,
} &&
#[allow(non_exhaustive_omitted_patterns)] match tcx.constness(def_id)
{
hir::Constness::Const { always: true } => true,
_ => false,
} {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/query.rs:47",
"rustc_mir_transform::coverage::query",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/query.rs"),
::tracing_core::__macro_support::Option::Some(47u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coverage::query"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("InstrumentCoverage skipped for {0:?} (comptime)",
def_id) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return false;
}
if tcx.codegen_fn_attrs(def_id).flags.contains(CodegenFnAttrFlags::NAKED)
{
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/query.rs:52",
"rustc_mir_transform::coverage::query",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/query.rs"),
::tracing_core::__macro_support::Option::Some(52u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coverage::query"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("InstrumentCoverage skipped for {0:?} (`#[naked]`)",
def_id) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return false;
}
if !tcx.coverage_attr_on(def_id) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/query.rs:57",
"rustc_mir_transform::coverage::query",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/query.rs"),
::tracing_core::__macro_support::Option::Some(57u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coverage::query"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("InstrumentCoverage skipped for {0:?} (`#[coverage(off)]`)",
def_id) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return false;
}
true
}
fn coverage_attr_on(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
if let Some(kind) =
{
{
'done:
{
for i in ::rustc_attr_ir::HasAttrs::get_attrs(def_id, &tcx)
{
#[allow(unused_imports)]
use ::rustc_attr_ir::AttributeKind::*;
let i: &::rustc_attr_ir::Attribute = i;
match i {
::rustc_attr_ir::Attribute::Parsed(Coverage(kind)) => {
break 'done Some(kind);
}
::rustc_attr_ir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
} {
match kind {
CoverageAttrKind::On => return true,
CoverageAttrKind::Off => return false,
}
};
if tcx.is_automatically_derived(def_id.to_def_id()) {
return false;
}
match tcx.opt_local_parent(def_id) {
Some(parent) => tcx.coverage_attr_on(parent),
None => true,
}
}
fn coverage_codegen_info<'tcx>(tcx: TyCtxt<'tcx>,
instance_def: ty::InstanceKind<'tcx>)
-> Option<CoverageCodegenInfo> {
let mir_body = tcx.instance_mir(instance_def);
let mir_info = mir_body.coverage_mir_info.as_deref()?;
let mut bcbs_seen =
DenseBitSet::new_empty(mir_info.priority_list.len());
for kind in all_coverage_in_mir_body(mir_body) {
match *kind {
CoverageKind::VirtualCounter { bcb } => {
bcbs_seen.insert(bcb);
}
_ => {}
}
}
let mut bcb_needs_counter =
DenseBitSet::<BasicCoverageBlock>::new_empty(mir_info.priority_list.len());
for mapping in &mir_info.mappings {
match mapping.kind {
MappingKind::Code { bcb } => {
bcb_needs_counter.insert(bcb);
}
MappingKind::Branch { true_bcb, false_bcb } => {
bcb_needs_counter.insert(true_bcb);
bcb_needs_counter.insert(false_bcb);
}
}
}
let mut priority_list = mir_info.priority_list.clone();
if true {
{
match (&priority_list[0],
&priority_list.iter().copied().max().unwrap()) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
if !!bcbs_seen.contains(priority_list[0]) {
::core::panicking::panic("assertion failed: !bcbs_seen.contains(priority_list[0])")
};
priority_list[1..].sort_by_key(|&bcb| !bcbs_seen.contains(bcb));
let node_counters =
make_node_counters(&mir_info.node_flow_data, &priority_list);
let coverage_counters =
transcribe_counters(&node_counters, &bcb_needs_counter,
&bcbs_seen);
let CoverageCounters {
phys_counter_for_node,
next_counter_id,
node_counters,
expressions, .. } = coverage_counters;
Some(CoverageCodegenInfo {
num_counters: next_counter_id.as_u32(),
phys_counter_for_node,
term_for_bcb: node_counters,
expressions,
})
}
fn all_coverage_in_mir_body<'a, 'tcx>(body: &'a Body<'tcx>)
-> impl Iterator<Item = &'a CoverageKind> {
body.basic_blocks.iter().flat_map(|bb_data|
&bb_data.statements).filter_map(|statement|
{
match statement.kind {
StatementKind::Coverage(ref kind) if
!is_inlined(body, statement) => Some(kind),
_ => None,
}
})
}
fn is_inlined(body: &Body<'_>, statement: &Statement<'_>) -> bool {
let scope_data = &body.source_scopes[statement.source_info.scope];
scope_data.inlined.is_some() ||
scope_data.inlined_parent_scope.is_some()
}
}
mod spans {
use rustc_middle::mir::coverage::{Mapping, MappingKind, START_BCB};
use rustc_middle::ty::TyCtxt;
use rustc_span::source_map::SourceMap;
use rustc_span::{
BytePos, DesugaringKind, ExpnKind, MacroKind, Span, SyntaxContext,
};
use tracing::instrument;
use crate::coverage::expansion::{ExpnTree, SpanWithBcb};
use crate::coverage::graph::{BasicCoverageBlock, CoverageGraph};
use crate::coverage::hir_info::ExtractedHirInfo;
pub(super) fn extract_refined_covspans<'tcx>(tcx: TyCtxt<'tcx>,
hir_info: &ExtractedHirInfo, graph: &CoverageGraph,
expn_tree: &ExpnTree, mappings: &mut Vec<Mapping>) {
if hir_info.is_async_fn {
if let Some(span) = hir_info.fn_sig_span {
mappings.push(Mapping {
span,
kind: MappingKind::Code { bcb: START_BCB },
})
}
return;
}
let Some(node) =
expn_tree.get(hir_info.body_span.ctxt()) else { return };
let mut covspans = ::alloc::vec::Vec::new();
for &SpanWithBcb { span, bcb } in &node.spans {
covspans.push(Covspan { span, bcb });
}
for &child_context in &node.child_contexts {
if let Some(covspan) =
single_covspan_for_child_context(tcx, &expn_tree,
child_context) {
covspans.push(covspan);
}
}
if let Some(body_span) = node.body_span {
covspans.retain(|covspan: &Covspan|
{
let covspan_span = covspan.span;
if !body_span.contains(covspan_span) ||
body_span.source_equal(covspan_span) {
return false;
}
if !body_span.eq_ctxt(covspan_span) { return false; }
true
});
}
if covspans.is_empty() { return; }
if let Some(span) =
node.fn_sig_span.or_else(||
try { node.body_span?.shrink_to_lo() }) {
covspans.push(Covspan { span, bcb: START_BCB });
}
let compare_covspans =
|a: &Covspan, b: &Covspan|
{
compare_spans(a.span,
b.span).then_with(||
graph.cmp_in_dominator_order(a.bcb, b.bcb).reverse())
};
covspans.sort_by(compare_covspans);
covspans.dedup_by(|b, a| a.span.source_equal(b.span));
let mut holes =
node.hole_spans.iter().copied().map(|span|
Hole { span }).collect::<Vec<_>>();
holes.sort_by(|a, b| compare_spans(a.span, b.span));
holes.dedup_by(|b, a| a.merge_if_overlapping_or_adjacent(b));
discard_spans_overlapping_holes(&mut covspans, &holes);
let mut covspans = remove_unwanted_overlapping_spans(covspans);
let source_map = tcx.sess.source_map();
covspans.retain_mut(|covspan|
{
let Some(span) =
ensure_non_empty_span(source_map,
covspan.span) else { return false };
covspan.span = span;
true
});
covspans.dedup_by(|b, a| a.merge_if_eligible(b));
mappings.extend(covspans.into_iter().map(|Covspan { span, bcb }|
{ Mapping { span, kind: MappingKind::Code { bcb } } }));
}
fn single_covspan_for_child_context(tcx: TyCtxt<'_>,
expn_tree: &ExpnTree, child_context: SyntaxContext)
-> Option<Covspan> {
let node = expn_tree.get(child_context)?;
let minmax_bcbs = node.minmax_bcbs?;
let bcb =
match node.expn_kind {
ExpnKind::Macro(MacroKind::Bang, _) |
ExpnKind::Desugaring(DesugaringKind::Await) => {
minmax_bcbs.min
}
_ => minmax_bcbs.max,
};
let mut span = node.call_site?;
if #[allow(non_exhaustive_omitted_patterns)] match node.expn_kind
{
ExpnKind::Macro(MacroKind::Bang, _) => true,
_ => false,
} {
span = tcx.sess.source_map().span_through_char(span, '!');
}
Some(Covspan { span, bcb })
}
fn discard_spans_overlapping_holes(covspans: &mut Vec<Covspan>,
holes: &[Hole]) {
if true {
if !covspans.is_sorted_by(|a, b|
compare_spans(a.span, b.span).is_le()) {
::core::panicking::panic("assertion failed: covspans.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le())")
};
};
if true {
if !holes.is_sorted_by(|a, b|
compare_spans(a.span, b.span).is_le()) {
::core::panicking::panic("assertion failed: holes.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le())")
};
};
if true {
if !holes.array_windows().all(|[a, b]|
!a.span.overlaps_or_adjacent(b.span)) {
::core::panicking::panic("assertion failed: holes.array_windows().all(|[a, b]| !a.span.overlaps_or_adjacent(b.span))")
};
};
let mut curr_hole = 0usize;
let mut overlaps_hole =
|covspan: &Covspan| -> bool
{
while let Some(hole) = holes.get(curr_hole) {
if hole.span.hi() <= covspan.span.lo() {
curr_hole += 1;
continue;
}
return hole.span.overlaps(covspan.span);
}
false
};
covspans.retain(|covspan| !overlaps_hole(covspan));
}
#[doc =
" Takes a list of sorted spans extracted from MIR, and \"refines\""]
#[doc =
" those spans by removing spans that overlap in unwanted ways."]
fn remove_unwanted_overlapping_spans(sorted_spans: Vec<Covspan>)
-> Vec<Covspan> {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("remove_unwanted_overlapping_spans",
"rustc_mir_transform::coverage::spans",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/spans.rs"),
::tracing_core::__macro_support::Option::Some(186u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coverage::spans"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("sorted_spans")
}> =
::tracing::__macro_support::FieldName::new("sorted_spans");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&sorted_spans)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Vec<Covspan> = loop {};
return __tracing_attr_fake_return;
}
{
if true {
if !sorted_spans.is_sorted_by(|a, b|
compare_spans(a.span, b.span).is_le()) {
::core::panicking::panic("assertion failed: sorted_spans.is_sorted_by(|a, b| compare_spans(a.span, b.span).is_le())")
};
};
let mut pending = ::alloc::vec::Vec::new();
let mut refined = ::alloc::vec::Vec::new();
for curr in sorted_spans {
pending.retain(|prev: &Covspan|
{
if prev.span.hi() <= curr.span.lo() {
refined.push(prev.clone());
false
} else { prev.bcb == curr.bcb }
});
pending.push(curr);
}
refined.extend(pending);
refined
}
}
}
}
struct Covspan {
span: Span,
bcb: BasicCoverageBlock,
}
#[automatically_derived]
impl ::core::clone::Clone for Covspan {
#[inline]
fn clone(&self) -> Covspan {
Covspan {
span: ::core::clone::Clone::clone(&self.span),
bcb: ::core::clone::Clone::clone(&self.bcb),
}
}
}
#[automatically_derived]
impl ::core::fmt::Debug for Covspan {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"Covspan", "span", &self.span, "bcb", &&self.bcb)
}
}
impl Covspan {
fn merge_if_eligible(&mut self, other: &Self) -> bool {
let eligible_for_merge =
|a: &Self, b: &Self|
(a.bcb == b.bcb) && a.span.overlaps_or_adjacent(b.span);
if eligible_for_merge(self, other) {
self.span = self.span.to(other.span);
true
} else { false }
}
}
fn compare_spans(a: Span, b: Span) -> std::cmp::Ordering {
Ord::cmp(&a.lo(),
&b.lo()).then_with(|| Ord::cmp(&a.hi(), &b.hi()).reverse())
}
fn ensure_non_empty_span(source_map: &SourceMap, span: Span)
-> Option<Span> {
if !span.is_empty() { return Some(span); }
source_map.span_to_source(span,
|src, start, end|
try {
if src.as_bytes().get(end).copied() == Some(b'{') {
Some(span.with_hi(span.hi() + BytePos(1)))
} else if start > 0 && src.as_bytes()[start - 1] == b'}' {
Some(span.with_lo(span.lo() - BytePos(1)))
} else { None }
}).ok()?
}
struct Hole {
span: Span,
}
#[automatically_derived]
impl ::core::fmt::Debug for Hole {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f, "Hole",
"span", &&self.span)
}
}
impl Hole {
fn merge_if_overlapping_or_adjacent(&mut self, other: &mut Self)
-> bool {
if !self.span.overlaps_or_adjacent(other.span) {
return false;
}
self.span = self.span.to(other.span);
true
}
}
}
pub(super) struct InstrumentCoverage;
impl<'tcx> crate::MirPass<'tcx> for InstrumentCoverage {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.instrument_coverage())
}
fn run_pass(&self, tcx: TyCtxt<'tcx>,
mir_body: &mut mir::Body<'tcx>) {
let mir_source = mir_body.source;
if !mir_source.promoted.is_none() {
::core::panicking::panic("assertion failed: mir_source.promoted.is_none()")
};
let def_id = mir_source.def_id().expect_local();
if !tcx.is_eligible_for_coverage(def_id) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/mod.rs:42",
"rustc_mir_transform::coverage", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/mod.rs"),
::tracing_core::__macro_support::Option::Some(42u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coverage"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("InstrumentCoverage skipped for {0:?} (not eligible)",
def_id) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return;
}
match mir_body.basic_blocks[mir::START_BLOCK].terminator().kind {
TerminatorKind::Unreachable => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/mod.rs:50",
"rustc_mir_transform::coverage", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/mod.rs"),
::tracing_core::__macro_support::Option::Some(50u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coverage"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("InstrumentCoverage skipped for unreachable `START_BLOCK`")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return;
}
_ => {}
}
instrument_function_for_coverage(tcx, mir_body);
}
}
fn instrument_function_for_coverage<'tcx>(tcx: TyCtxt<'tcx>,
mir_body: &mut mir::Body<'tcx>) {
let _span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("instrument_function_for_coverage",
"rustc_mir_transform::coverage", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/mod.rs"),
::tracing_core::__macro_support::Option::Some(61u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coverage"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&mir_body.source.def_id())
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
}.entered();
let hir_info = hir_info::extract_hir_info(tcx, mir_body);
let graph = CoverageGraph::from_mir(mir_body);
let ExtractedMappings { mappings } =
match mappings::extract_mappings_from_mir(tcx, mir_body,
&hir_info, &graph) {
Ok(m) => m,
Err(error) => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/mod.rs:76",
"rustc_mir_transform::coverage", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/mod.rs"),
::tracing_core::__macro_support::Option::Some(76u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coverage"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("error")
}> =
::tracing::__macro_support::FieldName::new("error");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("mapping extraction failed; skipping this function")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&error)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return;
}
};
let BcbCountersData { node_flow_data, priority_list } =
counters::prepare_bcb_counters_data(&graph);
inject_coverage_statements(mir_body, &graph);
mir_body.coverage_mir_info =
Some(Box::new(CoverageMirInfo {
function_source_hash: hir_info.function_source_hash,
node_flow_data,
priority_list,
mappings,
}));
}
fn inject_coverage_statements<'tcx>(mir_body: &mut mir::Body<'tcx>,
graph: &CoverageGraph) {
for (bcb, data) in graph.iter_enumerated() {
let target_bb = data.leader_bb();
inject_statement(mir_body, CoverageKind::VirtualCounter { bcb },
target_bb);
}
}
fn inject_statement(mir_body: &mut mir::Body<'_>,
counter_kind: CoverageKind, bb: BasicBlock) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/mod.rs:109",
"rustc_mir_transform::coverage", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/coverage/mod.rs"),
::tracing_core::__macro_support::Option::Some(109u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::coverage"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!(" injecting statement {0:?} for {1:?}",
counter_kind, bb) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let data = &mut mir_body[bb];
let source_info = data.terminator().source_info;
let statement =
Statement::new(source_info,
StatementKind::Coverage(counter_kind));
data.statements.insert(0, statement);
}
}
#[allow(unused_imports)]
use coverage::InstrumentCoverage as _;
mod ctfe_limit {
use rustc_data_structures::graph::dominators::Dominators;
use rustc_middle::mir::{
BasicBlock, BasicBlockData, Body, Statement, StatementKind,
TerminatorKind,
};
use rustc_middle::ty::TyCtxt;
use tracing::instrument;
use crate::PassPolicy;
pub(super) struct CtfeLimit;
impl<'tcx> crate::MirPass<'tcx> for CtfeLimit {
fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::INFO <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::INFO <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("run_pass",
"rustc_mir_transform::ctfe_limit", ::tracing::Level::INFO,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ctfe_limit.rs"),
::tracing_core::__macro_support::Option::Some(16u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::ctfe_limit"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::INFO <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::INFO <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let doms = body.basic_blocks.dominators();
let indices: Vec<BasicBlock> =
body.basic_blocks.iter_enumerated().filter_map(|(node,
node_data)|
{
if #[allow(non_exhaustive_omitted_patterns)] match node_data.terminator().kind
{
TerminatorKind::Call { .. } | TerminatorKind::TailCall { ..
} => true,
_ => false,
} || has_back_edge(doms, node, node_data) {
Some(node)
} else { None }
}).collect();
let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
for index in indices {
let bbdata = &mut basic_blocks[index];
let source_info = bbdata.terminator().source_info;
bbdata.statements.push(Statement::new(source_info,
StatementKind::ConstEvalCounter));
}
}
}
}
}
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(true)
}
}
fn has_back_edge(doms: &Dominators<BasicBlock>, node: BasicBlock,
node_data: &BasicBlockData<'_>) -> bool {
if !doms.is_reachable(node) { return false; }
node_data.terminator().successors().any(|succ|
doms.dominates(succ, node))
}
}
#[allow(unused_imports)]
use ctfe_limit::CtfeLimit as _;
mod dataflow_const_prop {
use std::assert_matches;
use std::fmt::Formatter;
use rustc_abi::{BackendRepr, FIRST_VARIANT, FieldIdx, Size, VariantIdx};
use rustc_const_eval::const_eval::{DummyMachine, throw_machine_stop_str};
use rustc_const_eval::interpret::{
ImmTy, Immediate, InterpCx, OpTy, PlaceTy, Projectable, interp_ok,
};
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def::DefKind;
use rustc_middle::bug;
use rustc_middle::mir::interpret::{InterpResult, Scalar};
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_mir_dataflow::fmt::DebugWithContext;
use rustc_mir_dataflow::lattice::{FlatSet, HasBottom};
use rustc_mir_dataflow::value_analysis::{
Map, PlaceCollectionMode, PlaceIndex, State, TrackElem, ValueOrPlace,
debug_with_context,
};
use rustc_mir_dataflow::{Analysis, ResultsVisitor, visit_results};
use rustc_span::DUMMY_SP;
use tracing::{debug, debug_span, instrument};
use crate::PassPolicy;
const BLOCK_LIMIT: usize = 100;
const PLACE_LIMIT: usize = 100;
pub(super) struct DataflowConstProp;
impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 3)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("run_pass",
"rustc_mir_transform::dataflow_const_prop",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs"),
::tracing_core::__macro_support::Option::Some(43u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dataflow_const_prop"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
if body.coroutine.is_some() { return; }
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs:50",
"rustc_mir_transform::dataflow_const_prop",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs"),
::tracing_core::__macro_support::Option::Some(50u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dataflow_const_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&body.source.def_id())
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if tcx.sess.mir_opt_level() < 4 &&
body.basic_blocks.len() > BLOCK_LIMIT {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs:52",
"rustc_mir_transform::dataflow_const_prop",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs"),
::tracing_core::__macro_support::Option::Some(52u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dataflow_const_prop"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("aborted dataflow const prop due too many basic blocks")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return;
}
let value_limit =
if tcx.sess.mir_opt_level() < 4 {
Some(PLACE_LIMIT)
} else { None };
let map =
Map::new(tcx, body,
PlaceCollectionMode::Full { value_limit });
let const_ =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("analyze",
"rustc_mir_transform::dataflow_const_prop",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs"),
::tracing_core::__macro_support::Option::Some(70u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dataflow_const_prop"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
}.in_scope(||
ConstAnalysis::new(tcx, body,
map).iterate_to_fixpoint(tcx, body, None));
let mut visitor =
Collector::new(tcx, body, &const_.analysis.map);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("collect",
"rustc_mir_transform::dataflow_const_prop",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs"),
::tracing_core::__macro_support::Option::Some(75u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dataflow_const_prop"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
}.in_scope(||
{
visit_results(body,
traversal::reachable(body).map(|(bb, _)| bb), &const_,
&mut visitor)
});
let mut patch = visitor.patch;
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("patch",
"rustc_mir_transform::dataflow_const_prop",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs"),
::tracing_core::__macro_support::Option::Some(79u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dataflow_const_prop"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
}.in_scope(|| patch.visit_body_preserves_cfg(body));
}
}
}
}
}
struct ConstAnalysis<'a, 'tcx> {
map: Map<'tcx>,
tcx: TyCtxt<'tcx>,
local_decls: &'a LocalDecls<'tcx>,
ecx: InterpCx<'tcx, DummyMachine>,
typing_env: ty::TypingEnv<'tcx>,
}
impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> {
type Domain = State<FlatSet<Scalar>>;
const NAME: &'static str = "ConstAnalysis";
fn bottom_value(&self, _body: &Body<'tcx>) -> Self::Domain {
State::Unreachable
}
fn initialize_start_block(&self, body: &Body<'tcx>,
state: &mut Self::Domain) {
{
match state {
State::Unreachable => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"State::Unreachable", ::core::option::Option::None);
}
}
};
*state = State::new_reachable();
for arg in body.args_iter() {
state.flood(PlaceRef { local: arg, projection: &[] },
&self.map);
}
}
fn apply_primary_statement_effect(&self, state: &mut Self::Domain,
statement: &Statement<'tcx>, _location: Location) {
if state.is_reachable() {
self.handle_statement(statement, state);
}
}
fn get_terminator_edges<'mir>(&self, state: &Self::Domain,
terminator: &'mir Terminator<'tcx>, _location: Location)
-> TerminatorEdges<'mir, 'tcx> {
if state.is_reachable() {
if let TerminatorKind::SwitchInt { discr, targets } =
&terminator.kind {
self.get_switch_int_edges(discr, targets, state)
} else { terminator.edges() }
} else { TerminatorEdges::None }
}
fn apply_primary_terminator_effect(&self, state: &mut Self::Domain,
terminator: &Terminator<'tcx>, _location: Location) {
if state.is_reachable() {
self.handle_terminator(terminator, state)
}
}
fn apply_call_return_effect(&self, state: &mut Self::Domain,
_block: BasicBlock, return_places: CallReturnPlaces<'_, 'tcx>) {
if state.is_reachable() {
self.handle_call_return(return_places, state)
}
}
}
impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> {
fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: Map<'tcx>)
-> Self {
let typing_env = body.typing_env(tcx);
Self {
map,
tcx,
local_decls: &body.local_decls,
ecx: InterpCx::new(tcx, DUMMY_SP, typing_env, DummyMachine),
typing_env,
}
}
fn handle_statement(&self, statement: &Statement<'tcx>,
state: &mut State<FlatSet<Scalar>>) {
match &statement.kind {
StatementKind::Assign((place, rvalue)) => {
self.handle_assign(*place, rvalue, state);
}
StatementKind::SetDiscriminant { place, variant_index } => {
self.handle_set_discriminant(**place, *variant_index,
state);
}
StatementKind::Intrinsic(intrinsic) => {
self.handle_intrinsic(intrinsic);
}
StatementKind::StorageLive(local) |
StatementKind::StorageDead(local) => {
state.flood_with(Place::from(*local).as_ref(), &self.map,
FlatSet::<Scalar>::BOTTOM);
}
StatementKind::ConstEvalCounter | StatementKind::Nop |
StatementKind::FakeRead(..) |
StatementKind::PlaceMention(..) |
StatementKind::Coverage(..) |
StatementKind::BackwardIncompatibleDropHint { .. } |
StatementKind::AscribeUserType(..) => {}
}
}
fn handle_intrinsic(&self, intrinsic: &NonDivergingIntrinsic<'tcx>) {
match intrinsic {
NonDivergingIntrinsic::Assume(..) => {}
NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
dst: _, src: _, count: _ }) => {}
}
}
fn handle_operand(&self, operand: &Operand<'tcx>)
-> ValueOrPlace<FlatSet<Scalar>> {
match operand {
Operand::RuntimeChecks(_) => ValueOrPlace::TOP,
Operand::Constant(constant) =>
ValueOrPlace::Value(self.handle_constant(constant)),
Operand::Copy(place) | Operand::Move(place) => {
self.map.find(place.as_ref()).map(ValueOrPlace::Place).unwrap_or(ValueOrPlace::TOP)
}
}
}
fn handle_terminator<'mir>(&self, terminator: &'mir Terminator<'tcx>,
state: &mut State<FlatSet<Scalar>>) {
match &terminator.kind {
TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. }
=> {}
TerminatorKind::Drop { place, .. } => {
state.flood_with(place.as_ref(), &self.map,
FlatSet::<Scalar>::BOTTOM);
}
TerminatorKind::Yield { .. } => {
::rustc_middle::util::bug::bug_fmt(format_args!("encountered disallowed terminator"));
}
TerminatorKind::TailCall { .. } => {}
TerminatorKind::SwitchInt { .. } | TerminatorKind::Goto { .. }
| TerminatorKind::UnwindResume |
TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return
| TerminatorKind::Unreachable | TerminatorKind::Assert { ..
} | TerminatorKind::CoroutineDrop |
TerminatorKind::FalseEdge { .. } |
TerminatorKind::FalseUnwind { .. } => {}
}
}
fn handle_call_return(&self,
return_places: CallReturnPlaces<'_, 'tcx>,
state: &mut State<FlatSet<Scalar>>) {
return_places.for_each(|place|
{ state.flood(place.as_ref(), &self.map); })
}
fn handle_set_discriminant(&self, place: Place<'tcx>,
variant_index: VariantIdx, state: &mut State<FlatSet<Scalar>>) {
state.flood_discr(place.as_ref(), &self.map);
if self.map.find_discr(place.as_ref()).is_some() {
let enum_ty = place.ty(self.local_decls, self.tcx).ty;
if let Some(discr) =
self.eval_discriminant(enum_ty, variant_index) {
state.assign_discr(place.as_ref(),
ValueOrPlace::Value(FlatSet::Elem(discr)), &self.map);
}
}
}
fn handle_assign(&self, target: Place<'tcx>, rvalue: &Rvalue<'tcx>,
state: &mut State<FlatSet<Scalar>>) {
match rvalue {
Rvalue::Use(operand, _) => {
state.flood(target.as_ref(), &self.map);
if let Some(target) = self.map.find(target.as_ref()) {
self.assign_operand(state, target, operand);
}
}
Rvalue::CopyForDeref(_) =>
::rustc_middle::util::bug::bug_fmt(format_args!("`CopyForDeref` in runtime MIR")),
Rvalue::Aggregate(kind, operands) => {
state.flood(target.as_ref(), &self.map);
let Some(target_idx) =
self.map.find(target.as_ref()) else { return };
let (variant_target, variant_index) =
match **kind {
AggregateKind::Tuple | AggregateKind::Closure(..) =>
(Some(target_idx), None),
AggregateKind::Adt(def_id, variant_index, ..) => {
match self.tcx.def_kind(def_id) {
DefKind::Struct => (Some(target_idx), None),
DefKind::Enum =>
(self.map.apply(target_idx,
TrackElem::Variant(variant_index)), Some(variant_index)),
_ => return,
}
}
_ => return,
};
if let Some(variant_target_idx) = variant_target {
for (field_index, operand) in operands.iter_enumerated() {
if let Some(field) =
self.map.apply(variant_target_idx,
TrackElem::Field(field_index)) {
self.assign_operand(state, field, operand);
}
}
}
if let Some(variant_index) = variant_index &&
let Some(discr_idx) =
self.map.apply(target_idx, TrackElem::Discriminant) {
let enum_ty = target.ty(self.local_decls, self.tcx).ty;
if let Some(discr_val) =
self.eval_discriminant(enum_ty, variant_index) {
state.insert_value_idx(discr_idx, FlatSet::Elem(discr_val),
&self.map);
}
}
}
Rvalue::BinaryOp(op, (left, right)) if op.is_overflowing() =>
{
state.flood(target.as_ref(), &self.map);
let Some(target) =
self.map.find(target.as_ref()) else { return };
let value_target =
self.map.apply(target, TrackElem::Field(0_u32.into()));
let overflow_target =
self.map.apply(target, TrackElem::Field(1_u32.into()));
if value_target.is_some() || overflow_target.is_some() {
let (val, overflow) =
self.binary_op(state, *op, left, right);
if let Some(value_target) = value_target {
state.insert_value_idx(value_target, val, &self.map);
}
if let Some(overflow_target) = overflow_target {
state.insert_value_idx(overflow_target, overflow,
&self.map);
}
}
}
Rvalue::Cast(CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize,
_), operand, _) => {
let pointer = self.handle_operand(operand);
state.assign(target.as_ref(), pointer, &self.map);
if let Some(target_len) = self.map.find_len(target.as_ref())
&& let operand_ty = operand.ty(self.local_decls, self.tcx)
&& let Some(operand_ty) = operand_ty.builtin_deref(true) &&
let ty::Array(_, len) = operand_ty.kind() &&
let Some(len) =
Const::Ty(self.tcx.types.usize,
*len).try_eval_scalar_int(self.tcx, self.typing_env) {
state.insert_value_idx(target_len,
FlatSet::Elem(len.into()), &self.map);
}
}
_ => {
let result = self.handle_rvalue(rvalue, state);
state.assign(target.as_ref(), result, &self.map);
}
}
}
fn handle_rvalue(&self, rvalue: &Rvalue<'tcx>,
state: &mut State<FlatSet<Scalar>>)
-> ValueOrPlace<FlatSet<Scalar>> {
let val =
match rvalue {
Rvalue::Cast(CastKind::IntToInt | CastKind::IntToFloat,
operand, ty) => {
let Ok(layout) =
self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else {
return ValueOrPlace::Value(FlatSet::Top);
};
match self.eval_operand(operand, state) {
FlatSet::Elem(op) =>
self.ecx.int_to_int_or_float(&op,
layout).discard_err().map_or(FlatSet::Top,
|result| self.wrap_immediate(*result)),
FlatSet::Bottom => FlatSet::Bottom,
FlatSet::Top => FlatSet::Top,
}
}
Rvalue::Cast(CastKind::FloatToInt | CastKind::FloatToFloat,
operand, ty) => {
let Ok(layout) =
self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else {
return ValueOrPlace::Value(FlatSet::Top);
};
match self.eval_operand(operand, state) {
FlatSet::Elem(op) =>
self.ecx.float_to_float_or_int(&op,
layout).discard_err().map_or(FlatSet::Top,
|result| self.wrap_immediate(*result)),
FlatSet::Bottom => FlatSet::Bottom,
FlatSet::Top => FlatSet::Top,
}
}
Rvalue::Cast(CastKind::Transmute | CastKind::Subtype,
operand, _) => {
match self.eval_operand(operand, state) {
FlatSet::Elem(op) => self.wrap_immediate(*op),
FlatSet::Bottom => FlatSet::Bottom,
FlatSet::Top => FlatSet::Top,
}
}
Rvalue::BinaryOp(op, (left, right)) if !op.is_overflowing()
=> {
let (val, _overflow) =
self.binary_op(state, *op, left, right);
val
}
Rvalue::UnaryOp(op, operand) => {
if let UnOp::PtrMetadata = op &&
let Some(place) = operand.place() &&
let Some(len) = self.map.find_len(place.as_ref()) {
return ValueOrPlace::Place(len);
}
match self.eval_operand(operand, state) {
FlatSet::Elem(value) =>
self.ecx.unary_op(*op,
&value).discard_err().map_or(FlatSet::Top,
|val| self.wrap_immediate(*val)),
FlatSet::Bottom => FlatSet::Bottom,
FlatSet::Top => FlatSet::Top,
}
}
Rvalue::Discriminant(place) =>
state.get_discr(place.as_ref(), &self.map),
Rvalue::Use(operand, _) =>
return self.handle_operand(operand),
Rvalue::CopyForDeref(_) =>
::rustc_middle::util::bug::bug_fmt(format_args!("`CopyForDeref` in runtime MIR")),
Rvalue::Ref(..) | Rvalue::Reborrow(..) | Rvalue::RawPtr(..)
=> {
return ValueOrPlace::TOP;
}
Rvalue::Repeat(..) | Rvalue::ThreadLocalRef(..) |
Rvalue::Cast(..) | Rvalue::BinaryOp(..) |
Rvalue::Aggregate(..) | Rvalue::WrapUnsafeBinder(..) => {
return ValueOrPlace::TOP;
}
};
ValueOrPlace::Value(val)
}
fn handle_constant(&self, constant: &ConstOperand<'tcx>)
-> FlatSet<Scalar> {
constant.const_.try_eval_scalar(self.tcx,
self.typing_env).map_or(FlatSet::Top, FlatSet::Elem)
}
fn get_switch_int_edges<'mir>(&self, discr: &'mir Operand<'tcx>,
targets: &'mir SwitchTargets, state: &State<FlatSet<Scalar>>)
-> TerminatorEdges<'mir, 'tcx> {
let value =
match self.handle_operand(discr) {
ValueOrPlace::Value(value) => value,
ValueOrPlace::Place(place) =>
state.get_idx(place, &self.map),
};
match value {
FlatSet::Bottom => TerminatorEdges::None,
FlatSet::Elem(scalar) => {
if let Ok(scalar_int) = scalar.try_to_scalar_int() {
TerminatorEdges::Single(targets.target_for_value(scalar_int.to_bits_unchecked()))
} else { TerminatorEdges::SwitchInt { discr, targets } }
}
FlatSet::Top => TerminatorEdges::SwitchInt { discr, targets },
}
}
fn assign_operand(&self, state: &mut State<FlatSet<Scalar>>,
place: PlaceIndex, operand: &Operand<'tcx>) {
match operand {
Operand::RuntimeChecks(_) => {}
Operand::Copy(rhs) | Operand::Move(rhs) => {
if let Some(rhs) = self.map.find(rhs.as_ref()) {
state.insert_place_idx(place, rhs, &self.map);
} else if rhs.projection.first() == Some(&PlaceElem::Deref)
&&
let FlatSet::Elem(pointer) =
state.get(rhs.local.into(), &self.map) &&
let rhs_ty = self.local_decls[rhs.local].ty &&
let Ok(rhs_layout) =
self.tcx.layout_of(self.typing_env.as_query_input(rhs_ty)) {
let op = ImmTy::from_scalar(pointer, rhs_layout).into();
self.assign_constant(state, place, op, rhs.projection);
}
}
Operand::Constant(constant) => {
if let Some(constant) =
self.ecx.eval_mir_constant(&constant.const_, constant.span,
None).discard_err() {
self.assign_constant(state, place, constant, &[]);
}
}
}
}
#[doc = " The caller must have flooded `place`."]
#[doc = ""]
#[doc = " Perform: `place = operand.projection`."]
fn assign_constant(&self, state: &mut State<FlatSet<Scalar>>,
place: PlaceIndex, mut operand: OpTy<'tcx>,
projection: &[PlaceElem<'tcx>]) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("assign_constant",
"rustc_mir_transform::dataflow_const_prop",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs"),
::tracing_core::__macro_support::Option::Some(560u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dataflow_const_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("place")
}> =
::tracing::__macro_support::FieldName::new("place");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("operand")
}> =
::tracing::__macro_support::FieldName::new("operand");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("projection")
}> =
::tracing::__macro_support::FieldName::new("projection");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&operand)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&projection)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
for &(mut proj_elem) in projection {
if let PlaceElem::Index(index) = proj_elem {
if let FlatSet::Elem(index) =
state.get(index.into(), &self.map) &&
let Some(offset) =
index.to_target_usize(&self.tcx).discard_err() &&
let Some(min_length) = offset.checked_add(1) {
proj_elem =
PlaceElem::ConstantIndex {
offset,
min_length,
from_end: false,
};
} else { return; }
}
operand =
if let Some(operand) =
self.ecx.project(&operand, proj_elem).discard_err() {
operand
} else { return; }
}
self.map.for_each_projection_value(place, operand,
&mut |elem, op|
match elem {
TrackElem::Field(idx) =>
self.ecx.project_field(op, idx).discard_err(),
TrackElem::Variant(idx) =>
self.ecx.project_downcast(op, idx).discard_err(),
TrackElem::Discriminant => {
let variant = self.ecx.read_discriminant(op).discard_err()?;
let discr_value =
self.ecx.discriminant_for_variant(op.layout.ty,
variant).discard_err()?;
Some(discr_value.into())
}
TrackElem::DerefLen => {
let op: OpTy<'_> =
self.ecx.deref_pointer(op).discard_err()?.into();
let len_usize = op.len(&self.ecx).discard_err()?;
let layout =
self.tcx.layout_of(self.typing_env.as_query_input(self.tcx.types.usize)).unwrap();
Some(ImmTy::from_uint(len_usize, layout).into())
}
},
&mut |place, op|
{
if let Some(imm) =
self.ecx.read_immediate_raw(op).discard_err() &&
let Some(imm) = imm.right() {
let elem = self.wrap_immediate(*imm);
state.insert_value_idx(place, elem, &self.map);
}
});
}
}
}
}
fn binary_op(&self, state: &mut State<FlatSet<Scalar>>, op: BinOp,
left: &Operand<'tcx>, right: &Operand<'tcx>)
-> (FlatSet<Scalar>, FlatSet<Scalar>) {
let left = self.eval_operand(left, state);
let right = self.eval_operand(right, state);
match (left, right) {
(FlatSet::Bottom, _) | (_, FlatSet::Bottom) =>
(FlatSet::Bottom, FlatSet::Bottom),
(FlatSet::Elem(left), FlatSet::Elem(right)) => {
match self.ecx.binary_op(op, &left, &right).discard_err() {
Some(val) => {
if #[allow(non_exhaustive_omitted_patterns)] match val.layout.backend_repr
{
BackendRepr::ScalarPair { .. } => true,
_ => false,
} {
let (val, overflow) = val.to_scalar_pair();
(FlatSet::Elem(val), FlatSet::Elem(overflow))
} else { (FlatSet::Elem(val.to_scalar()), FlatSet::Bottom) }
}
_ => (FlatSet::Top, FlatSet::Top),
}
}
(FlatSet::Elem(const_arg), _) | (_, FlatSet::Elem(const_arg))
=> {
let layout = const_arg.layout;
if !#[allow(non_exhaustive_omitted_patterns)] match layout.backend_repr
{
rustc_abi::BackendRepr::Scalar(..) => true,
_ => false,
} {
return (FlatSet::Top, FlatSet::Top);
}
let arg_scalar = const_arg.to_scalar();
let Some(arg_value) =
arg_scalar.to_bits(layout.size).discard_err() else {
return (FlatSet::Top, FlatSet::Top);
};
match op {
BinOp::BitAnd if arg_value == 0 =>
(FlatSet::Elem(arg_scalar), FlatSet::Bottom),
BinOp::BitOr if
arg_value == layout.size.truncate(u128::MAX) ||
(layout.ty.is_bool() && arg_value == 1) => {
(FlatSet::Elem(arg_scalar), FlatSet::Bottom)
}
BinOp::Mul if layout.ty.is_integral() && arg_value == 0 => {
(FlatSet::Elem(arg_scalar),
FlatSet::Elem(Scalar::from_bool(false)))
}
_ => (FlatSet::Top, FlatSet::Top),
}
}
(FlatSet::Top, FlatSet::Top) => (FlatSet::Top, FlatSet::Top),
}
}
fn eval_operand(&self, op: &Operand<'tcx>,
state: &mut State<FlatSet<Scalar>>) -> FlatSet<ImmTy<'tcx>> {
let value =
match self.handle_operand(op) {
ValueOrPlace::Value(value) => value,
ValueOrPlace::Place(place) =>
state.get_idx(place, &self.map),
};
match value {
FlatSet::Top => FlatSet::Top,
FlatSet::Elem(scalar) => {
let ty = op.ty(self.local_decls, self.tcx);
self.tcx.layout_of(self.typing_env.as_query_input(ty)).map_or(FlatSet::Top,
|layout|
{ FlatSet::Elem(ImmTy::from_scalar(scalar, layout)) })
}
FlatSet::Bottom => FlatSet::Bottom,
}
}
fn eval_discriminant(&self, enum_ty: Ty<'tcx>,
variant_index: VariantIdx) -> Option<Scalar> {
if !enum_ty.is_enum() { return None; }
let enum_ty_layout =
self.tcx.layout_of(self.typing_env.as_query_input(enum_ty)).ok()?;
let discr_value =
self.ecx.discriminant_for_variant(enum_ty_layout.ty,
variant_index).discard_err()?;
Some(discr_value.to_scalar())
}
fn wrap_immediate(&self, imm: Immediate) -> FlatSet<Scalar> {
match imm {
Immediate::Scalar(scalar) => FlatSet::Elem(scalar),
Immediate::Uninit => FlatSet::Bottom,
_ => FlatSet::Top,
}
}
}
impl<'tcx> DebugWithContext<ConstAnalysis<'_, 'tcx>> for
State<FlatSet<Scalar>> {
fn fmt_with(&self, ctxt: &ConstAnalysis<'_, 'tcx>,
f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
State::Reachable(values) =>
debug_with_context(values, None, &ctxt.map, f),
State::Unreachable =>
f.write_fmt(format_args!("unreachable")),
}
}
fn fmt_diff_with(&self, old: &Self, ctxt: &ConstAnalysis<'_, 'tcx>,
f: &mut Formatter<'_>) -> std::fmt::Result {
match (self, old) {
(State::Reachable(this), State::Reachable(old)) => {
debug_with_context(this, Some(old), &ctxt.map, f)
}
_ => Ok(()),
}
}
}
struct Patch<'tcx> {
tcx: TyCtxt<'tcx>,
before_effect: FxHashMap<(Location, Place<'tcx>), Const<'tcx>>,
assignments: FxHashMap<Location, Const<'tcx>>,
}
impl<'tcx> Patch<'tcx> {
pub(crate) fn new(tcx: TyCtxt<'tcx>) -> Self {
Self {
tcx,
before_effect: FxHashMap::default(),
assignments: FxHashMap::default(),
}
}
fn make_operand(&self, const_: Const<'tcx>) -> Operand<'tcx> {
Operand::Constant(Box::new(ConstOperand {
span: DUMMY_SP,
user_ty: None,
const_,
}))
}
}
struct Collector<'a, 'tcx> {
patch: Patch<'tcx>,
local_decls: &'a LocalDecls<'tcx>,
ecx: InterpCx<'tcx, DummyMachine>,
map: &'a Map<'tcx>,
}
impl<'a, 'tcx> Collector<'a, 'tcx> {
pub(crate) fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>,
map: &'a Map<'tcx>) -> Self {
Self {
patch: Patch::new(tcx),
local_decls: &body.local_decls,
ecx: InterpCx::new(tcx, DUMMY_SP, body.typing_env(tcx),
DummyMachine),
map,
}
}
fn try_make_constant(&mut self, place: Place<'tcx>,
state: &State<FlatSet<Scalar>>) -> Option<Const<'tcx>> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("try_make_constant",
"rustc_mir_transform::dataflow_const_prop",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs"),
::tracing_core::__macro_support::Option::Some(783u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dataflow_const_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("place")
}> =
::tracing::__macro_support::FieldName::new("place");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("state")
}> =
::tracing::__macro_support::FieldName::new("state");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&state)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Option<Const<'tcx>> =
loop {};
return __tracing_attr_fake_return;
}
{
let ty = place.ty(self.local_decls, self.patch.tcx).ty;
let layout = self.ecx.layout_of(ty).ok()?;
if layout.is_zst() { return Some(Const::zero_sized(ty)); }
if layout.is_unsized() { return None; }
let place = self.map.find(place.as_ref())?;
if layout.backend_repr.is_scalar() &&
let Some(value) =
propagatable_scalar(place, state, self.map) {
return Some(Const::Val(ConstValue::Scalar(value), ty));
}
if #[allow(non_exhaustive_omitted_patterns)] match layout.backend_repr
{
BackendRepr::Scalar(..) | BackendRepr::ScalarPair { .. } =>
true,
_ => false,
} {
let alloc_id =
self.ecx.intern_with_temp_alloc(layout,
|ecx, dest|
{
try_write_constant(ecx, dest, place, ty, state, self.map)
}).discard_err()?;
return Some(Const::Val(ConstValue::Indirect {
alloc_id,
offset: Size::ZERO,
}, ty));
}
None
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs:783",
"rustc_mir_transform::dataflow_const_prop",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs"),
::tracing_core::__macro_support::Option::Some(783u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dataflow_const_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
}
fn propagatable_scalar(place: PlaceIndex, state: &State<FlatSet<Scalar>>,
map: &Map<'_>) -> Option<Scalar> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("propagatable_scalar",
"rustc_mir_transform::dataflow_const_prop",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs"),
::tracing_core::__macro_support::Option::Some(821u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dataflow_const_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("place")
}> =
::tracing::__macro_support::FieldName::new("place");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("state")
}> =
::tracing::__macro_support::FieldName::new("state");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&state)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Option<Scalar> = loop {};
return __tracing_attr_fake_return;
}
{
if let FlatSet::Elem(value) = state.get_idx(place, map) &&
value.try_to_scalar_int().is_ok() {
Some(value)
} else { None }
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs:821",
"rustc_mir_transform::dataflow_const_prop",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs"),
::tracing_core::__macro_support::Option::Some(821u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dataflow_const_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn try_write_constant<'tcx>(ecx: &mut InterpCx<'tcx, DummyMachine>,
dest: &PlaceTy<'tcx>, place: PlaceIndex, ty: Ty<'tcx>,
state: &State<FlatSet<Scalar>>, map: &Map<'tcx>)
-> InterpResult<'tcx> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("try_write_constant",
"rustc_mir_transform::dataflow_const_prop",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs"),
::tracing_core::__macro_support::Option::Some(837u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dataflow_const_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("dest")
}> =
::tracing::__macro_support::FieldName::new("dest");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("place")
}> =
::tracing::__macro_support::FieldName::new("place");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("ty")
}> =
::tracing::__macro_support::FieldName::new("ty");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&dest)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: InterpResult<'tcx> =
loop {};
return __tracing_attr_fake_return;
}
{
let layout = ecx.layout_of(ty)?;
if layout.is_zst() { return interp_ok(()); }
if layout.backend_repr.is_scalar() &&
let Some(value) = propagatable_scalar(place, state, map) {
return ecx.write_immediate(Immediate::Scalar(value), dest);
}
match ty.kind() {
ty::FnDef(..) => {}
ty::Bool | ty::Int(_) | ty::Uint(_) | ty::Float(_) |
ty::Char => {
{
struct Zst;
#[automatically_derived]
impl ::core::fmt::Debug for Zst {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "Zst")
}
}
impl std::fmt::Display for Zst {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
-> std::fmt::Result {
f.write_fmt(format_args!("primitive type with provenance"))
}
}
impl rustc_middle::mir::interpret::MachineStopType for Zst
{}
do yeet ::rustc_middle::mir::interpret::InterpErrorKind::MachineStop(Box::new(Zst))
}
}
ty::Tuple(elem_tys) => {
for (i, elem) in elem_tys.iter().enumerate() {
let i = FieldIdx::from_usize(i);
let Some(field) =
map.apply(place,
TrackElem::Field(i)) else {
{
struct Zst;
#[automatically_derived]
impl ::core::fmt::Debug for Zst {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "Zst")
}
}
impl std::fmt::Display for Zst {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
-> std::fmt::Result {
f.write_fmt(format_args!("missing field in tuple"))
}
}
impl rustc_middle::mir::interpret::MachineStopType for Zst
{}
do yeet ::rustc_middle::mir::interpret::InterpErrorKind::MachineStop(Box::new(Zst))
}
};
let field_dest = ecx.project_field(dest, i)?;
try_write_constant(ecx, &field_dest, field, elem, state,
map)?;
}
}
ty::Adt(def, args) => {
if def.is_union() {
{
struct Zst;
#[automatically_derived]
impl ::core::fmt::Debug for Zst {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "Zst")
}
}
impl std::fmt::Display for Zst {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
-> std::fmt::Result {
f.write_fmt(format_args!("cannot propagate unions"))
}
}
impl rustc_middle::mir::interpret::MachineStopType for Zst
{}
do yeet ::rustc_middle::mir::interpret::InterpErrorKind::MachineStop(Box::new(Zst))
}
}
let (variant_idx, variant_def, variant_place,
variant_dest) =
if def.is_enum() {
let Some(discr) =
map.apply(place,
TrackElem::Discriminant) else {
{
struct Zst;
#[automatically_derived]
impl ::core::fmt::Debug for Zst {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "Zst")
}
}
impl std::fmt::Display for Zst {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
-> std::fmt::Result {
f.write_fmt(format_args!("missing discriminant for enum"))
}
}
impl rustc_middle::mir::interpret::MachineStopType for Zst
{}
do yeet ::rustc_middle::mir::interpret::InterpErrorKind::MachineStop(Box::new(Zst))
}
};
let FlatSet::Elem(Scalar::Int(discr)) =
state.get_idx(discr,
map) else {
{
struct Zst;
#[automatically_derived]
impl ::core::fmt::Debug for Zst {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "Zst")
}
}
impl std::fmt::Display for Zst {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
-> std::fmt::Result {
f.write_fmt(format_args!("discriminant with provenance"))
}
}
impl rustc_middle::mir::interpret::MachineStopType for Zst
{}
do yeet ::rustc_middle::mir::interpret::InterpErrorKind::MachineStop(Box::new(Zst))
}
};
let discr_bits = discr.to_bits(discr.size());
let Some((variant, _)) =
def.discriminants(*ecx.tcx).find(|(_, var)|
discr_bits ==
var.val) else {
{
struct Zst;
#[automatically_derived]
impl ::core::fmt::Debug for Zst {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "Zst")
}
}
impl std::fmt::Display for Zst {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
-> std::fmt::Result {
f.write_fmt(format_args!("illegal discriminant for enum"))
}
}
impl rustc_middle::mir::interpret::MachineStopType for Zst
{}
do yeet ::rustc_middle::mir::interpret::InterpErrorKind::MachineStop(Box::new(Zst))
}
};
let Some(variant_place) =
map.apply(place,
TrackElem::Variant(variant)) else {
{
struct Zst;
#[automatically_derived]
impl ::core::fmt::Debug for Zst {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "Zst")
}
}
impl std::fmt::Display for Zst {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
-> std::fmt::Result {
f.write_fmt(format_args!("missing variant for enum"))
}
}
impl rustc_middle::mir::interpret::MachineStopType for Zst
{}
do yeet ::rustc_middle::mir::interpret::InterpErrorKind::MachineStop(Box::new(Zst))
}
};
let variant_dest = ecx.project_downcast(dest, variant)?;
(variant, def.variant(variant), variant_place, variant_dest)
} else {
(FIRST_VARIANT, def.non_enum_variant(), place, dest.clone())
};
for (i, field) in variant_def.fields.iter_enumerated() {
let ty = field.ty(*ecx.tcx, args).skip_norm_wip();
let Some(field) =
map.apply(variant_place,
TrackElem::Field(i)) else {
{
struct Zst;
#[automatically_derived]
impl ::core::fmt::Debug for Zst {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "Zst")
}
}
impl std::fmt::Display for Zst {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
-> std::fmt::Result {
f.write_fmt(format_args!("missing field in ADT"))
}
}
impl rustc_middle::mir::interpret::MachineStopType for Zst
{}
do yeet ::rustc_middle::mir::interpret::InterpErrorKind::MachineStop(Box::new(Zst))
}
};
let field_dest = ecx.project_field(&variant_dest, i)?;
try_write_constant(ecx, &field_dest, field, ty, state,
map)?;
}
ecx.write_discriminant(variant_idx, dest)?;
}
ty::Array(_, _) | ty::Pat(_, _) | ty::Ref(..) |
ty::RawPtr(..) | ty::FnPtr(..) | ty::Str | ty::Slice(_) |
ty::Never | ty::Foreign(..) | ty::Alias(..) | ty::Param(_) |
ty::Bound(..) | ty::Placeholder(..) | ty::Closure(..) |
ty::CoroutineClosure(..) | ty::Coroutine(..) |
ty::Dynamic(..) | ty::UnsafeBinder(_) => {
struct Zst;
#[automatically_derived]
impl ::core::fmt::Debug for Zst {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter)
-> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "Zst")
}
}
impl std::fmt::Display for Zst {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>)
-> std::fmt::Result {
f.write_fmt(format_args!("unsupported type"))
}
}
impl rustc_middle::mir::interpret::MachineStopType for Zst
{}
do yeet ::rustc_middle::mir::interpret::InterpErrorKind::MachineStop(Box::new(Zst))
}
ty::Error(_) | ty::Infer(..) | ty::CoroutineWitness(..) =>
::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached")),
}
interp_ok(())
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs:837",
"rustc_mir_transform::dataflow_const_prop",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs"),
::tracing_core::__macro_support::Option::Some(837u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dataflow_const_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
impl<'tcx> ResultsVisitor<'tcx, ConstAnalysis<'_, 'tcx>> for
Collector<'_, 'tcx> {
fn visit_after_early_statement_effect(&mut self,
state: &State<FlatSet<Scalar>>, statement: &Statement<'tcx>,
location: Location) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("visit_after_early_statement_effect",
"rustc_mir_transform::dataflow_const_prop",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs"),
::tracing_core::__macro_support::Option::Some(944u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dataflow_const_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("state")
}> =
::tracing::__macro_support::FieldName::new("state");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("location")
}> =
::tracing::__macro_support::FieldName::new("location");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&state)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&location)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
match &statement.kind {
StatementKind::Assign((_, rvalue)) => {
OperandCollector {
state,
visitor: self,
}.visit_rvalue(rvalue, location);
}
_ => (),
}
}
}
}
}
fn visit_after_primary_statement_effect(&mut self,
state: &State<FlatSet<Scalar>>, statement: &Statement<'tcx>,
location: Location) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("visit_after_primary_statement_effect",
"rustc_mir_transform::dataflow_const_prop",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs"),
::tracing_core::__macro_support::Option::Some(959u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dataflow_const_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("state")
}> =
::tracing::__macro_support::FieldName::new("state");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("location")
}> =
::tracing::__macro_support::FieldName::new("location");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&state)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&location)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
match statement.kind {
StatementKind::Assign((_,
Rvalue::Use(Operand::Constant(_), _))) => {}
StatementKind::Assign((place, _)) => {
if let Some(value) = self.try_make_constant(place, state) {
self.patch.assignments.insert(location, value);
}
}
_ => (),
}
}
}
}
}
fn visit_after_early_terminator_effect(&mut self,
state: &State<FlatSet<Scalar>>, terminator: &Terminator<'tcx>,
location: Location) {
OperandCollector {
state,
visitor: self,
}.visit_terminator(terminator, location);
}
}
impl<'tcx> MutVisitor<'tcx> for Patch<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_statement(&mut self, statement: &mut Statement<'tcx>,
location: Location) {
if let Some(value) = self.assignments.get(&location) {
match &mut statement.kind {
StatementKind::Assign((_, rvalue)) => {
let old_retag =
match rvalue {
Rvalue::Use(_, retag) => *retag,
_ => WithRetag::Yes,
};
*rvalue = Rvalue::Use(self.make_operand(*value), old_retag);
}
_ =>
::rustc_middle::util::bug::bug_fmt(format_args!("found assignment info for non-assign statement")),
}
} else { self.super_statement(statement, location); }
}
fn visit_operand(&mut self, operand: &mut Operand<'tcx>,
location: Location) {
match operand {
Operand::Copy(place) | Operand::Move(place) => {
if let Some(value) =
self.before_effect.get(&(location, *place)) {
*operand = self.make_operand(*value);
} else if !place.projection.is_empty() {
self.super_operand(operand, location)
}
}
Operand::Constant(_) | Operand::RuntimeChecks(_) => {}
}
}
fn process_projection_elem(&mut self, elem: PlaceElem<'tcx>,
location: Location) -> Option<PlaceElem<'tcx>> {
if let PlaceElem::Index(local) = elem {
let offset =
self.before_effect.get(&(location, local.into()))?;
let offset = offset.try_to_scalar()?;
let offset = offset.to_target_usize(&self.tcx).discard_err()?;
let min_length = offset.checked_add(1)?;
Some(PlaceElem::ConstantIndex {
offset,
min_length,
from_end: false,
})
} else { None }
}
}
struct OperandCollector<'a, 'b, 'tcx> {
state: &'a State<FlatSet<Scalar>>,
visitor: &'a mut Collector<'b, 'tcx>,
}
impl<'tcx> Visitor<'tcx> for OperandCollector<'_, '_, 'tcx> {
fn visit_projection_elem(&mut self, _: PlaceRef<'tcx>,
elem: PlaceElem<'tcx>, _: PlaceContext, location: Location) {
if let PlaceElem::Index(local) = elem &&
let Some(value) =
self.visitor.try_make_constant(local.into(), self.state) {
self.visitor.patch.before_effect.insert((location,
local.into()), value);
}
}
fn visit_operand(&mut self, operand: &Operand<'tcx>,
location: Location) {
if let Some(place) = operand.place() {
if let Some(value) =
self.visitor.try_make_constant(place, self.state) {
self.visitor.patch.before_effect.insert((location, place),
value);
} else if !place.projection.is_empty() {
self.super_operand(operand, location)
}
}
}
}
}
#[allow(unused_imports)]
use dataflow_const_prop::DataflowConstProp as _;
mod dead_store_elimination {
use rustc_middle::bug;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use rustc_mir_dataflow::Analysis;
use rustc_mir_dataflow::debuginfo::debuginfo_locals;
use rustc_mir_dataflow::impls::{
LivenessTransferFunction, MaybeTransitiveLiveLocals, borrowed_locals,
};
use crate::PassPolicy;
use crate::simplify::UsedInStmtLocals;
use crate::util::most_packed_projection;
fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
let borrowed_locals = borrowed_locals(body);
let debuginfo_locals = debuginfo_locals(body);
let mut live =
MaybeTransitiveLiveLocals::new(&borrowed_locals,
&debuginfo_locals).iterate_to_fixpoint(tcx, body,
None).into_results_cursor(body);
let mut call_operands_to_move = Vec::new();
let mut patch = Vec::new();
for (bb, bb_data) in traversal::preorder(body) {
if let TerminatorKind::Call { ref args, ref destination, .. } =
bb_data.terminator().kind {
let loc =
Location {
block: bb,
statement_index: bb_data.statements.len(),
};
live.seek_to_block_end(bb);
let mut state = live.get().clone();
LivenessTransferFunction(&mut state).visit_place(destination,
visit::PlaceContext::MutatingUse(visit::MutatingUseContext::Call),
loc);
for (index, arg) in
args.iter().map(|a| &a.node).enumerate().rev() {
if let Operand::Copy(place) = *arg && !place.is_indirect()
&& !borrowed_locals.contains(place.local) &&
!state.contains(place.local) &&
most_packed_projection(tcx, body, place).is_none() {
call_operands_to_move.push((bb, index));
}
LivenessTransferFunction(&mut state).visit_operand(arg,
loc);
}
}
for (statement_index, statement) in
bb_data.statements.iter().enumerate().rev() {
if let Some(destination) =
MaybeTransitiveLiveLocals::can_be_removed_if_dead(&statement.kind,
&borrowed_locals, &debuginfo_locals) {
let loc = Location { block: bb, statement_index };
live.seek_before_primary_effect(loc);
if !live.get().contains(destination.local) {
let drop_debuginfo =
!debuginfo_locals.contains(destination.local);
if !(drop_debuginfo ||
statement.kind.as_debuginfo().is_some()) {
{
::core::panicking::panic_fmt(format_args!("don\'t know how to retain the debug information for {0:?}",
statement.kind));
}
};
patch.push((loc, drop_debuginfo));
}
}
}
}
if patch.is_empty() && call_operands_to_move.is_empty() {
return false;
}
let eliminated = !patch.is_empty();
let bbs = body.basic_blocks.as_mut_preserves_cfg();
for (Location { block, statement_index }, drop_debuginfo) in patch {
bbs[block].statements[statement_index].make_nop(drop_debuginfo);
}
for (block, argument_index) in call_operands_to_move {
let TerminatorKind::Call { ref mut args, .. } =
bbs[block].terminator_mut().kind else {
::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))
};
let arg = &mut args[argument_index].node;
let Operand::Copy(place) =
*arg else {
::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))
};
*arg = Operand::Move(place);
}
eliminated
}
pub(super) enum DeadStoreElimination { Initial, Final, }
impl<'tcx> crate::MirPass<'tcx> for DeadStoreElimination {
fn name(&self) -> &'static str {
match self {
DeadStoreElimination::Initial =>
"DeadStoreElimination-initial",
DeadStoreElimination::Final => "DeadStoreElimination-final",
}
}
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 2)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
if eliminate(tcx, body) {
UsedInStmtLocals::new(body).remove_unused_storage_annotations(body);
for data in body.basic_blocks.as_mut_preserves_cfg() {
data.strip_nops();
}
}
}
}
}
#[allow(unused_imports)]
use dead_store_elimination::DeadStoreElimination as _;
mod deref_separator {
use rustc_middle::mir::visit::NonUseContext::VarDebugInfo;
use rustc_middle::mir::visit::{MutVisitor, PlaceContext};
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use crate::PassPolicy;
use crate::patch::MirPatch;
pub(super) struct Derefer;
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> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_place(&mut self, place: &mut Place<'tcx>,
cntxt: PlaceContext, loc: Location) {
if !place.projection.is_empty() &&
cntxt != PlaceContext::NonUse(VarDebugInfo) &&
place.projection[1..].contains(&ProjectionElem::Deref) {
let mut place_local = place.local;
let mut last_len = 0;
let mut last_deref_idx = 0;
for (idx, elem) in place.projection[0..].iter().enumerate() {
if *elem == ProjectionElem::Deref { last_deref_idx = idx; }
}
for (idx, (p_ref, p_elem)) in
place.iter_projections().enumerate() {
if !p_ref.projection.is_empty() &&
p_elem == ProjectionElem::Deref {
let ty = p_ref.ty(self.local_decls, self.tcx).ty;
let temp =
self.patcher.new_local_with_info(ty,
self.local_decls[p_ref.local].source_info.span,
if self.add_deref_metadata {
LocalInfo::DerefTemp
} else { LocalInfo::Boring });
let deref_place =
Place::from(place_local).project_deeper(&p_ref.projection[last_len..],
self.tcx);
self.patcher.add_assign(loc, Place::from(temp),
if self.add_deref_metadata {
Rvalue::CopyForDeref(deref_place)
} else {
Rvalue::Use(Operand::Copy(deref_place), WithRetag::No)
});
place_local = temp;
last_len = p_ref.projection.len();
if idx == last_deref_idx {
let temp_place =
Place::from(temp).project_deeper(&place.projection[idx..],
self.tcx);
*place = temp_place;
}
}
}
}
}
}
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,
add_deref_metadata,
};
for (bb, data) in
body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
checker.visit_basic_block_data(bb, data);
}
checker.patcher.apply(body);
}
impl<'tcx> crate::MirPass<'tcx> for Derefer {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
deref_finder(tcx, body, true);
}
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::Required
}
}
}
#[allow(unused_imports)]
use deref_separator::Derefer as _;
mod dest_prop {
use rustc_data_structures::union_find::UnionFind;
use rustc_index::bit_set::DenseBitSet;
use rustc_index::interval::SparseIntervalMatrix;
use rustc_index::{IndexVec, newtype_index};
use rustc_middle::mir::visit::{
MutVisitor, PlaceContext, VisitPlacesWith, Visitor,
};
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use rustc_mir_dataflow::impls::{
DefUse, LivenessTransferFunction, MaybeLiveLocals,
};
use rustc_mir_dataflow::points::DenseLocationMap;
use rustc_mir_dataflow::{Analysis, EntryStates, GenKill};
use tracing::{debug, trace};
use crate::PassPolicy;
pub(super) struct DestinationPropagation;
impl<'tcx> crate::MirPass<'tcx> for DestinationPropagation {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 2)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("run_pass",
"rustc_mir_transform::dest_prop", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs"),
::tracing_core::__macro_support::Option::Some(161u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dest_prop"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let def_id = body.source.def_id();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs:164",
"rustc_mir_transform::dest_prop", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs"),
::tracing_core::__macro_support::Option::Some(164u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dest_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let borrowed =
rustc_mir_dataflow::impls::borrowed_locals(body);
let candidates = Candidates::find(body, &borrowed);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs:169",
"rustc_mir_transform::dest_prop", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs"),
::tracing_core::__macro_support::Option::Some(169u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dest_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("candidates")
}> =
::tracing::__macro_support::FieldName::new("candidates");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&candidates)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if candidates.c.is_empty() { return; }
let live =
MaybeLiveLocals.iterate_to_fixpoint(tcx, body,
Some("MaybeLiveLocals-DestProp"));
let points = DenseLocationMap::new(body);
let mut relevant =
RelevantLocals::compute(&candidates,
body.local_decls.len());
let mut live =
save_as_intervals(&points, body, &relevant,
live.entry_states);
dest_prop_mir_dump(tcx, body, &points, &live, &relevant);
let mut merged_locals =
DenseBitSet::new_empty(body.local_decls.len());
for (src, dst) in candidates.c.into_iter() {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs:185",
"rustc_mir_transform::dest_prop", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs"),
::tracing_core::__macro_support::Option::Some(185u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dest_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("src")
}> =
::tracing::__macro_support::FieldName::new("src");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("dst")
}> =
::tracing::__macro_support::FieldName::new("dst");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&src)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&dst)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let Some(mut src) = relevant.find(src) else { continue };
let Some(mut dst) = relevant.find(dst) else { continue };
if src == dst { continue; }
let Some(src_live_ranges) = live.row(src) else { continue };
let Some(dst_live_ranges) = live.row(dst) else { continue };
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs:195",
"rustc_mir_transform::dest_prop", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs"),
::tracing_core::__macro_support::Option::Some(195u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dest_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("src")
}> =
::tracing::__macro_support::FieldName::new("src");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("src_live_ranges")
}> =
::tracing::__macro_support::FieldName::new("src_live_ranges");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&src)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&src_live_ranges)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs:196",
"rustc_mir_transform::dest_prop", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs"),
::tracing_core::__macro_support::Option::Some(196u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dest_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("dst")
}> =
::tracing::__macro_support::FieldName::new("dst");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("dst_live_ranges")
}> =
::tracing::__macro_support::FieldName::new("dst_live_ranges");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&dst)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&dst_live_ranges)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if src_live_ranges.disjoint(dst_live_ranges) {
let mut orig_src = relevant.original[src];
let mut orig_dst = relevant.original[dst];
match (is_local_required(orig_src, body),
is_local_required(orig_dst, body)) {
(false, _) => {}
(true, false) => {
std::mem::swap(&mut src, &mut dst);
std::mem::swap(&mut orig_src, &mut orig_dst);
}
(true, true) => continue,
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs:218",
"rustc_mir_transform::dest_prop", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs"),
::tracing_core::__macro_support::Option::Some(218u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dest_prop"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("src")
}> =
::tracing::__macro_support::FieldName::new("src");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("dst")
}> =
::tracing::__macro_support::FieldName::new("dst");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("merge")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&src)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&dst)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
merged_locals.insert(orig_src);
merged_locals.insert(orig_dst);
let head = relevant.union(src, dst);
live.union_rows(src, head);
live.union_rows(dst, head);
}
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs:228",
"rustc_mir_transform::dest_prop", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs"),
::tracing_core::__macro_support::Option::Some(228u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dest_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("merged_locals")
}> =
::tracing::__macro_support::FieldName::new("merged_locals");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&merged_locals)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs:229",
"rustc_mir_transform::dest_prop", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs"),
::tracing_core::__macro_support::Option::Some(229u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dest_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("relevant.renames")
}> =
::tracing::__macro_support::FieldName::new("relevant.renames");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&relevant.renames)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if merged_locals.is_empty() { return; }
apply_merges(body, tcx, relevant, merged_locals);
}
}
}
}
}
fn apply_merges<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>,
relevant: RelevantLocals, merged_locals: DenseBitSet<Local>) {
let mut merger = Merger { tcx, relevant, merged_locals };
merger.visit_body_preserves_cfg(body);
}
struct Merger<'tcx> {
tcx: TyCtxt<'tcx>,
relevant: RelevantLocals,
merged_locals: DenseBitSet<Local>,
}
impl<'tcx> MutVisitor<'tcx> for Merger<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_local(&mut self, local: &mut Local, _: PlaceContext,
_location: Location) {
if let Some(relevant) = self.relevant.find(*local) {
*local = self.relevant.original[relevant];
}
}
fn visit_statement(&mut self, statement: &mut Statement<'tcx>,
location: Location) {
match &statement.kind {
StatementKind::StorageDead(local) |
StatementKind::StorageLive(local) if
self.merged_locals.contains(*local) => {
statement.make_nop(true);
}
_ => (),
};
self.super_statement(statement, location);
match &statement.kind {
StatementKind::Assign((dest, rvalue)) => {
match rvalue {
Rvalue::Use(Operand::Copy(place) | Operand::Move(place), _)
=> {
if dest == place {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs:289",
"rustc_mir_transform::dest_prop", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs"),
::tracing_core::__macro_support::Option::Some(289u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dest_prop"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("{0:?} turned into self-assignment, deleting",
location) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
statement.make_nop(true);
}
}
_ => {}
}
}
_ => {}
}
}
}
#[doc = " Represent a subset of locals which appear in candidates."]
#[rustc_pass_by_value]
struct RelevantLocal {
private_use_as_methods_instead: u32 is const 0..=const 0xFFFF_FF00,
}
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for RelevantLocal { }
#[automatically_derived]
impl ::core::clone::Clone for RelevantLocal {
#[inline]
fn clone(&self) -> RelevantLocal {
let _:
::core::clone::AssertParamIsClone<u32 is const 0..=const 0xFFFF_FF00>;
*self
}
}
#[automatically_derived]
impl ::core::marker::Copy for RelevantLocal { }
impl RelevantLocal {
#[doc = r" Maximum value the index can take, as a `u32`."]
const MAX_AS_U32: u32 = 0xFFFF_FF00;
#[doc = r" Maximum value the index can take."]
const MAX: Self = Self::from_u32(0xFFFF_FF00);
#[doc = r" Zero value of the index."]
const ZERO: Self = Self::from_u32(0);
#[doc = r" Creates a new index from a given `usize`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
const fn from_usize(value: usize) -> Self {
if !(value <= (0xFFFF_FF00 as usize)) {
::core::panicking::panic("assertion failed: value <= (0xFFFF_FF00 as usize)")
};
unsafe { Self::from_u32_unchecked(value as u32) }
}
#[doc = r" Creates a new index from a given `u32`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
const fn from_u32(value: u32) -> Self {
if !(value <= 0xFFFF_FF00) {
::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
};
unsafe { Self::from_u32_unchecked(value) }
}
#[doc = r" Creates a new index from a given `u16`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
const fn from_u16(value: u16) -> Self {
let value = value as u32;
if !(value <= 0xFFFF_FF00) {
::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
};
unsafe { Self::from_u32_unchecked(value) }
}
#[doc = r" Creates a new index from a given `u32`."]
#[doc = r""]
#[doc = r" # Safety"]
#[doc = r""]
#[doc =
r" The provided value must be less than or equal to the maximum value for the newtype."]
#[doc =
r" Providing a value outside this range is undefined due to layout restrictions."]
#[doc = r""]
#[doc = r" Prefer using `from_u32`."]
#[inline]
const unsafe fn from_u32_unchecked(value: u32) -> Self {
Self {
private_use_as_methods_instead: unsafe {
std::mem::transmute(value)
},
}
}
#[doc = r" Extracts the value of this index as a `usize`."]
#[inline]
const fn index(self) -> usize { self.as_usize() }
#[doc = r" Extracts the value of this index as a `u32`."]
#[inline]
const fn as_u32(self) -> u32 {
unsafe {
std::mem::transmute(self.private_use_as_methods_instead)
}
}
#[doc = r" Extracts the value of this index as a `usize`."]
#[inline]
const fn as_usize(self) -> usize { self.as_u32() as usize }
}
impl std::ops::Add<usize> for RelevantLocal {
type Output = Self;
#[inline]
fn add(self, other: usize) -> Self {
Self::from_usize(self.index() + other)
}
}
impl std::ops::AddAssign<usize> for RelevantLocal {
#[inline]
fn add_assign(&mut self, other: usize) { *self = *self + other; }
}
impl rustc_index::Idx for RelevantLocal {
#[inline]
fn new(value: usize) -> Self { Self::from_usize(value) }
#[inline]
fn index(self) -> usize { self.as_usize() }
}
impl From<RelevantLocal> for u32 {
#[inline]
fn from(v: RelevantLocal) -> u32 { v.as_u32() }
}
impl From<RelevantLocal> for usize {
#[inline]
fn from(v: RelevantLocal) -> usize { v.as_usize() }
}
impl From<usize> for RelevantLocal {
#[inline]
fn from(value: usize) -> Self { Self::from_usize(value) }
}
impl From<u32> for RelevantLocal {
#[inline]
fn from(value: u32) -> Self { Self::from_u32(value) }
}
impl ::std::cmp::Eq for RelevantLocal {}
impl ::std::cmp::PartialEq for RelevantLocal {
fn eq(&self, other: &Self) -> bool {
self.as_u32().eq(&other.as_u32())
}
}
impl ::std::marker::StructuralPartialEq for RelevantLocal {}
impl ::std::hash::Hash for RelevantLocal {
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
self.as_u32().hash(state)
}
}
impl ::std::fmt::Debug for RelevantLocal {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>)
-> ::std::fmt::Result {
fmt.write_fmt(format_args!("{0}", self.as_u32()))
}
}
struct RelevantLocals {
original: IndexVec<RelevantLocal, Local>,
shrink: IndexVec<Local, Option<RelevantLocal>>,
renames: UnionFind<RelevantLocal>,
}
#[automatically_derived]
impl ::core::fmt::Debug for RelevantLocals {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"RelevantLocals", "original", &self.original, "shrink",
&self.shrink, "renames", &&self.renames)
}
}
impl RelevantLocals {
fn compute(candidates: &Candidates, num_locals: usize)
-> RelevantLocals {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("compute",
"rustc_mir_transform::dest_prop", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs"),
::tracing_core::__macro_support::Option::Some(321u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dest_prop"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: RelevantLocals = loop {};
return __tracing_attr_fake_return;
}
{
let mut original =
IndexVec::with_capacity(candidates.c.len());
let mut shrink = IndexVec::from_elem_n(None, num_locals);
let mut declare =
|local|
{
shrink.get_or_insert_with(local, || original.push(local));
};
for &(src, dest) in candidates.c.iter() {
declare(src);
declare(dest)
}
let renames = UnionFind::new(original.len());
RelevantLocals { original, shrink, renames }
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs:321",
"rustc_mir_transform::dest_prop", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs"),
::tracing_core::__macro_support::Option::Some(321u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dest_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn find(&mut self, src: Local) -> Option<RelevantLocal> {
let src = self.shrink[src]?;
let src = self.renames.find(src);
Some(src)
}
fn union(&mut self, lhs: RelevantLocal, rhs: RelevantLocal)
-> RelevantLocal {
let head = self.renames.unify(lhs, rhs);
self.original[head] = self.original[rhs];
head
}
}
struct Candidates {
c: Vec<(Local, Local)>,
}
#[automatically_derived]
impl ::core::fmt::Debug for Candidates {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"Candidates", "c", &&self.c)
}
}
#[automatically_derived]
impl ::core::default::Default for Candidates {
#[inline]
fn default() -> Candidates {
Candidates { c: ::core::default::Default::default() }
}
}
impl Candidates {
fn find(body: &Body<'_>, borrowed: &DenseBitSet<Local>)
-> Candidates {
let mut visitor =
FindAssignments {
body,
candidates: Default::default(),
borrowed,
};
visitor.visit_body(body);
Candidates { c: visitor.candidates }
}
}
struct FindAssignments<'a, 'tcx> {
body: &'a Body<'tcx>,
candidates: Vec<(Local, Local)>,
borrowed: &'a DenseBitSet<Local>,
}
impl<'tcx> Visitor<'tcx> for FindAssignments<'_, 'tcx> {
fn visit_statement(&mut self, statement: &Statement<'tcx>,
_: Location) {
if let StatementKind::Assign((lhs,
Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs), _))) =
&statement.kind && let Some(src) = lhs.as_local() &&
let Some(dest) = rhs.as_local() {
if self.borrowed.contains(src) || self.borrowed.contains(dest)
{
return;
}
let src_ty = self.body.local_decls()[src].ty;
let dest_ty = self.body.local_decls()[dest].ty;
if src_ty != dest_ty {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs:414",
"rustc_mir_transform::dest_prop", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs"),
::tracing_core::__macro_support::Option::Some(414u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dest_prop"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("skipped `{0:?} = {1:?}` due to subtyping: {2} != {3}",
src, dest, src_ty, dest_ty) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};
return;
}
self.candidates.push((src, dest));
}
}
}
fn is_local_required(local: Local, body: &Body<'_>) -> bool {
match body.local_kind(local) {
LocalKind::Arg | LocalKind::ReturnPointer => true,
LocalKind::Temp => false,
}
}
fn dest_prop_mir_dump<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>,
points: &DenseLocationMap,
live: &SparseIntervalMatrix<RelevantLocal, TwoStepIndex>,
relevant: &RelevantLocals) {
let locals_live_at =
|location|
{
live.rows().filter(|&r|
live.contains(r,
location)).map(|rl|
relevant.original[rl]).collect::<Vec<_>>()
};
if let Some(dumper) =
MirDumper::new(tcx, "DestinationPropagation-dataflow", body) {
let extra_data =
&|pass_where, w: &mut dyn std::io::Write|
{
if let PassWhere::BeforeLocation(loc) = pass_where {
let location =
TwoStepIndex::new(points, loc, Effect::Before);
let live = locals_live_at(location);
w.write_fmt(format_args!(" // before: {0:?} => {1:?}\n",
location, live))?;
}
if let PassWhere::AfterLocation(loc) = pass_where {
let location =
TwoStepIndex::new(points, loc, Effect::After);
let live = locals_live_at(location);
w.write_fmt(format_args!(" // after: {0:?} => {1:?}\n",
location, live))?;
}
Ok(())
};
dumper.set_extra_data(extra_data).dump_mir(body)
}
}
enum Effect { Before, After, }
#[automatically_derived]
impl ::core::marker::Copy for Effect { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Effect { }
#[automatically_derived]
impl ::core::clone::Clone for Effect {
#[inline]
fn clone(&self) -> Effect { *self }
}
#[automatically_derived]
impl ::core::fmt::Debug for Effect {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
Effect::Before => "Before",
Effect::After => "After",
})
}
}
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for Effect { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Effect {
#[inline]
fn eq(&self, other: &Effect) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}
#[automatically_derived]
impl ::core::cmp::Eq for Effect {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}
#[doc =
" A reversed `PointIndex` but with the lower bit encoding early/late inside the statement."]
#[doc =
" The reversed order allows to use the more efficient `IntervalSet::append` method while we"]
#[doc = " iterate on the statements in reverse order."]
#[rustc_pass_by_value]
struct TwoStepIndex {
private_use_as_methods_instead: u32 is const 0..=const 0xFFFF_FF00,
}
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for TwoStepIndex { }
#[automatically_derived]
impl ::core::clone::Clone for TwoStepIndex {
#[inline]
fn clone(&self) -> TwoStepIndex {
let _:
::core::clone::AssertParamIsClone<u32 is const 0..=const 0xFFFF_FF00>;
*self
}
}
#[automatically_derived]
impl ::core::marker::Copy for TwoStepIndex { }
impl TwoStepIndex {
#[doc = r" Maximum value the index can take, as a `u32`."]
const MAX_AS_U32: u32 = 0xFFFF_FF00;
#[doc = r" Maximum value the index can take."]
const MAX: Self = Self::from_u32(0xFFFF_FF00);
#[doc = r" Zero value of the index."]
const ZERO: Self = Self::from_u32(0);
#[doc = r" Creates a new index from a given `usize`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
const fn from_usize(value: usize) -> Self {
if !(value <= (0xFFFF_FF00 as usize)) {
::core::panicking::panic("assertion failed: value <= (0xFFFF_FF00 as usize)")
};
unsafe { Self::from_u32_unchecked(value as u32) }
}
#[doc = r" Creates a new index from a given `u32`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
const fn from_u32(value: u32) -> Self {
if !(value <= 0xFFFF_FF00) {
::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
};
unsafe { Self::from_u32_unchecked(value) }
}
#[doc = r" Creates a new index from a given `u16`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
const fn from_u16(value: u16) -> Self {
let value = value as u32;
if !(value <= 0xFFFF_FF00) {
::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
};
unsafe { Self::from_u32_unchecked(value) }
}
#[doc = r" Creates a new index from a given `u32`."]
#[doc = r""]
#[doc = r" # Safety"]
#[doc = r""]
#[doc =
r" The provided value must be less than or equal to the maximum value for the newtype."]
#[doc =
r" Providing a value outside this range is undefined due to layout restrictions."]
#[doc = r""]
#[doc = r" Prefer using `from_u32`."]
#[inline]
const unsafe fn from_u32_unchecked(value: u32) -> Self {
Self {
private_use_as_methods_instead: unsafe {
std::mem::transmute(value)
},
}
}
#[doc = r" Extracts the value of this index as a `usize`."]
#[inline]
const fn index(self) -> usize { self.as_usize() }
#[doc = r" Extracts the value of this index as a `u32`."]
#[inline]
const fn as_u32(self) -> u32 {
unsafe {
std::mem::transmute(self.private_use_as_methods_instead)
}
}
#[doc = r" Extracts the value of this index as a `usize`."]
#[inline]
const fn as_usize(self) -> usize { self.as_u32() as usize }
}
impl std::ops::Add<usize> for TwoStepIndex {
type Output = Self;
#[inline]
fn add(self, other: usize) -> Self {
Self::from_usize(self.index() + other)
}
}
impl std::ops::AddAssign<usize> for TwoStepIndex {
#[inline]
fn add_assign(&mut self, other: usize) { *self = *self + other; }
}
impl rustc_index::Idx for TwoStepIndex {
#[inline]
fn new(value: usize) -> Self { Self::from_usize(value) }
#[inline]
fn index(self) -> usize { self.as_usize() }
}
impl ::std::iter::Step for TwoStepIndex {
#[inline]
fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
<usize as
::std::iter::Step>::steps_between(&Self::index(*start),
&Self::index(*end))
}
#[inline]
fn forward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_add(u).map(Self::from_usize)
}
#[inline]
fn backward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_sub(u).map(Self::from_usize)
}
#[inline]
fn forward_overflowing(start: Self, u: usize) -> (Self, bool) {
let (s, o) = Self::index(start).overflowing_add(u);
(Self::from_usize(s), o)
}
#[inline]
fn backward_overflowing(start: Self, u: usize) -> (Self, bool) {
let (s, o) = Self::index(start).overflowing_sub(u);
(Self::from_usize(s), o)
}
}
impl ::std::cmp::Ord for TwoStepIndex {
#[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.as_u32().cmp(&other.as_u32())
}
}
impl ::std::cmp::PartialOrd for TwoStepIndex {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl From<TwoStepIndex> for u32 {
#[inline]
fn from(v: TwoStepIndex) -> u32 { v.as_u32() }
}
impl From<TwoStepIndex> for usize {
#[inline]
fn from(v: TwoStepIndex) -> usize { v.as_usize() }
}
impl From<usize> for TwoStepIndex {
#[inline]
fn from(value: usize) -> Self { Self::from_usize(value) }
}
impl From<u32> for TwoStepIndex {
#[inline]
fn from(value: u32) -> Self { Self::from_u32(value) }
}
impl ::std::cmp::Eq for TwoStepIndex {}
impl ::std::cmp::PartialEq for TwoStepIndex {
fn eq(&self, other: &Self) -> bool {
self.as_u32().eq(&other.as_u32())
}
}
impl ::std::marker::StructuralPartialEq for TwoStepIndex {}
impl ::std::hash::Hash for TwoStepIndex {
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
self.as_u32().hash(state)
}
}
impl ::std::fmt::Debug for TwoStepIndex {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>)
-> ::std::fmt::Result {
fmt.write_fmt(format_args!("TwoStepIndex({0})", self.as_u32()))
}
}
impl TwoStepIndex {
fn new(elements: &DenseLocationMap, location: Location,
effect: Effect) -> TwoStepIndex {
let point = elements.point_from_location(location);
let effect =
match effect { Effect::Before => 0, Effect::After => 1, };
let max_index = 2 * elements.num_points() as u32 - 1;
let index = 2 * point.as_u32() + (effect as u32);
TwoStepIndex::from_u32(max_index - index)
}
fn effect(self) -> Effect {
if self.as_u32() & 1 == 0 {
Effect::After
} else { Effect::Before }
}
}
#[doc =
" Add points depending on the result of the given dataflow analysis."]
fn save_as_intervals<'tcx>(elements: &DenseLocationMap, body: &Body<'tcx>,
relevant: &RelevantLocals,
entry_states: EntryStates<DenseBitSet<Local>>)
-> SparseIntervalMatrix<RelevantLocal, TwoStepIndex> {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("save_as_intervals",
"rustc_mir_transform::dest_prop", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/dest_prop.rs"),
::tracing_core::__macro_support::Option::Some(505u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::dest_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("relevant")
}> =
::tracing::__macro_support::FieldName::new("relevant");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("entry_states")
}> =
::tracing::__macro_support::FieldName::new("entry_states");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&relevant)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&entry_states)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
SparseIntervalMatrix<RelevantLocal, TwoStepIndex> = loop {};
return __tracing_attr_fake_return;
}
{
#[doc =
" Generalized dataflow state for use inside a given block."]
struct GenKillIntervalMatrix<'a> {
values: SparseIntervalMatrix<RelevantLocal, TwoStepIndex>,
relevant: &'a RelevantLocals,
#[doc =
" If a local is live, this stores the start of the live range."]
#[doc = " If a local is dead, this stores `None`."]
pending: IndexVec<RelevantLocal, Option<TwoStepIndex>>,
#[doc =
" The current position of the cursor inside the MIR body."]
current: TwoStepIndex,
}
impl GenKill<Local> for GenKillIntervalMatrix<'_> {
fn gen_(&mut self, elem: Local) {
let Some(elem) = self.relevant.shrink[elem] else { return };
let _ = self.pending[elem].get_or_insert(self.current);
}
fn kill(&mut self, elem: Local) {
if true {
{
match (&self.current.effect(), &Effect::Before) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
let Some(elem) = self.relevant.shrink[elem] else { return };
if let Some(start) = self.pending[elem].take() {
if true {
if !(start <= self.current) {
::core::panicking::panic("assertion failed: start <= self.current")
};
};
self.values.append_range(elem, start..self.current);
}
}
}
impl GenKillIntervalMatrix<'_> {
#[doc =
" Insert a singleton range. This can be used for dead locals to mark conflicts, for"]
#[doc =
" instance `move` operands in function calls or partial writes."]
fn insert_single(&mut self, elem: RelevantLocal) {
if true {
{
match (&self.current.effect(), &Effect::After) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
if self.pending[elem].is_none() {
self.values.append(elem, self.current);
}
}
fn start_block(&mut self,
entry_state: &DenseBitSet<Local>) {
if true {
if !self.pending.iter().all(Option::is_none) {
::core::panicking::panic("assertion failed: self.pending.iter().all(Option::is_none)")
};
};
for local in entry_state.iter() {
if let Some(elem) = self.relevant.shrink[local] {
self.pending[elem] = Some(self.current);
}
}
}
fn end_block(&mut self) {
for (elem, start) in self.pending.iter_enumerated_mut() {
if let Some(start) = start.take() {
if true {
if !(start <= self.current) {
::core::panicking::panic("assertion failed: start <= self.current")
};
};
self.values.append_range(elem, start..=self.current);
}
}
}
}
let reachable_blocks = traversal::reachable_as_bitset(body);
let two_step_loc =
|location, effect|
TwoStepIndex::new(elements, location, effect);
let mut state =
GenKillIntervalMatrix {
values: SparseIntervalMatrix::new(2 *
elements.num_points()),
relevant,
pending: IndexVec::from_elem(None, &relevant.original),
current: TwoStepIndex::from_u32(0),
};
for block in body.basic_blocks.indices().rev() {
if !reachable_blocks.contains(block) { continue; }
let block_data = &body.basic_blocks[block];
let loc =
Location {
block,
statement_index: block_data.statements.len(),
};
state.current = two_step_loc(loc, Effect::After);
state.start_block(&entry_states[block]);
let term = block_data.terminator();
VisitPlacesWith(|place: Place<'tcx>, ctxt|
{
if let Some(relevant) = relevant.shrink[place.local] {
match DefUse::for_place(place, ctxt) {
DefUse::Def | DefUse::Use | DefUse::PartialWrite => {
state.insert_single(relevant);
}
DefUse::NonUse => {}
}
}
}).visit_terminator(term, loc);
state.current = state.current + 1;
if true {
{
match (&state.current, &two_step_loc(loc, Effect::Before)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
LivenessTransferFunction(&mut state).visit_terminator(term,
loc);
for (statement_index, stmt) in
block_data.statements.iter().enumerate().rev() {
let loc = Location { block, statement_index };
state.current = state.current + 1;
if true {
{
match (&state.current, &two_step_loc(loc, Effect::After)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
let is_simple_assignment =
match stmt.kind {
StatementKind::Assign((lhs,
Rvalue::CopyForDeref(rhs) |
Rvalue::Use(Operand::Copy(rhs) | Operand::Move(rhs), _))) =>
lhs.projection == rhs.projection,
_ => false,
};
VisitPlacesWith(|place: Place<'tcx>, ctxt|
{
if let Some(relevant) = relevant.shrink[place.local] {
match DefUse::for_place(place, ctxt) {
DefUse::Def | DefUse::PartialWrite => {
state.insert_single(relevant);
}
DefUse::Use if !is_simple_assignment => {
state.insert_single(relevant);
}
DefUse::Use | DefUse::NonUse => {}
}
}
}).visit_statement(stmt, loc);
state.current =
TwoStepIndex::from_u32(state.current.as_u32() + 1);
if true {
{
match (&state.current, &two_step_loc(loc, Effect::Before)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
LivenessTransferFunction(&mut state).visit_statement(stmt,
loc);
}
state.end_block();
}
state.values
}
}
}
}
}
#[allow(unused_imports)]
use dest_prop::DestinationPropagation as _;
mod early_otherwise_branch {
use std::fmt::Debug;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_middle::mir::*;
use rustc_middle::ty::{Ty, TyCtxt};
use tracing::trace;
use super::simplify::simplify_cfg;
use crate::PassPolicy;
use crate::patch::MirPatch;
pub(super) struct EarlyOtherwiseBranch;
impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 2)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs:103",
"rustc_mir_transform::early_otherwise_branch",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs"),
::tracing_core::__macro_support::Option::Some(103u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::early_otherwise_branch"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("running EarlyOtherwiseBranch on {0:?}",
body.source) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let mut should_cleanup = false;
for parent in body.basic_blocks.indices() {
let bbs = &*body.basic_blocks;
let Some(opt_data) =
evaluate_candidate(tcx, body, parent) else { continue };
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs:112",
"rustc_mir_transform::early_otherwise_branch",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs"),
::tracing_core::__macro_support::Option::Some(112u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::early_otherwise_branch"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("SUCCESS: found optimization possibility to apply: {0:?}",
opt_data) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
should_cleanup = true;
let TerminatorKind::SwitchInt {
discr: parent_op, targets: parent_targets } =
&bbs[parent].terminator().kind else {
::core::panicking::panic("internal error: entered unreachable code")
};
let parent_op = parent_op.to_copy();
let parent_ty = parent_op.ty(body.local_decls(), tcx);
let statements_before = bbs[parent].statements.len();
let parent_end =
Location {
block: parent,
statement_index: statements_before,
};
let mut patch = MirPatch::new(body);
let second_operand =
if opt_data.need_hoist_discriminant {
let second_discriminant_temp =
patch.new_temp(opt_data.child_ty,
opt_data.child_source.span);
patch.add_assign(parent_end,
Place::from(second_discriminant_temp),
Rvalue::Discriminant(opt_data.child_place));
Operand::Move(Place::from(second_discriminant_temp))
} else { Operand::Copy(opt_data.child_place) };
let nequal = BinOp::Ne;
let comp_res_type =
nequal.ty(tcx, parent_ty, opt_data.child_ty);
let comp_temp =
patch.new_temp(comp_res_type, opt_data.child_source.span);
let comp_rvalue =
Rvalue::BinaryOp(nequal,
Box::new((parent_op.clone(), second_operand)));
patch.add_statement(parent_end,
StatementKind::Assign(Box::new((Place::from(comp_temp),
comp_rvalue))));
let eq_new_targets =
parent_targets.iter().map(|(value, child)|
{
let TerminatorKind::SwitchInt { targets, .. } =
&bbs[child].terminator().kind else {
::core::panicking::panic("internal error: entered unreachable code")
};
(value, targets.target_for_value(value))
});
let eq_targets =
SwitchTargets::new(eq_new_targets,
parent_targets.otherwise());
let eq_switch =
BasicBlockData::new(Some(Terminator {
source_info: bbs[parent].terminator().source_info,
kind: TerminatorKind::SwitchInt {
discr: parent_op,
targets: eq_targets,
},
attributes: ThinVec::new(),
}), bbs[parent].is_cleanup);
let eq_bb = patch.new_block(eq_switch);
let true_case = opt_data.destination;
let false_case = eq_bb;
patch.patch_terminator(parent,
TerminatorKind::if_(Operand::Move(Place::from(comp_temp)),
true_case, false_case));
patch.apply(body);
}
if should_cleanup { simplify_cfg(tcx, body); }
}
}
struct OptimizationData<'tcx> {
destination: BasicBlock,
child_place: Place<'tcx>,
child_ty: Ty<'tcx>,
child_source: SourceInfo,
need_hoist_discriminant: bool,
}
#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for OptimizationData<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field5_finish(f,
"OptimizationData", "destination", &self.destination,
"child_place", &self.child_place, "child_ty", &self.child_ty,
"child_source", &self.child_source, "need_hoist_discriminant",
&&self.need_hoist_discriminant)
}
}
fn evaluate_candidate<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>,
parent: BasicBlock) -> Option<OptimizationData<'tcx>> {
let bbs = &body.basic_blocks;
if bbs[parent].is_cleanup { return None; }
let TerminatorKind::SwitchInt { targets, discr: parent_discr } =
&bbs[parent].terminator().kind else { return None; };
let parent_ty = parent_discr.ty(body.local_decls(), tcx);
let (_, child) = targets.iter().next()?;
let Terminator {
kind: TerminatorKind::SwitchInt {
targets: child_targets, discr: child_discr
},
source_info,
attributes: _ } =
bbs[child].terminator() else { return None; };
let child_ty = child_discr.ty(body.local_decls(), tcx);
if child_ty != parent_ty { return None; }
if bbs[child].statements.len() > 1 { return None; }
let need_hoist_discriminant = bbs[child].statements.len() == 1;
let otherwise_is_empty_unreachable =
bbs[targets.otherwise()].is_empty_unreachable();
let child_place =
if need_hoist_discriminant {
let [Statement {
kind: StatementKind::Assign((_,
Rvalue::Discriminant(child_place))), .. }] =
bbs[child].statements.as_slice() else { return None; };
*child_place
} else {
let Operand::Copy(child_place) =
child_discr else { return None; };
*child_place
};
let destination =
if otherwise_is_empty_unreachable {
child_targets.otherwise()
} else { targets.otherwise() };
for (value, child) in targets.iter() {
if !verify_candidate_branch(&bbs[child], value, child_place,
destination, need_hoist_discriminant,
otherwise_is_empty_unreachable) {
return None;
}
}
Some(OptimizationData {
destination,
child_place,
child_ty,
child_source: *source_info,
need_hoist_discriminant,
})
}
fn verify_candidate_branch<'tcx>(branch: &BasicBlockData<'tcx>,
value: u128, place: Place<'tcx>, destination: BasicBlock,
need_hoist_discriminant: bool, otherwise_is_empty_unreachable: bool)
-> bool {
let TerminatorKind::SwitchInt { discr: switch_op, targets } =
&branch.terminator().kind else { return false; };
if !otherwise_is_empty_unreachable {
if need_hoist_discriminant { return false; }
if let Some(place) = switch_op.place() &&
!place.is_stable_offset() {
return false;
}
}
if need_hoist_discriminant {
let [statement] =
branch.statements.as_slice() else { return false; };
let StatementKind::Assign((discr_place,
Rvalue::Discriminant(from_place))) =
statement.kind else { return false; };
if from_place != place { return false; }
if !discr_place.projection.is_empty() ||
*switch_op != Operand::Move(discr_place) {
return false;
}
} else {
if !branch.statements.is_empty() { return false; }
if *switch_op != Operand::Copy(place) { return false; }
}
if destination != targets.otherwise() { return false; }
let mut iter = targets.iter();
let (Some((target_value, _)), None) =
(iter.next(), iter.next()) else { return false; };
target_value == value
}
}
#[allow(unused_imports)]
use early_otherwise_branch::EarlyOtherwiseBranch as _;
mod erase_deref_temps {
use rustc_middle::mir::visit::MutVisitor;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use crate::PassPolicy;
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), WithRetag::No)
}
}
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 policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::Required
}
}
}
#[allow(unused_imports)]
use erase_deref_temps::EraseDerefTemps as _;
mod elaborate_box_derefs {
use rustc_abi::FieldIdx;
use rustc_middle::mir::visit::MutVisitor;
use rustc_middle::mir::*;
use rustc_middle::span_bug;
use rustc_middle::ty::{self, PatternKind, Ty, TyCtxt};
use crate::PassPolicy;
use crate::patch::MirPatch;
fn build_ptr_tys<'tcx>(tcx: TyCtxt<'tcx>, pointee: Ty<'tcx>,
unique_def: ty::AdtDef<'tcx>, nonnull_def: ty::AdtDef<'tcx>)
-> (Ty<'tcx>, Ty<'tcx>, Ty<'tcx>) {
let args = tcx.mk_args(&[pointee.into()]);
let unique_ty = Ty::new_adt(tcx, unique_def, args);
let nonnull_ty = Ty::new_adt(tcx, nonnull_def, args);
let ptr_ty = Ty::new_imm_ptr(tcx, pointee);
(unique_ty, nonnull_ty, ptr_ty)
}
struct ElaborateBoxDerefVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
local_decls: &'a mut LocalDecls<'tcx>,
patch: MirPatch<'tcx>,
}
impl<'a, 'tcx> MutVisitor<'tcx> for ElaborateBoxDerefVisitor<'a, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_place(&mut self, place: &mut Place<'tcx>,
context: visit::PlaceContext, location: Location) {
let tcx = self.tcx;
let base_ty = self.local_decls[place.local].ty;
if let Some(PlaceElem::Deref) = place.projection.first() &&
let Some(boxed_ty) = base_ty.boxed_ty() {
let source_info = self.local_decls[place.local].source_info;
let ptr_ty = Ty::new_imm_ptr(tcx, boxed_ty);
let ptr_local = self.patch.new_temp(ptr_ty, source_info.span);
let field_place =
Place::from(place.local).project_to_field(FieldIdx::ZERO,
&*self.local_decls, tcx);
self.patch.add_assign(location, Place::from(ptr_local),
Rvalue::Cast(CastKind::BoxDerefTransmute,
Operand::Copy(field_place), ptr_ty));
place.local = ptr_local;
}
self.super_place(place, context, location);
}
}
pub(super) struct ElaborateBoxDerefs;
impl<'tcx> crate::MirPass<'tcx> for ElaborateBoxDerefs {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let Some(def_id) = tcx.lang_items().owned_box() else { return };
let unique_did =
tcx.adt_def(def_id).non_enum_variant().fields[FieldIdx::ZERO].did;
let Some(unique_def) =
tcx.type_of(unique_did).instantiate_identity().skip_norm_wip().ty_adt_def() else {
::rustc_middle::util::bug::span_bug_fmt(tcx.def_span(unique_did),
format_args!("expected Box to contain Unique"))
};
let nonnull_did =
unique_def.non_enum_variant().fields[FieldIdx::ZERO].did;
let Some(nonnull_def) =
tcx.type_of(nonnull_did).instantiate_identity().skip_norm_wip().ty_adt_def() else {
::rustc_middle::util::bug::span_bug_fmt(tcx.def_span(nonnull_did),
format_args!("expected Unique to contain Nonnull"))
};
let patch = MirPatch::new(body);
let local_decls = &mut body.local_decls;
let mut visitor =
ElaborateBoxDerefVisitor { tcx, local_decls, patch };
for (block, data) in
body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut()
{
visitor.visit_basic_block_data(block, data);
}
visitor.patch.apply(body);
for debug_info in body.var_debug_info.iter_mut() {
if let VarDebugInfoContents::Place(place) =
&mut debug_info.value {
let mut new_projections: Option<Vec<_>> = None;
for (base, elem) in place.iter_projections() {
let base_ty = base.ty(&body.local_decls, tcx).ty;
if let PlaceElem::Deref = elem &&
let Some(boxed_ty) = base_ty.boxed_ty() {
let new_projections =
new_projections.get_or_insert_with(||
base.projection.to_vec());
let (unique_ty, nonnull_ty, ptr_ty) =
build_ptr_tys(tcx, boxed_ty, unique_def, nonnull_def);
new_projections.extend_from_slice(&[PlaceElem::Field(FieldIdx::ZERO,
unique_ty), PlaceElem::Field(FieldIdx::ZERO, nonnull_ty)]);
let pat_ty =
Ty::new_pat(tcx, ptr_ty, tcx.mk_pat(PatternKind::NotNull));
new_projections.push(PlaceElem::Field(FieldIdx::ZERO,
pat_ty));
new_projections.push(PlaceElem::Field(FieldIdx::ZERO,
ptr_ty));
new_projections.push(PlaceElem::Deref);
} else if let Some(new_projections) =
new_projections.as_mut() {
new_projections.push(elem);
}
}
if let Some(new_projections) = new_projections {
place.projection = tcx.mk_place_elems(&new_projections);
}
}
}
}
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::Required
}
}
}
#[allow(unused_imports)]
use elaborate_box_derefs::ElaborateBoxDerefs as _;
mod elaborate_drops {
use std::fmt;
use rustc_abi::{FieldIdx, VariantIdx};
use rustc_index::IndexVec;
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, TyCtxt};
use rustc_mir_dataflow::impls::{
MaybeInitializedPlaces, MaybeUninitializedPlaces,
};
use rustc_mir_dataflow::move_paths::{
LookupResult, MoveData, MovePathIndex,
};
use rustc_mir_dataflow::{
Analysis, DropFlagState, MoveDataTypingEnv, ResultsCursor,
on_all_children_bits, on_lookup_result_bits,
};
use rustc_span::Span;
use tracing::{debug, instrument};
use crate::PassPolicy;
use crate::elaborate_drop::{
DropElaborator, DropFlagMode, DropStyle, Unwind, elaborate_drop,
};
use crate::patch::MirPatch;
pub(super) struct ElaborateDrops;
impl<'tcx> crate::MirPass<'tcx> for ElaborateDrops {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("run_pass",
"rustc_mir_transform::elaborate_drops",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs"),
::tracing_core::__macro_support::Option::Some(52u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::elaborate_drops"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs:54",
"rustc_mir_transform::elaborate_drops",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs"),
::tracing_core::__macro_support::Option::Some(54u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::elaborate_drops"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("elaborate_drops({0:?} @ {1:?})",
body.source, body.span) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let typing_env =
ty::TypingEnv::post_analysis(tcx, body.source.def_id());
let move_data =
MoveData::gather_moves(body, tcx,
|ty| ty.needs_drop(tcx, typing_env));
let elaborate_patch =
{
let env = MoveDataTypingEnv { move_data, typing_env };
let mut inits =
MaybeInitializedPlaces::new(tcx, body,
&env.move_data).exclude_inactive_in_otherwise().skipping_unreachable_unwind().iterate_to_fixpoint(tcx,
body, Some("elaborate_drops")).into_results_cursor(body);
let dead_unwinds = compute_dead_unwinds(body, &mut inits);
let uninits =
MaybeUninitializedPlaces::new(tcx, body,
&env.move_data).mark_inactive_variants_as_uninit().skipping_unreachable_unwind(dead_unwinds).iterate_to_fixpoint(tcx,
body, Some("elaborate_drops")).into_results_cursor(body);
let drop_flags =
IndexVec::from_elem(None, &env.move_data.move_paths);
ElaborateDropsCtxt {
tcx,
body,
env: &env,
init_data: InitializationData { inits, uninits },
drop_flags,
patch: MirPatch::new(body),
}.elaborate()
};
elaborate_patch.apply(body);
}
}
}
}
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::Required
}
}
#[doc =
" Records unwind edges which are known to be unreachable, because they are in `drop` terminators"]
#[doc = " that can\'t drop anything."]
fn compute_dead_unwinds<'a,
'tcx>(body: &'a Body<'tcx>,
flow_inits:
&mut ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>)
-> DenseBitSet<BasicBlock> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("compute_dead_unwinds",
"rustc_mir_transform::elaborate_drops",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs"),
::tracing_core::__macro_support::Option::Some(99u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::elaborate_drops"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: DenseBitSet<BasicBlock> =
loop {};
return __tracing_attr_fake_return;
}
{
let mut dead_unwinds =
DenseBitSet::new_empty(body.basic_blocks.len());
for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
let TerminatorKind::Drop {
place, unwind: UnwindAction::Cleanup(_), .. } =
bb_data.terminator().kind else { continue; };
flow_inits.seek_before_primary_effect(body.terminator_loc(bb));
if flow_inits.analysis().is_unwind_dead(place,
flow_inits.get()) {
dead_unwinds.insert(bb);
}
}
dead_unwinds
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs:99",
"rustc_mir_transform::elaborate_drops",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs"),
::tracing_core::__macro_support::Option::Some(99u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::elaborate_drops"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
struct InitializationData<'a, 'tcx> {
inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
uninits: ResultsCursor<'a, 'tcx, MaybeUninitializedPlaces<'a, 'tcx>>,
}
impl InitializationData<'_, '_> {
fn seek_before(&mut self, loc: Location) {
self.inits.seek_before_primary_effect(loc);
self.uninits.seek_before_primary_effect(loc);
}
fn maybe_init_uninit(&self, path: MovePathIndex) -> (bool, bool) {
(self.inits.get().contains(path),
self.uninits.get().contains(path))
}
}
impl<'a, 'tcx> DropElaborator<'a, 'tcx> for ElaborateDropsCtxt<'a, 'tcx> {
type Path = MovePathIndex;
fn patch_ref(&self) -> &MirPatch<'tcx> { &self.patch }
fn patch(&mut self) -> &mut MirPatch<'tcx> { &mut self.patch }
fn body(&self) -> &'a Body<'tcx> { self.body }
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn typing_env(&self) -> ty::TypingEnv<'tcx> { self.env.typing_env }
fn allow_async_drops(&self) -> bool { true }
fn drop_style(&self, path: Self::Path, mode: DropFlagMode)
-> DropStyle {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("drop_style",
"rustc_mir_transform::elaborate_drops",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs"),
::tracing_core::__macro_support::Option::Some(166u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::elaborate_drops"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("path")
}> =
::tracing::__macro_support::FieldName::new("path");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("mode")
}> =
::tracing::__macro_support::FieldName::new("mode");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&path)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&mode)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: DropStyle = loop {};
return __tracing_attr_fake_return;
}
{
let ((maybe_init, maybe_uninit), multipart) =
match mode {
DropFlagMode::Shallow =>
(self.init_data.maybe_init_uninit(path), false),
DropFlagMode::Deep => {
let mut some_maybe_init = false;
let mut some_maybe_uninit = false;
let mut children_count = 0;
on_all_children_bits(self.move_data(), path,
|child|
{
let (maybe_init, maybe_uninit) =
self.init_data.maybe_init_uninit(child);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs:176",
"rustc_mir_transform::elaborate_drops",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs"),
::tracing_core::__macro_support::Option::Some(176u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::elaborate_drops"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("elaborate_drop: state({0:?}) = {1:?}",
child, (maybe_init, maybe_uninit)) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};
some_maybe_init |= maybe_init;
some_maybe_uninit |= maybe_uninit;
children_count += 1;
});
((some_maybe_init, some_maybe_uninit), children_count != 1)
}
};
match (maybe_init, maybe_uninit, multipart) {
(false, _, _) => DropStyle::Dead,
(true, false, _) => DropStyle::Static,
(true, true, false) => DropStyle::Conditional,
(true, true, true) => DropStyle::Open,
}
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs:166",
"rustc_mir_transform::elaborate_drops",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs"),
::tracing_core::__macro_support::Option::Some(166u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::elaborate_drops"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn drop_flags_for(&mut self, path: Self::Path, mode: DropFlagMode)
-> Vec<Place<'tcx>> {
let mut flags = ::alloc::vec::Vec::new();
match mode {
DropFlagMode::Shallow => {
if let Some(flag) = self.drop_flags[path] {
flags.push(flag.into());
}
}
DropFlagMode::Deep => {
on_all_children_bits(self.move_data(), path,
|child|
{
if let Some(flag) = self.drop_flags[child] {
flags.push(flag.into());
}
});
}
}
flags
}
fn field_subpath(&self, path: Self::Path, field: FieldIdx)
-> Option<Self::Path> {
rustc_mir_dataflow::move_path_children_matching(self.move_data(),
path,
|e|
match e {
ProjectionElem::Field(idx, _) => idx == field,
_ => false,
})
}
fn array_subpath(&self, path: Self::Path, index: u64, size: u64)
-> Option<Self::Path> {
rustc_mir_dataflow::move_path_children_matching(self.move_data(),
path,
|e|
match e {
ProjectionElem::ConstantIndex { offset, min_length, from_end
} => {
if true {
if !(size == min_length) {
{
::core::panicking::panic_fmt(format_args!("min_length should be exact for arrays"));
}
};
};
if !!from_end {
{
::core::panicking::panic_fmt(format_args!("from_end should not be used for array element ConstantIndex"));
}
};
offset == index
}
_ => false,
})
}
fn deref_subpath(&self, path: Self::Path) -> Option<Self::Path> {
rustc_mir_dataflow::move_path_children_matching(self.move_data(),
path, |e| { e == ProjectionElem::Deref })
}
fn downcast_subpath(&self, path: Self::Path, variant: VariantIdx)
-> Option<Self::Path> {
rustc_mir_dataflow::move_path_children_matching(self.move_data(),
path,
|e|
match e {
ProjectionElem::Downcast(_, idx) => idx == variant,
_ => false,
})
}
fn get_drop_flag(&mut self, path: Self::Path)
-> Option<Operand<'tcx>> {
self.drop_flag(path).map(Operand::Copy)
}
}
struct ElaborateDropsCtxt<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
body: &'a Body<'tcx>,
env: &'a MoveDataTypingEnv<'tcx>,
init_data: InitializationData<'a, 'tcx>,
drop_flags: IndexVec<MovePathIndex, Option<Local>>,
patch: MirPatch<'tcx>,
}
impl fmt::Debug for ElaborateDropsCtxt<'_, '_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ElaborateDropsCtxt").finish_non_exhaustive()
}
}
impl<'a, 'tcx> ElaborateDropsCtxt<'a, 'tcx> {
fn move_data(&self) -> &'a MoveData<'tcx> { &self.env.move_data }
fn create_drop_flag(&mut self, index: MovePathIndex, span: Span) {
let patch = &mut self.patch;
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs:269",
"rustc_mir_transform::elaborate_drops",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs"),
::tracing_core::__macro_support::Option::Some(269u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::elaborate_drops"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("create_drop_flag({0:?})",
self.body.span) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
self.drop_flags[index].get_or_insert_with(||
patch.new_temp(self.tcx.types.bool, span));
}
fn drop_flag(&mut self, index: MovePathIndex) -> Option<Place<'tcx>> {
self.drop_flags[index].map(Place::from)
}
fn elaborate(mut self) -> MirPatch<'tcx> {
self.collect_drop_flags();
self.elaborate_drops();
self.drop_flags_on_init();
self.drop_flags_for_fn_rets();
self.drop_flags_for_args();
self.drop_flags_for_locs();
self.patch
}
fn collect_drop_flags(&mut self) {
for (bb, data) in self.body.basic_blocks.iter_enumerated() {
let terminator = data.terminator();
let TerminatorKind::Drop { ref place, .. } =
terminator.kind else { continue };
let path = self.move_data().rev_lookup.find(place.as_ref());
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs:298",
"rustc_mir_transform::elaborate_drops",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs"),
::tracing_core::__macro_support::Option::Some(298u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::elaborate_drops"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("collect_drop_flags: {0:?}, place {1:?} ({2:?})",
bb, place, path) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
match path {
LookupResult::Exact(path) => {
self.init_data.seek_before(self.body.terminator_loc(bb));
on_all_children_bits(self.move_data(), path,
|child|
{
let (maybe_init, maybe_uninit) =
self.init_data.maybe_init_uninit(child);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs:305",
"rustc_mir_transform::elaborate_drops",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs"),
::tracing_core::__macro_support::Option::Some(305u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::elaborate_drops"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("collect_drop_flags: collecting {0:?} from {1:?}@{2:?} - {3:?}",
child, place, path, (maybe_init, maybe_uninit)) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};
if maybe_init && maybe_uninit {
self.create_drop_flag(child, terminator.source_info.span)
}
});
}
LookupResult::Parent(None) => {}
LookupResult::Parent(Some(parent)) => {
if self.body.local_decls[place.local].is_deref_temp() {
continue;
}
self.init_data.seek_before(self.body.terminator_loc(bb));
let (_maybe_init, maybe_uninit) =
self.init_data.maybe_init_uninit(parent);
if maybe_uninit {
self.tcx.dcx().span_delayed_bug(terminator.source_info.span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("drop of untracked, uninitialized value {0:?}, place {1:?} ({2:?})",
bb, place, path))
}));
}
}
};
}
}
fn elaborate_drops(&mut self) {
for (bb, data) in self.body.basic_blocks.iter_enumerated() {
let terminator = data.terminator();
let TerminatorKind::Drop {
place, target, unwind, replace, drop } =
terminator.kind else { continue; };
if !place.ty(&self.body.local_decls,
self.tcx).ty.needs_drop(self.tcx, self.typing_env()) {
self.patch.patch_terminator(bb,
TerminatorKind::Goto { target });
continue;
}
let path = self.move_data().rev_lookup.find(place.as_ref());
match path {
LookupResult::Exact(path) => {
let unwind =
match unwind {
_ if data.is_cleanup => Unwind::InCleanup,
UnwindAction::Cleanup(cleanup) => Unwind::To(cleanup),
UnwindAction::Continue =>
Unwind::To(self.patch.resume_block()),
UnwindAction::Unreachable => {
Unwind::To(self.patch.unreachable_cleanup_block())
}
UnwindAction::Terminate(reason) => {
if true {
{
match (&(reason), &(UnwindTerminateReason::InCleanup)) {
(left_val, right_val) => {
if *left_val == *right_val {
let kind = ::core::panicking::AssertKind::Ne;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val,
::core::option::Option::Some(format_args!("we are not in a cleanup block, InCleanup reason should be impossible")));
}
}
}
};
};
Unwind::To(self.patch.terminate_block(reason))
}
};
self.init_data.seek_before(self.body.terminator_loc(bb));
elaborate_drop(self, terminator.source_info, place, path,
target, unwind, bb, drop)
}
LookupResult::Parent(None) => {}
LookupResult::Parent(Some(_)) => {
if !replace {
self.tcx.dcx().span_bug(terminator.source_info.span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("drop of untracked value {0:?}",
bb))
}));
}
if !!data.is_cleanup {
::core::panicking::panic("assertion failed: !data.is_cleanup")
};
}
}
}
}
fn constant_bool(&self, span: Span, val: bool) -> Rvalue<'tcx> {
Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
span,
user_ty: None,
const_: Const::from_bool(self.tcx, val),
})), WithRetag::Yes)
}
fn set_drop_flag(&mut self, loc: Location, path: MovePathIndex,
val: DropFlagState) {
if let Some(flag) = self.drop_flags[path] {
let span =
self.patch.source_info_for_location(self.body, loc).span;
let val = self.constant_bool(span, val.value());
self.patch.add_assign(loc, Place::from(flag), val);
}
}
fn drop_flags_on_init(&mut self) {
let loc = Location::START;
let span =
self.patch.source_info_for_location(self.body, loc).span;
let false_ = self.constant_bool(span, false);
for flag in self.drop_flags.iter().flatten() {
self.patch.add_assign(loc, Place::from(*flag),
false_.clone());
}
}
fn drop_flags_for_fn_rets(&mut self) {
for (bb, data) in self.body.basic_blocks.iter_enumerated() {
if let TerminatorKind::Call {
destination,
target: Some(tgt),
unwind: UnwindAction::Cleanup(_), .. } =
data.terminator().kind {
if !!self.patch.is_term_patched(bb) {
::core::panicking::panic("assertion failed: !self.patch.is_term_patched(bb)")
};
let loc = Location { block: tgt, statement_index: 0 };
let path =
self.move_data().rev_lookup.find(destination.as_ref());
on_lookup_result_bits(self.move_data(), path,
|child|
{ self.set_drop_flag(loc, child, DropFlagState::Present) });
}
}
}
fn drop_flags_for_args(&mut self) {
let loc = Location::START;
rustc_mir_dataflow::drop_flag_effects_for_function_entry(self.body,
&self.env.move_data,
|path, ds| { self.set_drop_flag(loc, path, ds); })
}
fn drop_flags_for_locs(&mut self) {
for (bb, data) in self.body.basic_blocks.iter_enumerated() {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs:474",
"rustc_mir_transform::elaborate_drops",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs"),
::tracing_core::__macro_support::Option::Some(474u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::elaborate_drops"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("drop_flags_for_locs({0:?})",
data) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
for i in 0..(data.statements.len() + 1) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs:476",
"rustc_mir_transform::elaborate_drops",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/elaborate_drops.rs"),
::tracing_core::__macro_support::Option::Some(476u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::elaborate_drops"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("drop_flag_for_locs: stmt {0}",
i) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if i == data.statements.len() {
match data.terminator().kind {
TerminatorKind::Drop { .. } => { continue; }
TerminatorKind::UnwindResume => {}
_ => {
if !!self.patch.is_term_patched(bb) {
::core::panicking::panic("assertion failed: !self.patch.is_term_patched(bb)")
};
}
}
}
let loc = Location { block: bb, statement_index: i };
rustc_mir_dataflow::drop_flag_effects_for_location(self.body,
&self.env.move_data, loc,
|path, ds| self.set_drop_flag(loc, path, ds))
}
if let TerminatorKind::Call {
destination,
target: Some(_),
unwind: UnwindAction::Continue | UnwindAction::Unreachable |
UnwindAction::Terminate(_), .. } = data.terminator().kind {
if !!self.patch.is_term_patched(bb) {
::core::panicking::panic("assertion failed: !self.patch.is_term_patched(bb)")
};
let loc =
Location {
block: bb,
statement_index: data.statements.len(),
};
let path =
self.move_data().rev_lookup.find(destination.as_ref());
on_lookup_result_bits(self.move_data(), path,
|child|
{ self.set_drop_flag(loc, child, DropFlagState::Present) });
}
}
}
}
}
#[allow(unused_imports)]
use elaborate_drops::ElaborateDrops as _;
mod function_item_references {
use itertools::Itertools;
use rustc_abi::ExternAbi;
use rustc_hir::def_id::DefId;
use rustc_lint_defs::builtin::FUNCTION_ITEM_REFERENCES;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt};
use rustc_span::{Span, Spanned, sym};
use crate::diagnostics;
pub(super) struct FunctionItemReferences;
impl<'tcx> crate::MirLint<'tcx> for FunctionItemReferences {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
let mut checker = FunctionItemRefChecker { tcx, body };
checker.visit_body(body);
}
}
struct FunctionItemRefChecker<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
body: &'a Body<'tcx>,
}
impl<'tcx> Visitor<'tcx> for FunctionItemRefChecker<'_, 'tcx> {
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>,
location: Location) {
if let TerminatorKind::Call {
func,
args,
destination: _,
target: _,
unwind: _,
call_source: _,
fn_span: _ } = &terminator.kind {
let source_info = *self.body.source_info(location);
let func_ty = func.ty(self.body, self.tcx);
if let ty::FnDef(def_id, args_ref) = *func_ty.kind() {
if self.tcx.is_diagnostic_item(sym::transmute, def_id) {
let arg_ty = args[0].node.ty(self.body, self.tcx);
for inner_ty in
arg_ty.walk().filter_map(|arg| arg.as_type()) {
if let Some((fn_id, fn_args)) =
FunctionItemRefChecker::is_fn_ref(inner_ty) {
let span = self.nth_arg_span(args, 0);
self.emit_lint(fn_id, fn_args, source_info, span);
}
}
} else {
self.check_bound_args(def_id,
args_ref.no_bound_vars().unwrap(), args, source_info);
}
}
}
self.super_terminator(terminator, location);
}
}
impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
fn check_bound_args(&self, def_id: DefId,
args_ref: GenericArgsRef<'tcx>, args: &[Spanned<Operand<'tcx>>],
source_info: SourceInfo) {
let param_env = self.tcx.param_env(def_id);
let bounds = param_env.caller_bounds();
for bound in bounds {
if let Some(bound_ty) = self.is_pointer_trait(bound) {
let arg_defs =
self.tcx.fn_sig(def_id).instantiate_identity().skip_binder().inputs();
for (arg_num, arg_def) in arg_defs.iter().enumerate() {
for inner_ty in
arg_def.walk().filter_map(|arg| arg.as_type()) {
if inner_ty == bound_ty {
let instantiated_ty =
EarlyBinder::bind(self.tcx,
inner_ty).instantiate(self.tcx, args_ref).skip_norm_wip();
if let Some((fn_id, fn_args)) =
FunctionItemRefChecker::is_fn_ref(instantiated_ty) {
let mut span = self.nth_arg_span(args, arg_num);
if span.from_expansion() {
let callsite_ctxt = span.source_callsite().ctxt();
span = span.with_ctxt(callsite_ctxt);
}
self.emit_lint(fn_id, fn_args, source_info, span);
}
}
}
}
}
}
}
fn is_pointer_trait(&self, bound: ty::Clause<'tcx>)
-> Option<Ty<'tcx>> {
if let ty::ClauseKind::Trait(predicate) =
bound.kind().skip_binder() {
self.tcx.is_diagnostic_item(sym::Pointer,
predicate.def_id()).then(|| predicate.trait_ref.self_ty())
} else { None }
}
fn is_fn_ref(ty: Ty<'tcx>) -> Option<(DefId, GenericArgsRef<'tcx>)> {
let referent_ty =
match ty.kind() {
ty::Ref(_, referent_ty, _) => Some(referent_ty),
ty::RawPtr(referent_ty, _) => Some(referent_ty),
_ => None,
};
referent_ty.map(|ref_ty|
{
if let ty::FnDef(def_id, args_ref) = *ref_ty.kind() {
Some((def_id, args_ref.no_bound_vars().unwrap()))
} else { None }
}).unwrap_or(None)
}
fn nth_arg_span(&self, args: &[Spanned<Operand<'tcx>>], n: usize)
-> Span {
args[n].node.span(&self.body.local_decls)
}
fn emit_lint(&self, fn_id: DefId, fn_args: GenericArgsRef<'tcx>,
source_info: SourceInfo, span: Span) {
let lint_root =
self.body.source_scopes[source_info.scope].local_data.as_ref().unwrap_crate_local().lint_root;
let fn_sig =
self.tcx.fn_sig(fn_id).instantiate(self.tcx,
fn_args).skip_norm_wip();
let unsafety = fn_sig.safety().prefix_str();
let abi =
match fn_sig.abi() {
ExternAbi::Rust => String::from(""),
other_abi =>
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("extern {0} ", other_abi))
}),
};
let ident = self.tcx.item_ident(fn_id);
let params =
fn_args.terms().map(|term|
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}", term))
})).join(", ");
let num_args =
fn_sig.inputs().map_bound(|inputs|
inputs.len()).skip_binder();
let variadic = if fn_sig.c_variadic() { ", ..." } else { "" };
let ret =
if fn_sig.output().skip_binder().is_unit() {
""
} else { " -> _" };
let sugg =
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} as {1}{2}fn({3}{4}){5}",
if params.is_empty() {
ident.to_string()
} else {
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}::<{1}>", ident,
params))
})
}, unsafety, abi,
::alloc::vec::from_elem("_", num_args).join(", "), variadic,
ret))
});
self.tcx.emit_node_span_lint(FUNCTION_ITEM_REFERENCES, lint_root,
span, diagnostics::FnItemRef { span, sugg, ident });
}
}
}
#[allow(unused_imports)]
use function_item_references::FunctionItemReferences as _;
mod gvn {
use std::borrow::Cow;
use std::hash::{Hash, Hasher};
use either::Either;
use itertools::Itertools as _;
use rustc_abi::{
self as abi, BackendRepr, FIRST_VARIANT, FieldIdx, Primitive, Size,
VariantIdx,
};
use rustc_arena::DroplessArena;
use rustc_const_eval::const_eval::DummyMachine;
use rustc_const_eval::interpret::{
ImmTy, Immediate, InterpCx, MemPlaceMeta, MemoryKind, OpTy,
Projectable, Scalar, intern_const_alloc_for_constprop,
};
use rustc_data_structures::fx::FxHasher;
use rustc_data_structures::graph::dominators::Dominators;
use rustc_data_structures::hash_table::{Entry, HashTable};
use rustc_hir::def::DefKind;
use rustc_index::bit_set::DenseBitSet;
use rustc_index::{IndexVec, newtype_index};
use rustc_middle::bug;
use rustc_middle::mir::interpret::{AllocRange, GlobalAlloc};
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
use rustc_middle::ty::layout::HasTypingEnv;
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, Unnormalized};
use rustc_mir_dataflow::{Analysis, ResultsCursor};
use rustc_span::DUMMY_SP;
use smallvec::SmallVec;
use tracing::{debug, instrument, trace};
use crate::PassPolicy;
use crate::ssa::{MaybeUninitializedLocals, SsaLocals};
pub(super) struct GVN;
impl<'tcx> crate::MirPass<'tcx> for GVN {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 2)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("run_pass",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(135u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs:137",
"rustc_mir_transform::gvn", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(137u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&body.source.def_id())
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let typing_env = body.typing_env(tcx);
let ssa = SsaLocals::new(tcx, body, typing_env);
let dominators = body.basic_blocks.dominators().clone();
let arena = DroplessArena::default();
let mut state =
VnState::new(tcx, body, typing_env, &ssa, dominators,
&body.local_decls, &arena);
for local in
body.args_iter().filter(|&local| ssa.is_ssa(local)) {
let opaque = state.new_argument(body.local_decls[local].ty);
state.assign(local, opaque);
}
let reverse_postorder =
body.basic_blocks.reverse_postorder().to_vec();
for bb in reverse_postorder {
let data =
&mut body.basic_blocks.as_mut_preserves_cfg()[bb];
state.visit_basic_block_data(bb, data);
}
let storage_to_remove =
if tcx.sess.emit_lifetime_markers() {
let maybe_uninit =
MaybeUninitializedLocals.iterate_to_fixpoint(tcx, body,
Some("mir_opt::gvn")).into_results_cursor(body);
let mut storage_checker =
StorageChecker {
reused_locals: &state.reused_locals,
storage_to_remove: DenseBitSet::new_empty(body.local_decls.len()),
maybe_uninit,
};
for (bb, data) in traversal::reachable(body) {
storage_checker.visit_basic_block_data(bb, data);
}
Some(storage_checker.storage_to_remove)
} else { None };
let storage_to_remove =
storage_to_remove.as_ref().unwrap_or(&state.reused_locals);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs:184",
"rustc_mir_transform::gvn", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(184u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("storage_to_remove")
}> =
::tracing::__macro_support::FieldName::new("storage_to_remove");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&storage_to_remove)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
StorageRemover {
tcx,
reused_locals: &state.reused_locals,
storage_to_remove,
}.visit_body_preserves_cfg(body);
}
}
}
}
}
#[doc = " This represents a `Value` in the symbolic execution."]
#[rustc_pass_by_value]
struct VnIndex {
private_use_as_methods_instead: u32 is const 0..=const 0xFFFF_FF00,
}
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for VnIndex { }
#[automatically_derived]
impl ::core::clone::Clone for VnIndex {
#[inline]
fn clone(&self) -> VnIndex {
let _:
::core::clone::AssertParamIsClone<u32 is const 0..=const 0xFFFF_FF00>;
*self
}
}
#[automatically_derived]
impl ::core::marker::Copy for VnIndex { }
impl VnIndex {
#[doc = r" Maximum value the index can take, as a `u32`."]
const MAX_AS_U32: u32 = 0xFFFF_FF00;
#[doc = r" Maximum value the index can take."]
const MAX: Self = Self::from_u32(0xFFFF_FF00);
#[doc = r" Zero value of the index."]
const ZERO: Self = Self::from_u32(0);
#[doc = r" Creates a new index from a given `usize`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
const fn from_usize(value: usize) -> Self {
if !(value <= (0xFFFF_FF00 as usize)) {
::core::panicking::panic("assertion failed: value <= (0xFFFF_FF00 as usize)")
};
unsafe { Self::from_u32_unchecked(value as u32) }
}
#[doc = r" Creates a new index from a given `u32`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
const fn from_u32(value: u32) -> Self {
if !(value <= 0xFFFF_FF00) {
::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
};
unsafe { Self::from_u32_unchecked(value) }
}
#[doc = r" Creates a new index from a given `u16`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
const fn from_u16(value: u16) -> Self {
let value = value as u32;
if !(value <= 0xFFFF_FF00) {
::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
};
unsafe { Self::from_u32_unchecked(value) }
}
#[doc = r" Creates a new index from a given `u32`."]
#[doc = r""]
#[doc = r" # Safety"]
#[doc = r""]
#[doc =
r" The provided value must be less than or equal to the maximum value for the newtype."]
#[doc =
r" Providing a value outside this range is undefined due to layout restrictions."]
#[doc = r""]
#[doc = r" Prefer using `from_u32`."]
#[inline]
const unsafe fn from_u32_unchecked(value: u32) -> Self {
Self {
private_use_as_methods_instead: unsafe {
std::mem::transmute(value)
},
}
}
#[doc = r" Extracts the value of this index as a `usize`."]
#[inline]
const fn index(self) -> usize { self.as_usize() }
#[doc = r" Extracts the value of this index as a `u32`."]
#[inline]
const fn as_u32(self) -> u32 {
unsafe {
std::mem::transmute(self.private_use_as_methods_instead)
}
}
#[doc = r" Extracts the value of this index as a `usize`."]
#[inline]
const fn as_usize(self) -> usize { self.as_u32() as usize }
}
impl std::ops::Add<usize> for VnIndex {
type Output = Self;
#[inline]
fn add(self, other: usize) -> Self {
Self::from_usize(self.index() + other)
}
}
impl std::ops::AddAssign<usize> for VnIndex {
#[inline]
fn add_assign(&mut self, other: usize) { *self = *self + other; }
}
impl rustc_index::Idx for VnIndex {
#[inline]
fn new(value: usize) -> Self { Self::from_usize(value) }
#[inline]
fn index(self) -> usize { self.as_usize() }
}
impl From<VnIndex> for u32 {
#[inline]
fn from(v: VnIndex) -> u32 { v.as_u32() }
}
impl From<VnIndex> for usize {
#[inline]
fn from(v: VnIndex) -> usize { v.as_usize() }
}
impl From<usize> for VnIndex {
#[inline]
fn from(value: usize) -> Self { Self::from_usize(value) }
}
impl From<u32> for VnIndex {
#[inline]
fn from(value: u32) -> Self { Self::from_u32(value) }
}
impl ::std::cmp::Eq for VnIndex {}
impl ::std::cmp::PartialEq for VnIndex {
fn eq(&self, other: &Self) -> bool {
self.as_u32().eq(&other.as_u32())
}
}
impl ::std::marker::StructuralPartialEq for VnIndex {}
impl ::std::hash::Hash for VnIndex {
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
self.as_u32().hash(state)
}
}
impl ::std::fmt::Debug for VnIndex {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>)
-> ::std::fmt::Result {
fmt.write_fmt(format_args!("_v{0}", self.as_u32()))
}
}
struct VnOpaque;
#[automatically_derived]
impl ::core::marker::Copy for VnOpaque { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for VnOpaque { }
#[automatically_derived]
impl ::core::clone::Clone for VnOpaque {
#[inline]
fn clone(&self) -> VnOpaque { *self }
}
#[automatically_derived]
impl ::core::fmt::Debug for VnOpaque {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f, "VnOpaque")
}
}
#[automatically_derived]
impl ::core::cmp::Eq for VnOpaque {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}
impl PartialEq for VnOpaque {
fn eq(&self, _: &VnOpaque) -> bool {
::core::panicking::panic("internal error: entered unreachable code")
}
}
impl Hash for VnOpaque {
fn hash<T: Hasher>(&self, _: &mut T) {
::core::panicking::panic("internal error: entered unreachable code")
}
}
enum AddressKind { Ref(BorrowKind), Address(RawPtrKind), }
#[automatically_derived]
impl ::core::marker::Copy for AddressKind { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for AddressKind { }
#[automatically_derived]
impl ::core::clone::Clone for AddressKind {
#[inline]
fn clone(&self) -> AddressKind {
let _: ::core::clone::AssertParamIsClone<BorrowKind>;
let _: ::core::clone::AssertParamIsClone<RawPtrKind>;
*self
}
}
#[automatically_derived]
impl ::core::fmt::Debug for AddressKind {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
AddressKind::Ref(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Ref",
&__self_0),
AddressKind::Address(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Address", &__self_0),
}
}
}
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for AddressKind { }
#[automatically_derived]
impl ::core::cmp::PartialEq for AddressKind {
#[inline]
fn eq(&self, other: &AddressKind) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(AddressKind::Ref(__self_0), AddressKind::Ref(__arg1_0)) =>
__self_0 == __arg1_0,
(AddressKind::Address(__self_0),
AddressKind::Address(__arg1_0)) => __self_0 == __arg1_0,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}
#[automatically_derived]
impl ::core::cmp::Eq for AddressKind {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<BorrowKind>;
let _: ::core::cmp::AssertParamIsEq<RawPtrKind>;
}
}
#[automatically_derived]
impl ::core::hash::Hash for AddressKind {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state);
match self {
AddressKind::Ref(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
AddressKind::Address(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
}
}
}
enum AddressBase {
Local(Local),
Deref(VnIndex),
}
#[automatically_derived]
impl ::core::marker::Copy for AddressBase { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for AddressBase { }
#[automatically_derived]
impl ::core::clone::Clone for AddressBase {
#[inline]
fn clone(&self) -> AddressBase {
let _: ::core::clone::AssertParamIsClone<Local>;
let _: ::core::clone::AssertParamIsClone<VnIndex>;
*self
}
}
#[automatically_derived]
impl ::core::fmt::Debug for AddressBase {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
AddressBase::Local(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Local", &__self_0),
AddressBase::Deref(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Deref", &__self_0),
}
}
}
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for AddressBase { }
#[automatically_derived]
impl ::core::cmp::PartialEq for AddressBase {
#[inline]
fn eq(&self, other: &AddressBase) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(AddressBase::Local(__self_0), AddressBase::Local(__arg1_0))
=> __self_0 == __arg1_0,
(AddressBase::Deref(__self_0), AddressBase::Deref(__arg1_0))
=> __self_0 == __arg1_0,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}
#[automatically_derived]
impl ::core::cmp::Eq for AddressBase {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Local>;
let _: ::core::cmp::AssertParamIsEq<VnIndex>;
}
}
#[automatically_derived]
impl ::core::hash::Hash for AddressBase {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state);
match self {
AddressBase::Local(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
AddressBase::Deref(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
}
}
}
enum Value<'a, 'tcx> {
Opaque(VnOpaque),
Argument(VnOpaque),
Constant {
value: Const<'tcx>,
disambiguator: Option<VnOpaque>,
},
Aggregate(VariantIdx, &'a [VnIndex]),
Union(FieldIdx, VnIndex),
RawPtr {
pointer: VnIndex,
metadata: VnIndex,
},
Repeat(VnIndex, ty::Const<'tcx>),
Address {
base: AddressBase,
projection: &'a [ProjectionElem<VnIndex, Ty<'tcx>>],
kind: AddressKind,
provenance: VnOpaque,
},
Projection(VnIndex, ProjectionElem<VnIndex, ()>),
Discriminant(VnIndex),
RuntimeChecks(RuntimeChecks),
UnaryOp(UnOp, VnIndex),
BinaryOp(BinOp, VnIndex, VnIndex),
Cast {
kind: CastKind,
value: VnIndex,
},
}
#[automatically_derived]
impl<'a, 'tcx> ::core::marker::Copy for Value<'a, 'tcx> { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl<'a, 'tcx> ::core::clone::TrivialClone for Value<'a, 'tcx> { }
#[automatically_derived]
impl<'a, 'tcx> ::core::clone::Clone for Value<'a, 'tcx> {
#[inline]
fn clone(&self) -> Value<'a, 'tcx> {
let _: ::core::clone::AssertParamIsClone<VnOpaque>;
let _: ::core::clone::AssertParamIsClone<Const<'tcx>>;
let _: ::core::clone::AssertParamIsClone<Option<VnOpaque>>;
let _: ::core::clone::AssertParamIsClone<VariantIdx>;
let _: ::core::clone::AssertParamIsClone<&'a [VnIndex]>;
let _: ::core::clone::AssertParamIsClone<FieldIdx>;
let _: ::core::clone::AssertParamIsClone<VnIndex>;
let _: ::core::clone::AssertParamIsClone<ty::Const<'tcx>>;
let _: ::core::clone::AssertParamIsClone<AddressBase>;
let _:
::core::clone::AssertParamIsClone<&'a [ProjectionElem<VnIndex,
Ty<'tcx>>]>;
let _: ::core::clone::AssertParamIsClone<AddressKind>;
let _:
::core::clone::AssertParamIsClone<ProjectionElem<VnIndex,
()>>;
let _: ::core::clone::AssertParamIsClone<RuntimeChecks>;
let _: ::core::clone::AssertParamIsClone<UnOp>;
let _: ::core::clone::AssertParamIsClone<BinOp>;
let _: ::core::clone::AssertParamIsClone<CastKind>;
*self
}
}
#[automatically_derived]
impl<'a, 'tcx> ::core::fmt::Debug for Value<'a, 'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Value::Opaque(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Opaque", &__self_0),
Value::Argument(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Argument", &__self_0),
Value::Constant { value: __self_0, disambiguator: __self_1 }
=>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"Constant", "value", __self_0, "disambiguator", &__self_1),
Value::Aggregate(__self_0, __self_1) =>
::core::fmt::Formatter::debug_tuple_field2_finish(f,
"Aggregate", __self_0, &__self_1),
Value::Union(__self_0, __self_1) =>
::core::fmt::Formatter::debug_tuple_field2_finish(f,
"Union", __self_0, &__self_1),
Value::RawPtr { pointer: __self_0, metadata: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"RawPtr", "pointer", __self_0, "metadata", &__self_1),
Value::Repeat(__self_0, __self_1) =>
::core::fmt::Formatter::debug_tuple_field2_finish(f,
"Repeat", __self_0, &__self_1),
Value::Address {
base: __self_0,
projection: __self_1,
kind: __self_2,
provenance: __self_3 } =>
::core::fmt::Formatter::debug_struct_field4_finish(f,
"Address", "base", __self_0, "projection", __self_1, "kind",
__self_2, "provenance", &__self_3),
Value::Projection(__self_0, __self_1) =>
::core::fmt::Formatter::debug_tuple_field2_finish(f,
"Projection", __self_0, &__self_1),
Value::Discriminant(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Discriminant", &__self_0),
Value::RuntimeChecks(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"RuntimeChecks", &__self_0),
Value::UnaryOp(__self_0, __self_1) =>
::core::fmt::Formatter::debug_tuple_field2_finish(f,
"UnaryOp", __self_0, &__self_1),
Value::BinaryOp(__self_0, __self_1, __self_2) =>
::core::fmt::Formatter::debug_tuple_field3_finish(f,
"BinaryOp", __self_0, __self_1, &__self_2),
Value::Cast { kind: __self_0, value: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"Cast", "kind", __self_0, "value", &__self_1),
}
}
}
#[automatically_derived]
impl<'a, 'tcx> ::core::marker::StructuralPartialEq for Value<'a, 'tcx> { }
#[automatically_derived]
impl<'a, 'tcx> ::core::cmp::PartialEq for Value<'a, 'tcx> {
#[inline]
fn eq(&self, other: &Value<'a, 'tcx>) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(Value::Opaque(__self_0), Value::Opaque(__arg1_0)) =>
__self_0 == __arg1_0,
(Value::Argument(__self_0), Value::Argument(__arg1_0)) =>
__self_0 == __arg1_0,
(Value::Constant { value: __self_0, disambiguator: __self_1
}, Value::Constant {
value: __arg1_0, disambiguator: __arg1_1 }) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1,
(Value::Aggregate(__self_0, __self_1),
Value::Aggregate(__arg1_0, __arg1_1)) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1,
(Value::Union(__self_0, __self_1),
Value::Union(__arg1_0, __arg1_1)) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1,
(Value::RawPtr { pointer: __self_0, metadata: __self_1 },
Value::RawPtr { pointer: __arg1_0, metadata: __arg1_1 }) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1,
(Value::Repeat(__self_0, __self_1),
Value::Repeat(__arg1_0, __arg1_1)) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1,
(Value::Address {
base: __self_0,
projection: __self_1,
kind: __self_2,
provenance: __self_3 }, Value::Address {
base: __arg1_0,
projection: __arg1_1,
kind: __arg1_2,
provenance: __arg1_3 }) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1 &&
__self_2 == __arg1_2 && __self_3 == __arg1_3,
(Value::Projection(__self_0, __self_1),
Value::Projection(__arg1_0, __arg1_1)) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1,
(Value::Discriminant(__self_0),
Value::Discriminant(__arg1_0)) => __self_0 == __arg1_0,
(Value::RuntimeChecks(__self_0),
Value::RuntimeChecks(__arg1_0)) => __self_0 == __arg1_0,
(Value::UnaryOp(__self_0, __self_1),
Value::UnaryOp(__arg1_0, __arg1_1)) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1,
(Value::BinaryOp(__self_0, __self_1, __self_2),
Value::BinaryOp(__arg1_0, __arg1_1, __arg1_2)) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1 &&
__self_2 == __arg1_2,
(Value::Cast { kind: __self_0, value: __self_1 },
Value::Cast { kind: __arg1_0, value: __arg1_1 }) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}
#[automatically_derived]
impl<'a, 'tcx> ::core::cmp::Eq for Value<'a, 'tcx> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<VnOpaque>;
let _: ::core::cmp::AssertParamIsEq<Const<'tcx>>;
let _: ::core::cmp::AssertParamIsEq<Option<VnOpaque>>;
let _: ::core::cmp::AssertParamIsEq<VariantIdx>;
let _: ::core::cmp::AssertParamIsEq<&'a [VnIndex]>;
let _: ::core::cmp::AssertParamIsEq<FieldIdx>;
let _: ::core::cmp::AssertParamIsEq<VnIndex>;
let _: ::core::cmp::AssertParamIsEq<ty::Const<'tcx>>;
let _: ::core::cmp::AssertParamIsEq<AddressBase>;
let _:
::core::cmp::AssertParamIsEq<&'a [ProjectionElem<VnIndex,
Ty<'tcx>>]>;
let _: ::core::cmp::AssertParamIsEq<AddressKind>;
let _: ::core::cmp::AssertParamIsEq<ProjectionElem<VnIndex, ()>>;
let _: ::core::cmp::AssertParamIsEq<RuntimeChecks>;
let _: ::core::cmp::AssertParamIsEq<UnOp>;
let _: ::core::cmp::AssertParamIsEq<BinOp>;
let _: ::core::cmp::AssertParamIsEq<CastKind>;
}
}
#[automatically_derived]
impl<'a, 'tcx> ::core::hash::Hash for Value<'a, 'tcx> {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state);
match self {
Value::Opaque(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Value::Argument(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Value::Constant { value: __self_0, disambiguator: __self_1 }
=> {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state)
}
Value::Aggregate(__self_0, __self_1) => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state)
}
Value::Union(__self_0, __self_1) => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state)
}
Value::RawPtr { pointer: __self_0, metadata: __self_1 } => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state)
}
Value::Repeat(__self_0, __self_1) => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state)
}
Value::Address {
base: __self_0,
projection: __self_1,
kind: __self_2,
provenance: __self_3 } => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state);
::core::hash::Hash::hash(__self_2, state);
::core::hash::Hash::hash(__self_3, state)
}
Value::Projection(__self_0, __self_1) => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state)
}
Value::Discriminant(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Value::RuntimeChecks(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
Value::UnaryOp(__self_0, __self_1) => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state)
}
Value::BinaryOp(__self_0, __self_1, __self_2) => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state);
::core::hash::Hash::hash(__self_2, state)
}
Value::Cast { kind: __self_0, value: __self_1 } => {
::core::hash::Hash::hash(__self_0, state);
::core::hash::Hash::hash(__self_1, state)
}
}
}
}
struct ValueSet<'a, 'tcx> {
indices: HashTable<VnIndex>,
hashes: IndexVec<VnIndex, u64>,
values: IndexVec<VnIndex, Value<'a, 'tcx>>,
types: IndexVec<VnIndex, Ty<'tcx>>,
}
impl<'a, 'tcx> ValueSet<'a, 'tcx> {
fn new(num_values: usize) -> ValueSet<'a, 'tcx> {
ValueSet {
indices: HashTable::with_capacity(num_values),
hashes: IndexVec::with_capacity(num_values),
values: IndexVec::with_capacity(num_values),
types: IndexVec::with_capacity(num_values),
}
}
#[inline]
fn insert_unique(&mut self, ty: Ty<'tcx>,
value: impl FnOnce(VnOpaque) -> Value<'a, 'tcx>) -> VnIndex {
let value = value(VnOpaque);
if true {
if !match value {
Value::Opaque(_) | Value::Argument(_) | Value::Address { ..
} => true,
Value::Constant { disambiguator, .. } =>
disambiguator.is_some(),
_ => false,
} {
::core::panicking::panic("assertion failed: match value {\n Value::Opaque(_) | Value::Argument(_) | Value::Address { .. } => true,\n Value::Constant { disambiguator, .. } => disambiguator.is_some(),\n _ => false,\n}")
};
};
let index = self.hashes.push(0);
let _index = self.types.push(ty);
if true {
{
match (&index, &_index) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
let _index = self.values.push(value);
if true {
{
match (&index, &_index) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
index
}
#[allow(rustc::disallowed_pass_by_ref)]
fn insert(&mut self, ty: Ty<'tcx>, value: Value<'a, 'tcx>)
-> (VnIndex, bool) {
if true {
if !match value {
Value::Opaque(_) | Value::Address { .. } => false,
Value::Constant { disambiguator, .. } =>
disambiguator.is_none(),
_ => true,
} {
::core::panicking::panic("assertion failed: match value {\n Value::Opaque(_) | Value::Address { .. } => false,\n Value::Constant { disambiguator, .. } => disambiguator.is_none(),\n _ => true,\n}")
};
};
let hash: u64 =
{
let mut h = FxHasher::default();
value.hash(&mut h);
ty.hash(&mut h);
h.finish()
};
let eq =
|index: &VnIndex|
self.values[*index] == value && self.types[*index] == ty;
let hasher = |index: &VnIndex| self.hashes[*index];
match self.indices.entry(hash, eq, hasher) {
Entry::Occupied(entry) => {
let index = *entry.get();
(index, false)
}
Entry::Vacant(entry) => {
let index = self.hashes.push(hash);
entry.insert(index);
let _index = self.values.push(value);
if true {
{
match (&index, &_index) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
let _index = self.types.push(ty);
if true {
{
match (&index, &_index) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
(index, true)
}
}
}
#[inline]
fn value(&self, index: VnIndex) -> Value<'a, 'tcx> {
self.values[index]
}
#[inline]
fn ty(&self, index: VnIndex) -> Ty<'tcx> { self.types[index] }
}
struct VnState<'body, 'a, 'tcx> {
tcx: TyCtxt<'tcx>,
ecx: InterpCx<'tcx, DummyMachine>,
local_decls: &'body LocalDecls<'tcx>,
is_coroutine: bool,
locals: IndexVec<Local, Option<VnIndex>>,
rev_locals: IndexVec<VnIndex, SmallVec<[Local; 1]>>,
values: ValueSet<'a, 'tcx>,
evaluated: IndexVec<VnIndex, Option<Option<&'a OpTy<'tcx>>>>,
ssa: &'body SsaLocals,
dominators: Dominators<BasicBlock>,
reused_locals: DenseBitSet<Local>,
arena: &'a DroplessArena,
}
impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> {
fn new(tcx: TyCtxt<'tcx>, body: &Body<'tcx>,
typing_env: ty::TypingEnv<'tcx>, ssa: &'body SsaLocals,
dominators: Dominators<BasicBlock>,
local_decls: &'body LocalDecls<'tcx>, arena: &'a DroplessArena)
-> Self {
let num_values =
2 *
body.basic_blocks.iter().map(|bbdata|
bbdata.statements.len()).sum::<usize>() +
4 * body.basic_blocks.len();
VnState {
tcx,
ecx: InterpCx::new(tcx, DUMMY_SP, typing_env, DummyMachine),
local_decls,
is_coroutine: body.coroutine.is_some(),
locals: IndexVec::from_elem(None, local_decls),
rev_locals: IndexVec::with_capacity(num_values),
values: ValueSet::new(num_values),
evaluated: IndexVec::with_capacity(num_values),
ssa,
dominators,
reused_locals: DenseBitSet::new_empty(local_decls.len()),
arena,
}
}
fn typing_env(&self) -> ty::TypingEnv<'tcx> { self.ecx.typing_env() }
fn insert_unique(&mut self, ty: Ty<'tcx>,
value: impl FnOnce(VnOpaque) -> Value<'a, 'tcx>) -> VnIndex {
let index = self.values.insert_unique(ty, value);
let _index = self.evaluated.push(None);
if true {
{
match (&index, &_index) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
let _index = self.rev_locals.push(SmallVec::new());
if true {
{
match (&index, &_index) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
index
}
fn insert(&mut self, ty: Ty<'tcx>, value: Value<'a, 'tcx>)
-> VnIndex {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("insert",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(454u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("ty")
}> =
::tracing::__macro_support::FieldName::new("ty");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("value")
}> =
::tracing::__macro_support::FieldName::new("value");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&value)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: VnIndex = loop {};
return __tracing_attr_fake_return;
}
{
let (index, new) = self.values.insert(ty, value);
if new {
let _index = self.evaluated.push(None);
if true {
{
match (&index, &_index) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
let _index = self.rev_locals.push(SmallVec::new());
if true {
{
match (&index, &_index) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
}
index
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs:454",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(454u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
#[doc =
" Create a new `Value` for which we have no information at all, except that it is distinct"]
#[doc = " from all the others."]
fn new_opaque(&mut self, ty: Ty<'tcx>) -> VnIndex {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("new_opaque",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(469u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("ty")
}> =
::tracing::__macro_support::FieldName::new("ty");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: VnIndex = loop {};
return __tracing_attr_fake_return;
}
{
let index = self.insert_unique(ty, Value::Opaque);
self.evaluated[index] = Some(None);
index
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs:469",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(469u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn new_argument(&mut self, ty: Ty<'tcx>) -> VnIndex {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("new_argument",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(476u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("ty")
}> =
::tracing::__macro_support::FieldName::new("ty");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&ty)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: VnIndex = loop {};
return __tracing_attr_fake_return;
}
{
let index = self.insert_unique(ty, Value::Argument);
self.evaluated[index] = Some(None);
index
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs:476",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(476u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
#[doc =
" Create a new `Value::Address` distinct from all the others."]
fn new_pointer(&mut self, place: Place<'tcx>, kind: AddressKind)
-> Option<VnIndex> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("new_pointer",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(484u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("place")
}> =
::tracing::__macro_support::FieldName::new("place");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("kind")
}> =
::tracing::__macro_support::FieldName::new("kind");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&kind)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Option<VnIndex> = loop {};
return __tracing_attr_fake_return;
}
{
let pty = place.ty(self.local_decls, self.tcx).ty;
let ty =
match kind {
AddressKind::Ref(bk) => {
Ty::new_ref(self.tcx, self.tcx.lifetimes.re_erased, pty,
bk.to_mutbl_lossy())
}
AddressKind::Address(mutbl) =>
Ty::new_ptr(self.tcx, pty, mutbl.to_mutbl_lossy()),
};
let mut projection = place.projection.iter();
let base =
if place.is_indirect_first_projection() {
let base = self.locals[place.local]?;
projection.next();
AddressBase::Deref(base)
} else if self.ssa.is_ssa(place.local) {
AddressBase::Local(place.local)
} else { return None; };
let projection =
projection.map(|proj|
proj.try_map(|index| self.locals[index],
|ty| ty).ok_or(()));
let projection =
self.arena.try_alloc_from_iter(projection).ok()?;
let index =
self.insert_unique(ty,
|provenance|
Value::Address { base, projection, kind, provenance });
Some(index)
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs:484",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(484u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn insert_constant(&mut self, value: Const<'tcx>) -> VnIndex {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("insert_constant",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(520u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("value")
}> =
::tracing::__macro_support::FieldName::new("value");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&value)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: VnIndex = loop {};
return __tracing_attr_fake_return;
}
{
if is_deterministic(value) {
let constant =
Value::Constant { value, disambiguator: None };
self.insert(value.ty(), constant)
} else {
self.insert_unique(value.ty(),
|disambiguator|
Value::Constant {
value,
disambiguator: Some(disambiguator),
})
}
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs:520",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(520u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
#[inline]
fn get(&self, index: VnIndex) -> Value<'a, 'tcx> {
self.values.value(index)
}
#[inline]
fn ty(&self, index: VnIndex) -> Ty<'tcx> { self.values.ty(index) }
#[doc =
" Record that `local` is assigned `value`. `local` must be SSA."]
fn assign(&mut self, local: Local, value: VnIndex) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("assign",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(547u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("local")
}> =
::tracing::__macro_support::FieldName::new("local");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("value")
}> =
::tracing::__macro_support::FieldName::new("value");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&local)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&value)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
if true {
if !self.ssa.is_ssa(local) {
::core::panicking::panic("assertion failed: self.ssa.is_ssa(local)")
};
};
self.locals[local] = Some(value);
self.rev_locals[value].push(local);
}
}
}
}
fn insert_bool(&mut self, flag: bool) -> VnIndex {
let value = Const::from_bool(self.tcx, flag);
if true {
if !is_deterministic(value) {
::core::panicking::panic("assertion failed: is_deterministic(value)")
};
};
self.insert(self.tcx.types.bool,
Value::Constant { value, disambiguator: None })
}
fn insert_scalar(&mut self, ty: Ty<'tcx>, scalar: Scalar) -> VnIndex {
let value = Const::from_scalar(self.tcx, scalar, ty);
if true {
if !is_deterministic(value) {
::core::panicking::panic("assertion failed: is_deterministic(value)")
};
};
self.insert(ty, Value::Constant { value, disambiguator: None })
}
fn insert_tuple(&mut self, ty: Ty<'tcx>, values: &[VnIndex])
-> VnIndex {
self.insert(ty,
Value::Aggregate(VariantIdx::ZERO,
self.arena.alloc_slice(values)))
}
fn eval_to_const_inner(&mut self, value: VnIndex)
-> Option<OpTy<'tcx>> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("eval_to_const_inner",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(572u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("value")
}> =
::tracing::__macro_support::FieldName::new("value");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&value)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Option<OpTy<'tcx>> =
loop {};
return __tracing_attr_fake_return;
}
{
use Value::*;
let ty = self.ty(value);
let ty =
if !self.is_coroutine || ty.is_scalar() {
self.ecx.layout_of(ty).ok()?
} else { return None; };
let op =
match self.get(value) {
_ if ty.is_zst() => ImmTy::uninit(ty).into(),
Opaque(_) | Argument(_) => return None,
RuntimeChecks(..) => return None,
Repeat(value, _count) => {
let value = self.eval_to_const(value)?;
if value.is_immediate_uninit() {
ImmTy::uninit(ty).into()
} else { return None; }
}
Constant { ref value, disambiguator: _ } => {
self.ecx.eval_mir_constant(value, DUMMY_SP,
None).discard_err()?
}
Aggregate(variant, ref fields) => {
let fields =
fields.iter().map(|&f|
self.eval_to_const(f)).collect::<Option<Vec<_>>>()?;
let variant =
if ty.ty.is_enum() { Some(variant) } else { None };
let (BackendRepr::Scalar(..) | BackendRepr::ScalarPair { ..
}) = ty.backend_repr else { return None; };
let dest =
self.ecx.allocate(ty, MemoryKind::Stack).discard_err()?;
let variant_dest =
if let Some(variant) = variant {
self.ecx.project_downcast(&dest, variant).discard_err()?
} else { dest.clone() };
for (field_index, op) in fields.into_iter().enumerate() {
let field_dest =
self.ecx.project_field(&variant_dest,
FieldIdx::from_usize(field_index)).discard_err()?;
self.ecx.copy_op(op, &field_dest).discard_err()?;
}
self.ecx.write_discriminant(variant.unwrap_or(FIRST_VARIANT),
&dest).discard_err()?;
self.ecx.alloc_mark_immutable(dest.ptr().provenance.unwrap().alloc_id()).discard_err()?;
dest.into()
}
Union(active_field, field) => {
let field = self.eval_to_const(field)?;
if field.layout.layout.is_zst() {
ImmTy::from_immediate(Immediate::Uninit, ty).into()
} else if #[allow(non_exhaustive_omitted_patterns)] match ty.backend_repr
{
BackendRepr::Scalar(..) | BackendRepr::ScalarPair { .. } =>
true,
_ => false,
} {
let dest =
self.ecx.allocate(ty, MemoryKind::Stack).discard_err()?;
let field_dest =
self.ecx.project_field(&dest, active_field).discard_err()?;
self.ecx.copy_op(field, &field_dest).discard_err()?;
self.ecx.alloc_mark_immutable(dest.ptr().provenance.unwrap().alloc_id()).discard_err()?;
dest.into()
} else { return None; }
}
RawPtr { pointer, metadata } => {
let pointer = self.eval_to_const(pointer)?;
let metadata = self.eval_to_const(metadata)?;
let data = self.ecx.read_pointer(pointer).discard_err()?;
let meta =
if metadata.layout.is_zst() {
MemPlaceMeta::None
} else {
MemPlaceMeta::Meta(self.ecx.read_scalar(metadata).discard_err()?)
};
let ptr_imm =
Immediate::new_pointer_with_meta(data, meta, &self.ecx);
ImmTy::from_immediate(ptr_imm, ty).into()
}
Projection(base, elem) => {
let base = self.eval_to_const(base)?;
let elem = elem.try_map(|_| None, |()| ty.ty)?;
self.ecx.project(base, elem).discard_err()?
}
Address { base, projection, .. } => {
if true {
if !!projection.contains(&ProjectionElem::Deref) {
::core::panicking::panic("assertion failed: !projection.contains(&ProjectionElem::Deref)")
};
};
let pointer =
match base {
AddressBase::Deref(pointer) => self.eval_to_const(pointer)?,
AddressBase::Local(_) => return None,
};
let mut mplace =
self.ecx.deref_pointer(pointer).discard_err()?;
for elem in projection {
let elem = elem.try_map(|_| None, |ty| ty)?;
mplace = self.ecx.project(&mplace, elem).discard_err()?;
}
let pointer = mplace.to_ref(&self.ecx);
ImmTy::from_immediate(pointer, ty).into()
}
Discriminant(base) => {
let base = self.eval_to_const(base)?;
let variant =
self.ecx.read_discriminant(base).discard_err()?;
let discr_value =
self.ecx.discriminant_for_variant(base.layout.ty,
variant).discard_err()?;
discr_value.into()
}
UnaryOp(un_op, operand) => {
let operand = self.eval_to_const(operand)?;
let operand =
self.ecx.read_immediate(operand).discard_err()?;
let val = self.ecx.unary_op(un_op, &operand).discard_err()?;
val.into()
}
BinaryOp(bin_op, lhs, rhs) => {
let lhs = self.eval_to_const(lhs)?;
let rhs = self.eval_to_const(rhs)?;
let lhs = self.ecx.read_immediate(lhs).discard_err()?;
let rhs = self.ecx.read_immediate(rhs).discard_err()?;
let val =
self.ecx.binary_op(bin_op, &lhs, &rhs).discard_err()?;
val.into()
}
Cast { kind, value } =>
match kind {
CastKind::IntToInt | CastKind::IntToFloat => {
let value = self.eval_to_const(value)?;
let value = self.ecx.read_immediate(value).discard_err()?;
let res =
self.ecx.int_to_int_or_float(&value, ty).discard_err()?;
res.into()
}
CastKind::FloatToFloat | CastKind::FloatToInt => {
let value = self.eval_to_const(value)?;
let value = self.ecx.read_immediate(value).discard_err()?;
let res =
self.ecx.float_to_float_or_int(&value, ty).discard_err()?;
res.into()
}
CastKind::Transmute | CastKind::Subtype => {
let value = self.eval_to_const(value)?;
if value.as_mplace_or_imm().is_right() {
let can_transmute =
match (value.layout.backend_repr, ty.backend_repr) {
(BackendRepr::Scalar(s1), BackendRepr::Scalar(s2)) => {
s1.size(&self.ecx) == s2.size(&self.ecx) &&
!#[allow(non_exhaustive_omitted_patterns)] match s1.primitive()
{
Primitive::Pointer(..) => true,
_ => false,
}
}
(BackendRepr::ScalarPair { a: a1, b: b1, b_offset: b1_offset
}, BackendRepr::ScalarPair {
a: a2, b: b2, b_offset: b2_offset }) => {
a1.size(&self.ecx) == a2.size(&self.ecx) &&
b1.size(&self.ecx) == b2.size(&self.ecx) &&
b1_offset == b2_offset &&
!#[allow(non_exhaustive_omitted_patterns)] match a1.primitive()
{
Primitive::Pointer(..) => true,
_ => false,
} &&
!#[allow(non_exhaustive_omitted_patterns)] match b1.primitive()
{
Primitive::Pointer(..) => true,
_ => false,
}
}
_ => false,
};
if !can_transmute { return None; }
}
value.offset(Size::ZERO, ty, &self.ecx).discard_err()?
}
CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize,
_) => {
let src = self.eval_to_const(value)?;
let dest =
self.ecx.allocate(ty, MemoryKind::Stack).discard_err()?;
self.ecx.unsize_into(src, ty, &dest).discard_err()?;
self.ecx.alloc_mark_immutable(dest.ptr().provenance.unwrap().alloc_id()).discard_err()?;
dest.into()
}
CastKind::FnPtrToPtr | CastKind::PtrToPtr => {
let src = self.eval_to_const(value)?;
let src = self.ecx.read_immediate(src).discard_err()?;
let ret = self.ecx.ptr_to_ptr(&src, ty).discard_err()?;
ret.into()
}
CastKind::PointerCoercion(ty::adjustment::PointerCoercion::UnsafeFnPointer,
_) => {
let src = self.eval_to_const(value)?;
let src = self.ecx.read_immediate(src).discard_err()?;
ImmTy::from_immediate(*src, ty).into()
}
_ => return None,
},
};
Some(op)
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs:572",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(572u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn eval_to_const(&mut self, index: VnIndex)
-> Option<&'a OpTy<'tcx>> {
if let Some(op) = self.evaluated[index] { return op; }
let op = self.eval_to_const_inner(index);
self.evaluated[index] = Some(self.arena.alloc(op).as_ref());
self.evaluated[index].unwrap()
}
#[doc =
" Represent the *value* we obtain by dereferencing an `Address` value."]
fn dereference_address(&mut self, base: AddressBase,
projection: &[ProjectionElem<VnIndex, Ty<'tcx>>])
-> Option<VnIndex> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("dereference_address",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(795u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("base")
}> =
::tracing::__macro_support::FieldName::new("base");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("projection")
}> =
::tracing::__macro_support::FieldName::new("projection");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&base)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&projection)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Option<VnIndex> = loop {};
return __tracing_attr_fake_return;
}
{
let (mut place_ty, mut value) =
match base {
AddressBase::Local(local) => {
let local = self.locals[local]?;
let place_ty = PlaceTy::from_ty(self.ty(local));
(place_ty, local)
}
AddressBase::Deref(reborrow) => {
let place_ty = PlaceTy::from_ty(self.ty(reborrow));
self.project(place_ty, reborrow, ProjectionElem::Deref)?
}
};
for &proj in projection {
(place_ty, value) = self.project(place_ty, value, proj)?;
}
Some(value)
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs:795",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(795u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn project(&mut self, place_ty: PlaceTy<'tcx>, value: VnIndex,
proj: ProjectionElem<VnIndex, Ty<'tcx>>)
-> Option<(PlaceTy<'tcx>, VnIndex)> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("project",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(820u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("place_ty")
}> =
::tracing::__macro_support::FieldName::new("place_ty");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("value")
}> =
::tracing::__macro_support::FieldName::new("value");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("proj")
}> =
::tracing::__macro_support::FieldName::new("proj");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place_ty)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&value)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&proj)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<(PlaceTy<'tcx>, VnIndex)> = loop {};
return __tracing_attr_fake_return;
}
{
let projection_ty = place_ty.projection_ty(self.tcx, proj);
let proj =
match proj {
ProjectionElem::Deref => {
if let Some(Mutability::Not) = place_ty.ty.ref_mutability()
&& projection_ty.ty.is_freeze(self.tcx, self.typing_env()) {
if let Value::Address { base, projection, .. } =
self.get(value) &&
let Some(value) = self.dereference_address(base, projection)
{
return Some((projection_ty, value));
}
if self.ty_may_have_ref(projection_ty.ty) { return None; }
let deref =
self.insert(projection_ty.ty,
Value::Projection(value, ProjectionElem::Deref));
return Some((projection_ty, deref));
} else { return None; }
}
ProjectionElem::PhantomDeref =>
::rustc_middle::util::bug::bug_fmt(format_args!("PhantomDeref in GVN")),
ProjectionElem::Downcast(name, index) =>
ProjectionElem::Downcast(name, index),
ProjectionElem::Field(f, _) =>
match self.get(value) {
Value::Aggregate(_, fields) =>
return Some((projection_ty, fields[f.as_usize()])),
Value::Union(active, field) if active == f =>
return Some((projection_ty, field)),
Value::Projection(outer_value,
ProjectionElem::Downcast(_, read_variant)) if
let Value::Aggregate(written_variant, fields) =
self.get(outer_value) && written_variant == read_variant =>
{
return Some((projection_ty, fields[f.as_usize()]));
}
_ => ProjectionElem::Field(f, ()),
},
ProjectionElem::Index(idx) => {
if let Value::Repeat(inner, _) = self.get(value) {
return Some((projection_ty, inner));
}
ProjectionElem::Index(idx)
}
ProjectionElem::ConstantIndex { offset, min_length, from_end
} => {
match self.get(value) {
Value::Repeat(inner, _) => {
return Some((projection_ty, inner));
}
Value::Aggregate(_, operands) => {
let offset =
if from_end {
operands.len() - offset as usize
} else { offset as usize };
let value = operands.get(offset).copied()?;
return Some((projection_ty, value));
}
_ => {}
};
ProjectionElem::ConstantIndex {
offset,
min_length,
from_end,
}
}
ProjectionElem::Subslice { from, to, from_end } => {
ProjectionElem::Subslice { from, to, from_end }
}
ProjectionElem::OpaqueCast(_) =>
ProjectionElem::OpaqueCast(()),
ProjectionElem::UnwrapUnsafeBinder(_) =>
ProjectionElem::UnwrapUnsafeBinder(()),
};
let value =
self.insert(projection_ty.ty,
Value::Projection(value, proj));
Some((projection_ty, value))
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs:820",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(820u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
#[doc = " Simplify the projection chain if we know better."]
fn simplify_place_projection(&mut self, place: &mut Place<'tcx>,
location: Location) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("simplify_place_projection",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(928u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("place")
}> =
::tracing::__macro_support::FieldName::new("place");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("location")
}> =
::tracing::__macro_support::FieldName::new("location");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&location)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
if place.is_indirect_first_projection() &&
let Some(base) = self.locals[place.local] &&
let Some(new_local) = self.try_as_local(base, location) &&
place.local != new_local {
place.local = new_local;
self.reused_locals.insert(new_local);
}
let mut projection = Cow::Borrowed(&place.projection[..]);
for i in 0..projection.len() {
let elem = projection[i];
if let ProjectionElem::Index(idx_local) = elem &&
let Some(idx) = self.locals[idx_local] {
if let Some(offset) = self.eval_to_const(idx) &&
let Some(offset) =
self.ecx.read_target_usize(offset).discard_err() &&
let Some(min_length) = offset.checked_add(1) {
projection.to_mut()[i] =
ProjectionElem::ConstantIndex {
offset,
min_length,
from_end: false,
};
} else if let Some(new_idx_local) =
self.try_as_local(idx, location) &&
idx_local != new_idx_local {
projection.to_mut()[i] =
ProjectionElem::Index(new_idx_local);
self.reused_locals.insert(new_idx_local);
}
}
}
if Cow::is_owned(&projection) {
place.projection = self.tcx.mk_place_elems(&projection);
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs:967",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(967u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("place")
}> =
::tracing::__macro_support::FieldName::new("place");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
}
}
}
}
#[doc =
" Represent the *value* which would be read from `place`. If we succeed, return it."]
#[doc =
" If we fail, return a `PlaceRef` that contains the same value."]
fn compute_place_value(&mut self, place: Place<'tcx>,
location: Location) -> Result<VnIndex, PlaceRef<'tcx>> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("compute_place_value",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(972u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("place")
}> =
::tracing::__macro_support::FieldName::new("place");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("location")
}> =
::tracing::__macro_support::FieldName::new("location");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&location)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Result<VnIndex, PlaceRef<'tcx>> = loop {};
return __tracing_attr_fake_return;
}
{
let mut place_ref = place.as_ref();
let Some(mut value) =
self.locals[place.local] else { return Err(place_ref) };
let mut place_ty =
PlaceTy::from_ty(self.local_decls[place.local].ty);
for (index, proj) in place.projection.iter().enumerate() {
if let Some(local) = self.try_as_local(value, location) {
place_ref =
PlaceRef { local, projection: &place.projection[index..] };
}
let Some(proj) =
proj.try_map(|value| self.locals[value],
|ty| ty) else { return Err(place_ref); };
let Some(ty_and_value) =
self.project(place_ty, value,
proj) else { return Err(place_ref); };
(place_ty, value) = ty_and_value;
}
Ok(value)
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs:972",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(972u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
#[doc =
" Represent the *value* which would be read from `place`, and point `place` to a preexisting"]
#[doc = " place with the same value (if that already exists)."]
fn simplify_place_value(&mut self, place: &mut Place<'tcx>,
location: Location) -> Option<VnIndex> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("simplify_place_value",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(1008u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("place")
}> =
::tracing::__macro_support::FieldName::new("place");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("location")
}> =
::tracing::__macro_support::FieldName::new("location");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&location)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Option<VnIndex> = loop {};
return __tracing_attr_fake_return;
}
{
self.simplify_place_projection(place, location);
match self.compute_place_value(*place, location) {
Ok(value) => {
if let Some(new_place) =
self.try_as_place(value, location, true) &&
(new_place.local != place.local ||
new_place.projection.len() < place.projection.len()) {
*place = new_place;
self.reused_locals.insert(new_place.local);
}
Some(value)
}
Err(place_ref) => {
if place_ref.local != place.local ||
place_ref.projection.len() < place.projection.len() {
*place = place_ref.project_deeper(&[], self.tcx);
self.reused_locals.insert(place_ref.local);
}
None
}
}
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs:1008",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(1008u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn simplify_operand(&mut self, operand: &mut Operand<'tcx>,
location: Location) -> Option<VnIndex> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("simplify_operand",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(1040u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("operand")
}> =
::tracing::__macro_support::FieldName::new("operand");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("location")
}> =
::tracing::__macro_support::FieldName::new("location");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&operand)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&location)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Option<VnIndex> = loop {};
return __tracing_attr_fake_return;
}
{
let value =
match *operand {
Operand::RuntimeChecks(c) =>
self.insert(self.tcx.types.bool, Value::RuntimeChecks(c)),
Operand::Constant(ref constant) =>
self.insert_constant(constant.const_),
Operand::Copy(ref mut place) | Operand::Move(ref mut place)
=> {
self.simplify_place_value(place, location)?
}
};
if let Some(const_) = self.try_as_constant(value) {
*operand = Operand::Constant(Box::new(const_));
} else if let Value::RuntimeChecks(c) = self.get(value) {
*operand = Operand::RuntimeChecks(c);
}
Some(value)
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs:1040",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(1040u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn simplify_rvalue(&mut self, lhs: &Place<'tcx>,
rvalue: &mut Rvalue<'tcx>, location: Location)
-> Option<VnIndex> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("simplify_rvalue",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(1061u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("lhs")
}> =
::tracing::__macro_support::FieldName::new("lhs");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("rvalue")
}> =
::tracing::__macro_support::FieldName::new("rvalue");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("location")
}> =
::tracing::__macro_support::FieldName::new("location");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&lhs)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&rvalue)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&location)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Option<VnIndex> = loop {};
return __tracing_attr_fake_return;
}
{
let value =
match *rvalue {
Rvalue::Use(ref mut operand, _) =>
return self.simplify_operand(operand, location),
Rvalue::Repeat(ref mut op, amount) => {
let op = self.simplify_operand(op, location)?;
Value::Repeat(op, amount)
}
Rvalue::Aggregate(..) =>
return self.simplify_aggregate(rvalue, location),
Rvalue::Ref(_, borrow_kind, ref mut place) => {
self.simplify_place_projection(place, location);
return self.new_pointer(*place,
AddressKind::Ref(borrow_kind));
}
Rvalue::Reborrow(_, mutbl, place) => {
if mutbl == Mutability::Mut {
let mut operand = Operand::Copy(place);
let val = self.simplify_operand(&mut operand, location);
*rvalue = Rvalue::Use(Operand::Copy(place), WithRetag::Yes);
return val;
} else { return None; }
}
Rvalue::RawPtr(mutbl, ref mut place) => {
self.simplify_place_projection(place, location);
return self.new_pointer(*place,
AddressKind::Address(mutbl));
}
Rvalue::WrapUnsafeBinder(ref mut op, _) => {
let value = self.simplify_operand(op, location)?;
Value::Cast { kind: CastKind::Transmute, value }
}
Rvalue::Cast(ref mut kind, ref mut value, to) => {
return self.simplify_cast(kind, value, to, location);
}
Rvalue::BinaryOp(op, (ref mut lhs, ref mut rhs)) => {
return self.simplify_binary(op, lhs, rhs, location);
}
Rvalue::UnaryOp(op, ref mut arg_op) => {
return self.simplify_unary(op, arg_op, location);
}
Rvalue::Discriminant(ref mut place) => {
let place = self.simplify_place_value(place, location)?;
if let Some(discr) = self.simplify_discriminant(place) {
return Some(discr);
}
Value::Discriminant(place)
}
Rvalue::ThreadLocalRef(..) => return None,
Rvalue::CopyForDeref(_) => {
::rustc_middle::util::bug::bug_fmt(format_args!("forbidden in runtime MIR: {0:?}",
rvalue))
}
};
let ty = rvalue.ty(self.local_decls, self.tcx);
Some(self.insert(ty, value))
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs:1061",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(1061u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn simplify_discriminant(&mut self, place: VnIndex)
-> Option<VnIndex> {
let enum_ty = self.ty(place);
if enum_ty.is_enum() &&
let Value::Aggregate(variant, _) = self.get(place) {
let discr =
self.ecx.discriminant_for_variant(enum_ty,
variant).discard_err()?;
return Some(self.insert_scalar(discr.layout.ty,
discr.to_scalar()));
}
None
}
fn try_as_place_elem(&mut self, ty: Ty<'tcx>,
proj: ProjectionElem<VnIndex, ()>, loc: Location)
-> Option<PlaceElem<'tcx>> {
proj.try_map(|value|
{
let local = self.try_as_local(value, loc)?;
self.reused_locals.insert(local);
Some(local)
}, |()| ty)
}
fn simplify_aggregate_to_copy(&mut self, ty: Ty<'tcx>,
variant_index: VariantIdx, fields: &[VnIndex])
-> Option<VnIndex> {
let Some(&first_field) = fields.first() else { return None };
let Value::Projection(copy_from_value, _) =
self.get(first_field) else { return None };
if fields.iter().enumerate().any(|(index, &v)|
{
if let Value::Projection(pointer,
ProjectionElem::Field(from_index, _)) = self.get(v) &&
copy_from_value == pointer && from_index.index() == index {
return false;
}
true
}) {
return None;
}
let mut copy_from_local_value = copy_from_value;
if let Value::Projection(pointer, proj) =
self.get(copy_from_value) &&
let ProjectionElem::Downcast(_, read_variant) = proj {
if variant_index == read_variant {
copy_from_local_value = pointer;
} else { return None; }
}
if self.ty(copy_from_local_value) == ty {
Some(copy_from_local_value)
} else { None }
}
fn simplify_aggregate(&mut self, rvalue: &mut Rvalue<'tcx>,
location: Location) -> Option<VnIndex> {
let tcx = self.tcx;
let ty = rvalue.ty(self.local_decls, tcx);
let Rvalue::Aggregate(ref kind, ref mut field_ops) =
*rvalue else {
::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))
};
if field_ops.is_empty() {
let is_zst =
match *kind {
AggregateKind::Array(..) | AggregateKind::Tuple |
AggregateKind::Closure(..) |
AggregateKind::CoroutineClosure(..) => true,
AggregateKind::Adt(did, ..) =>
tcx.def_kind(did) != DefKind::Enum,
AggregateKind::Coroutine(..) => false,
AggregateKind::RawPtr(..) =>
::rustc_middle::util::bug::bug_fmt(format_args!("MIR for RawPtr aggregate must have 2 fields")),
};
if is_zst {
return Some(self.insert_constant(Const::zero_sized(ty)));
}
}
let fields =
self.arena.alloc_from_iter(field_ops.iter_mut().map(|op|
{
self.simplify_operand(op,
location).unwrap_or_else(||
self.new_opaque(op.ty(self.local_decls, self.tcx)))
}));
let variant_index =
match *kind {
AggregateKind::Array(..) | AggregateKind::Tuple => {
if !!field_ops.is_empty() {
::core::panicking::panic("assertion failed: !field_ops.is_empty()")
};
FIRST_VARIANT
}
AggregateKind::Closure(..) |
AggregateKind::CoroutineClosure(..) |
AggregateKind::Coroutine(..) => FIRST_VARIANT,
AggregateKind::Adt(_, variant_index, _, _, None) =>
variant_index,
AggregateKind::Adt(_, _, _, _, Some(active_field)) => {
let field = *fields.first()?;
return Some(self.insert(ty,
Value::Union(active_field, field)));
}
AggregateKind::RawPtr(..) => {
{
match (&field_ops.len(), &2) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
let [mut pointer, metadata] = fields.try_into().unwrap();
let mut was_updated = false;
while let Value::Cast {
kind: CastKind::PtrToPtr, value: cast_value } =
self.get(pointer) &&
let ty::RawPtr(from_pointee_ty, from_mtbl) =
self.ty(cast_value).kind() &&
let ty::RawPtr(_, output_mtbl) = ty.kind() &&
from_mtbl == output_mtbl &&
from_pointee_ty.is_sized(self.tcx, self.typing_env()) {
pointer = cast_value;
was_updated = true;
}
if was_updated &&
let Some(op) = self.try_as_operand(pointer, location) {
field_ops[FieldIdx::ZERO] = op;
}
return Some(self.insert(ty,
Value::RawPtr { pointer, metadata }));
}
};
if ty.is_array() && fields.len() > 4 &&
let Ok(&first) = fields.iter().all_equal_value() {
let len =
ty::Const::from_target_usize(self.tcx,
fields.len().try_into().unwrap());
if let Some(op) = self.try_as_operand(first, location) {
*rvalue = Rvalue::Repeat(op, len);
}
return Some(self.insert(ty, Value::Repeat(first, len)));
}
if let Some(value) =
self.simplify_aggregate_to_copy(ty, variant_index, &fields)
{
if let Some(place) = self.try_as_place(value, location, true)
{
self.reused_locals.insert(place.local);
*rvalue = Rvalue::Use(Operand::Copy(place), WithRetag::Yes);
}
return Some(value);
}
Some(self.insert(ty, Value::Aggregate(variant_index, fields)))
}
fn simplify_unary(&mut self, op: UnOp, arg_op: &mut Operand<'tcx>,
location: Location) -> Option<VnIndex> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("simplify_unary",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(1296u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("op")
}> =
::tracing::__macro_support::FieldName::new("op");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("arg_op")
}> =
::tracing::__macro_support::FieldName::new("arg_op");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("location")
}> =
::tracing::__macro_support::FieldName::new("location");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&op)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&arg_op)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&location)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Option<VnIndex> = loop {};
return __tracing_attr_fake_return;
}
{
let mut arg_index =
self.simplify_operand(arg_op, location)?;
let arg_ty = self.ty(arg_index);
let ret_ty = op.ty(self.tcx, arg_ty);
if op == UnOp::PtrMetadata {
let mut was_updated = false;
loop {
arg_index =
match self.get(arg_index) {
Value::Cast { kind: CastKind::PtrToPtr, value: inner } if
self.pointers_have_same_metadata(self.ty(inner), arg_ty) =>
{
inner
}
Value::Cast {
kind: CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize,
_),
value: from } if
let Some(from) = self.ty(from).builtin_deref(true) &&
let ty::Array(_, len) = from.kind() &&
let Some(to) = self.ty(arg_index).builtin_deref(true) &&
let ty::Slice(..) = to.kind() => {
return Some(self.insert_constant(Const::Ty(self.tcx.types.usize,
*len)));
}
Value::Address {
base: AddressBase::Deref(reborrowed), projection, .. } if
projection.is_empty() => {
reborrowed
}
_ => break,
};
was_updated = true;
}
if was_updated &&
let Some(op) = self.try_as_operand(arg_index, location) {
*arg_op = op;
}
}
let value =
match (op, self.get(arg_index)) {
(UnOp::Not, Value::UnaryOp(UnOp::Not, inner)) =>
return Some(inner),
(UnOp::Neg, Value::UnaryOp(UnOp::Neg, inner)) =>
return Some(inner),
(UnOp::Not, Value::BinaryOp(BinOp::Eq, lhs, rhs)) => {
Value::BinaryOp(BinOp::Ne, lhs, rhs)
}
(UnOp::Not, Value::BinaryOp(BinOp::Ne, lhs, rhs)) => {
Value::BinaryOp(BinOp::Eq, lhs, rhs)
}
(UnOp::PtrMetadata, Value::RawPtr { metadata, .. }) =>
return Some(metadata),
(UnOp::PtrMetadata, Value::Cast {
kind: CastKind::PointerCoercion(ty::adjustment::PointerCoercion::Unsize,
_),
value: inner }) if
let ty::Slice(..) =
arg_ty.builtin_deref(true).unwrap().kind() &&
let ty::Array(_, len) =
self.ty(inner).builtin_deref(true).unwrap().kind() => {
return Some(self.insert_constant(Const::Ty(self.tcx.types.usize,
*len)));
}
_ => Value::UnaryOp(op, arg_index),
};
Some(self.insert(ret_ty, value))
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs:1296",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(1296u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn simplify_binary(&mut self, op: BinOp,
lhs_operand: &mut Operand<'tcx>, rhs_operand: &mut Operand<'tcx>,
location: Location) -> Option<VnIndex> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("simplify_binary",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(1383u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("op")
}> =
::tracing::__macro_support::FieldName::new("op");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("lhs_operand")
}> =
::tracing::__macro_support::FieldName::new("lhs_operand");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("rhs_operand")
}> =
::tracing::__macro_support::FieldName::new("rhs_operand");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("location")
}> =
::tracing::__macro_support::FieldName::new("location");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&op)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&lhs_operand)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&rhs_operand)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&location)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Option<VnIndex> = loop {};
return __tracing_attr_fake_return;
}
{
let lhs = self.simplify_operand(lhs_operand, location);
let rhs = self.simplify_operand(rhs_operand, location);
let mut lhs = lhs?;
let mut rhs = rhs?;
let lhs_ty = self.ty(lhs);
if let BinOp::Eq | BinOp::Ne | BinOp::Lt | BinOp::Le |
BinOp::Gt | BinOp::Ge = op && lhs_ty.is_any_ptr() &&
let Value::Cast { kind: CastKind::PtrToPtr, value: lhs_value
} = self.get(lhs) &&
let Value::Cast { kind: CastKind::PtrToPtr, value: rhs_value
} = self.get(rhs) && let lhs_from = self.ty(lhs_value) &&
lhs_from == self.ty(rhs_value) &&
self.pointers_have_same_metadata(lhs_from, lhs_ty) {
lhs = lhs_value;
rhs = rhs_value;
if let Some(lhs_op) = self.try_as_operand(lhs, location) &&
let Some(rhs_op) = self.try_as_operand(rhs, location) {
*lhs_operand = lhs_op;
*rhs_operand = rhs_op;
}
}
if let Some(value) =
self.simplify_binary_inner(op, lhs_ty, lhs, rhs) {
return Some(value);
}
let ty = op.ty(self.tcx, lhs_ty, self.ty(rhs));
let value = Value::BinaryOp(op, lhs, rhs);
Some(self.insert(ty, value))
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs:1383",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(1383u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn simplify_binary_inner(&mut self, op: BinOp, lhs_ty: Ty<'tcx>,
lhs: VnIndex, rhs: VnIndex) -> Option<VnIndex> {
let reasonable_ty =
lhs_ty.is_integral() || lhs_ty.is_bool() || lhs_ty.is_char()
|| lhs_ty.is_any_ptr();
if !reasonable_ty { return None; }
let layout = self.ecx.layout_of(lhs_ty).ok()?;
let mut as_bits =
|value: VnIndex|
{
let constant = self.eval_to_const(value)?;
if layout.backend_repr.is_scalar() {
let scalar = self.ecx.read_scalar(constant).discard_err()?;
scalar.to_bits(constant.layout.size).discard_err()
} else { None }
};
use Either::{Left, Right};
let a = as_bits(lhs).map_or(Right(lhs), Left);
let b = as_bits(rhs).map_or(Right(rhs), Left);
let result =
match (op, a, b) {
(BinOp::Add | BinOp::AddWithOverflow | BinOp::AddUnchecked |
BinOp::BitOr | BinOp::BitXor, Left(0), Right(p)) |
(BinOp::Add | BinOp::AddWithOverflow | BinOp::AddUnchecked |
BinOp::BitOr | BinOp::BitXor | BinOp::Sub |
BinOp::SubWithOverflow | BinOp::SubUnchecked | BinOp::Offset
| BinOp::Shl | BinOp::Shr, Right(p), Left(0)) |
(BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked,
Left(1), Right(p)) |
(BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked |
BinOp::Div, Right(p), Left(1)) => p,
(BinOp::BitAnd, Right(p), Left(ones)) |
(BinOp::BitAnd, Left(ones), Right(p)) if
ones == layout.size.truncate(u128::MAX) ||
(layout.ty.is_bool() && ones == 1) => {
p
}
(BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked |
BinOp::BitAnd, _, Left(0)) | (BinOp::Rem, _, Left(1)) |
(BinOp::Mul | BinOp::MulWithOverflow | BinOp::MulUnchecked |
BinOp::Div | BinOp::Rem | BinOp::BitAnd | BinOp::Shl |
BinOp::Shr, Left(0), _) =>
self.insert_scalar(lhs_ty,
Scalar::from_uint(0u128, layout.size)),
(BinOp::BitOr, _, Left(ones)) |
(BinOp::BitOr, Left(ones), _) if
ones == layout.size.truncate(u128::MAX) ||
(layout.ty.is_bool() && ones == 1) => {
self.insert_scalar(lhs_ty,
Scalar::from_uint(ones, layout.size))
}
(BinOp::Sub | BinOp::SubWithOverflow | BinOp::SubUnchecked |
BinOp::BitXor, a, b) if a == b => {
self.insert_scalar(lhs_ty,
Scalar::from_uint(0u128, layout.size))
}
(BinOp::Eq, Left(a), Left(b)) => self.insert_bool(a == b),
(BinOp::Eq, a, b) if a == b => self.insert_bool(true),
(BinOp::Ne, Left(a), Left(b)) => self.insert_bool(a != b),
(BinOp::Ne, a, b) if a == b => self.insert_bool(false),
_ => return None,
};
if op.is_overflowing() {
let ty =
Ty::new_tup(self.tcx,
&[self.ty(result), self.tcx.types.bool]);
let false_val = self.insert_bool(false);
Some(self.insert_tuple(ty, &[result, false_val]))
} else { Some(result) }
}
fn simplify_cast(&mut self, initial_kind: &mut CastKind,
initial_operand: &mut Operand<'tcx>, to: Ty<'tcx>,
location: Location) -> Option<VnIndex> {
use CastKind::*;
use rustc_middle::ty::adjustment::PointerCoercion::*;
let mut kind = *initial_kind;
let mut value = self.simplify_operand(initial_operand, location)?;
let mut from = self.ty(value);
if from == to { return Some(value); }
if let CastKind::PointerCoercion(ReifyFnPointer(_) |
ClosureFnPointer(_), _) = kind {
return Some(self.new_opaque(to));
}
let mut was_ever_updated = false;
loop {
let mut was_updated_this_iteration = false;
if let Transmute = kind && from.is_raw_ptr() &&
to.is_raw_ptr() &&
self.pointers_have_same_metadata(from, to) {
kind = PtrToPtr;
was_updated_this_iteration = true;
}
if let PtrToPtr = kind &&
let Value::RawPtr { pointer, .. } = self.get(value) &&
let ty::RawPtr(to_pointee, _) = to.kind() &&
to_pointee.is_sized(self.tcx, self.typing_env()) {
from = self.ty(pointer);
value = pointer;
was_updated_this_iteration = true;
if from == to { return Some(pointer); }
}
if let Transmute = kind &&
let Value::Aggregate(variant_idx, field_values) =
self.get(value) &&
let Some((field_idx, field_ty)) =
self.value_is_all_in_one_field(from, variant_idx) {
from = field_ty;
value = field_values[field_idx.as_usize()];
was_updated_this_iteration = true;
if field_ty == to { return Some(value); }
}
if let Value::Cast { kind: inner_kind, value: inner_value } =
self.get(value) {
let inner_from = self.ty(inner_value);
let new_kind =
match (inner_kind, kind) {
(PtrToPtr, PtrToPtr) => Some(PtrToPtr),
(PtrToPtr, Transmute) if
self.pointers_have_same_metadata(inner_from, from) => {
Some(Transmute)
}
(Transmute, PtrToPtr) if
self.pointers_have_same_metadata(from, to) => {
Some(Transmute)
}
(Transmute, Transmute) if
!self.transmute_may_have_niche_of_interest_to_backend(inner_from,
from, to) => {
Some(Transmute)
}
_ => None,
};
if let Some(new_kind) = new_kind {
kind = new_kind;
from = inner_from;
value = inner_value;
was_updated_this_iteration = true;
if inner_from == to { return Some(inner_value); }
}
}
if was_updated_this_iteration {
was_ever_updated = true;
} else { break; }
}
if was_ever_updated &&
let Some(op) = self.try_as_operand(value, location) {
*initial_operand = op;
*initial_kind = kind;
}
Some(self.insert(to, Value::Cast { kind, value }))
}
fn pointers_have_same_metadata(&self, left_ptr_ty: Ty<'tcx>,
right_ptr_ty: Ty<'tcx>) -> bool {
let left_meta_ty =
left_ptr_ty.pointee_metadata_ty_or_projection(self.tcx);
let right_meta_ty =
right_ptr_ty.pointee_metadata_ty_or_projection(self.tcx);
if left_meta_ty == right_meta_ty {
true
} else if let Ok(left) =
self.tcx.try_normalize_erasing_regions(self.typing_env(),
Unnormalized::new_wip(left_meta_ty)) &&
let Ok(right) =
self.tcx.try_normalize_erasing_regions(self.typing_env(),
Unnormalized::new_wip(right_meta_ty)) {
left == right
} else { false }
}
fn ty_may_have_ref(&self, ty: Ty<'tcx>) -> bool {
fn ty_may_have_ref_inner<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>,
depth: usize) -> bool {
if !tcx.recursion_limit().value_within_limit(depth) {
return true;
}
let depth = depth + 1;
match ty.kind() {
ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Bool |
ty::Char | ty::Str | ty::Never | ty::FnDef(..) |
ty::Error(_) | ty::FnPtr(..) => false,
ty::Tuple(fields) => {
fields.iter().any(|field|
ty_may_have_ref_inner(tcx, field, depth))
}
ty::Pat(ty, _) | ty::Slice(ty) | ty::Array(ty, _) => {
ty_may_have_ref_inner(tcx, *ty, depth)
}
ty::Adt(adt_def, args) => {
adt_def.has_param() || adt_def.has_aliases() ||
adt_def.all_fields().any(|field|
{
ty_may_have_ref_inner(tcx,
field.ty(tcx, args).skip_normalization(), depth)
})
}
ty::Ref(..) | ty::RawPtr(_, _) | ty::Bound(..) |
ty::Closure(..) | ty::CoroutineClosure(..) | ty::Dynamic(..)
| ty::Foreign(_) | ty::Coroutine(..) |
ty::CoroutineWitness(..) | ty::UnsafeBinder(_) |
ty::Infer(_) | ty::Alias(..) | ty::Param(_) |
ty::Placeholder(_) => true,
}
}
ty_may_have_ref_inner(self.tcx, ty, 0)
}
fn transmute_may_have_niche_of_interest_to_backend(&self,
from_ty: Ty<'tcx>, middle_ty: Ty<'tcx>, to_ty: Ty<'tcx>) -> bool {
let Ok(middle_layout) =
self.ecx.layout_of(middle_ty) else { return true; };
if middle_layout.uninhabited { return true; }
match middle_layout.backend_repr {
BackendRepr::Scalar(mid) => {
if mid.is_always_valid(&self.ecx) {
false
} else if let Ok(from_layout) = self.ecx.layout_of(from_ty)
&& !from_layout.uninhabited &&
from_layout.size == middle_layout.size &&
let BackendRepr::Scalar(from_a) = from_layout.backend_repr
&& let mid_range = mid.valid_range(&self.ecx) &&
let from_range = from_a.valid_range(&self.ecx) &&
mid_range.contains_range(from_range, middle_layout.size) {
false
} else if let Ok(to_layout) = self.ecx.layout_of(to_ty) &&
!to_layout.uninhabited &&
to_layout.size == middle_layout.size &&
let BackendRepr::Scalar(to_a) = to_layout.backend_repr &&
let mid_range = mid.valid_range(&self.ecx) &&
let to_range = to_a.valid_range(&self.ecx) &&
mid_range.contains_range(to_range, middle_layout.size) {
false
} else { true }
}
BackendRepr::ScalarPair { a, b, b_offset: _ } => {
!a.is_always_valid(&self.ecx) ||
!b.is_always_valid(&self.ecx)
}
BackendRepr::SimdVector { .. } |
BackendRepr::SimdScalableVector { .. } |
BackendRepr::Memory { .. } => false,
}
}
fn value_is_all_in_one_field(&self, ty: Ty<'tcx>, variant: VariantIdx)
-> Option<(FieldIdx, Ty<'tcx>)> {
if let Ok(layout) = self.ecx.layout_of(ty) &&
let abi::Variants::Single { index } = layout.variants &&
index == variant &&
let Some((field_idx, field_layout)) =
layout.non_1zst_field(&self.ecx) &&
layout.size == field_layout.size {
Some((field_idx, field_layout.ty))
} else if let ty::Adt(adt, args) = ty.kind() && adt.is_struct() &&
adt.repr().transparent() &&
let [single_field] =
adt.non_enum_variant().fields.raw.as_slice() {
Some((FieldIdx::ZERO,
single_field.ty(self.tcx, args).skip_norm_wip()))
} else { None }
}
}
fn is_deterministic(c: Const<'_>) -> bool {
if c.ty().is_primitive() { return true; }
match c {
Const::Ty(..) => false,
Const::Unevaluated(..) => false,
Const::Val(..) => true,
}
}
fn may_have_provenance(tcx: TyCtxt<'_>, value: ConstValue, size: Size)
-> bool {
match value {
ConstValue::ZeroSized | ConstValue::Scalar(Scalar::Int(_)) =>
return false,
ConstValue::Scalar(Scalar::Ptr(..)) | ConstValue::Slice { .. } =>
return true,
ConstValue::Indirect { alloc_id, offset } =>
!tcx.global_alloc(alloc_id).unwrap_memory().inner().provenance().range_empty(AllocRange::from(offset..offset
+ size), &tcx),
}
}
fn op_to_prop_const<'tcx>(ecx: &mut InterpCx<'tcx, DummyMachine>,
op: &OpTy<'tcx>) -> Option<ConstValue> {
if op.layout.is_unsized() { return None; }
if op.layout.is_zst() { return Some(ConstValue::ZeroSized); }
if !op.is_immediate_uninit() &&
!#[allow(non_exhaustive_omitted_patterns)] match op.layout.backend_repr
{
BackendRepr::Scalar(..) | BackendRepr::ScalarPair { .. } =>
true,
_ => false,
} {
return None;
}
if let BackendRepr::Scalar(abi::Scalar::Initialized { .. }) =
op.layout.backend_repr &&
let Some(scalar) = ecx.read_scalar(op).discard_err() {
if !scalar.try_to_scalar_int().is_ok() { return None; }
return Some(ConstValue::Scalar(scalar));
}
if let Either::Left(mplace) = op.as_mplace_or_imm() {
let (size, _align) =
ecx.size_and_align_of_val(&mplace).discard_err()??;
let alloc_ref =
ecx.get_ptr_alloc(mplace.ptr(), size).discard_err()??;
if alloc_ref.has_provenance() { return None; }
let pointer = mplace.ptr().into_pointer_or_addr().ok()?;
let (prov, offset) = pointer.prov_and_relative_offset();
let alloc_id = prov.alloc_id();
intern_const_alloc_for_constprop(ecx, alloc_id).discard_err()?;
if let GlobalAlloc::Memory(alloc) = ecx.tcx.global_alloc(alloc_id)
&& alloc.inner().align >= op.layout.align.abi {
return Some(ConstValue::Indirect { alloc_id, offset });
}
}
let alloc_id =
ecx.intern_with_temp_alloc(op.layout,
|ecx, dest| ecx.copy_op(op, dest)).discard_err()?;
Some(ConstValue::Indirect { alloc_id, offset: Size::ZERO })
}
impl<'tcx> VnState<'_, '_, 'tcx> {
fn try_as_operand(&mut self, index: VnIndex, location: Location)
-> Option<Operand<'tcx>> {
if let Some(const_) = self.try_as_constant(index) {
Some(Operand::Constant(Box::new(const_)))
} else if let Value::RuntimeChecks(c) = self.get(index) {
Some(Operand::RuntimeChecks(c))
} else if let Some(place) =
self.try_as_place(index, location, false) {
self.reused_locals.insert(place.local);
Some(Operand::Copy(place))
} else { None }
}
fn try_as_constant(&mut self, index: VnIndex)
-> Option<ConstOperand<'tcx>> {
let value = self.get(index);
if let Value::Constant { value, disambiguator: None } = value &&
let Const::Val(..) = value {
return Some(ConstOperand {
span: DUMMY_SP,
user_ty: None,
const_: value,
});
}
if let Some(value) = self.try_as_evaluated_constant(index) {
return Some(ConstOperand {
span: DUMMY_SP,
user_ty: None,
const_: value,
});
}
if let Value::Constant { value, disambiguator: None } = value {
return Some(ConstOperand {
span: DUMMY_SP,
user_ty: None,
const_: value,
});
}
None
}
fn try_as_evaluated_constant(&mut self, index: VnIndex)
-> Option<Const<'tcx>> {
let op = self.eval_to_const(index)?;
if op.layout.is_unsized() { return None; }
let value = op_to_prop_const(&mut self.ecx, op)?;
if may_have_provenance(self.tcx, value, op.layout.size) {
return None;
}
Some(Const::Val(value, op.layout.ty))
}
#[doc =
" Construct a place which holds the same value as `index` and for which all locals strictly"]
#[doc =
" dominate `loc`. If you used this place, add its base local to `reused_locals` to remove"]
#[doc = " storage statements."]
fn try_as_place(&mut self, mut index: VnIndex, loc: Location,
allow_complex_projection: bool) -> Option<Place<'tcx>> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("try_as_place",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(2027u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("index")
}> =
::tracing::__macro_support::FieldName::new("index");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("loc")
}> =
::tracing::__macro_support::FieldName::new("loc");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("allow_complex_projection")
}> =
::tracing::__macro_support::FieldName::new("allow_complex_projection");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&index)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&loc)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&allow_complex_projection
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Option<Place<'tcx>> =
loop {};
return __tracing_attr_fake_return;
}
{
let mut projection =
SmallVec::<[PlaceElem<'tcx>; 1]>::new();
loop {
if let Some(local) = self.try_as_local(index, loc) {
projection.reverse();
let place =
Place {
local,
projection: self.tcx.mk_place_elems(projection.as_slice()),
};
return Some(place);
} else if projection.last() == Some(&PlaceElem::Deref) {
return None;
} else if let Value::Projection(pointer, proj) =
self.get(index) &&
(allow_complex_projection || proj.is_stable_offset()) &&
let Some(proj) =
self.try_as_place_elem(self.ty(index), proj, loc) {
if proj == PlaceElem::Deref {
match self.get(pointer) {
Value::Argument(_) if
let Some(Mutability::Not) =
self.ty(pointer).ref_mutability() => {}
_ => { return None; }
}
}
projection.push(proj);
index = pointer;
} else { return None; }
}
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs:2027",
"rustc_mir_transform::gvn", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(2027u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn try_as_local(&mut self, index: VnIndex, loc: Location)
-> Option<Local> {
let other = self.rev_locals.get(index)?;
other.iter().find(|&&other|
self.ssa.assignment_dominates(&self.dominators, other,
loc)).copied()
}
}
impl<'tcx> MutVisitor<'tcx> for VnState<'_, '_, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_place(&mut self, place: &mut Place<'tcx>,
context: PlaceContext, location: Location) {
self.simplify_place_projection(place, location);
self.super_place(place, context, location);
}
fn visit_operand(&mut self, operand: &mut Operand<'tcx>,
location: Location) {
self.simplify_operand(operand, location);
self.super_operand(operand, location);
}
fn visit_assign(&mut self, lhs: &mut Place<'tcx>,
rvalue: &mut Rvalue<'tcx>, location: Location) {
self.simplify_place_projection(lhs, location);
let value = self.simplify_rvalue(lhs, rvalue, location);
if let Some(value) = value {
if let Some(const_) = self.try_as_constant(value) {
*rvalue =
Rvalue::Use(Operand::Constant(Box::new(const_)),
WithRetag::Yes);
} else if let Some(place) =
self.try_as_place(value, location, false) &&
!#[allow(non_exhaustive_omitted_patterns)] match rvalue {
Rvalue::Use(Operand::Move(p) | Operand::Copy(p), _) if
p == &place => true,
_ => false,
} {
*rvalue = Rvalue::Use(Operand::Copy(place), WithRetag::Yes);
self.reused_locals.insert(place.local);
}
}
if let Some(local) = lhs.as_local() && self.ssa.is_ssa(local) &&
let rvalue_ty = rvalue.ty(self.local_decls, self.tcx) &&
self.local_decls[local].ty == rvalue_ty {
let value =
value.unwrap_or_else(|| self.new_opaque(rvalue_ty));
self.assign(local, value);
}
}
fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>,
location: Location) {
if let Terminator {
kind: TerminatorKind::Call { destination, .. }, .. } =
terminator {
if let Some(local) = destination.as_local() &&
self.ssa.is_ssa(local) {
let ty = self.local_decls[local].ty;
let opaque = self.new_opaque(ty);
self.assign(local, opaque);
}
}
self.super_terminator(terminator, location);
}
}
struct StorageRemover<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
reused_locals: &'a DenseBitSet<Local>,
storage_to_remove: &'a DenseBitSet<Local>,
}
impl<'a, 'tcx> MutVisitor<'tcx> for StorageRemover<'a, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_operand(&mut self, operand: &mut Operand<'tcx>,
_: Location) {
if let Operand::Move(place) = *operand &&
!place.is_indirect_first_projection() &&
self.reused_locals.contains(place.local) {
*operand = Operand::Copy(place);
}
}
fn visit_statement(&mut self, stmt: &mut Statement<'tcx>,
loc: Location) {
match stmt.kind {
StatementKind::StorageLive(l) | StatementKind::StorageDead(l)
if self.storage_to_remove.contains(l) => {
stmt.make_nop(true)
}
_ => self.super_statement(stmt, loc),
}
}
}
struct StorageChecker<'a, 'tcx> {
reused_locals: &'a DenseBitSet<Local>,
storage_to_remove: DenseBitSet<Local>,
maybe_uninit: ResultsCursor<'a, 'tcx, MaybeUninitializedLocals>,
}
impl<'a, 'tcx> Visitor<'tcx> for StorageChecker<'a, 'tcx> {
fn visit_local(&mut self, local: Local, context: PlaceContext,
location: Location) {
match context {
PlaceContext::MutatingUse(MutatingUseContext::AsmOutput) |
PlaceContext::MutatingUse(MutatingUseContext::Call) |
PlaceContext::MutatingUse(MutatingUseContext::Store) |
PlaceContext::MutatingUse(MutatingUseContext::Yield) |
PlaceContext::NonUse(_) => {
return;
}
PlaceContext::MutatingUse(_) | PlaceContext::NonMutatingUse(_)
=> {}
}
if !self.reused_locals.contains(local) ||
self.storage_to_remove.contains(local) {
return;
}
self.maybe_uninit.seek_before_primary_effect(location);
if self.maybe_uninit.get().contains(local) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs:2207",
"rustc_mir_transform::gvn", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/gvn.rs"),
::tracing_core::__macro_support::Option::Some(2207u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::gvn"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("location")
}> =
::tracing::__macro_support::FieldName::new("location");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("local")
}> =
::tracing::__macro_support::FieldName::new("local");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("local is reused and is maybe uninit at this location, marking it for storage statement removal")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&location)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&local)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
self.storage_to_remove.insert(local);
}
}
}
}
#[allow(unused_imports)]
use gvn::GVN as _;
pub mod inline {
use std::ops::{Range, RangeFrom};
use std::{debug_assert_matches, iter};
use rustc_abi::{ExternAbi, FieldIdx};
use rustc_data_structures::thin_vec::ThinVec;
use rustc_hir::attrs::lang_items::LangItem;
use rustc_hir::attrs::{InlineAttr, OptimizeAttr};
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_index::Idx;
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::bug;
use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs;
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
use rustc_middle::ty::{
self, Instance, InstanceKind, ShimKind, Ty, TyCtxt, TypeFlags,
TypeVisitableExt, Unnormalized,
};
use rustc_session::config::{DebugInfo, OptLevel};
use rustc_span::Spanned;
use tracing::{debug, instrument, trace, trace_span};
use crate::cost_checker::{CostChecker, is_call_like};
use crate::simplify::{UsedInStmtLocals, simplify_cfg};
use crate::validate::validate_types;
use crate::{PassPolicy, check_inline, util};
pub(crate) mod cycle {
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_data_structures::unord::UnordSet;
use rustc_hir::def_id::{DefId, LocalDefId};
use rustc_middle::mir::TerminatorKind;
use rustc_middle::ty::{
self, GenericArgsRef, InstanceKind, ShimKind, TyCtxt,
TypeVisitableExt,
};
use rustc_span::sym;
use rustc_structures::Limit;
use tracing::{instrument, trace};
fn should_recurse<'tcx>(tcx: TyCtxt<'tcx>, callee: ty::Instance<'tcx>)
-> bool {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("should_recurse",
"rustc_mir_transform::inline::cycle",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs"),
::tracing_core::__macro_support::Option::Some(10u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline::cycle"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("callee")
}> =
::tracing::__macro_support::FieldName::new("callee");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&callee)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: bool = loop {};
return __tracing_attr_fake_return;
}
{
match callee.def {
InstanceKind::Item(_) => {
if !tcx.is_mir_available(callee.def_id()) { return false; }
}
InstanceKind::Intrinsic(_) | InstanceKind::LlvmIntrinsic(_)
| InstanceKind::Virtual(..) => {
return false;
}
InstanceKind::Shim(ShimKind::VTable(_)) |
InstanceKind::Shim(ShimKind::Reify(..)) |
InstanceKind::Shim(ShimKind::FnPtr(..)) |
InstanceKind::Shim(ShimKind::ClosureOnce { .. }) |
InstanceKind::Shim(ShimKind::ConstructCoroutineInClosure {
.. }) | InstanceKind::Shim(ShimKind::ThreadLocal { .. }) |
InstanceKind::Shim(ShimKind::Clone(..)) => {}
InstanceKind::Shim(ShimKind::FnPtrAsPtr(..) |
ShimKind::FnPtrFromPtr(..)) => return false,
InstanceKind::Shim(ShimKind::DropGlue(..)) |
InstanceKind::Shim(ShimKind::FutureDropPoll(..)) |
InstanceKind::Shim(ShimKind::AsyncDropGlue(..)) |
InstanceKind::Shim(ShimKind::AsyncDropGlueCtor(..)) => {
if callee.has_param() { return false; }
}
}
crate::pm::should_run_pass(&crate::inline::Inline,
&crate::pm::PassCtx::for_body(tcx, callee.def_id())) ||
crate::inline::ForceInline::should_run_pass_for_callee(tcx,
callee.def.def_id())
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs:10",
"rustc_mir_transform::inline::cycle",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs"),
::tracing_core::__macro_support::Option::Some(10u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline::cycle"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn process<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>,
caller: ty::Instance<'tcx>, target: LocalDefId,
seen: &mut FxHashMap<ty::Instance<'tcx>, bool>,
involved: &mut FxHashSet<LocalDefId>,
recursion_limiter: &mut FxHashMap<DefId, usize>,
recursion_limit: Limit) -> Option<bool> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("process",
"rustc_mir_transform::inline::cycle",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs"),
::tracing_core::__macro_support::Option::Some(60u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline::cycle"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("caller")
}> =
::tracing::__macro_support::FieldName::new("caller");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("target")
}> =
::tracing::__macro_support::FieldName::new("target");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&caller)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Option<bool> = loop {};
return __tracing_attr_fake_return;
}
{
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs:75",
"rustc_mir_transform::inline::cycle",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs"),
::tracing_core::__macro_support::Option::Some(75u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline::cycle"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("caller")
}> =
::tracing::__macro_support::FieldName::new("caller");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::display(&caller)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let mut reaches_root = false;
for &(callee_def_id, args) in
tcx.mir_inliner_callees(caller.def) {
let Ok(args) =
caller.try_instantiate_mir_and_normalize_erasing_regions(tcx,
typing_env,
ty::EarlyBinder::bind(tcx,
args)) else {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs:84",
"rustc_mir_transform::inline::cycle",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs"),
::tracing_core::__macro_support::Option::Some(84u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline::cycle"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("caller")
}> =
::tracing::__macro_support::FieldName::new("caller");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("typing_env")
}> =
::tracing::__macro_support::FieldName::new("typing_env");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("args")
}> =
::tracing::__macro_support::FieldName::new("args");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("cannot normalize, skipping")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&caller)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&typing_env)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&args)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
continue;
};
let Ok(Some(callee)) =
ty::Instance::try_resolve(tcx, typing_env, callee_def_id,
args) else {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs:89",
"rustc_mir_transform::inline::cycle",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs"),
::tracing_core::__macro_support::Option::Some(89u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline::cycle"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("callee_def_id")
}> =
::tracing::__macro_support::FieldName::new("callee_def_id");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("cannot resolve, skipping")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&callee_def_id)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
continue;
};
if callee.def_id() == target.to_def_id() {
reaches_root = true;
seen.insert(callee, true);
continue;
}
if tcx.is_constructor(callee.def_id()) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs:101",
"rustc_mir_transform::inline::cycle",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs"),
::tracing_core::__macro_support::Option::Some(101u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline::cycle"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("constructors always have MIR")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
continue;
}
if !should_recurse(tcx, callee) { continue; }
let callee_reaches_root =
if let Some(&c) = seen.get(&callee) {
c
} else {
seen.insert(callee, false);
let recursion =
recursion_limiter.entry(callee.def_id()).or_default();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs:119",
"rustc_mir_transform::inline::cycle",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs"),
::tracing_core::__macro_support::Option::Some(119u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline::cycle"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("callee")
}> =
::tracing::__macro_support::FieldName::new("callee");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("recursion")
}> =
::tracing::__macro_support::FieldName::new("recursion");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&callee)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&*recursion as
&dyn ::tracing::field::Value))])
});
} else { ; }
};
let callee_reaches_root =
if recursion_limit.value_within_limit(*recursion) {
*recursion += 1;
process(tcx, typing_env, callee, target, seen, involved,
recursion_limiter, recursion_limit)?
} else { return None; };
seen.insert(callee, callee_reaches_root);
callee_reaches_root
};
if callee_reaches_root {
if let Some(callee_def_id) = callee.def_id().as_local() {
involved.insert(callee_def_id);
}
reaches_root = true;
}
}
Some(reaches_root)
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs:60",
"rustc_mir_transform::inline::cycle",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs"),
::tracing_core::__macro_support::Option::Some(60u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline::cycle"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
pub(crate) fn mir_callgraph_cyclic<'tcx>(tcx: TyCtxt<'tcx>,
root: LocalDefId) -> Option<&'tcx UnordSet<LocalDefId>> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("mir_callgraph_cyclic",
"rustc_mir_transform::inline::cycle",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs"),
::tracing_core::__macro_support::Option::Some(151u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline::cycle"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("root")
}> =
::tracing::__macro_support::FieldName::new("root");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&root)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<&'tcx UnordSet<LocalDefId>> = loop {};
return __tracing_attr_fake_return;
}
{
if !!tcx.is_constructor(root.to_def_id()) {
{
::core::panicking::panic_fmt(format_args!("you should not call `mir_callgraph_reachable` on enum/struct constructor functions"));
}
};
let recursion_limit = tcx.recursion_limit() / 8;
let mut involved = FxHashSet::default();
let typing_env = ty::TypingEnv::post_analysis(tcx, root);
let root_instance =
ty::Instance::new_raw(root.to_def_id(),
ty::GenericArgs::identity_for_item(tcx, root));
if !should_recurse(tcx, root_instance) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs:174",
"rustc_mir_transform::inline::cycle",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs"),
::tracing_core::__macro_support::Option::Some(174u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline::cycle"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("cannot walk, skipping")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return Some(tcx.arena.alloc(involved.into()));
}
match process(tcx, typing_env, root_instance, root,
&mut FxHashMap::default(), &mut involved,
&mut FxHashMap::default(), recursion_limit) {
Some(_) => Some(tcx.arena.alloc(involved.into())),
_ => None,
}
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs:151",
"rustc_mir_transform::inline::cycle",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline/cycle.rs"),
::tracing_core::__macro_support::Option::Some(151u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline::cycle"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
pub(crate) fn mir_inliner_callees<'tcx>(tcx: TyCtxt<'tcx>,
instance: ty::InstanceKind<'tcx>)
-> &'tcx [(DefId, GenericArgsRef<'tcx>)] {
let steal;
let guard;
let body =
match (instance, instance.def_id().as_local()) {
(InstanceKind::Item(_), Some(def_id)) => {
steal = tcx.mir_promoted(def_id).0;
guard = steal.borrow();
&*guard
}
_ => tcx.instance_mir(instance),
};
let mut calls = FxIndexSet::default();
for bb_data in body.basic_blocks.iter() {
let terminator = bb_data.terminator();
if let TerminatorKind::Call { func, args: call_args, .. } =
&terminator.kind {
let ty = func.ty(&body.local_decls, tcx);
let ty::FnDef(def_id, generic_args) =
ty.kind() else { continue; };
let call =
if tcx.is_intrinsic(*def_id, sym::const_eval_select) {
let func = &call_args[2].node;
let ty = func.ty(&body.local_decls, tcx);
let ty::FnDef(def_id, generic_args) =
ty.kind() else { continue; };
(*def_id, *generic_args)
} else { (*def_id, *generic_args) };
calls.insert(call);
}
}
tcx.arena.alloc_from_iter(calls.iter().map(|(did, args)|
(*did, args.no_bound_vars().unwrap())))
}
}
const HISTORY_DEPTH_LIMIT: usize = 20;
const TOP_DOWN_DEPTH_LIMIT: usize = 5;
struct CallSite<'tcx> {
callee: Instance<'tcx>,
fn_sig: ty::PolyFnSig<'tcx>,
block: BasicBlock,
source_info: SourceInfo,
}
#[automatically_derived]
impl<'tcx> ::core::clone::Clone for CallSite<'tcx> {
#[inline]
fn clone(&self) -> CallSite<'tcx> {
CallSite {
callee: ::core::clone::Clone::clone(&self.callee),
fn_sig: ::core::clone::Clone::clone(&self.fn_sig),
block: ::core::clone::Clone::clone(&self.block),
source_info: ::core::clone::Clone::clone(&self.source_info),
}
}
}
#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for CallSite<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field4_finish(f, "CallSite",
"callee", &self.callee, "fn_sig", &self.fn_sig, "block",
&self.block, "source_info", &&self.source_info)
}
}
pub struct Inline;
impl<'tcx> crate::MirPass<'tcx> for Inline {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
match ctx.opts.unstable_opts.inline_mir {
Some(enabled) => PassPolicy::optional(enabled),
None =>
PassPolicy::optional(match ctx.mir_opt_level() {
0 | 1 => false,
2 => {
(ctx.opts.optimize == OptLevel::More ||
ctx.opts.optimize == OptLevel::Aggressive) &&
ctx.opts.incremental.is_none()
}
_ => true,
}),
}
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("inline",
"rustc_mir_transform::inline", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(67u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("body")
}> =
::tracing::__macro_support::FieldName::new("body");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::display(&tcx.def_path_str(body.source.def_id()))
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
let _guard = span.enter();
if inline::<NormalInliner<'tcx>>(tcx, body) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:70",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(70u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("running simplify cfg on {0:?}",
body.source) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
simplify_cfg(tcx, body);
}
}
}
pub struct ForceInline;
impl ForceInline {
pub fn should_run_pass_for_callee<'tcx>(tcx: TyCtxt<'tcx>,
def_id: DefId) -> bool {
#[allow(non_exhaustive_omitted_patterns)]
match tcx.codegen_fn_attrs(def_id).inline {
InlineAttr::Force { .. } => true,
_ => false,
}
}
}
impl<'tcx> crate::MirPass<'tcx> for ForceInline {
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::Required
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("force_inline",
"rustc_mir_transform::inline", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(91u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("body")
}> =
::tracing::__macro_support::FieldName::new("body");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::display(&tcx.def_path_str(body.source.def_id()))
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
let _guard = span.enter();
if inline::<ForceInliner<'tcx>>(tcx, body) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:94",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(94u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("running simplify cfg on {0:?}",
body.source) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
simplify_cfg(tcx, body);
}
}
}
trait Inliner<'tcx> {
fn new(tcx: TyCtxt<'tcx>, def_id: DefId, body: &Body<'tcx>)
-> Self;
fn tcx(&self)
-> TyCtxt<'tcx>;
fn typing_env(&self)
-> ty::TypingEnv<'tcx>;
fn history(&self)
-> &[DefId];
fn caller_def_id(&self)
-> DefId;
fn changed(self)
-> bool;
fn should_inline_for_callee(&self, def_id: DefId)
-> bool;
fn check_codegen_attributes_extra(&self,
callee_attrs: &CodegenFnAttrs)
-> Result<(), &'static str>;
fn check_caller_mir_body(&self, body: &Body<'tcx>)
-> bool;
fn check_callee_mir_body(&self, callsite: &CallSite<'tcx>,
callee_body: &Body<'tcx>, callee_attrs: &CodegenFnAttrs)
-> Result<(), &'static str>;
fn on_inline_success(&mut self, callsite: &CallSite<'tcx>,
caller_body: &mut Body<'tcx>,
new_blocks: std::ops::Range<BasicBlock>);
fn on_inline_failure(&self, callsite: &CallSite<'tcx>,
reason: &'static str);
}
struct ForceInliner<'tcx> {
tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
def_id: DefId,
history: Vec<DefId>,
changed: bool,
}
impl<'tcx> Inliner<'tcx> for ForceInliner<'tcx> {
fn new(tcx: TyCtxt<'tcx>, def_id: DefId, body: &Body<'tcx>) -> Self {
Self {
tcx,
typing_env: body.typing_env(tcx),
def_id,
history: Vec::new(),
changed: false,
}
}
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn typing_env(&self) -> ty::TypingEnv<'tcx> { self.typing_env }
fn history(&self) -> &[DefId] { &self.history }
fn caller_def_id(&self) -> DefId { self.def_id }
fn changed(self) -> bool { self.changed }
fn should_inline_for_callee(&self, def_id: DefId) -> bool {
ForceInline::should_run_pass_for_callee(self.tcx(), def_id)
}
fn check_codegen_attributes_extra(&self,
callee_attrs: &CodegenFnAttrs) -> Result<(), &'static str> {
if true {
{
match callee_attrs.inline {
InlineAttr::Force { .. } => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"InlineAttr::Force { .. }", ::core::option::Option::None);
}
}
};
};
Ok(())
}
fn check_caller_mir_body(&self, _: &Body<'tcx>) -> bool { true }
fn check_callee_mir_body(&self, _: &CallSite<'tcx>,
callee_body: &Body<'tcx>, callee_attrs: &CodegenFnAttrs)
-> Result<(), &'static str> {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("check_callee_mir_body",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(198u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("callee_attrs")
}> =
::tracing::__macro_support::FieldName::new("callee_attrs");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&callee_attrs)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Result<(), &'static str> =
loop {};
return __tracing_attr_fake_return;
}
{
if callee_body.tainted_by_errors.is_some() {
return Err("body has errors");
}
let caller_attrs =
self.tcx().codegen_fn_attrs(self.caller_def_id());
if callee_attrs.instruction_set !=
caller_attrs.instruction_set &&
callee_body.basic_blocks.iter().any(|bb|
#[allow(non_exhaustive_omitted_patterns)] match bb.terminator().kind
{
TerminatorKind::InlineAsm { .. } => true,
_ => false,
}) {
Err("cannot move inline-asm across instruction sets")
} else { Ok(()) }
}
}
}
}
fn on_inline_success(&mut self, callsite: &CallSite<'tcx>,
caller_body: &mut Body<'tcx>,
new_blocks: std::ops::Range<BasicBlock>) {
self.changed = true;
self.history.push(callsite.callee.def_id());
process_blocks(self, caller_body, new_blocks);
self.history.pop();
}
fn on_inline_failure(&self, callsite: &CallSite<'tcx>,
reason: &'static str) {
let tcx = self.tcx();
let InlineAttr::Force { attr_span, reason: justification } =
tcx.codegen_instance_attrs(callsite.callee.def).inline else {
::rustc_middle::util::bug::bug_fmt(format_args!("called on item without required inlining"));
};
let call_span = callsite.source_info.span;
let callee = tcx.def_path_str(callsite.callee.def_id());
tcx.dcx().emit_err(crate::diagnostics::ForceInlineFailure {
call_span,
attr_span,
caller_span: tcx.def_span(self.def_id),
caller: tcx.def_path_str(self.def_id),
callee_span: tcx.def_span(callsite.callee.def_id()),
callee: callee.clone(),
reason,
justification: justification.map(|sym|
crate::diagnostics::ForceInlineJustification {
sym,
callee,
}),
});
}
}
struct NormalInliner<'tcx> {
tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
def_id: DefId,
history: Vec<DefId>,
top_down_counter: usize,
changed: bool,
caller_is_inline_forwarder: bool,
}
impl<'tcx> NormalInliner<'tcx> {
fn past_depth_limit(&self) -> bool {
self.history.len() > HISTORY_DEPTH_LIMIT ||
self.top_down_counter > TOP_DOWN_DEPTH_LIMIT
}
}
impl<'tcx> Inliner<'tcx> for NormalInliner<'tcx> {
fn new(tcx: TyCtxt<'tcx>, def_id: DefId, body: &Body<'tcx>) -> Self {
let typing_env = body.typing_env(tcx);
let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id);
Self {
tcx,
typing_env,
def_id,
history: Vec::new(),
top_down_counter: 0,
changed: false,
caller_is_inline_forwarder: #[allow(non_exhaustive_omitted_patterns)] match codegen_fn_attrs.inline
{
InlineAttr::Hint | InlineAttr::Always | InlineAttr::Force {
.. } => true,
_ => false,
} && body_is_forwarder(body),
}
}
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn caller_def_id(&self) -> DefId { self.def_id }
fn typing_env(&self) -> ty::TypingEnv<'tcx> { self.typing_env }
fn history(&self) -> &[DefId] { &self.history }
fn changed(self) -> bool { self.changed }
fn should_inline_for_callee(&self, _: DefId) -> bool { true }
fn check_codegen_attributes_extra(&self,
callee_attrs: &CodegenFnAttrs) -> Result<(), &'static str> {
if self.past_depth_limit() &&
#[allow(non_exhaustive_omitted_patterns)] match callee_attrs.inline
{
InlineAttr::None => true,
_ => false,
} {
Err("Past depth limit so not inspecting unmarked callee")
} else { Ok(()) }
}
fn check_caller_mir_body(&self, body: &Body<'tcx>) -> bool {
body.coroutine.is_none()
}
fn check_callee_mir_body(&self, callsite: &CallSite<'tcx>,
callee_body: &Body<'tcx>, callee_attrs: &CodegenFnAttrs)
-> Result<(), &'static str> {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("check_callee_mir_body",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(353u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("callsite")
}> =
::tracing::__macro_support::FieldName::new("callsite");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("callee_attrs")
}> =
::tracing::__macro_support::FieldName::new("callee_attrs");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&callsite)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&callee_attrs)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Result<(), &'static str> =
loop {};
return __tracing_attr_fake_return;
}
{
let tcx = self.tcx();
if let Some(_) = callee_body.tainted_by_errors {
return Err("body has errors");
}
if self.past_depth_limit() &&
callee_body.basic_blocks.len() > 1 {
return Err("Not inlining multi-block body as we're past a depth limit");
}
let mut threshold =
if self.caller_is_inline_forwarder ||
self.past_depth_limit() {
tcx.sess.opts.unstable_opts.inline_mir_forwarder_threshold.unwrap_or(30)
} else if tcx.cross_crate_inlinable(callsite.callee.def_id())
{
tcx.sess.opts.unstable_opts.inline_mir_hint_threshold.unwrap_or(100)
} else {
tcx.sess.opts.unstable_opts.inline_mir_threshold.unwrap_or(50)
};
if callee_body.basic_blocks.len() <= 3 {
threshold += threshold / 4;
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:384",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(384u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!(" final inline threshold = {0}",
threshold) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let mut checker =
CostChecker::new(tcx, self.typing_env(),
Some(callsite.callee), callee_body);
checker.add_function_level_costs();
let mut work_list =
::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[START_BLOCK]));
let mut visited =
DenseBitSet::new_empty(callee_body.basic_blocks.len());
while let Some(bb) = work_list.pop() {
if !visited.insert(bb.index()) { continue; }
let blk = &callee_body.basic_blocks[bb];
checker.visit_basic_block_data(bb, blk);
let term = blk.terminator();
let caller_attrs =
tcx.codegen_fn_attrs(self.caller_def_id());
if let TerminatorKind::Drop {
ref place, target, unwind, replace: _, drop: _ } = term.kind
{
work_list.push(target);
let ty =
callsite.callee.instantiate_mir(tcx,
ty::EarlyBinder::bind(tcx, place.ty(callee_body, tcx).ty));
if ty.needs_drop(tcx, self.typing_env()) &&
let UnwindAction::Cleanup(unwind) = unwind {
work_list.push(unwind);
}
} else if callee_attrs.instruction_set !=
caller_attrs.instruction_set &&
#[allow(non_exhaustive_omitted_patterns)] match term.kind {
TerminatorKind::InlineAsm { .. } => true,
_ => false,
} {
return Err("cannot move inline-asm across instruction sets");
} else if let TerminatorKind::TailCall { .. } = term.kind {
return Err("can't inline functions with tail calls");
} else { work_list.extend(term.successors()) }
}
let cost = checker.cost();
if cost <= threshold {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:445",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(445u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("INLINING {0:?} [cost={1} <= threshold={2}]",
callsite, cost, threshold) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};
Ok(())
} else {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:448",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(448u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("NOT inlining {0:?} [cost={1} > threshold={2}]",
callsite, cost, threshold) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};
Err("cost above threshold")
}
}
}
}
}
fn on_inline_success(&mut self, callsite: &CallSite<'tcx>,
caller_body: &mut Body<'tcx>,
new_blocks: std::ops::Range<BasicBlock>) {
self.changed = true;
let new_calls_count =
new_blocks.clone().filter(|&bb|
is_call_like(caller_body.basic_blocks[bb].terminator())).count();
if new_calls_count > 1 { self.top_down_counter += 1; }
self.history.push(callsite.callee.def_id());
process_blocks(self, caller_body, new_blocks);
self.history.pop();
if self.history.is_empty() { self.top_down_counter = 0; }
}
fn on_inline_failure(&self, _: &CallSite<'tcx>, _: &'static str) {}
}
fn inline<'tcx,
T: Inliner<'tcx>>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
let def_id = body.source.def_id();
if !tcx.hir_body_owner_kind(def_id).is_fn_or_closure() {
return false;
}
let mut inliner = T::new(tcx, def_id, body);
if !inliner.check_caller_mir_body(body) { return false; }
let blocks = START_BLOCK..body.basic_blocks.next_index();
process_blocks(&mut inliner, body, blocks);
inliner.changed()
}
fn process_blocks<'tcx,
I: Inliner<'tcx>>(inliner: &mut I, caller_body: &mut Body<'tcx>,
blocks: Range<BasicBlock>) {
for bb in blocks {
let bb_data = &caller_body[bb];
if bb_data.is_cleanup { continue; }
let Some(callsite) =
resolve_callsite(inliner, caller_body, bb,
bb_data) else { continue; };
let span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("process_blocks",
"rustc_mir_transform::inline", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(514u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("callsite.callee")
}> =
::tracing::__macro_support::FieldName::new("callsite.callee");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("bb")
}> =
::tracing::__macro_support::FieldName::new("bb");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::display(&callsite.callee)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&bb)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
let _guard = span.enter();
match try_inlining(inliner, caller_body, &callsite) {
Err(reason) => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:519",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(519u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("not-inlined {0} [{1}]",
callsite.callee, reason) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
inliner.on_inline_failure(&callsite, reason);
}
Ok(new_blocks) => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:523",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(523u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("inlined {0}",
callsite.callee) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
inliner.on_inline_success(&callsite, caller_body,
new_blocks);
}
}
}
}
fn resolve_callsite<'tcx,
I: Inliner<'tcx>>(inliner: &I, caller_body: &Body<'tcx>,
bb: BasicBlock, bb_data: &BasicBlockData<'tcx>)
-> Option<CallSite<'tcx>> {
let tcx = inliner.tcx();
let terminator = bb_data.terminator();
if let TerminatorKind::Call { ref func, fn_span, .. } =
terminator.kind {
let func_ty = func.ty(caller_body, tcx);
if let ty::FnDef(def_id, args) = *func_ty.kind() {
if !inliner.should_inline_for_callee(def_id) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:545",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(545u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("not enabled")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return None;
}
let args =
tcx.try_normalize_erasing_regions(inliner.typing_env(),
Unnormalized::new_wip(args)).ok()?.no_bound_vars().unwrap();
let mut callee =
Instance::try_resolve(tcx, inliner.typing_env(), def_id,
args).ok().flatten()?;
if let InstanceKind::Virtual(..) = callee.def { return None; }
if let InstanceKind::Intrinsic(..) = callee.def {
let intrinsic = tcx.intrinsic(def_id).unwrap();
if intrinsic.must_be_overridden { return None; }
if !tcx.sess.fallback_intrinsics.contains(&intrinsic.name) {
return None;
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:570",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(570u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("callsite is fallback body: {0:?}",
def_id) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
callee =
ty::Instance {
def: ty::InstanceKind::Item(def_id),
args: callee.args,
};
}
if inliner.history().contains(&callee.def_id()) {
return None;
}
let fn_sig =
tcx.fn_sig(def_id).instantiate(tcx, args).skip_norm_wip();
if let InstanceKind::Item(instance_def_id) = callee.def &&
tcx.def_kind(instance_def_id) == DefKind::AssocFn &&
let instance_fn_sig =
tcx.fn_sig(instance_def_id).skip_binder() &&
instance_fn_sig.abi() != fn_sig.abi() {
return None;
}
let source_info =
SourceInfo { span: fn_span, ..terminator.source_info };
return Some(CallSite {
callee,
fn_sig,
block: bb,
source_info,
});
}
}
None
}
fn try_inlining<'tcx,
I: Inliner<'tcx>>(inliner: &I, caller_body: &mut Body<'tcx>,
callsite: &CallSite<'tcx>)
-> Result<std::ops::Range<BasicBlock>, &'static str> {
let tcx = inliner.tcx();
check_mir_is_available(inliner, caller_body, callsite.callee)?;
let callee_attrs = tcx.codegen_instance_attrs(callsite.callee.def);
let callee_attrs = callee_attrs.as_ref();
check_inline::is_inline_valid_on_fn(tcx, callsite.callee.def_id())?;
check_codegen_attributes(inliner, callsite, callee_attrs)?;
let terminator =
caller_body[callsite.block].terminator.as_ref().unwrap();
let TerminatorKind::Call { args, destination, .. } =
&terminator.kind else {
::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))
};
let destination_ty = destination.ty(&caller_body.local_decls, tcx).ty;
for arg in args {
if !arg.node.ty(&caller_body.local_decls,
tcx).is_sized(tcx, inliner.typing_env()) {
return Err("call has unsized argument");
}
}
let callee_body = try_instance_mir(tcx, callsite.callee.def)?;
check_inline::is_inline_valid_on_body(tcx, callee_body)?;
inliner.check_callee_mir_body(callsite, callee_body, callee_attrs)?;
let Ok(callee_body) =
callsite.callee.try_instantiate_mir_and_normalize_erasing_regions(tcx,
inliner.typing_env(),
ty::EarlyBinder::bind(tcx,
callee_body.clone())) else {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:635",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(635u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("failed to normalize callee body")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return Err("implementation limitation -- could not normalize callee body");
};
if !validate_types(tcx, inliner.typing_env(), &callee_body,
caller_body).is_empty() {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:642",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(642u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("failed to validate callee body")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return Err("implementation limitation -- callee body failed validation");
}
let output_type = callee_body.return_ty();
if !util::sub_types(tcx, inliner.typing_env(), output_type,
destination_ty) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:651",
"rustc_mir_transform::inline", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(651u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("output_type")
}> =
::tracing::__macro_support::FieldName::new("output_type");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("destination_ty")
}> =
::tracing::__macro_support::FieldName::new("destination_ty");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&output_type)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&destination_ty)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return Err("implementation limitation -- return type mismatch");
}
if callsite.fn_sig.abi() == ExternAbi::RustCall {
let (self_arg, arg_tuple) =
match &args[..] {
[arg_tuple] => (None, arg_tuple),
[self_arg, arg_tuple] => (Some(self_arg), arg_tuple),
_ =>
::rustc_middle::util::bug::bug_fmt(format_args!("Expected `rust-call` to have 1 or 2 args")),
};
let self_arg_ty =
self_arg.map(|self_arg|
self_arg.node.ty(&caller_body.local_decls, tcx));
let arg_tuple_ty =
arg_tuple.node.ty(&caller_body.local_decls, tcx);
let arg_tys =
if callee_body.spread_arg.is_some() {
std::slice::from_ref(&arg_tuple_ty)
} else {
let ty::Tuple(arg_tuple_tys) =
*arg_tuple_ty.kind() else {
::rustc_middle::util::bug::bug_fmt(format_args!("Closure arguments are not passed as a tuple"));
};
arg_tuple_tys.as_slice()
};
for (arg_ty, input) in
self_arg_ty.into_iter().chain(arg_tys.iter().copied()).zip(callee_body.args_iter())
{
let input_type = callee_body.local_decls[input].ty;
if !util::sub_types(tcx, inliner.typing_env(), input_type,
arg_ty) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:678",
"rustc_mir_transform::inline", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(678u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("arg_ty")
}> =
::tracing::__macro_support::FieldName::new("arg_ty");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("input_type")
}> =
::tracing::__macro_support::FieldName::new("input_type");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&arg_ty)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&input_type)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:679",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(679u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("failed to normalize tuple argument type")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return Err("implementation limitation");
}
}
} else {
for (arg, input) in args.iter().zip(callee_body.args_iter()) {
let input_type = callee_body.local_decls[input].ty;
let arg_ty = arg.node.ty(&caller_body.local_decls, tcx);
if !util::sub_types(tcx, inliner.typing_env(), input_type,
arg_ty) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:688",
"rustc_mir_transform::inline", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(688u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("arg_ty")
}> =
::tracing::__macro_support::FieldName::new("arg_ty");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("input_type")
}> =
::tracing::__macro_support::FieldName::new("input_type");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&arg_ty)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&input_type)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:689",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(689u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("failed to normalize argument type")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return Err("implementation limitation -- arg mismatch");
}
}
}
let old_blocks = caller_body.basic_blocks.next_index();
inline_call(inliner, caller_body, callsite, callee_body);
let new_blocks = old_blocks..caller_body.basic_blocks.next_index();
Ok(new_blocks)
}
fn check_mir_is_available<'tcx,
I: Inliner<'tcx>>(inliner: &I, caller_body: &Body<'tcx>,
callee: Instance<'tcx>) -> Result<(), &'static str> {
let caller_def_id = caller_body.source.def_id();
let callee_def_id = callee.def_id();
if callee_def_id == caller_def_id { return Err("self-recursion"); }
match callee.def {
InstanceKind::Item(_) => {
if !inliner.tcx().is_mir_available(callee_def_id) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:719",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(719u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("item MIR unavailable")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return Err("implementation limitation -- MIR unavailable");
}
}
InstanceKind::Intrinsic(_) | InstanceKind::LlvmIntrinsic(_) |
InstanceKind::Virtual(..) => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:725",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(725u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("instance without MIR (intrinsic / virtual)")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return Err("implementation limitation -- cannot inline intrinsic");
}
InstanceKind::Shim(ShimKind::DropGlue(_, Some(ty))) if
ty.has_type_flags(TypeFlags::HAS_CT_PARAM) => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:737",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(737u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("still needs substitution")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return Err("implementation limitation -- HACK for dropping polymorphic type");
}
InstanceKind::Shim(ShimKind::AsyncDropGlue(_, ty)) |
InstanceKind::Shim(ShimKind::AsyncDropGlueCtor(_, ty)) => {
return if ty.still_further_specializable() {
Err("still needs substitution")
} else { Ok(()) };
}
InstanceKind::Shim(ShimKind::FutureDropPoll(_, ty, ty2)) => {
return if ty.still_further_specializable() ||
ty2.still_further_specializable() {
Err("still needs substitution")
} else { Ok(()) };
}
InstanceKind::Shim(ShimKind::VTable(_)) |
InstanceKind::Shim(ShimKind::Reify(..)) |
InstanceKind::Shim(ShimKind::FnPtr(..)) |
InstanceKind::Shim(ShimKind::ClosureOnce { .. }) |
InstanceKind::Shim(ShimKind::ConstructCoroutineInClosure { ..
}) | InstanceKind::Shim(ShimKind::DropGlue(..)) |
InstanceKind::Shim(ShimKind::Clone(..)) |
InstanceKind::Shim(ShimKind::ThreadLocal(..)) |
InstanceKind::Shim(ShimKind::FnPtrAsPtr(..)) |
InstanceKind::Shim(ShimKind::FnPtrFromPtr(..)) =>
return Ok(()),
}
if inliner.tcx().is_constructor(callee_def_id) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:773",
"rustc_mir_transform::inline", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(773u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("constructors always have MIR")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return Ok(());
}
if let Some(callee_def_id) = callee_def_id.as_local() &&
!inliner.tcx().is_lang_item(inliner.tcx().parent(caller_def_id),
LangItem::FnOnce) {
let Some(cyclic_callees) =
inliner.tcx().mir_callgraph_cyclic(caller_def_id.expect_local()) else {
return Err("call graph cycle detection bailed due to recursion limit");
};
if cyclic_callees.contains(&callee_def_id) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:788",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(788u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("query cycle avoidance")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return Err("caller might be reachable from callee");
}
Ok(())
} else {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:798",
"rustc_mir_transform::inline", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(798u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("functions from other crates always have MIR")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
Ok(())
}
}
fn check_codegen_attributes<'tcx,
I: Inliner<'tcx>>(inliner: &I, callsite: &CallSite<'tcx>,
callee_attrs: &CodegenFnAttrs) -> Result<(), &'static str> {
let tcx = inliner.tcx();
if let InlineAttr::Never = callee_attrs.inline {
return Err("never inline attribute");
}
if let OptimizeAttr::DoNotOptimize = callee_attrs.optimize {
return Err("has DoNotOptimize attribute");
}
inliner.check_codegen_attributes_extra(callee_attrs)?;
let is_generic =
callsite.callee.args.non_erasable_generics().next().is_some();
if !is_generic && !tcx.cross_crate_inlinable(callsite.callee.def_id())
{
return Err("not exported");
}
let codegen_fn_attrs = tcx.codegen_fn_attrs(inliner.caller_def_id());
if callee_attrs.sanitizers != codegen_fn_attrs.sanitizers {
return Err("incompatible sanitizer set");
}
if callee_attrs.instruction_set.is_some() &&
callee_attrs.instruction_set !=
codegen_fn_attrs.instruction_set {
return Err("incompatible instruction set");
}
let callee_feature_names =
callee_attrs.target_features.iter().map(|f| f.name);
let this_feature_names =
codegen_fn_attrs.target_features.iter().map(|f| f.name);
if callee_feature_names.ne(this_feature_names) {
return Err("incompatible target features");
}
Ok(())
}
fn inline_call<'tcx,
I: Inliner<'tcx>>(inliner: &I, caller_body: &mut Body<'tcx>,
callsite: &CallSite<'tcx>, mut callee_body: Body<'tcx>) {
let tcx = inliner.tcx();
let terminator =
caller_body[callsite.block].terminator.take().unwrap();
let TerminatorKind::Call { func, args, destination, unwind, target, ..
} =
terminator.kind else {
::rustc_middle::util::bug::bug_fmt(format_args!("unexpected terminator kind {0:?}",
terminator.kind));
};
let return_block =
if let Some(block) = target {
let data =
BasicBlockData::new(Some(Terminator {
source_info: terminator.source_info,
kind: TerminatorKind::Goto { target: block },
attributes: ThinVec::new(),
}), caller_body[block].is_cleanup);
Some(caller_body.basic_blocks_mut().push(data))
} else { None };
fn dest_needs_borrow(place: Place<'_>) -> bool {
for elem in place.projection.iter() {
match elem {
ProjectionElem::Deref | ProjectionElem::Index(_) =>
return true,
_ => {}
}
}
false
}
let dest =
if dest_needs_borrow(destination) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:902",
"rustc_mir_transform::inline", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(902u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("creating temp for return destination")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let dest =
Rvalue::Ref(tcx.lifetimes.re_erased,
BorrowKind::Mut { kind: MutBorrowKind::Default },
destination);
let dest_ty = dest.ty(caller_body, tcx);
let temp =
Place::from(new_call_temp(caller_body, callsite, dest_ty,
return_block));
caller_body[callsite.block].statements.push(Statement::new(callsite.source_info,
StatementKind::Assign(Box::new((temp, dest)))));
tcx.mk_place_deref(temp)
} else { destination };
let (remap_destination, destination_local) =
if let Some(d) = dest.as_local() {
(false, d)
} else {
(true,
new_call_temp(caller_body, callsite,
destination.ty(caller_body, tcx).ty, return_block))
};
let args =
make_call_args(inliner, args, callsite, caller_body, &callee_body,
return_block);
let mut integrator =
Integrator {
args: &args,
new_locals: caller_body.local_decls.next_index()..,
new_scopes: caller_body.source_scopes.next_index()..,
new_blocks: caller_body.basic_blocks.next_index()..,
destination: destination_local,
callsite_scope: caller_body.source_scopes[callsite.source_info.scope].clone(),
callsite,
cleanup_block: unwind,
in_cleanup_block: false,
return_block,
tcx,
always_live_locals: UsedInStmtLocals::new(&callee_body).locals,
};
integrator.visit_body(&mut callee_body);
for local in callee_body.vars_and_temps_iter() {
if integrator.always_live_locals.contains(local) {
let new_local = integrator.map_local(local);
caller_body[callsite.block].statements.push(Statement::new(callsite.source_info,
StatementKind::StorageLive(new_local)));
}
}
if let Some(block) = return_block {
let mut n = 0;
if remap_destination {
caller_body[block].statements.push(Statement::new(callsite.source_info,
StatementKind::Assign(Box::new((dest,
Rvalue::Use(Operand::Move(destination_local.into()),
WithRetag::Yes))))));
n += 1;
}
for local in callee_body.vars_and_temps_iter().rev() {
if integrator.always_live_locals.contains(local) {
let new_local = integrator.map_local(local);
caller_body[block].statements.push(Statement::new(callsite.source_info,
StatementKind::StorageDead(new_local)));
n += 1;
}
}
caller_body[block].statements.rotate_right(n);
}
caller_body.local_decls.extend(callee_body.drain_vars_and_temps());
caller_body.source_scopes.append(&mut callee_body.source_scopes);
if tcx.sess.opts.unstable_opts.inline_mir_preserve_debug.unwrap_or(tcx.sess.opts.debuginfo
== DebugInfo::Full) {
caller_body.var_debug_info.append(&mut callee_body.var_debug_info);
} else {
for bb in callee_body.basic_blocks_mut() { bb.drop_debuginfo(); }
}
caller_body.basic_blocks_mut().append(callee_body.basic_blocks_mut());
caller_body[callsite.block].terminator =
Some(Terminator {
source_info: callsite.source_info,
kind: TerminatorKind::Goto {
target: integrator.map_block(START_BLOCK),
},
attributes: ThinVec::new(),
});
caller_body.required_consts.as_mut().unwrap().extend(callee_body.required_consts().into_iter().filter(|ct|
ct.const_.is_required_const()));
let callee_item = MentionedItem::Fn(func.ty(caller_body, tcx));
let caller_mentioned_items =
caller_body.mentioned_items.as_mut().unwrap();
if let Some(idx) =
caller_mentioned_items.iter().position(|item|
item.node == callee_item) {
caller_mentioned_items.remove(idx);
caller_mentioned_items.extend(callee_body.mentioned_items());
} else {}
}
fn make_call_args<'tcx,
I: Inliner<'tcx>>(inliner: &I, args: Box<[Spanned<Operand<'tcx>>]>,
callsite: &CallSite<'tcx>, caller_body: &mut Body<'tcx>,
callee_body: &Body<'tcx>, return_block: Option<BasicBlock>)
-> Box<[Local]> {
let tcx = inliner.tcx();
if callsite.fn_sig.abi() == ExternAbi::RustCall &&
callee_body.spread_arg.is_none() {
let mut args = args.into_iter();
let self_ =
create_temp_if_necessary(inliner, args.next().unwrap().node,
callsite, caller_body, return_block);
let tuple =
create_temp_if_necessary(inliner, args.next().unwrap().node,
callsite, caller_body, return_block);
if !args.next().is_none() {
::core::panicking::panic("assertion failed: args.next().is_none()")
};
let tuple = Place::from(tuple);
let ty::Tuple(tuple_tys) =
tuple.ty(caller_body,
tcx).ty.kind() else {
::rustc_middle::util::bug::bug_fmt(format_args!("Closure arguments are not passed as a tuple"));
};
let closure_ref_arg = iter::once(self_);
let tuple_tmp_args =
tuple_tys.iter().enumerate().map(|(i, ty)|
{
let tuple_field =
Operand::Move(tcx.mk_place_field(tuple, FieldIdx::new(i),
ty));
create_temp_if_necessary(inliner, tuple_field, callsite,
caller_body, return_block)
});
closure_ref_arg.chain(tuple_tmp_args).collect()
} else {
args.into_iter().map(|a|
create_temp_if_necessary(inliner, a.node, callsite,
caller_body, return_block)).collect()
}
}
fn create_temp_if_necessary<'tcx,
I: Inliner<'tcx>>(inliner: &I, arg: Operand<'tcx>,
callsite: &CallSite<'tcx>, caller_body: &mut Body<'tcx>,
return_block: Option<BasicBlock>) -> Local {
if let Operand::Move(place) = &arg &&
let Some(local) = place.as_local() &&
caller_body.local_kind(local) == LocalKind::Temp {
return local;
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:1138",
"rustc_mir_transform::inline", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(1138u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("creating temp for argument {0:?}",
arg) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let arg_ty = arg.ty(caller_body, inliner.tcx());
let local =
new_call_temp(caller_body, callsite, arg_ty, return_block);
caller_body[callsite.block].statements.push(Statement::new(callsite.source_info,
StatementKind::Assign(Box::new((Place::from(local),
Rvalue::Use(arg, WithRetag::Yes))))));
local
}
fn new_call_temp<'tcx>(caller_body: &mut Body<'tcx>,
callsite: &CallSite<'tcx>, ty: Ty<'tcx>,
return_block: Option<BasicBlock>) -> Local {
let local =
caller_body.local_decls.push(LocalDecl::new(ty,
callsite.source_info.span));
caller_body[callsite.block].statements.push(Statement::new(callsite.source_info,
StatementKind::StorageLive(local)));
if let Some(block) = return_block {
caller_body[block].statements.insert(0,
Statement::new(callsite.source_info,
StatementKind::StorageDead(local)));
}
local
}
struct Integrator<'a, 'tcx> {
args: &'a [Local],
new_locals: RangeFrom<Local>,
new_scopes: RangeFrom<SourceScope>,
new_blocks: RangeFrom<BasicBlock>,
destination: Local,
callsite_scope: SourceScopeData<'tcx>,
callsite: &'a CallSite<'tcx>,
cleanup_block: UnwindAction,
in_cleanup_block: bool,
return_block: Option<BasicBlock>,
tcx: TyCtxt<'tcx>,
always_live_locals: DenseBitSet<Local>,
}
impl Integrator<'_, '_> {
fn map_local(&self, local: Local) -> Local {
let new =
if local == RETURN_PLACE {
self.destination
} else {
let idx = local.index() - 1;
if idx < self.args.len() {
self.args[idx]
} else { self.new_locals.start + (idx - self.args.len()) }
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:1204",
"rustc_mir_transform::inline", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(1204u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("mapping local `{0:?}` to `{1:?}`",
local, new) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
new
}
fn map_scope(&self, scope: SourceScope) -> SourceScope {
let new = self.new_scopes.start + scope.index();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:1210",
"rustc_mir_transform::inline", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(1210u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("mapping scope `{0:?}` to `{1:?}`",
scope, new) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
new
}
fn map_block(&self, block: BasicBlock) -> BasicBlock {
let new = self.new_blocks.start + block.index();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs:1216",
"rustc_mir_transform::inline", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(1216u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("mapping block `{0:?}` to `{1:?}`",
block, new) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
new
}
fn map_unwind(&self, unwind: UnwindAction) -> UnwindAction {
if self.in_cleanup_block {
match unwind {
UnwindAction::Cleanup(_) | UnwindAction::Continue => {
::rustc_middle::util::bug::bug_fmt(format_args!("cleanup on cleanup block"));
}
UnwindAction::Unreachable | UnwindAction::Terminate(_) =>
return unwind,
}
}
match unwind {
UnwindAction::Unreachable | UnwindAction::Terminate(_) =>
unwind,
UnwindAction::Cleanup(target) =>
UnwindAction::Cleanup(self.map_block(target)),
UnwindAction::Continue => self.cleanup_block,
}
}
}
impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_local(&mut self, local: &mut Local, _ctxt: PlaceContext,
_location: Location) {
*local = self.map_local(*local);
}
fn visit_source_scope_data(&mut self,
scope_data: &mut SourceScopeData<'tcx>) {
self.super_source_scope_data(scope_data);
if scope_data.parent_scope.is_none() {
scope_data.parent_scope =
Some(self.callsite.source_info.scope);
{
match (&scope_data.inlined_parent_scope, &None) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
scope_data.inlined_parent_scope =
if self.callsite_scope.inlined.is_some() {
Some(self.callsite.source_info.scope)
} else { self.callsite_scope.inlined_parent_scope };
{
match (&scope_data.inlined, &None) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
scope_data.inlined =
Some((self.callsite.callee,
self.callsite.source_info.span));
} else if scope_data.inlined_parent_scope.is_none() {
scope_data.inlined_parent_scope =
Some(self.map_scope(OUTERMOST_SOURCE_SCOPE));
}
}
fn visit_source_scope(&mut self, scope: &mut SourceScope) {
*scope = self.map_scope(*scope);
}
fn visit_basic_block_data(&mut self, block: BasicBlock,
data: &mut BasicBlockData<'tcx>) {
self.in_cleanup_block = data.is_cleanup;
self.super_basic_block_data(block, data);
self.in_cleanup_block = false;
}
fn visit_statement(&mut self, statement: &mut Statement<'tcx>,
location: Location) {
if let StatementKind::StorageLive(local) |
StatementKind::StorageDead(local) = statement.kind {
self.always_live_locals.remove(local);
}
self.super_statement(statement, location);
}
fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>,
loc: Location) {
if !#[allow(non_exhaustive_omitted_patterns)] match terminator.kind
{
TerminatorKind::Return => true,
_ => false,
} {
self.super_terminator(terminator, loc);
} else { self.visit_source_info(&mut terminator.source_info); }
match terminator.kind {
TerminatorKind::CoroutineDrop | TerminatorKind::Yield { .. }
=>
::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached")),
TerminatorKind::Goto { ref mut target } => {
*target = self.map_block(*target);
}
TerminatorKind::SwitchInt { ref mut targets, .. } => {
for tgt in targets.all_targets_mut() {
*tgt = self.map_block(*tgt);
}
}
TerminatorKind::Drop { ref mut target, ref mut unwind, .. } =>
{
*target = self.map_block(*target);
*unwind = self.map_unwind(*unwind);
}
TerminatorKind::TailCall { .. } => {
::core::panicking::panic("internal error: entered unreachable code")
}
TerminatorKind::Call { ref mut target, ref mut unwind, .. } =>
{
if let Some(ref mut tgt) = *target {
*tgt = self.map_block(*tgt);
}
*unwind = self.map_unwind(*unwind);
}
TerminatorKind::Assert { ref mut target, ref mut unwind, .. }
=> {
*target = self.map_block(*target);
*unwind = self.map_unwind(*unwind);
}
TerminatorKind::Return => {
terminator.kind =
if let Some(tgt) = self.return_block {
TerminatorKind::Goto { target: tgt }
} else { TerminatorKind::Unreachable }
}
TerminatorKind::UnwindResume => {
terminator.kind =
match self.cleanup_block {
UnwindAction::Cleanup(tgt) =>
TerminatorKind::Goto { target: tgt },
UnwindAction::Continue => TerminatorKind::UnwindResume,
UnwindAction::Unreachable => TerminatorKind::Unreachable,
UnwindAction::Terminate(reason) =>
TerminatorKind::UnwindTerminate(reason),
};
}
TerminatorKind::UnwindTerminate(_) => {}
TerminatorKind::Unreachable => {}
TerminatorKind::FalseEdge {
ref mut real_target, ref mut imaginary_target } => {
*real_target = self.map_block(*real_target);
*imaginary_target = self.map_block(*imaginary_target);
}
TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => {
::rustc_middle::util::bug::bug_fmt(format_args!("False unwinds should have been removed before inlining"))
}
TerminatorKind::InlineAsm { ref mut targets, ref mut unwind,
.. } => {
for tgt in targets.iter_mut() {
*tgt = self.map_block(*tgt);
}
*unwind = self.map_unwind(*unwind);
}
}
}
}
fn try_instance_mir<'tcx>(tcx: TyCtxt<'tcx>, instance: InstanceKind<'tcx>)
-> Result<&'tcx Body<'tcx>, &'static str> {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("try_instance_mir",
"rustc_mir_transform::inline", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/inline.rs"),
::tracing_core::__macro_support::Option::Some(1362u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::inline"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("instance")
}> =
::tracing::__macro_support::FieldName::new("instance");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&instance)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Result<&'tcx Body<'tcx>, &'static str> = loop {};
return __tracing_attr_fake_return;
}
{
if let ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_,
Some(ty))) |
ty::InstanceKind::Shim(ty::ShimKind::AsyncDropGlueCtor(_,
ty)) = instance && let ty::Adt(def, args) = ty.kind() {
let fields = def.all_fields();
for field in fields {
let field_ty = field.ty(tcx, args);
if field_ty.has_param() && field_ty.has_aliases() {
return Err("cannot build drop shim for polymorphic type");
}
}
}
Ok(tcx.instance_mir(instance))
}
}
}
}
fn body_is_forwarder(body: &Body<'_>) -> bool {
let TerminatorKind::Call { target, .. } =
body.basic_blocks[START_BLOCK].terminator().kind else {
return false;
};
if let Some(target) = target {
let TerminatorKind::Return =
body.basic_blocks[target].terminator().kind else {
return false;
};
}
let max_blocks =
if !body.is_polymorphic {
2
} else if target.is_none() { 3 } else { 4 };
if body.basic_blocks.len() > max_blocks { return false; }
body.basic_blocks.iter_enumerated().all(|(bb, bb_data)|
{
bb == START_BLOCK ||
#[allow(non_exhaustive_omitted_patterns)] match bb_data.terminator().kind
{
TerminatorKind::Return | TerminatorKind::Drop { .. } |
TerminatorKind::UnwindResume |
TerminatorKind::UnwindTerminate(_) => true,
_ => false,
}
})
}
}
#[allow(unused_imports)]
use inline::Inline as _;
#[allow(unused_imports)]
use inline::ForceInline as _;
mod impossible_clauses {
use rustc_middle::mir::{Body, START_BLOCK, TerminatorKind};
use rustc_middle::ty::{
self, Ty, TyCtxt, TypeFlags, TypeVisitableExt, Unnormalized,
};
use rustc_span::def_id::DefId;
use rustc_trait_selection::traits;
use tracing::trace;
use crate::PassPolicy;
use crate::pass_manager::MirPass;
fn is_structurally_unsized<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>)
-> bool {
match ty.kind() {
ty::Str | ty::Slice(_) | ty::Dynamic(_, _) | ty::Foreign(_) =>
true,
ty::Tuple(tys) =>
tys.last().is_some_and(|ty|
is_structurally_unsized(tcx, *ty)),
ty::Adt(def, args) => {
def.sizedness_constraint(tcx,
ty::SizedTraitKind::Sized).is_some_and(|ty|
{
is_structurally_unsized(tcx,
ty.instantiate(tcx, args).skip_norm_wip())
})
}
_ => false,
}
}
fn has_structurally_impossible_sized_clause<'tcx>(tcx: TyCtxt<'tcx>,
sized_trait: DefId, predicate: ty::Clause<'tcx>) -> bool {
let Some(trait_predicate) =
predicate.as_trait_clause() else { return false; };
let trait_predicate = trait_predicate.skip_binder();
trait_predicate.polarity == ty::ClausePolarity::Positive &&
trait_predicate.def_id() == sized_trait &&
is_structurally_unsized(tcx, trait_predicate.self_ty())
}
pub(crate) struct ImpossibleClauses;
pub(crate) fn has_impossible_clauses<'tcx>(tcx: TyCtxt<'tcx>,
def_id: DefId) -> bool {
let clauses = tcx.clauses_of(def_id).instantiate_identity(tcx);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/impossible_clauses.rs:70",
"rustc_mir_transform::impossible_clauses",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/impossible_clauses.rs"),
::tracing_core::__macro_support::Option::Some(70u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::impossible_clauses"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("clauses")
}> =
::tracing::__macro_support::FieldName::new("clauses");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&clauses)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if let Some(sized_trait) = tcx.lang_items().sized_trait() {
if clauses.clauses.iter().copied().map(Unnormalized::skip_norm_wip).any(|clause|
has_structurally_impossible_sized_clause(tcx, sized_trait,
clause)) {
return true;
}
}
let clauses =
clauses.clauses.into_iter().map(Unnormalized::skip_norm_wip).filter(|c|
{
!c.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES |
TypeFlags::HAS_CONST_ALIAS)
});
let clauses: Vec<_> = traits::elaborate(tcx, clauses).collect();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/impossible_clauses.rs:95",
"rustc_mir_transform::impossible_clauses",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/impossible_clauses.rs"),
::tracing_core::__macro_support::Option::Some(95u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::impossible_clauses"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("clauses")
}> =
::tracing::__macro_support::FieldName::new("clauses");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&clauses)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
clauses.references_error() || traits::impossible_clauses(tcx, clauses)
}
impl<'tcx> MirPass<'tcx> for ImpossibleClauses {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("run_pass",
"rustc_mir_transform::impossible_clauses",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/impossible_clauses.rs"),
::tracing_core::__macro_support::Option::Some(100u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::impossible_clauses"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/impossible_clauses.rs:102",
"rustc_mir_transform::impossible_clauses",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/impossible_clauses.rs"),
::tracing_core::__macro_support::Option::Some(102u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::impossible_clauses"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&body.source.def_id())
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let impossible =
body.tainted_by_errors.is_some() ||
has_impossible_clauses(tcx, body.source.def_id());
if impossible {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/impossible_clauses.rs:106",
"rustc_mir_transform::impossible_clauses",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/impossible_clauses.rs"),
::tracing_core::__macro_support::Option::Some(106u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::impossible_clauses"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("found unsatisfiable clauses")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let bbs = body.basic_blocks.as_mut();
bbs.raw.truncate(1);
bbs[START_BLOCK].statements.clear();
bbs[START_BLOCK].terminator_mut().kind =
TerminatorKind::Unreachable;
body.var_debug_info.clear();
body.local_decls.raw.truncate(body.arg_count + 1);
}
}
}
}
}
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(true)
}
}
}
#[allow(unused_imports)]
use impossible_clauses::ImpossibleClauses as _;
mod instsimplify {
use rustc_abi::{ExternAbi, Integer};
use rustc_hir::attrs::lang_items::LangItem;
use rustc_hir::find_attr;
use rustc_index::IndexVec;
use rustc_middle::bug;
use rustc_middle::mir::visit::MutVisitor;
use rustc_middle::mir::*;
use rustc_middle::ty::layout::{IntegerExt, ValidityRequirement};
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, layout};
use rustc_span::{Symbol, sym};
use crate::PassPolicy;
use crate::simplify::simplify_duplicate_switch_targets;
pub(super) enum InstSimplify { BeforeInline, AfterSimplifyCfg, }
impl<'tcx> crate::MirPass<'tcx> for InstSimplify {
fn name(&self) -> &'static str {
match self {
InstSimplify::BeforeInline => "InstSimplify-before-inline",
InstSimplify::AfterSimplifyCfg =>
"InstSimplify-after-simplifycfg",
}
}
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 1)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let preserve_ub_checks =
{
{
'done:
{
for i in tcx.hir_krate_attrs() {
#[allow(unused_imports)]
use ::rustc_attr_ir::AttributeKind::*;
let i: &::rustc_attr_ir::Attribute = i;
match i {
::rustc_attr_ir::Attribute::Parsed(RustcPreserveUbChecks) =>
{
break 'done Some(());
}
::rustc_attr_ir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}.is_some()
};
if !preserve_ub_checks {
SimplifyUbCheck { tcx }.visit_body(body);
}
let mut ctx =
InstSimplifyContext {
tcx,
typing_env: body.typing_env(tcx),
local_decls: &mut body.local_decls,
};
for block in body.basic_blocks.as_mut() {
for statement in block.statements.iter_mut() {
let StatementKind::Assign((.., rvalue)) =
&mut statement.kind else { continue; };
ctx.simplify_bool_cmp(rvalue);
ctx.simplify_ref_deref(rvalue);
ctx.simplify_ptr_aggregate(rvalue);
ctx.simplify_cast(rvalue);
ctx.simplify_repeated_aggregate(rvalue);
ctx.simplify_repeat_once(rvalue);
}
let terminator = block.terminator.as_mut().unwrap();
ctx.simplify_primitive_clone(terminator,
&mut block.statements);
ctx.simplify_size_or_align_of_val(terminator,
&mut block.statements);
ctx.simplify_raw_eq(terminator, &mut block.statements);
ctx.simplify_intrinsic_assert(terminator);
ctx.simplify_nounwind_call(terminator);
simplify_duplicate_switch_targets(terminator);
}
}
}
struct InstSimplifyContext<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
local_decls: &'a mut IndexVec<Local, LocalDecl<'tcx>>,
typing_env: ty::TypingEnv<'tcx>,
}
impl<'tcx> InstSimplifyContext<'_, 'tcx> {
fn simplify_repeated_aggregate(&self, rvalue: &mut Rvalue<'tcx>) {
let Rvalue::Aggregate(AggregateKind::Array(_), fields) =
&*rvalue else { return; };
if fields.len() < 5 { return; }
let (first, rest) = fields[..].split_first().unwrap();
let Operand::Constant(first) = first else { return; };
let Ok(first_val) =
first.const_.eval(self.tcx, self.typing_env,
first.span) else { return; };
if rest.iter().all(|field|
{
let Operand::Constant(field) = field else { return false; };
let field =
field.const_.eval(self.tcx, self.typing_env, field.span);
field == Ok(first_val)
}) {
let len =
ty::Const::from_target_usize(self.tcx,
fields.len().try_into().unwrap());
*rvalue =
Rvalue::Repeat(Operand::Constant(first.clone()), len);
}
}
fn simplify_bool_cmp(&self, rvalue: &mut Rvalue<'tcx>) {
let Rvalue::BinaryOp(op @ (BinOp::Eq | BinOp::Ne), (a, b)) =
&*rvalue else { return };
*rvalue =
match (op, self.try_eval_bool(a), self.try_eval_bool(b)) {
(BinOp::Eq, _, Some(true)) =>
Rvalue::Use(a.clone(), WithRetag::Yes),
(BinOp::Ne, _, Some(false)) =>
Rvalue::Use(a.clone(), WithRetag::Yes),
(BinOp::Eq, Some(true), _) =>
Rvalue::Use(b.clone(), WithRetag::Yes),
(BinOp::Ne, Some(false), _) =>
Rvalue::Use(b.clone(), WithRetag::Yes),
(BinOp::Eq, Some(false), _) =>
Rvalue::UnaryOp(UnOp::Not, b.clone()),
(BinOp::Ne, Some(true), _) =>
Rvalue::UnaryOp(UnOp::Not, b.clone()),
(BinOp::Eq, _, Some(false)) =>
Rvalue::UnaryOp(UnOp::Not, a.clone()),
(BinOp::Ne, _, Some(true)) =>
Rvalue::UnaryOp(UnOp::Not, a.clone()),
_ => return,
};
}
fn try_eval_bool(&self, a: &Operand<'_>) -> Option<bool> {
let a = a.constant()?;
if a.const_.ty().is_bool() {
a.const_.try_to_bool()
} else { None }
}
fn simplify_ref_deref(&self, rvalue: &mut Rvalue<'tcx>) {
if let Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) =
rvalue &&
let Some((base, ProjectionElem::Deref)) =
place.as_ref().last_projection() &&
rvalue.ty(self.local_decls, self.tcx) ==
base.ty(self.local_decls, self.tcx).ty {
*rvalue =
Rvalue::Use(Operand::Copy(Place {
local: base.local,
projection: self.tcx.mk_place_elems(base.projection),
}),
if #[allow(non_exhaustive_omitted_patterns)] match rvalue {
Rvalue::Ref(_, BorrowKind::Mut {
kind: MutBorrowKind::TwoPhaseBorrow }, _) => true,
_ => false,
} {
WithRetag::No
} else { WithRetag::Yes });
}
}
fn simplify_ptr_aggregate(&self, rvalue: &mut Rvalue<'tcx>) {
if let Rvalue::Aggregate(AggregateKind::RawPtr(pointee_ty,
mutability), fields) = rvalue &&
let meta_ty = fields.raw[1].ty(self.local_decls, self.tcx)
&& meta_ty.is_unit() {
let mut fields = std::mem::take(fields);
let _meta = fields.pop().unwrap();
let data = fields.pop().unwrap();
let ptr_ty = Ty::new_ptr(self.tcx, *pointee_ty, *mutability);
*rvalue = Rvalue::Cast(CastKind::PtrToPtr, data, ptr_ty);
}
}
fn simplify_cast(&self, rvalue: &mut Rvalue<'tcx>) {
let Rvalue::Cast(kind, operand, cast_ty) = rvalue else { return };
let operand_ty = operand.ty(self.local_decls, self.tcx);
if operand_ty == *cast_ty {
*rvalue = Rvalue::Use(operand.clone(), WithRetag::Yes);
} else if *kind == CastKind::Transmute &&
let (ty::Int(int), ty::Uint(uint)) |
(ty::Uint(uint), ty::Int(int)) =
(operand_ty.kind(), cast_ty.kind()) &&
int.bit_width() == uint.bit_width() {
*kind = CastKind::IntToInt;
}
}
fn simplify_repeat_once(&self, rvalue: &mut Rvalue<'tcx>) {
if let Rvalue::Repeat(operand, count) = rvalue &&
let Some(1) = count.try_to_target_usize(self.tcx) {
*rvalue =
Rvalue::Aggregate(Box::new(AggregateKind::Array(operand.ty(self.local_decls,
self.tcx))), [operand.clone()].into());
}
}
fn simplify_primitive_clone(&self, terminator: &mut Terminator<'tcx>,
statements: &mut Vec<Statement<'tcx>>) {
let TerminatorKind::Call {
func, args, destination, target: Some(destination_block), ..
} = &terminator.kind else { return; };
let [arg] = &args[..] else { return };
let Some((fn_def_id, ..)) = func.const_fn_def() else { return };
let arg_ty = arg.node.ty(self.local_decls, self.tcx);
let ty::Ref(_region, inner_ty, Mutability::Not) =
*arg_ty.kind() else { return };
if !self.tcx.is_lang_item(fn_def_id, LangItem::CloneFn) ||
!inner_ty.is_trivially_pure_clone_copy() {
return;
}
let Some(arg_place) = arg.node.place() else { return };
statements.push(Statement::new(terminator.source_info,
StatementKind::Assign(Box::new((*destination,
Rvalue::Use(Operand::Copy(arg_place.project_deeper(&[ProjectionElem::Deref],
self.tcx)), WithRetag::Yes))))));
terminator.kind =
TerminatorKind::Goto { target: *destination_block };
}
fn simplify_size_or_align_of_val(&self,
terminator: &mut Terminator<'tcx>,
statements: &mut Vec<Statement<'tcx>>) {
let source_info = terminator.source_info;
if let TerminatorKind::Call {
func, args, destination, target: Some(destination_block), ..
} = &terminator.kind && args.len() == 1 &&
let Some((fn_def_id, generics)) = func.const_fn_def() {
let lang_item =
if self.tcx.is_intrinsic(fn_def_id, sym::size_of_val) {
LangItem::SizeOf
} else if self.tcx.is_intrinsic(fn_def_id,
sym::align_of_val) {
LangItem::AlignOf
} else { return; };
let generic_ty = generics.type_at(0);
let ty =
if generic_ty.is_sized(self.tcx, self.typing_env) {
generic_ty
} else if let LangItem::AlignOf = lang_item &&
let ty::Slice(elem_ty) = *generic_ty.kind() {
elem_ty
} else { return; };
let const_def_id =
self.tcx.require_lang_item(lang_item, source_info.span);
let const_op =
Operand::unevaluated_constant(self.tcx, const_def_id,
&[ty.into()], source_info.span);
statements.push(Statement::new(source_info,
StatementKind::Assign(Box::new((*destination,
Rvalue::Use(const_op, WithRetag::Yes))))));
terminator.kind =
TerminatorKind::Goto { target: *destination_block };
}
}
fn simplify_raw_eq(&mut self, terminator: &mut Terminator<'tcx>,
statements: &mut Vec<Statement<'tcx>>) {
let tcx = self.tcx;
let source_info = terminator.source_info;
let span = source_info.span;
if let TerminatorKind::Call {
func, args, destination, target: Some(destination_block), ..
} = &terminator.kind && args.len() == 2 &&
let Some((fn_def_id, generics)) = func.const_fn_def() &&
tcx.is_intrinsic(fn_def_id, sym::raw_eq) &&
let generic_ty = generics.type_at(0) &&
let Ok(layout) =
tcx.layout_of(self.typing_env.as_query_input(generic_ty)) &&
let Ok(integer) = Integer::from_size(layout.size) {
let ref_ty =
Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, generic_ty);
let uint_ty = integer.to_ty(tcx, false);
let mut transmute_operand =
|op: &Operand<'tcx>| -> Operand<'tcx>
{
let ref_local =
self.local_decls.push(LocalDecl::new(ref_ty, span));
statements.push(Statement::new(source_info,
StatementKind::Assign(Box::new((Place::from(ref_local),
Rvalue::Use(op.clone(), WithRetag::Yes))))));
let place =
Place::from(ref_local).project_deeper(&[ProjectionElem::Deref],
tcx);
let int_local =
self.local_decls.push(LocalDecl::new(uint_ty, span));
statements.push(Statement::new(source_info,
StatementKind::Assign(Box::new((Place::from(int_local),
Rvalue::Cast(CastKind::Transmute, Operand::Copy(place),
uint_ty))))));
Operand::Move(Place::from(int_local))
};
let lhs_op = transmute_operand(&args[0].node);
let rhs_op = transmute_operand(&args[1].node);
statements.push(Statement::new(source_info,
StatementKind::Assign(Box::new((*destination,
Rvalue::BinaryOp(BinOp::Eq,
Box::new((lhs_op, rhs_op))))))));
terminator.kind =
TerminatorKind::Goto { target: *destination_block };
}
}
fn simplify_nounwind_call(&self, terminator: &mut Terminator<'tcx>) {
let TerminatorKind::Call { ref func, ref mut unwind, .. } =
terminator.kind else { return; };
let Some((def_id, _)) = func.const_fn_def() else { return; };
let body_ty = self.tcx.type_of(def_id).skip_binder();
let body_abi =
match body_ty.kind() {
ty::FnDef(..) => body_ty.fn_sig(self.tcx).abi(),
ty::Closure(..) => ExternAbi::RustCall,
ty::Coroutine(..) => ExternAbi::Rust,
_ =>
::rustc_middle::util::bug::bug_fmt(format_args!("unexpected body ty: {0:?}",
body_ty)),
};
if !layout::fn_can_unwind(self.tcx, Some(def_id), body_abi) {
*unwind = UnwindAction::Unreachable;
}
}
fn simplify_intrinsic_assert(&self,
terminator: &mut Terminator<'tcx>) {
let TerminatorKind::Call {
ref func, target: ref mut target @ Some(target_block), ..
} = terminator.kind else { return; };
let func_ty = func.ty(self.local_decls, self.tcx);
let Some((intrinsic_name, args)) =
resolve_rust_intrinsic(self.tcx, func_ty) else { return; };
let [arg, ..] = args[..] else { return };
let known_is_valid =
intrinsic_assert_panics(self.tcx, self.typing_env, arg,
intrinsic_name);
match known_is_valid {
None => {}
Some(true) => { *target = None; }
Some(false) => {
terminator.kind =
TerminatorKind::Goto { target: target_block };
}
}
}
}
fn intrinsic_assert_panics<'tcx>(tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>, arg: ty::GenericArg<'tcx>,
intrinsic_name: Symbol) -> Option<bool> {
let requirement =
ValidityRequirement::from_intrinsic(intrinsic_name)?;
let ty = arg.expect_ty();
Some(!tcx.check_validity_requirement((requirement,
typing_env.as_query_input(ty))).ok()?)
}
fn resolve_rust_intrinsic<'tcx>(tcx: TyCtxt<'tcx>, func_ty: Ty<'tcx>)
-> Option<(Symbol, GenericArgsRef<'tcx>)> {
let ty::FnDef(def_id, args) = *func_ty.kind() else { return None };
let intrinsic = tcx.intrinsic(def_id)?;
Some((intrinsic.name, args.no_bound_vars().unwrap()))
}
struct SimplifyUbCheck<'tcx> {
tcx: TyCtxt<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for SimplifyUbCheck<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_operand(&mut self, operand: &mut Operand<'tcx>,
_: Location) {
if let Operand::RuntimeChecks(RuntimeChecks::UbChecks) = operand {
*operand =
Operand::Constant(Box::new(ConstOperand {
span: rustc_span::DUMMY_SP,
user_ty: None,
const_: Const::Val(ConstValue::from_bool(self.tcx.sess.ub_checks()),
self.tcx.types.bool),
}));
}
}
}
}
#[allow(unused_imports)]
use instsimplify::InstSimplify as _;
mod jump_threading {
use itertools::Itertools as _;
use rustc_const_eval::const_eval::DummyMachine;
use rustc_const_eval::interpret::{
ImmTy, Immediate, InterpCx, OpTy, Projectable,
};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
use rustc_index::IndexVec;
use rustc_index::bit_set::{DenseBitSet, GrowableBitSet};
use rustc_middle::bug;
use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, ScalarInt, TyCtxt};
use rustc_mir_dataflow::value_analysis::{
Map, PlaceCollectionMode, PlaceIndex, TrackElem, ValueIndex,
};
use rustc_span::DUMMY_SP;
use tracing::{debug, instrument, trace};
use crate::PassPolicy;
use crate::cost_checker::CostChecker;
pub(super) struct JumpThreading;
const MAX_COST: u8 = 100;
impl<'tcx> crate::MirPass<'tcx> for JumpThreading {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 2 &&
!ctx.target.is_like_gpu)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("run_pass",
"rustc_mir_transform::jump_threading",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(88u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let def_id = body.source.def_id();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:91",
"rustc_mir_transform::jump_threading",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(91u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if tcx.is_coroutine(def_id) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:95",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(95u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Skipped for coroutine {0:?}",
def_id) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return;
}
let typing_env = body.typing_env(tcx);
let mut finder =
TOFinder {
tcx,
typing_env,
ecx: InterpCx::new(tcx, DUMMY_SP, typing_env, DummyMachine),
body,
map: Map::new(tcx, body, PlaceCollectionMode::OnDemand),
maybe_loop_headers: maybe_loop_headers(body),
entry_states: IndexVec::from_elem(ConditionSet::default(),
&body.basic_blocks),
};
for (bb, bbdata) in traversal::postorder(body) {
if bbdata.is_cleanup { continue; }
let mut state = finder.populate_from_outgoing_edges(bb);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:116",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(116u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("output_states[{0:?}] = {1:?}",
bb, state) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
finder.process_terminator(bb, &mut state);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:119",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(119u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("pre_terminator_states[{0:?}] = {1:?}",
bb, state) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
for stmt in bbdata.statements.iter().rev() {
if state.is_empty() { break; }
finder.process_statement(stmt, &mut state);
if let Some((lhs, tail)) = finder.mutated_statement(stmt) {
finder.flood_state(lhs, tail, &mut state);
}
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:137",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(137u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("entry_states[{0:?}] = {1:?}",
bb, state) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
finder.entry_states[bb] = state;
}
let mut entry_states = finder.entry_states;
simplify_conditions(body, &mut entry_states);
remove_costly_conditions(tcx, typing_env, body,
&mut entry_states);
if let Some(opportunities) =
OpportunitySet::new(body, entry_states) {
opportunities.apply();
}
}
}
}
}
}
struct TOFinder<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
ecx: InterpCx<'tcx, DummyMachine>,
body: &'a Body<'tcx>,
map: Map<'tcx>,
maybe_loop_headers: DenseBitSet<BasicBlock>,
entry_states: IndexVec<BasicBlock, ConditionSet>,
}
#[rustc_pass_by_value]
struct ConditionIndex {
private_use_as_methods_instead: u32 is const 0..=const 0xFFFF_FF00,
}
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for ConditionIndex { }
#[automatically_derived]
impl ::core::clone::Clone for ConditionIndex {
#[inline]
fn clone(&self) -> ConditionIndex {
let _:
::core::clone::AssertParamIsClone<u32 is const 0..=const 0xFFFF_FF00>;
*self
}
}
#[automatically_derived]
impl ::core::marker::Copy for ConditionIndex { }
impl ConditionIndex {
#[doc = r" Maximum value the index can take, as a `u32`."]
const MAX_AS_U32: u32 = 0xFFFF_FF00;
#[doc = r" Maximum value the index can take."]
const MAX: Self = Self::from_u32(0xFFFF_FF00);
#[doc = r" Zero value of the index."]
const ZERO: Self = Self::from_u32(0);
#[doc = r" Creates a new index from a given `usize`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
const fn from_usize(value: usize) -> Self {
if !(value <= (0xFFFF_FF00 as usize)) {
::core::panicking::panic("assertion failed: value <= (0xFFFF_FF00 as usize)")
};
unsafe { Self::from_u32_unchecked(value as u32) }
}
#[doc = r" Creates a new index from a given `u32`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
const fn from_u32(value: u32) -> Self {
if !(value <= 0xFFFF_FF00) {
::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
};
unsafe { Self::from_u32_unchecked(value) }
}
#[doc = r" Creates a new index from a given `u16`."]
#[doc = r""]
#[doc = r" # Panics"]
#[doc = r""]
#[doc = r" Will panic if `value` exceeds `MAX`."]
#[inline]
const fn from_u16(value: u16) -> Self {
let value = value as u32;
if !(value <= 0xFFFF_FF00) {
::core::panicking::panic("assertion failed: value <= 0xFFFF_FF00")
};
unsafe { Self::from_u32_unchecked(value) }
}
#[doc = r" Creates a new index from a given `u32`."]
#[doc = r""]
#[doc = r" # Safety"]
#[doc = r""]
#[doc =
r" The provided value must be less than or equal to the maximum value for the newtype."]
#[doc =
r" Providing a value outside this range is undefined due to layout restrictions."]
#[doc = r""]
#[doc = r" Prefer using `from_u32`."]
#[inline]
const unsafe fn from_u32_unchecked(value: u32) -> Self {
Self {
private_use_as_methods_instead: unsafe {
std::mem::transmute(value)
},
}
}
#[doc = r" Extracts the value of this index as a `usize`."]
#[inline]
const fn index(self) -> usize { self.as_usize() }
#[doc = r" Extracts the value of this index as a `u32`."]
#[inline]
const fn as_u32(self) -> u32 {
unsafe {
std::mem::transmute(self.private_use_as_methods_instead)
}
}
#[doc = r" Extracts the value of this index as a `usize`."]
#[inline]
const fn as_usize(self) -> usize { self.as_u32() as usize }
}
impl std::ops::Add<usize> for ConditionIndex {
type Output = Self;
#[inline]
fn add(self, other: usize) -> Self {
Self::from_usize(self.index() + other)
}
}
impl std::ops::AddAssign<usize> for ConditionIndex {
#[inline]
fn add_assign(&mut self, other: usize) { *self = *self + other; }
}
impl rustc_index::Idx for ConditionIndex {
#[inline]
fn new(value: usize) -> Self { Self::from_usize(value) }
#[inline]
fn index(self) -> usize { self.as_usize() }
}
impl ::std::iter::Step for ConditionIndex {
#[inline]
fn steps_between(start: &Self, end: &Self) -> (usize, Option<usize>) {
<usize as
::std::iter::Step>::steps_between(&Self::index(*start),
&Self::index(*end))
}
#[inline]
fn forward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_add(u).map(Self::from_usize)
}
#[inline]
fn backward_checked(start: Self, u: usize) -> Option<Self> {
Self::index(start).checked_sub(u).map(Self::from_usize)
}
#[inline]
fn forward_overflowing(start: Self, u: usize) -> (Self, bool) {
let (s, o) = Self::index(start).overflowing_add(u);
(Self::from_usize(s), o)
}
#[inline]
fn backward_overflowing(start: Self, u: usize) -> (Self, bool) {
let (s, o) = Self::index(start).overflowing_sub(u);
(Self::from_usize(s), o)
}
}
impl ::std::cmp::Ord for ConditionIndex {
#[inline]
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
self.as_u32().cmp(&other.as_u32())
}
}
impl ::std::cmp::PartialOrd for ConditionIndex {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
impl From<ConditionIndex> for u32 {
#[inline]
fn from(v: ConditionIndex) -> u32 { v.as_u32() }
}
impl From<ConditionIndex> for usize {
#[inline]
fn from(v: ConditionIndex) -> usize { v.as_usize() }
}
impl From<usize> for ConditionIndex {
#[inline]
fn from(value: usize) -> Self { Self::from_usize(value) }
}
impl From<u32> for ConditionIndex {
#[inline]
fn from(value: u32) -> Self { Self::from_u32(value) }
}
impl ::std::cmp::Eq for ConditionIndex {}
impl ::std::cmp::PartialEq for ConditionIndex {
fn eq(&self, other: &Self) -> bool {
self.as_u32().eq(&other.as_u32())
}
}
impl ::std::marker::StructuralPartialEq for ConditionIndex {}
impl ::std::hash::Hash for ConditionIndex {
fn hash<H: ::std::hash::Hasher>(&self, state: &mut H) {
self.as_u32().hash(state)
}
}
impl ::std::fmt::Debug for ConditionIndex {
fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>)
-> ::std::fmt::Result {
fmt.write_fmt(format_args!("_c{0}", self.as_u32()))
}
}
struct Condition {
place: ValueIndex,
value: ScalarInt,
polarity: Polarity,
}
#[automatically_derived]
impl ::core::marker::Copy for Condition { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Condition { }
#[automatically_derived]
impl ::core::clone::Clone for Condition {
#[inline]
fn clone(&self) -> Condition {
let _: ::core::clone::AssertParamIsClone<ValueIndex>;
let _: ::core::clone::AssertParamIsClone<ScalarInt>;
let _: ::core::clone::AssertParamIsClone<Polarity>;
*self
}
}
#[automatically_derived]
impl ::core::fmt::Debug for Condition {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f, "Condition",
"place", &self.place, "value", &self.value, "polarity",
&&self.polarity)
}
}
#[automatically_derived]
impl ::core::hash::Hash for Condition {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.place, state);
::core::hash::Hash::hash(&self.value, state);
::core::hash::Hash::hash(&self.polarity, state)
}
}
#[automatically_derived]
impl ::core::cmp::Eq for Condition {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<ValueIndex>;
let _: ::core::cmp::AssertParamIsEq<ScalarInt>;
let _: ::core::cmp::AssertParamIsEq<Polarity>;
}
}
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for Condition { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Condition {
#[inline]
fn eq(&self, other: &Condition) -> bool {
self.place == other.place && self.value == other.value &&
self.polarity == other.polarity
}
}
enum Polarity { Ne, Eq, }
#[automatically_derived]
impl ::core::marker::Copy for Polarity { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Polarity { }
#[automatically_derived]
impl ::core::clone::Clone for Polarity {
#[inline]
fn clone(&self) -> Polarity { *self }
}
#[automatically_derived]
impl ::core::fmt::Debug for Polarity {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self { Polarity::Ne => "Ne", Polarity::Eq => "Eq", })
}
}
#[automatically_derived]
impl ::core::hash::Hash for Polarity {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
let __self_discr = ::core::intrinsics::discriminant_value(self);
::core::hash::Hash::hash(&__self_discr, state)
}
}
#[automatically_derived]
impl ::core::cmp::Eq for Polarity {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for Polarity { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Polarity {
#[inline]
fn eq(&self, other: &Polarity) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}
impl Condition {
fn matches(&self, place: ValueIndex, value: ScalarInt) -> bool {
self.place == place &&
(self.value == value) == (self.polarity == Polarity::Eq)
}
}
enum EdgeEffect {
Goto {
target: BasicBlock,
},
Chain {
succ_block: BasicBlock,
succ_condition: ConditionIndex,
},
}
#[automatically_derived]
impl ::core::marker::Copy for EdgeEffect { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for EdgeEffect { }
#[automatically_derived]
impl ::core::clone::Clone for EdgeEffect {
#[inline]
fn clone(&self) -> EdgeEffect {
let _: ::core::clone::AssertParamIsClone<BasicBlock>;
let _: ::core::clone::AssertParamIsClone<ConditionIndex>;
*self
}
}
#[automatically_derived]
impl ::core::fmt::Debug for EdgeEffect {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
EdgeEffect::Goto { target: __self_0 } =>
::core::fmt::Formatter::debug_struct_field1_finish(f,
"Goto", "target", &__self_0),
EdgeEffect::Chain {
succ_block: __self_0, succ_condition: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"Chain", "succ_block", __self_0, "succ_condition",
&__self_1),
}
}
}
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for EdgeEffect { }
#[automatically_derived]
impl ::core::cmp::PartialEq for EdgeEffect {
#[inline]
fn eq(&self, other: &EdgeEffect) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(EdgeEffect::Goto { target: __self_0 }, EdgeEffect::Goto {
target: __arg1_0 }) => __self_0 == __arg1_0,
(EdgeEffect::Chain {
succ_block: __self_0, succ_condition: __self_1 },
EdgeEffect::Chain {
succ_block: __arg1_0, succ_condition: __arg1_1 }) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}
#[automatically_derived]
impl ::core::cmp::Eq for EdgeEffect {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<BasicBlock>;
let _: ::core::cmp::AssertParamIsEq<ConditionIndex>;
}
}
#[automatically_derived]
impl ::core::cmp::PartialOrd for EdgeEffect {
#[inline]
fn partial_cmp(&self, other: &EdgeEffect)
-> ::core::option::Option<::core::cmp::Ordering> {
::core::option::Option::Some(::core::cmp::Ord::cmp(self, other))
}
}
#[automatically_derived]
impl ::core::cmp::Ord for EdgeEffect {
#[inline]
fn cmp(&self, other: &EdgeEffect) -> ::core::cmp::Ordering {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) {
::core::cmp::Ordering::Equal =>
match (self, other) {
(EdgeEffect::Goto { target: __self_0 }, EdgeEffect::Goto {
target: __arg1_0 }) =>
::core::cmp::Ord::cmp(__self_0, __arg1_0),
(EdgeEffect::Chain {
succ_block: __self_0, succ_condition: __self_1 },
EdgeEffect::Chain {
succ_block: __arg1_0, succ_condition: __arg1_1 }) =>
match ::core::cmp::Ord::cmp(__self_0, __arg1_0) {
::core::cmp::Ordering::Equal =>
::core::cmp::Ord::cmp(__self_1, __arg1_1),
cmp => cmp,
},
_ => unsafe { ::core::intrinsics::unreachable() }
},
cmp => cmp,
}
}
}
impl EdgeEffect {
fn block(self) -> BasicBlock {
match self {
EdgeEffect::Goto { target: bb } | EdgeEffect::Chain {
succ_block: bb, .. } => bb,
}
}
fn replace_block(&mut self, target: BasicBlock,
new_target: BasicBlock) {
match self {
EdgeEffect::Goto { target: bb } | EdgeEffect::Chain {
succ_block: bb, .. } => {
if *bb == target { *bb = new_target }
}
}
}
}
struct ConditionSet {
active: Vec<(ConditionIndex, Condition)>,
fulfilled: Vec<ConditionIndex>,
targets: IndexVec<ConditionIndex, Vec<EdgeEffect>>,
}
#[automatically_derived]
impl ::core::clone::Clone for ConditionSet {
#[inline]
fn clone(&self) -> ConditionSet {
ConditionSet {
active: ::core::clone::Clone::clone(&self.active),
fulfilled: ::core::clone::Clone::clone(&self.fulfilled),
targets: ::core::clone::Clone::clone(&self.targets),
}
}
}
#[automatically_derived]
impl ::core::fmt::Debug for ConditionSet {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field3_finish(f,
"ConditionSet", "active", &self.active, "fulfilled",
&self.fulfilled, "targets", &&self.targets)
}
}
#[automatically_derived]
impl ::core::default::Default for ConditionSet {
#[inline]
fn default() -> ConditionSet {
ConditionSet {
active: ::core::default::Default::default(),
fulfilled: ::core::default::Default::default(),
targets: ::core::default::Default::default(),
}
}
}
impl ConditionSet {
fn is_empty(&self) -> bool { self.active.is_empty() }
fn push_condition(&mut self, c: Condition, target: BasicBlock) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("push_condition",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(231u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("c")
}> =
::tracing::__macro_support::FieldName::new("c");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("target")
}> =
::tracing::__macro_support::FieldName::new("target");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&c)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let index =
self.targets.push(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[EdgeEffect::Goto { target }])));
self.active.push((index, c));
}
}
}
}
fn fulfill_if(&mut self,
f: impl Fn(Condition, &Vec<EdgeEffect>) -> bool) {
self.active.retain(|&(index, condition)|
{
let targets = &self.targets[index];
if f(condition, targets) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:242",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(242u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("index")
}> =
::tracing::__macro_support::FieldName::new("index");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("condition")
}> =
::tracing::__macro_support::FieldName::new("condition");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("fulfill")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&index)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&condition)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
self.fulfilled.push(index);
false
} else { true }
})
}
fn fulfill_matches(&mut self, place: ValueIndex, value: ScalarInt) {
self.fulfill_if(|c, _| c.matches(place, value))
}
fn retain(&mut self, mut f: impl FnMut(Condition) -> bool) {
self.active.retain(|&(_, c)| f(c))
}
fn retain_mut(&mut self,
mut f: impl FnMut(Condition) -> Option<Condition>) {
self.active.retain_mut(|(_, c)|
{
if let Some(new) = f(*c) { *c = new; true } else { false }
})
}
fn for_each_mut(&mut self, f: impl Fn(&mut Condition)) {
for (_, c) in &mut self.active { f(c) }
}
}
impl<'a, 'tcx> TOFinder<'a, 'tcx> {
fn place(&mut self, place: Place<'tcx>, tail: Option<TrackElem>)
-> Option<PlaceIndex> {
self.map.register_place(self.tcx, self.body, place, tail)
}
fn value(&mut self, place: PlaceIndex) -> Option<ValueIndex> {
self.map.register_value(self.tcx, self.typing_env, place)
}
fn place_value(&mut self, place: Place<'tcx>, tail: Option<TrackElem>)
-> Option<ValueIndex> {
let place = self.place(place, tail)?;
self.value(place)
}
#[doc =
" Construct the condition set for `bb` from the terminator, without executing its effect."]
fn populate_from_outgoing_edges(&mut self, bb: BasicBlock)
-> ConditionSet {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("populate_from_outgoing_edges",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(293u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("bb")
}> =
::tracing::__macro_support::FieldName::new("bb");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&bb)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: ConditionSet = loop {};
return __tracing_attr_fake_return;
}
{
let bbdata = &self.body[bb];
if true {
if !self.entry_states[bb].is_empty() {
::core::panicking::panic("assertion failed: self.entry_states[bb].is_empty()")
};
};
let state_len =
bbdata.terminator().successors().map(|succ|
self.entry_states[succ].active.len()).sum();
let mut state =
ConditionSet {
active: Vec::with_capacity(state_len),
targets: IndexVec::with_capacity(state_len),
fulfilled: Vec::new(),
};
let mut known_conditions =
FxIndexSet::with_capacity_and_hasher(state_len,
Default::default());
let mut insert =
|condition, succ_block, succ_condition|
{
let (index, new) = known_conditions.insert_full(condition);
let index = ConditionIndex::from_usize(index);
if new {
state.active.push((index, condition));
let _index = state.targets.push(Vec::new());
if true {
{
match (&_index, &index) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
}
let target =
EdgeEffect::Chain { succ_block, succ_condition };
if true {
if !!state.targets[index].contains(&target) {
{
::core::panicking::panic_fmt(format_args!("duplicate targets for index={1:?} as {2:?} targets={0:#?}",
&state.targets[index], index, target));
}
};
};
state.targets[index].push(target);
};
let mut seen = FxHashSet::default();
for succ in bbdata.terminator().successors() {
if !seen.insert(succ) { continue; }
if self.maybe_loop_headers.contains(succ) { continue; }
for &(succ_index, cond) in
self.entry_states[succ].active.iter() {
insert(cond, succ, succ_index);
}
}
let num_conditions = known_conditions.len();
if true {
{
match (&num_conditions, &state.active.len()) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
if true {
{
match (&num_conditions, &state.targets.len()) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
state.fulfilled.reserve(num_conditions);
state
}
}
}
}
fn flood_state(&self, place: Place<'tcx>,
extra_elem: Option<TrackElem>, state: &mut ConditionSet) {
if state.is_empty() { return; }
let mut places_to_exclude = FxHashSet::default();
self.map.for_each_aliasing_place(place.as_ref(), extra_elem,
&mut |vi| { places_to_exclude.insert(vi); });
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:367",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(367u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("places_to_exclude")
}> =
::tracing::__macro_support::FieldName::new("places_to_exclude");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("flood_state")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&places_to_exclude)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if places_to_exclude.is_empty() { return; }
state.retain(|c| !places_to_exclude.contains(&c.place));
}
#[doc = " Extract the mutated place from a statement."]
#[doc = ""]
#[doc =
" This method returns the `Place` so we can flood the state in case of a partial assignment."]
#[doc = " (_1 as Ok).0 = _5;"]
#[doc = " (_1 as Err).0 = _6;"]
#[doc =
" We want to ensure that a `SwitchInt((_1 as Ok).0)` does not see the first assignment, as"]
#[doc = " the value may have been mangled by the second assignment."]
#[doc = ""]
#[doc =
" In case we assign to a discriminant, we return `Some(TrackElem::Discriminant)`, so we can"]
#[doc =
" stop at flooding the discriminant, and preserve the variant fields."]
#[doc = " (_1 as Some).0 = _6;"]
#[doc = " SetDiscriminant(_1, 1);"]
#[doc = " switchInt((_1 as Some).0)"]
fn mutated_statement(&self, stmt: &Statement<'tcx>)
-> Option<(Place<'tcx>, Option<TrackElem>)> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("mutated_statement",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(387u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("stmt")
}> =
::tracing::__macro_support::FieldName::new("stmt");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&stmt)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<(Place<'tcx>, Option<TrackElem>)> = loop {};
return __tracing_attr_fake_return;
}
{
match stmt.kind {
StatementKind::Assign((place, _)) => Some((place, None)),
StatementKind::SetDiscriminant { ref place, variant_index: _
} => {
Some((**place, Some(TrackElem::Discriminant)))
}
StatementKind::StorageLive(local) |
StatementKind::StorageDead(local) => {
Some((Place::from(local), None))
}
StatementKind::Intrinsic(NonDivergingIntrinsic::Assume(..))
|
StatementKind::Intrinsic(NonDivergingIntrinsic::CopyNonOverlapping(..))
| StatementKind::AscribeUserType(..) |
StatementKind::Coverage(..) | StatementKind::FakeRead(..) |
StatementKind::ConstEvalCounter |
StatementKind::PlaceMention(..) |
StatementKind::BackwardIncompatibleDropHint { .. } |
StatementKind::Nop => None,
}
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:387",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(387u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn process_immediate(&mut self, lhs: PlaceIndex, rhs: ImmTy<'tcx>,
state: &mut ConditionSet) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("process_immediate",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(413u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("lhs")
}> =
::tracing::__macro_support::FieldName::new("lhs");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("rhs")
}> =
::tracing::__macro_support::FieldName::new("rhs");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&lhs)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&rhs)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
if let Some(lhs) = self.value(lhs) &&
let Immediate::Scalar(Scalar::Int(int)) = *rhs {
state.fulfill_matches(lhs, int)
}
}
}
}
}
#[doc =
" If we expect `lhs ?= A`, we have an opportunity if we assume `constant == A`."]
fn process_constant(&mut self, lhs: PlaceIndex, constant: OpTy<'tcx>,
state: &mut ConditionSet) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("process_constant",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(423u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("lhs")
}> =
::tracing::__macro_support::FieldName::new("lhs");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("constant")
}> =
::tracing::__macro_support::FieldName::new("constant");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&lhs)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&constant)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
self.map.for_each_projection_value(lhs, constant,
&mut |elem, op|
match elem {
TrackElem::Field(idx) =>
self.ecx.project_field(op, idx).discard_err(),
TrackElem::Variant(idx) =>
self.ecx.project_downcast(op, idx).discard_err(),
TrackElem::Discriminant => {
let variant = self.ecx.read_discriminant(op).discard_err()?;
let discr_value =
self.ecx.discriminant_for_variant(op.layout.ty,
variant).discard_err()?;
Some(discr_value.into())
}
TrackElem::DerefLen => {
let op: OpTy<'_> =
self.ecx.deref_pointer(op).discard_err()?.into();
let len_usize = op.len(&self.ecx).discard_err()?;
let layout =
self.ecx.layout_of(self.tcx.types.usize).unwrap();
Some(ImmTy::from_uint(len_usize, layout).into())
}
},
&mut |place, op|
{
if let Some(place) = self.map.value(place) &&
let Some(imm) =
self.ecx.read_immediate_raw(op).discard_err() &&
let Some(imm) = imm.right() &&
let Immediate::Scalar(Scalar::Int(int)) = *imm {
state.fulfill_matches(place, int)
}
});
}
}
}
}
fn process_copy(&mut self, lhs: PlaceIndex, rhs: PlaceIndex,
state: &mut ConditionSet) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("process_copy",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(461u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("lhs")
}> =
::tracing::__macro_support::FieldName::new("lhs");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("rhs")
}> =
::tracing::__macro_support::FieldName::new("rhs");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&lhs)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&rhs)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let mut renames = FxHashMap::default();
self.map.register_copy_tree(lhs, rhs,
&mut |lhs, rhs| { renames.insert(lhs, rhs); });
state.for_each_mut(|c|
{
if let Some(rhs) = renames.get(&c.place) { c.place = *rhs }
});
}
}
}
}
fn process_operand(&mut self, lhs: PlaceIndex, rhs: &Operand<'tcx>,
state: &mut ConditionSet) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("process_operand",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(478u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("lhs")
}> =
::tracing::__macro_support::FieldName::new("lhs");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("rhs")
}> =
::tracing::__macro_support::FieldName::new("rhs");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&lhs)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&rhs)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
match rhs {
Operand::Constant(constant) => {
let Some(constant) =
self.ecx.eval_mir_constant(&constant.const_, constant.span,
None).discard_err() else { return; };
self.process_constant(lhs, constant, state);
}
Operand::Move(rhs) | Operand::Copy(rhs) => {
let Some(rhs) = self.place(*rhs, None) else { return };
self.process_copy(lhs, rhs, state)
}
Operand::RuntimeChecks(_) => {}
}
}
}
}
}
fn process_assign(&mut self, lhs_place: &Place<'tcx>,
rvalue: &Rvalue<'tcx>, state: &mut ConditionSet) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("process_assign",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(499u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("lhs_place")
}> =
::tracing::__macro_support::FieldName::new("lhs_place");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("rvalue")
}> =
::tracing::__macro_support::FieldName::new("rvalue");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&lhs_place)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&rvalue)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let Some(lhs) =
self.place(*lhs_place, None) else { return };
match rvalue {
Rvalue::Use(operand, _) =>
self.process_operand(lhs, operand, state),
Rvalue::Discriminant(rhs) => {
let Some(rhs) =
self.place(*rhs,
Some(TrackElem::Discriminant)) else { return };
self.process_copy(lhs, rhs, state)
}
Rvalue::Aggregate(kind, operands) => {
let agg_ty = lhs_place.ty(self.body, self.tcx).ty;
let lhs =
match kind {
AggregateKind::Adt(.., Some(_)) => return,
AggregateKind::Adt(_, variant_index, ..) if agg_ty.is_enum()
=> {
let discr_ty = agg_ty.discriminant_ty(self.tcx);
let discr_target =
self.map.register_place_index(discr_ty, lhs,
TrackElem::Discriminant);
if let Some(discr_value) =
self.ecx.discriminant_for_variant(agg_ty,
*variant_index).discard_err() {
self.process_immediate(discr_target, discr_value, state);
}
self.map.register_place_index(agg_ty, lhs,
TrackElem::Variant(*variant_index))
}
_ => lhs,
};
for (field_index, operand) in operands.iter_enumerated() {
let operand_ty = operand.ty(self.body, self.tcx);
let field =
self.map.register_place_index(operand_ty, lhs,
TrackElem::Field(field_index));
self.process_operand(field, operand, state);
}
}
Rvalue::UnaryOp(UnOp::Not,
Operand::Move(operand) | Operand::Copy(operand)) => {
let layout =
self.ecx.layout_of(operand.ty(self.body,
self.tcx).ty).unwrap();
let Some(lhs) = self.value(lhs) else { return };
let Some(operand) =
self.place_value(*operand, None) else { return };
state.retain_mut(|mut c|
{
if c.place == lhs {
let value =
self.ecx.unary_op(UnOp::Not,
&ImmTy::from_scalar_int(c.value,
layout)).discard_err()?.to_scalar_int().discard_err()?;
c.place = operand;
c.value = value;
}
Some(c)
});
}
Rvalue::BinaryOp(op,
(Operand::Move(operand) | Operand::Copy(operand),
Operand::Constant(value)) |
(Operand::Constant(value),
Operand::Move(operand) | Operand::Copy(operand))) => {
let equals =
match op {
BinOp::Eq => ScalarInt::TRUE,
BinOp::Ne => ScalarInt::FALSE,
_ => return,
};
if value.const_.ty().is_floating_point() { return; }
let Some(lhs) = self.value(lhs) else { return };
let Some(operand) =
self.place_value(*operand, None) else { return };
let Some(value) =
value.const_.try_eval_scalar_int(self.tcx,
self.typing_env) else { return; };
state.for_each_mut(|c|
{
if c.place == lhs {
let polarity =
if c.matches(lhs, equals) {
Polarity::Eq
} else { Polarity::Ne };
c.place = operand;
c.value = value;
c.polarity = polarity;
}
});
}
_ => {}
}
}
}
}
}
fn process_statement(&mut self, stmt: &Statement<'tcx>,
state: &mut ConditionSet) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("process_statement",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(606u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("stmt")
}> =
::tracing::__macro_support::FieldName::new("stmt");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&stmt)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
match &stmt.kind {
StatementKind::SetDiscriminant { place, variant_index } => {
let Some(discr_target) =
self.place(**place,
Some(TrackElem::Discriminant)) else { return; };
let enum_ty = place.ty(self.body, self.tcx).ty;
let Some(discr) =
self.ecx.discriminant_for_variant(enum_ty,
*variant_index).discard_err() else { return; };
self.process_immediate(discr_target, discr, state)
}
StatementKind::Intrinsic(NonDivergingIntrinsic::Assume(Operand::Copy(place)
| Operand::Move(place))) => {
let Some(place) =
self.place_value(*place, None) else { return };
state.fulfill_matches(place, ScalarInt::TRUE);
}
StatementKind::Assign((lhs_place, rhs)) =>
self.process_assign(lhs_place, rhs, state),
_ => {}
}
}
}
}
}
#[doc =
" Execute the terminator for block `bb` into state `entry_states[bb]`."]
fn process_terminator(&mut self, bb: BasicBlock,
state: &mut ConditionSet) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("process_terminator",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(642u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("bb")
}> =
::tracing::__macro_support::FieldName::new("bb");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&bb)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let term = self.body.basic_blocks[bb].terminator();
let place_to_flood =
match term.kind {
TerminatorKind::FalseEdge { .. } |
TerminatorKind::FalseUnwind { .. } | TerminatorKind::Yield {
.. } =>
::rustc_middle::util::bug::bug_fmt(format_args!("{0:?} invalid",
term)),
TerminatorKind::InlineAsm { .. } => {
state.active.clear();
return;
}
TerminatorKind::SwitchInt { ref discr, ref targets } => {
return self.process_switch_int(discr, targets, state);
}
TerminatorKind::UnwindResume |
TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return
| TerminatorKind::Unreachable |
TerminatorKind::CoroutineDrop | TerminatorKind::Assert { ..
} | TerminatorKind::Goto { .. } => None,
TerminatorKind::Drop { place: destination, .. } |
TerminatorKind::Call { destination, .. } =>
Some(destination),
TerminatorKind::TailCall { .. } =>
Some(RETURN_PLACE.into()),
};
if let Some(place_to_flood) = place_to_flood {
self.flood_state(place_to_flood, None, state);
}
}
}
}
}
fn process_switch_int(&mut self, discr: &Operand<'tcx>,
targets: &SwitchTargets, state: &mut ConditionSet) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("process_switch_int",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(680u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("discr")
}> =
::tracing::__macro_support::FieldName::new("discr");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("targets")
}> =
::tracing::__macro_support::FieldName::new("targets");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("state")
}> =
::tracing::__macro_support::FieldName::new("state");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&discr)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&targets)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&state)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let Some(discr) = discr.place() else { return };
let Some(discr_idx) =
self.place_value(discr, None) else { return };
let discr_ty = discr.ty(self.body, self.tcx).ty;
let Ok(discr_layout) =
self.ecx.layout_of(discr_ty) else { return };
if targets.is_distinct() {
for &(index, c) in state.active.iter() {
if c.place != discr_idx { continue; }
let mut edges_fulfilling_condition = FxHashSet::default();
for (branch, tgt) in targets.iter() {
if let Some(branch) =
ScalarInt::try_from_uint(branch, discr_layout.size) &&
c.matches(discr_idx, branch) {
edges_fulfilling_condition.insert(tgt);
}
}
if c.polarity == Polarity::Ne &&
let value = c.value.to_bits(discr_layout.size) &&
targets.all_values().contains(&value.into()) {
edges_fulfilling_condition.insert(targets.otherwise());
}
let condition_targets = &state.targets[index];
let new_edges: Vec<_> =
condition_targets.iter().copied().filter(|&target|
match target {
EdgeEffect::Goto { .. } => false,
EdgeEffect::Chain { succ_block, .. } => {
edges_fulfilling_condition.contains(&succ_block)
}
}).collect();
if new_edges.len() == condition_targets.len() {
state.fulfilled.push(index);
} else {
let index = state.targets.push(new_edges);
state.fulfilled.push(index);
}
}
}
let mut mk_condition =
|value, polarity, target|
{
let c = Condition { place: discr_idx, value, polarity };
state.push_condition(c, target);
};
if let Some((value, then_, else_)) = targets.as_static_if()
{
let Some(value) =
ScalarInt::try_from_uint(value,
discr_layout.size) else { return };
mk_condition(value, Polarity::Eq, then_);
mk_condition(value, Polarity::Ne, else_);
} else {
for (value, target) in targets.iter() {
if let Some(value) =
ScalarInt::try_from_uint(value, discr_layout.size) {
mk_condition(value, Polarity::Eq, target);
}
}
}
}
}
}
}
}
#[doc =
" Propagate fulfilled conditions forward in the CFG to reduce the amount of duplication."]
fn simplify_conditions(body: &Body<'_>,
entry_states: &mut IndexVec<BasicBlock, ConditionSet>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("simplify_conditions",
"rustc_mir_transform::jump_threading",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(776u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let basic_blocks = &body.basic_blocks;
let reverse_postorder = basic_blocks.reverse_postorder();
let mut predecessors =
IndexVec::from_elem(0, &entry_states);
predecessors[START_BLOCK] = 1;
for &bb in reverse_postorder {
let term = basic_blocks[bb].terminator();
for s in term.successors() { predecessors[s] += 1; }
}
let mut fulfill_in_pred_count =
IndexVec::from_fn_n(|bb: BasicBlock|
IndexVec::from_elem_n(0, entry_states[bb].targets.len()),
entry_states.len());
for &bb in reverse_postorder {
let preds = predecessors[bb];
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:801",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(801u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("bb")
}> =
::tracing::__macro_support::FieldName::new("bb");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("preds")
}> =
::tracing::__macro_support::FieldName::new("preds");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&bb)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&preds)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if preds == 0 { continue; }
let state = &mut entry_states[bb];
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:809",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(809u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("state")
}> =
::tracing::__macro_support::FieldName::new("state");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&state)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:812",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(812u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("fulfilled_count")
}> =
::tracing::__macro_support::FieldName::new("fulfilled_count");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&fulfill_in_pred_count[bb])
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
for (condition, &cond_preds) in
fulfill_in_pred_count[bb].iter_enumerated() {
if cond_preds == preds {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:815",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(815u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("condition")
}> =
::tracing::__macro_support::FieldName::new("condition");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&condition)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
state.fulfilled.push(condition);
}
}
let mut targets: Vec<_> =
state.fulfilled.iter().flat_map(|&index|
state.targets[index].iter().copied()).collect();
targets.sort();
targets.dedup();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:829",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(829u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("targets")
}> =
::tracing::__macro_support::FieldName::new("targets");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&targets)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let mut successors =
basic_blocks[bb].terminator().successors().collect::<Vec<_>>();
targets.reverse();
while let Some(target) = targets.pop() {
match target {
EdgeEffect::Goto { target } => {
predecessors[target] += 1;
for &s in successors.iter() { predecessors[s] -= 1; }
targets.retain(|t| t.block() == target);
successors.clear();
successors.push(target);
}
EdgeEffect::Chain { succ_block, succ_condition } => {
let count =
successors.iter().filter(|&&s| s == succ_block).count();
fulfill_in_pred_count[succ_block][succ_condition] += count;
}
}
}
}
}
}
}
}
fn remove_costly_conditions<'tcx>(tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>, body: &Body<'tcx>,
entry_states: &mut IndexVec<BasicBlock, ConditionSet>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("remove_costly_conditions",
"rustc_mir_transform::jump_threading",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(860u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let basic_blocks = &body.basic_blocks;
let mut costs = IndexVec::from_elem(None, basic_blocks);
let mut cost =
|bb: BasicBlock| -> u8
{
let c =
*costs[bb].get_or_insert_with(||
{
let bbdata = &basic_blocks[bb];
let mut cost =
CostChecker::new(tcx, typing_env, None, body);
cost.visit_basic_block_data(bb, bbdata);
cost.cost().try_into().unwrap_or(MAX_COST)
});
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:877",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(877u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("cost[{0:?}] = {1}",
bb, c) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
c
};
let mut condition_cost =
IndexVec::from_fn_n(|bb: BasicBlock|
IndexVec::from_elem_n(MAX_COST,
entry_states[bb].targets.len()), entry_states.len());
let reverse_postorder = basic_blocks.reverse_postorder();
for &bb in reverse_postorder.iter().rev() {
let state = &entry_states[bb];
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:891",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(891u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("bb")
}> =
::tracing::__macro_support::FieldName::new("bb");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("state")
}> =
::tracing::__macro_support::FieldName::new("state");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&bb)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&state)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let mut current_costs =
IndexVec::from_elem(0u8, &state.targets);
for (condition, targets) in state.targets.iter_enumerated()
{
for &target in targets {
match target {
EdgeEffect::Goto { .. } => {}
EdgeEffect::Chain { succ_block, succ_condition } if
entry_states[succ_block].fulfilled.contains(&succ_condition)
=> {}
EdgeEffect::Chain { succ_block, succ_condition } => {
let duplication_cost = cost(succ_block);
let target_cost =
*condition_cost[succ_block].get(succ_condition).unwrap_or(&MAX_COST);
let cost =
current_costs[condition].saturating_add(duplication_cost).saturating_add(target_cost);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:913",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(913u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("condition")
}> =
::tracing::__macro_support::FieldName::new("condition");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("succ_block")
}> =
::tracing::__macro_support::FieldName::new("succ_block");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("duplication_cost")
}> =
::tracing::__macro_support::FieldName::new("duplication_cost");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("target_cost")
}> =
::tracing::__macro_support::FieldName::new("target_cost");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&condition)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&succ_block)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&duplication_cost)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target_cost)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
current_costs[condition] = cost;
}
}
}
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:920",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(920u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("condition_cost[{1:?}] = {0:?}",
current_costs, bb) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
condition_cost[bb] = current_costs;
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:924",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(924u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("condition_cost")
}> =
::tracing::__macro_support::FieldName::new("condition_cost");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&condition_cost)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
for &bb in reverse_postorder {
for (index, targets) in
entry_states[bb].targets.iter_enumerated_mut() {
if condition_cost[bb][index] >= MAX_COST {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:929",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(929u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("bb")
}> =
::tracing::__macro_support::FieldName::new("bb");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("index")
}> =
::tracing::__macro_support::FieldName::new("index");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("targets")
}> =
::tracing::__macro_support::FieldName::new("targets");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("c")
}> =
::tracing::__macro_support::FieldName::new("c");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("remove")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&bb)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&index)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&targets)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&condition_cost[bb][index])
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
targets.clear()
}
}
}
}
}
}
}
struct OpportunitySet<'a, 'tcx> {
basic_blocks: &'a mut IndexVec<BasicBlock, BasicBlockData<'tcx>>,
entry_states: IndexVec<BasicBlock, ConditionSet>,
duplicates: FxHashMap<(BasicBlock, ConditionIndex), BasicBlock>,
}
impl<'a, 'tcx> OpportunitySet<'a, 'tcx> {
fn new(body: &'a mut Body<'tcx>,
mut entry_states: IndexVec<BasicBlock, ConditionSet>)
-> Option<OpportunitySet<'a, 'tcx>> {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:949",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(949u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("apply")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&body.source.def_id())
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if entry_states.iter().all(|state| state.fulfilled.is_empty()) {
return None;
}
for state in entry_states.iter_mut() {
state.active = Default::default();
}
let duplicates = Default::default();
let basic_blocks = body.basic_blocks.as_mut();
Some(OpportunitySet { basic_blocks, entry_states, duplicates })
}
#[doc = " Apply the opportunities on the graph."]
fn apply(mut self) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("apply",
"rustc_mir_transform::jump_threading",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(965u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let mut worklist =
Vec::with_capacity(self.basic_blocks.len());
worklist.push(START_BLOCK);
let mut visited =
GrowableBitSet::with_capacity(self.basic_blocks.len());
while let Some(bb) = worklist.pop() {
if !visited.insert(bb) { continue; }
self.apply_once(bb);
worklist.extend(self.basic_blocks[bb].terminator().successors());
}
}
}
}
}
#[doc = " Apply the opportunities on `bb`."]
fn apply_once(&mut self, bb: BasicBlock) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("apply_once",
"rustc_mir_transform::jump_threading",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(987u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("bb")
}> =
::tracing::__macro_support::FieldName::new("bb");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&bb)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let state = &mut self.entry_states[bb];
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:990",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(990u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("state")
}> =
::tracing::__macro_support::FieldName::new("state");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&state)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let mut targets: Vec<_> =
state.fulfilled.iter().flat_map(|&index|
std::mem::take(&mut state.targets[index])).collect();
targets.sort();
targets.dedup();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:1001",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(1001u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("targets")
}> =
::tracing::__macro_support::FieldName::new("targets");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&targets)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
targets.reverse();
while let Some(target) = targets.pop() {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:1006",
"rustc_mir_transform::jump_threading",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(1006u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("target")
}> =
::tracing::__macro_support::FieldName::new("target");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:1007",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(1007u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("term")
}> =
::tracing::__macro_support::FieldName::new("term");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.basic_blocks[bb].terminator().kind)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if true {
if !self.basic_blocks[bb].terminator().successors().contains(&target.block())
{
{
::core::panicking::panic_fmt(format_args!("missing {1:?} in successors for {2:?}, term={0:?}",
self.basic_blocks[bb].terminator(), target, bb));
}
};
};
match target {
EdgeEffect::Goto { target } => {
self.apply_goto(bb, target);
targets.retain(|t| t.block() == target);
for ts in self.entry_states[bb].targets.iter_mut() {
ts.retain(|t| t.block() == target);
}
}
EdgeEffect::Chain { succ_block, succ_condition } => {
let new_succ_block =
self.apply_chain(bb, succ_block, succ_condition);
if let Some(new_succ_block) = new_succ_block {
for t in targets.iter_mut() {
t.replace_block(succ_block, new_succ_block)
}
for t in
self.entry_states[bb].targets.iter_mut().flat_map(|ts|
ts.iter_mut()) {
t.replace_block(succ_block, new_succ_block)
}
}
}
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:1047",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(1047u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("post_term")
}> =
::tracing::__macro_support::FieldName::new("post_term");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&self.basic_blocks[bb].terminator().kind)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
}
}
}
}
}
fn apply_goto(&mut self, bb: BasicBlock, target: BasicBlock) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("apply_goto",
"rustc_mir_transform::jump_threading",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(1051u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("bb")
}> =
::tracing::__macro_support::FieldName::new("bb");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("target")
}> =
::tracing::__macro_support::FieldName::new("target");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&bb)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
self.basic_blocks[bb].terminator_mut().kind =
TerminatorKind::Goto { target };
}
}
}
}
fn apply_chain(&mut self, bb: BasicBlock, target: BasicBlock,
condition: ConditionIndex) -> Option<BasicBlock> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("apply_chain",
"rustc_mir_transform::jump_threading",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(1056u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("bb")
}> =
::tracing::__macro_support::FieldName::new("bb");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("target")
}> =
::tracing::__macro_support::FieldName::new("target");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("condition")
}> =
::tracing::__macro_support::FieldName::new("condition");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&bb)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&condition)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Option<BasicBlock> =
loop {};
return __tracing_attr_fake_return;
}
{
if self.entry_states[target].fulfilled.contains(&condition)
{
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:1065",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(1065u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("fulfilled")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return None;
}
let new_target =
*self.duplicates.entry((target,
condition)).or_insert_with(||
{
let new_target =
self.basic_blocks.push(self.basic_blocks[target].clone());
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:1078",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(1078u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("target")
}> =
::tracing::__macro_support::FieldName::new("target");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("new_target")
}> =
::tracing::__macro_support::FieldName::new("new_target");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("condition")
}> =
::tracing::__macro_support::FieldName::new("condition");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("clone")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&new_target)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&condition)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let mut condition_set = self.entry_states[target].clone();
condition_set.fulfilled.push(condition);
let _new_target = self.entry_states.push(condition_set);
if true {
{
match (&new_target, &_new_target) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
new_target
});
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:1089",
"rustc_mir_transform::jump_threading",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(1089u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("target")
}> =
::tracing::__macro_support::FieldName::new("target");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("new_target")
}> =
::tracing::__macro_support::FieldName::new("new_target");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("condition")
}> =
::tracing::__macro_support::FieldName::new("condition");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("reuse")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&new_target)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&condition)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
self.basic_blocks[bb].terminator_mut().successors_mut(|s|
{ if *s == target { *s = new_target; } });
Some(new_target)
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs:1056",
"rustc_mir_transform::jump_threading",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/jump_threading.rs"),
::tracing_core::__macro_support::Option::Some(1056u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::jump_threading"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
}
fn maybe_loop_headers(body: &Body<'_>) -> DenseBitSet<BasicBlock> {
let mut maybe_loop_headers =
DenseBitSet::new_empty(body.basic_blocks.len());
let mut visited = DenseBitSet::new_empty(body.basic_blocks.len());
for (bb, bbdata) in traversal::postorder(body) {
for succ in bbdata.terminator().successors() {
if !visited.contains(succ) {
maybe_loop_headers.insert(succ);
}
}
let _new = visited.insert(bb);
if true {
if !_new {
::core::panicking::panic("assertion failed: _new")
};
};
}
maybe_loop_headers
}
}
#[allow(unused_imports)]
use jump_threading::JumpThreading as _;
mod known_panics_lint {
use std::fmt::Debug;
use rustc_abi::{
BackendRepr, FieldIdx, HasDataLayout, Size, TargetDataLayout,
VariantIdx,
};
use rustc_const_eval::const_eval::DummyMachine;
use rustc_const_eval::interpret::{
ImmTy, InterpCx, InterpResult, Projectable, Scalar, interp_ok,
};
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def::DefKind;
use rustc_hir::{HirId, find_attr};
use rustc_index::IndexVec;
use rustc_index::bit_set::DenseBitSet;
use rustc_lint_defs::builtin::UNCONDITIONAL_PANIC;
use rustc_middle::bug;
use rustc_middle::mir::visit::{
MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor,
};
use rustc_middle::mir::*;
use rustc_middle::ty::layout::{
LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout,
};
use rustc_middle::ty::{
self, ConstInt, GenericArgKind, GenericParamDefKind, ScalarInt, Ty,
TyCtxt, TypeVisitableExt, Unnormalized,
};
use rustc_span::Span;
use tracing::{debug, instrument, trace};
use crate::diagnostics::{AssertLint, AssertLintKind, ConstNIsZero};
pub(super) struct KnownPanicsLint;
impl<'tcx> crate::MirLint<'tcx> for KnownPanicsLint {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
if body.tainted_by_errors.is_some() { return; }
let def_id = body.source.def_id().expect_local();
let def_kind = tcx.def_kind(def_id);
let is_fn_like = def_kind.is_fn_like();
let is_assoc_const =
#[allow(non_exhaustive_omitted_patterns)] match def_kind {
DefKind::AssocConst { .. } => true,
_ => false,
};
if !is_fn_like && !is_assoc_const {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:45",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(45u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("KnownPanicsLint skipped for {0:?}",
def_id) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return;
}
if tcx.is_coroutine(def_id.to_def_id()) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:52",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(52u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("KnownPanicsLint skipped for coroutine {0:?}",
def_id) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return;
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:56",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(56u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("KnownPanicsLint starting for {0:?}",
def_id) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let mut linter = ConstPropagator::new(body, tcx);
linter.visit_body(body);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:61",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(61u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("KnownPanicsLint done for {0:?}",
def_id) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
}
}
struct ConstPropagator<'mir, 'tcx> {
ecx: InterpCx<'tcx, DummyMachine>,
tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
worklist: Vec<BasicBlock>,
visited_blocks: DenseBitSet<BasicBlock>,
locals: IndexVec<Local, Value<'tcx>>,
body: &'mir Body<'tcx>,
written_only_inside_own_block_locals: FxHashSet<Local>,
can_const_prop: IndexVec<Local, ConstPropMode>,
}
enum Value<'tcx> {
Immediate(ImmTy<'tcx>),
Aggregate {
variant: VariantIdx,
fields: IndexVec<FieldIdx, Value<'tcx>>,
},
Uninit,
}
#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for Value<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Value::Immediate(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f,
"Immediate", &__self_0),
Value::Aggregate { variant: __self_0, fields: __self_1 } =>
::core::fmt::Formatter::debug_struct_field2_finish(f,
"Aggregate", "variant", __self_0, "fields", &__self_1),
Value::Uninit =>
::core::fmt::Formatter::write_str(f, "Uninit"),
}
}
}
#[automatically_derived]
impl<'tcx> ::core::clone::Clone for Value<'tcx> {
#[inline]
fn clone(&self) -> Value<'tcx> {
match self {
Value::Immediate(__self_0) =>
Value::Immediate(::core::clone::Clone::clone(__self_0)),
Value::Aggregate { variant: __self_0, fields: __self_1 } =>
Value::Aggregate {
variant: ::core::clone::Clone::clone(__self_0),
fields: ::core::clone::Clone::clone(__self_1),
},
Value::Uninit => Value::Uninit,
}
}
}
impl<'tcx> From<ImmTy<'tcx>> for Value<'tcx> {
fn from(v: ImmTy<'tcx>) -> Self { Self::Immediate(v) }
}
impl<'tcx> Value<'tcx> {
fn project(&self, proj: &[PlaceElem<'tcx>],
prop: &ConstPropagator<'_, 'tcx>) -> Option<&Value<'tcx>> {
let mut this = self;
for proj in proj {
this =
match (*proj, this) {
(PlaceElem::Field(idx, _), Value::Aggregate { fields, .. })
=> {
fields.get(idx).unwrap_or(&Value::Uninit)
}
(PlaceElem::Index(idx), Value::Aggregate { fields, .. }) =>
{
let idx = prop.get_const(idx.into())?.immediate()?;
let idx =
prop.ecx.read_target_usize(idx).discard_err()?.try_into().ok()?;
if idx <= FieldIdx::MAX_AS_U32 {
fields.get(FieldIdx::from_u32(idx)).unwrap_or(&Value::Uninit)
} else { return None; }
}
(PlaceElem::ConstantIndex {
offset, min_length: _, from_end: false }, Value::Aggregate {
fields, .. }) =>
fields.get(FieldIdx::from_u32(offset.try_into().ok()?)).unwrap_or(&Value::Uninit),
_ => return None,
};
}
Some(this)
}
fn project_mut(&mut self, proj: &[PlaceElem<'_>])
-> Option<&mut Value<'tcx>> {
let mut this = self;
for proj in proj {
this =
match (proj, this) {
(PlaceElem::Field(idx, _), Value::Aggregate { fields, .. })
=> {
fields.ensure_contains_elem(*idx, || Value::Uninit)
}
(PlaceElem::Field(..), val @ Value::Uninit) => {
*val =
Value::Aggregate {
variant: VariantIdx::ZERO,
fields: Default::default(),
};
val.project_mut(&[*proj])?
}
_ => return None,
};
}
Some(this)
}
fn immediate(&self) -> Option<&ImmTy<'tcx>> {
match self { Value::Immediate(op) => Some(op), _ => None, }
}
}
impl<'tcx> LayoutOfHelpers<'tcx> for ConstPropagator<'_, 'tcx> {
type LayoutOfResult = Result<TyAndLayout<'tcx>, LayoutError<'tcx>>;
#[inline]
fn handle_layout_err(&self, err: LayoutError<'tcx>, _: Span,
_: Ty<'tcx>) -> LayoutError<'tcx> {
err
}
}
impl HasDataLayout for ConstPropagator<'_, '_> {
#[inline]
fn data_layout(&self) -> &TargetDataLayout { &self.tcx.data_layout }
}
impl<'tcx> ty::layout::HasTyCtxt<'tcx> for ConstPropagator<'_, 'tcx> {
#[inline]
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
}
impl<'tcx> ty::layout::HasTypingEnv<'tcx> for ConstPropagator<'_, 'tcx> {
#[inline]
fn typing_env(&self) -> ty::TypingEnv<'tcx> { self.typing_env }
}
impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
fn new(body: &'mir Body<'tcx>, tcx: TyCtxt<'tcx>)
-> ConstPropagator<'mir, 'tcx> {
let def_id = body.source.def_id();
let typing_env =
ty::TypingEnv::post_analysis(tcx, body.source.def_id());
let can_const_prop = CanConstProp::check(tcx, typing_env, body);
let ecx =
InterpCx::new(tcx, tcx.def_span(def_id), typing_env,
DummyMachine);
ConstPropagator {
ecx,
tcx,
typing_env,
worklist: ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[START_BLOCK])),
visited_blocks: DenseBitSet::new_empty(body.basic_blocks.len()),
locals: IndexVec::from_elem_n(Value::Uninit,
body.local_decls.len()),
body,
can_const_prop,
written_only_inside_own_block_locals: Default::default(),
}
}
fn local_decls(&self) -> &'mir LocalDecls<'tcx> {
&self.body.local_decls
}
fn get_const(&self, place: Place<'tcx>) -> Option<&Value<'tcx>> {
self.locals[place.local].project(&place.projection, self)
}
fn remove_const(&mut self, local: Local) {
self.locals[local] = Value::Uninit;
self.written_only_inside_own_block_locals.remove(&local);
}
fn access_mut(&mut self, place: &Place<'_>)
-> Option<&mut Value<'tcx>> {
match self.can_const_prop[place.local] {
ConstPropMode::NoPropagation => return None,
ConstPropMode::OnlyInsideOwnBlock => {
self.written_only_inside_own_block_locals.insert(place.local);
}
ConstPropMode::FullConstProp => {}
}
self.locals[place.local].project_mut(place.projection)
}
fn lint_root(&self, source_info: SourceInfo) -> Option<HirId> {
source_info.scope.lint_root(&self.body.source_scopes)
}
fn use_ecx<F, T>(&mut self, f: F) -> Option<T> where
F: FnOnce(&mut Self) -> InterpResult<'tcx, T> {
f(self).inspect_err_info(|err|
{
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:239",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(239u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("InterpCx operation failed: {0:?}",
err) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if !!err.kind().formatted_string() {
{
::core::panicking::panic_fmt(format_args!("known panics lint encountered formatting error: {0}",
err.to_string()));
}
};
}).discard_err()
}
fn eval_constant(&mut self, c: &ConstOperand<'tcx>)
-> Option<ImmTy<'tcx>> {
if c.has_param() { return None; }
let val =
self.tcx.try_normalize_erasing_regions(self.typing_env,
Unnormalized::new_wip(c.const_)).ok()?;
self.use_ecx(|this|
this.ecx.eval_mir_constant(&val, c.span,
None))?.as_mplace_or_imm().right()
}
#[doc = " Returns the value, if any, of evaluating `place`."]
fn eval_place(&mut self, place: Place<'tcx>) -> Option<ImmTy<'tcx>> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("eval_place",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(276u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("place")
}> =
::tracing::__macro_support::FieldName::new("place");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Option<ImmTy<'tcx>> =
loop {};
return __tracing_attr_fake_return;
}
{
match self.get_const(place)? {
Value::Immediate(imm) => Some(imm.clone()),
Value::Aggregate { .. } => None,
Value::Uninit => None,
}
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:276",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(276u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
fn eval_operand(&mut self, op: &Operand<'tcx>)
-> Option<ImmTy<'tcx>> {
match *op {
Operand::RuntimeChecks(_) => None,
Operand::Constant(ref c) => self.eval_constant(c),
Operand::Move(place) | Operand::Copy(place) =>
self.eval_place(place),
}
}
fn report_assert_as_lint(&self, location: Location,
lint_kind: AssertLintKind, assert_kind: AssertKind<impl Debug>) {
let source_info = self.body.source_info(location);
if let Some(lint_root) = self.lint_root(*source_info) {
let span = source_info.span;
self.tcx.emit_node_span_lint(lint_kind.lint(), lint_root,
span, AssertLint { span, assert_kind, lint_kind });
}
}
fn check_unary_op(&mut self, op: UnOp, arg: &Operand<'tcx>,
location: Location) -> Option<()> {
let arg = self.eval_operand(arg)?;
if op == UnOp::Neg && arg.layout.ty.is_integral() {
let (arg, overflow) =
self.use_ecx(|this|
{
let arg = this.ecx.read_immediate(&arg)?;
let (_res, overflow) =
this.ecx.binary_op(BinOp::SubWithOverflow,
&ImmTy::from_int(0, arg.layout), &arg)?.to_scalar_pair();
interp_ok((arg, overflow.to_bool()?))
})?;
if overflow {
self.report_assert_as_lint(location,
AssertLintKind::ArithmeticOverflow,
AssertKind::OverflowNeg(arg.to_const_int()));
return None;
}
}
Some(())
}
fn check_binary_op(&mut self, op: BinOp, left: &Operand<'tcx>,
right: &Operand<'tcx>, location: Location) -> Option<()> {
let r =
self.eval_operand(right).and_then(|r|
self.use_ecx(|this| this.ecx.read_immediate(&r)));
let l =
self.eval_operand(left).and_then(|l|
self.use_ecx(|this| this.ecx.read_immediate(&l)));
if #[allow(non_exhaustive_omitted_patterns)] match op {
BinOp::Shr | BinOp::Shl => true,
_ => false,
} {
let r = r.clone()?;
let left_ty = left.ty(self.local_decls(), self.tcx);
let left_size = self.ecx.layout_of(left_ty).ok()?.size;
let right_size = r.layout.size;
let r_bits = r.to_scalar().to_bits(right_size).discard_err();
if r_bits.is_some_and(|b| b >= left_size.bits() as u128) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:360",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(360u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("check_binary_op: reporting assert for {0:?}",
location) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let panic =
AssertKind::Overflow(op,
ConstInt::new(ScalarInt::try_from_uint(1_u8,
left_size).unwrap(), left_ty.is_signed(),
left_ty.is_ptr_sized_integral()), r.to_const_int());
self.report_assert_as_lint(location,
AssertLintKind::ArithmeticOverflow, panic);
return None;
}
}
let op = op.wrapping_to_overflowing().unwrap_or(op);
if let (Some(l), Some(r)) = (l, r) && l.layout.ty.is_integral() &&
op.is_overflowing() &&
self.use_ecx(|this|
{
let (_res, overflow) =
this.ecx.binary_op(op, &l, &r)?.to_scalar_pair();
overflow.to_bool()
})? {
self.report_assert_as_lint(location,
AssertLintKind::ArithmeticOverflow,
AssertKind::Overflow(op, l.to_const_int(),
r.to_const_int()));
return None;
}
Some(())
}
fn check_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location)
-> Option<()> {
match rvalue {
Rvalue::UnaryOp(op, arg) => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:416",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(416u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("checking UnaryOp(op = {0:?}, arg = {1:?})",
op, arg) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
self.check_unary_op(*op, arg, location)?;
}
Rvalue::BinaryOp(op, (left, right)) => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:420",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(420u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("checking BinaryOp(op = {0:?}, left = {1:?}, right = {2:?})",
op, left, right) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
self.check_binary_op(*op, left, right, location)?;
}
Rvalue::RawPtr(_, place) | Rvalue::Ref(_, _, place) |
Rvalue::Reborrow(_, _, place) => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:426",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(426u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("skipping RawPtr | Ref | Reborrow for {0:?}",
place) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
self.remove_const(place.local);
return None;
}
Rvalue::ThreadLocalRef(def_id) => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:439",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(439u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("skipping ThreadLocalRef({0:?})",
def_id) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return None;
}
Rvalue::Aggregate(..) | Rvalue::Use(..) |
Rvalue::CopyForDeref(..) | Rvalue::Repeat(..) |
Rvalue::Cast(..) | Rvalue::Discriminant(..) |
Rvalue::WrapUnsafeBinder(..) => {}
}
if rvalue.has_param() { return None; }
if !rvalue.ty(self.local_decls(),
self.tcx).is_sized(self.tcx, self.typing_env) {
return None;
}
Some(())
}
fn check_assertion(&mut self, expected: bool,
msg: &AssertKind<Operand<'tcx>>, cond: &Operand<'tcx>,
location: Location) {
let Some(value) = &self.eval_operand(cond) else { return };
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:475",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(475u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("assertion on {0:?} should be {1:?}",
value, expected) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let expected = Scalar::from_bool(expected);
let Some(value_const) =
self.use_ecx(|this|
this.ecx.read_scalar(value)) else { return };
if expected != value_const {
if let Some(place) = cond.place() {
self.remove_const(place.local);
}
enum DbgVal<T> { Val(T), Underscore, }
impl<T: std::fmt::Debug> std::fmt::Debug for DbgVal<T> {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>)
-> std::fmt::Result {
match self {
Self::Val(val) => val.fmt(fmt),
Self::Underscore => fmt.write_str("_"),
}
}
}
let mut eval_to_int =
|op|
{
self.eval_operand(op).and_then(|op|
self.ecx.read_immediate(&op).discard_err()).map_or(DbgVal::Underscore,
|op| DbgVal::Val(op.to_const_int()))
};
let msg =
match msg {
AssertKind::DivisionByZero(op) =>
AssertKind::DivisionByZero(eval_to_int(op)),
AssertKind::RemainderByZero(op) =>
AssertKind::RemainderByZero(eval_to_int(op)),
AssertKind::Overflow(bin_op @ (BinOp::Div | BinOp::Rem),
op1, op2) => {
AssertKind::Overflow(*bin_op, eval_to_int(op1),
eval_to_int(op2))
}
AssertKind::BoundsCheck { len, index } => {
let len = eval_to_int(len);
let index = eval_to_int(index);
AssertKind::BoundsCheck { len, index }
}
AssertKind::Overflow(..) | AssertKind::OverflowNeg(_) =>
return,
_ => return,
};
self.report_assert_as_lint(location,
AssertLintKind::UnconditionalPanic, msg);
}
}
fn ensure_not_propagated(&self, local: Local) {
if true {
let val = self.get_const(local.into());
if !(#[allow(non_exhaustive_omitted_patterns)] match val {
Some(Value::Uninit) => true,
_ => false,
} ||
self.layout_of(self.local_decls()[local].ty).map_or(true,
|layout| layout.is_zst())) {
{
::core::panicking::panic_fmt(format_args!("failed to remove values for `{0:?}`, value={1:?}",
local, val));
}
}
}
}
fn eval_rvalue(&mut self, rvalue: &Rvalue<'tcx>, dest: &Place<'tcx>)
-> Option<()> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("eval_rvalue",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(541u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("rvalue")
}> =
::tracing::__macro_support::FieldName::new("rvalue");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("dest")
}> =
::tracing::__macro_support::FieldName::new("dest");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&rvalue)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&dest)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Option<()> = loop {};
return __tracing_attr_fake_return;
}
{
if !dest.projection.is_empty() { return None; }
use rustc_middle::mir::Rvalue::*;
let layout =
self.ecx.layout_of(dest.ty(self.body, self.tcx).ty).ok()?;
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:548",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(548u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("layout")
}> =
::tracing::__macro_support::FieldName::new("layout");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&layout)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let val: Value<'_> =
match *rvalue {
ThreadLocalRef(_) => return None,
Use(ref operand, _) | WrapUnsafeBinder(ref operand, _) => {
self.eval_operand(operand)?.into()
}
CopyForDeref(place) | Reborrow(_, _, place) =>
self.eval_place(place)?.into(),
BinaryOp(bin_op, (ref left, ref right)) => {
let left = self.eval_operand(left)?;
let left =
self.use_ecx(|this| this.ecx.read_immediate(&left))?;
let right = self.eval_operand(right)?;
let right =
self.use_ecx(|this| this.ecx.read_immediate(&right))?;
let val =
self.use_ecx(|this|
this.ecx.binary_op(bin_op, &left, &right))?;
if #[allow(non_exhaustive_omitted_patterns)] match val.layout.backend_repr
{
BackendRepr::ScalarPair { .. } => true,
_ => false,
} {
let (val, overflow) = val.to_pair(&self.ecx);
Value::Aggregate {
variant: VariantIdx::ZERO,
fields: [val.into(), overflow.into()].into_iter().collect(),
}
} else { val.into() }
}
UnaryOp(un_op, ref operand) => {
let operand = self.eval_operand(operand)?;
let val =
self.use_ecx(|this| this.ecx.read_immediate(&operand))?;
let val =
self.use_ecx(|this| this.ecx.unary_op(un_op, &val))?;
val.into()
}
Aggregate(ref kind, ref fields) =>
Value::Aggregate {
fields: fields.iter().map(|field|
self.eval_operand(field).map_or(Value::Uninit,
Value::Immediate)).collect(),
variant: match **kind {
AggregateKind::Adt(_, variant, _, _, _) => variant,
AggregateKind::Array(_) | AggregateKind::Tuple |
AggregateKind::RawPtr(_, _) | AggregateKind::Closure(_, _) |
AggregateKind::Coroutine(_, _) |
AggregateKind::CoroutineClosure(_, _) => VariantIdx::ZERO,
},
},
Repeat(ref op, n) => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:605",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(605u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("op")
}> =
::tracing::__macro_support::FieldName::new("op");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("n")
}> =
::tracing::__macro_support::FieldName::new("n");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&op)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&n)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return None;
}
Ref(..) | RawPtr(..) => return None,
Cast(ref kind, ref value, to) =>
match kind {
CastKind::IntToInt | CastKind::IntToFloat => {
let value = self.eval_operand(value)?;
let value = self.ecx.read_immediate(&value).discard_err()?;
let to = self.ecx.layout_of(to).ok()?;
let res =
self.ecx.int_to_int_or_float(&value, to).discard_err()?;
res.into()
}
CastKind::FloatToFloat | CastKind::FloatToInt => {
let value = self.eval_operand(value)?;
let value = self.ecx.read_immediate(&value).discard_err()?;
let to = self.ecx.layout_of(to).ok()?;
let res =
self.ecx.float_to_float_or_int(&value, to).discard_err()?;
res.into()
}
CastKind::Transmute | CastKind::Subtype => {
let value = self.eval_operand(value)?;
let to = self.ecx.layout_of(to).ok()?;
match (value.layout.backend_repr, to.backend_repr) {
(BackendRepr::Scalar(..), BackendRepr::Scalar(..)) => {}
(BackendRepr::ScalarPair { .. }, BackendRepr::ScalarPair {
.. }) => {}
_ => return None,
}
value.offset(Size::ZERO, to,
&self.ecx).discard_err()?.into()
}
_ => return None,
},
Discriminant(place) => {
let variant =
match self.get_const(place)? {
Value::Immediate(op) => {
let op = op.clone();
self.use_ecx(|this| this.ecx.read_discriminant(&op))?
}
Value::Aggregate { variant, .. } => *variant,
Value::Uninit => return None,
};
let imm =
self.use_ecx(|this|
{
this.ecx.discriminant_for_variant(place.ty(this.local_decls(),
this.tcx).ty, variant)
})?;
imm.into()
}
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:660",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(660u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("val")
}> =
::tracing::__macro_support::FieldName::new("val");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&val)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
*self.access_mut(dest)? = val;
Some(())
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:541",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(541u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
}
impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
fn visit_body(&mut self, body: &Body<'tcx>) {
while let Some(bb) = self.worklist.pop() {
if !self.visited_blocks.insert(bb) { continue; }
let data = &body.basic_blocks[bb];
self.visit_basic_block_data(bb, data);
}
}
fn visit_operand(&mut self, operand: &Operand<'tcx>,
location: Location) {
self.super_operand(operand, location);
}
fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>,
location: Location) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:685",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(685u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("visit_const_operand: {0:?}",
constant) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
self.super_const_operand(constant, location);
self.eval_constant(constant);
}
fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>,
location: Location) {
self.super_assign(place, rvalue, location);
let Some(()) =
self.check_rvalue(rvalue, location) else { return };
match self.can_const_prop[place.local] {
_ if place.is_indirect() => {}
ConstPropMode::NoPropagation =>
self.ensure_not_propagated(place.local),
ConstPropMode::OnlyInsideOwnBlock |
ConstPropMode::FullConstProp => {
if self.eval_rvalue(rvalue, place).is_none() {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:711",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(711u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("propagation into {0:?} failed.\n Nuking the entire site from orbit, it\'s the only way to be sure",
place) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
self.remove_const(place.local);
}
}
}
}
fn visit_statement(&mut self, statement: &Statement<'tcx>,
location: Location) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:723",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(723u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("visit_statement: {0:?}",
statement) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
self.super_statement(statement, location);
match statement.kind {
StatementKind::SetDiscriminant { ref place, variant_index } =>
{
match self.can_const_prop[place.local] {
_ if place.is_indirect() => {}
ConstPropMode::NoPropagation =>
self.ensure_not_propagated(place.local),
ConstPropMode::FullConstProp |
ConstPropMode::OnlyInsideOwnBlock => {
match self.access_mut(place) {
Some(Value::Aggregate { variant, .. }) =>
*variant = variant_index,
_ => self.remove_const(place.local),
}
}
}
}
StatementKind::StorageLive(local) => {
self.remove_const(local);
}
StatementKind::StorageDead(local) => {
self.remove_const(local);
}
_ => {}
}
}
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>,
location: Location) {
self.super_terminator(terminator, location);
match &terminator.kind {
TerminatorKind::Assert { expected, msg, cond, .. } => {
self.check_assertion(*expected, msg, cond, location);
}
TerminatorKind::SwitchInt { discr, targets } => {
if let Some(ref value) = self.eval_operand(discr) &&
let Some(value_const) =
self.use_ecx(|this| this.ecx.read_scalar(value)) &&
let Some(constant) =
value_const.to_bits(value_const.size()).discard_err() {
let target = targets.target_for_value(constant);
self.worklist.push(target);
return;
}
}
TerminatorKind::Call { func, args: _, .. } => {
if let Some((def_id, generic_args)) = func.const_fn_def() {
for (index, arg) in generic_args.iter().enumerate() {
if let GenericArgKind::Const(ct) = arg.kind() {
let generics = self.tcx.generics_of(def_id);
let param_def = generics.param_at(index, self.tcx);
if let GenericParamDefKind::Const { .. } = param_def.kind &&
{
{
'done:
{
for i in
::rustc_attr_ir::HasAttrs::get_attrs(param_def.def_id,
&self.tcx) {
#[allow(unused_imports)]
use ::rustc_attr_ir::AttributeKind::*;
let i: &::rustc_attr_ir::Attribute = i;
match i {
::rustc_attr_ir::Attribute::Parsed(RustcPanicsWhenZero) => {
break 'done Some(());
}
::rustc_attr_ir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}.is_some() &&
let Some(0) = ct.try_to_target_usize(self.tcx) {
let source_info = self.body.source_info(location);
if let Some(lint_root) = self.lint_root(*source_info) {
self.tcx.emit_node_span_lint(UNCONDITIONAL_PANIC, lint_root,
source_info.span,
ConstNIsZero {
const_param_span: source_info.span,
const_param_name: param_def.name,
});
}
}
}
}
}
}
TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume |
TerminatorKind::UnwindTerminate(_) | TerminatorKind::Return
| TerminatorKind::TailCall { .. } |
TerminatorKind::Unreachable | TerminatorKind::Drop { .. } |
TerminatorKind::Yield { .. } | TerminatorKind::CoroutineDrop
| TerminatorKind::FalseEdge { .. } |
TerminatorKind::FalseUnwind { .. } |
TerminatorKind::InlineAsm { .. } => {}
}
self.worklist.extend(terminator.successors());
}
fn visit_basic_block_data(&mut self, block: BasicBlock,
data: &BasicBlockData<'tcx>) {
self.super_basic_block_data(block, data);
let mut written_only_inside_own_block_locals =
std::mem::take(&mut self.written_only_inside_own_block_locals);
#[allow(rustc::potential_query_instability)]
for local in written_only_inside_own_block_locals.drain() {
if true {
{
match (&self.can_const_prop[local],
&ConstPropMode::OnlyInsideOwnBlock) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
self.remove_const(local);
}
self.written_only_inside_own_block_locals =
written_only_inside_own_block_locals;
if true {
for (local, &mode) in self.can_const_prop.iter_enumerated() {
match mode {
ConstPropMode::FullConstProp => {}
ConstPropMode::NoPropagation |
ConstPropMode::OnlyInsideOwnBlock => {
self.ensure_not_propagated(local);
}
}
}
}
}
}
const MAX_ALLOC_LIMIT: u64 = 1024;
enum ConstPropMode {
FullConstProp,
OnlyInsideOwnBlock,
NoPropagation,
}
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for ConstPropMode { }
#[automatically_derived]
impl ::core::clone::Clone for ConstPropMode {
#[inline]
fn clone(&self) -> ConstPropMode { *self }
}
#[automatically_derived]
impl ::core::marker::Copy for ConstPropMode { }
#[automatically_derived]
impl ::core::fmt::Debug for ConstPropMode {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
ConstPropMode::FullConstProp => "FullConstProp",
ConstPropMode::OnlyInsideOwnBlock => "OnlyInsideOwnBlock",
ConstPropMode::NoPropagation => "NoPropagation",
})
}
}
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for ConstPropMode { }
#[automatically_derived]
impl ::core::cmp::PartialEq for ConstPropMode {
#[inline]
fn eq(&self, other: &ConstPropMode) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}
struct CanConstProp {
can_const_prop: IndexVec<Local, ConstPropMode>,
found_assignment: DenseBitSet<Local>,
}
impl CanConstProp {
fn check<'tcx>(tcx: TyCtxt<'tcx>, typing_env: ty::TypingEnv<'tcx>,
body: &Body<'tcx>) -> IndexVec<Local, ConstPropMode> {
let mut cpv =
CanConstProp {
can_const_prop: IndexVec::from_elem(ConstPropMode::FullConstProp,
&body.local_decls),
found_assignment: DenseBitSet::new_empty(body.local_decls.len()),
};
for (local, val) in cpv.can_const_prop.iter_enumerated_mut() {
let ty = body.local_decls[local].ty;
if ty.is_async_drop_in_place_coroutine(tcx) {
*val = ConstPropMode::NoPropagation;
continue;
} else if ty.is_union() {
*val = ConstPropMode::NoPropagation;
} else {
match tcx.layout_of(typing_env.as_query_input(ty)) {
Ok(layout) if
layout.size < Size::from_bytes(MAX_ALLOC_LIMIT) => {}
_ => { *val = ConstPropMode::NoPropagation; continue; }
}
}
}
for arg in body.args_iter() { cpv.found_assignment.insert(arg); }
cpv.visit_body(body);
cpv.can_const_prop
}
}
impl<'tcx> Visitor<'tcx> for CanConstProp {
fn visit_place(&mut self, place: &Place<'tcx>,
mut context: PlaceContext, loc: Location) {
use rustc_middle::mir::visit::PlaceContext::*;
if place.projection.first() == Some(&PlaceElem::Deref) {
context = NonMutatingUse(NonMutatingUseContext::Copy);
}
self.visit_local(place.local, context, loc);
self.visit_projection(place.as_ref(), context, loc);
}
fn visit_local(&mut self, local: Local, context: PlaceContext,
_: Location) {
use rustc_middle::mir::visit::PlaceContext::*;
match context {
MutatingUse(MutatingUseContext::Call) |
MutatingUse(MutatingUseContext::AsmOutput) |
MutatingUse(MutatingUseContext::Store) |
MutatingUse(MutatingUseContext::SetDiscriminant) => {
if !self.found_assignment.insert(local) {
match &mut self.can_const_prop[local] {
ConstPropMode::OnlyInsideOwnBlock => {}
ConstPropMode::NoPropagation => {}
other @ ConstPropMode::FullConstProp => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:958",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(958u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("local {0:?} can\'t be propagated because of multiple assignments. Previous state: {1:?}",
local, other) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
*other = ConstPropMode::OnlyInsideOwnBlock;
}
}
}
}
NonMutatingUse(NonMutatingUseContext::Copy) |
NonMutatingUse(NonMutatingUseContext::Move) |
NonMutatingUse(NonMutatingUseContext::Inspect) |
NonMutatingUse(NonMutatingUseContext::PlaceMention) |
NonUse(_) => {}
MutatingUse(MutatingUseContext::Yield) |
MutatingUse(MutatingUseContext::Drop) |
NonMutatingUse(NonMutatingUseContext::SharedBorrow) |
NonMutatingUse(NonMutatingUseContext::FakeBorrow) |
NonMutatingUse(NonMutatingUseContext::RawBorrow) |
MutatingUse(MutatingUseContext::Borrow) |
MutatingUse(MutatingUseContext::RawBorrow) => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs:985",
"rustc_mir_transform::known_panics_lint",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/known_panics_lint.rs"),
::tracing_core::__macro_support::Option::Some(985u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::known_panics_lint"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("local {0:?} can\'t be propagated because it\'s used: {1:?}",
local, context) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
self.can_const_prop[local] = ConstPropMode::NoPropagation;
}
MutatingUse(MutatingUseContext::Projection) |
NonMutatingUse(NonMutatingUseContext::Projection) => {
::rustc_middle::util::bug::bug_fmt(format_args!("visit_place should not pass {0:?} for {1:?}",
context, local))
}
}
}
}
}
#[allow(unused_imports)]
use known_panics_lint::KnownPanicsLint as _;
mod lint_and_remove_uninhabited {
use rustc_hir::def::DefKind;
use rustc_lint_defs::builtin::UNREACHABLE_CODE;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use crate::PassPolicy;
use crate::diagnostics::UnreachableDueToUninhabited;
pub(super) struct LintAndRemoveUninhabited;
impl<'tcx> crate::MirPass<'tcx> for LintAndRemoveUninhabited {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("run_pass",
"rustc_mir_transform::lint_and_remove_uninhabited",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/lint_and_remove_uninhabited.rs"),
::tracing_core::__macro_support::Option::Some(14u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::lint_and_remove_uninhabited"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let def_id = body.source.def_id().expect_local();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/lint_and_remove_uninhabited.rs:17",
"rustc_mir_transform::lint_and_remove_uninhabited",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/lint_and_remove_uninhabited.rs"),
::tracing_core::__macro_support::Option::Some(17u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::lint_and_remove_uninhabited"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let parent_module = tcx.parent_module_from_def_id(def_id);
let typing_env = body.typing_env(tcx);
let return_ty_is_inhabited =
#[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(def_id)
{
DefKind::Fn | DefKind::AssocFn => true,
_ => false,
} &&
body.local_decls[RETURN_PLACE].ty.is_inhabited_from(tcx,
parent_module, typing_env);
let mut lints = ::alloc::vec::Vec::new();
for bbdata in body.basic_blocks.as_mut() {
let term = bbdata.terminator_mut();
let TerminatorKind::Call { ref mut target, destination, ..
} = term.kind else { continue; };
let Some(target_bb) = *target else { continue };
let ty = destination.ty(&body.local_decls, tcx).ty;
let ty_is_inhabited =
ty.is_inhabited_from(tcx, parent_module, typing_env);
if !ty_is_inhabited {
if !ty.is_never() && return_ty_is_inhabited {
lints.push((target_bb, ty, term.source_info.span));
}
*target = None;
}
}
for (target_bb, orig_ty, orig_span) in lints {
if orig_span.in_external_macro(tcx.sess.source_map()) {
continue;
}
let Some((target_loc, descr)) =
find_unreachable_code_from(target_bb,
body) else { continue; };
let lint_root =
body.source_scopes[target_loc.scope].local_data.as_ref().unwrap_crate_local().lint_root;
tcx.emit_node_span_lint(UNREACHABLE_CODE, lint_root,
target_loc.span,
UnreachableDueToUninhabited {
expr: target_loc.span,
orig: orig_span,
descr,
ty: orig_ty,
});
}
}
}
}
}
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::Required
}
}
#[doc =
" Starting at a target unreachable block, find some user code to lint as unreachable"]
fn find_unreachable_code_from<'tcx>(bb: BasicBlock, body: &Body<'tcx>)
-> Option<(SourceInfo, &'static str)> {
{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("find_unreachable_code_from",
"rustc_mir_transform::lint_and_remove_uninhabited",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/lint_and_remove_uninhabited.rs"),
::tracing_core::__macro_support::Option::Some(94u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::lint_and_remove_uninhabited"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("bb")
}> =
::tracing::__macro_support::FieldName::new("bb");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&bb)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
Option<(SourceInfo, &'static str)> = loop {};
return __tracing_attr_fake_return;
}
{
let bbdata = &body.basic_blocks[bb];
for stmt in &bbdata.statements {
match &stmt.kind {
StatementKind::Assign((_,
Rvalue::Use(Operand::Constant(const_), _))) if
const_.ty().is_unit() => {
continue;
}
StatementKind::Assign((place, _)) if
place.as_local() == Some(RETURN_PLACE) => {
continue;
}
StatementKind::StorageLive(_) |
StatementKind::StorageDead(_) |
StatementKind::BackwardIncompatibleDropHint { .. } => {
continue;
}
StatementKind::FakeRead(..) =>
return Some((stmt.source_info, "definition")),
_ => return Some((stmt.source_info, "expression")),
}
}
let term = bbdata.terminator();
match term.kind {
TerminatorKind::Goto { target } | TerminatorKind::Drop {
target, .. } => {
if &body.basic_blocks.predecessors()[target][..] == &[bb] {
find_unreachable_code_from(target, body)
} else { None }
}
TerminatorKind::Return => None,
_ => Some((term.source_info, "expression")),
}
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/lint_and_remove_uninhabited.rs:94",
"rustc_mir_transform::lint_and_remove_uninhabited",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/lint_and_remove_uninhabited.rs"),
::tracing_core::__macro_support::Option::Some(94u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::lint_and_remove_uninhabited"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x
}
}
#[allow(unused_imports)]
use lint_and_remove_uninhabited::LintAndRemoveUninhabited as _;
mod lower_intrinsics {
use rustc_middle::mir::*;
use rustc_middle::ty::{self, TyCtxt};
use rustc_middle::{bug, span_bug};
use rustc_span::sym;
use crate::{PassPolicy, take_array};
pub(super) struct LowerIntrinsics;
impl<'tcx> crate::MirPass<'tcx> for LowerIntrinsics {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let local_decls = &body.local_decls;
for block in body.basic_blocks.as_mut() {
let terminator = block.terminator.as_mut().unwrap();
if let TerminatorKind::Call { func, args, destination, target,
.. } = &mut terminator.kind &&
let ty::FnDef(def_id, generic_args) =
*func.ty(local_decls, tcx).kind() &&
let Some(intrinsic) = tcx.intrinsic(def_id) {
let generic_args = generic_args.no_bound_vars().unwrap();
match intrinsic.name {
sym::unreachable => {
terminator.kind = TerminatorKind::Unreachable;
}
sym::ub_checks | sym::overflow_checks | sym::contract_checks
=> {
let op =
match intrinsic.name {
sym::ub_checks => RuntimeChecks::UbChecks,
sym::contract_checks => RuntimeChecks::ContractChecks,
sym::overflow_checks => RuntimeChecks::OverflowChecks,
_ =>
::core::panicking::panic("internal error: entered unreachable code"),
};
let target = target.unwrap();
block.statements.push(Statement::new(terminator.source_info,
StatementKind::Assign(Box::new((*destination,
Rvalue::Use(Operand::RuntimeChecks(op),
WithRetag::Yes))))));
terminator.kind = TerminatorKind::Goto { target };
}
sym::forget => {
let target = target.unwrap();
block.statements.push(Statement::new(terminator.source_info,
StatementKind::Assign(Box::new((*destination,
Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
span: terminator.source_info.span,
user_ty: None,
const_: Const::zero_sized(tcx.types.unit),
})), WithRetag::Yes))))));
terminator.kind = TerminatorKind::Goto { target };
}
sym::copy_nonoverlapping => {
let target = target.unwrap();
let Ok([src, dst, count]) =
take_array(args) else {
::rustc_middle::util::bug::bug_fmt(format_args!("Wrong arguments for copy_non_overlapping intrinsic"));
};
block.statements.push(Statement::new(terminator.source_info,
StatementKind::Intrinsic(Box::new(NonDivergingIntrinsic::CopyNonOverlapping(rustc_middle::mir::CopyNonOverlapping {
src: src.node,
dst: dst.node,
count: count.node,
})))));
terminator.kind = TerminatorKind::Goto { target };
}
sym::assume => {
let target = target.unwrap();
let Ok([arg]) =
take_array(args) else {
::rustc_middle::util::bug::bug_fmt(format_args!("Wrong arguments for assume intrinsic"));
};
block.statements.push(Statement::new(terminator.source_info,
StatementKind::Intrinsic(Box::new(NonDivergingIntrinsic::Assume(arg.node)))));
terminator.kind = TerminatorKind::Goto { target };
}
sym::wrapping_add | sym::wrapping_sub | sym::wrapping_mul |
sym::three_way_compare | sym::unchecked_add |
sym::unchecked_sub | sym::unchecked_mul | sym::unchecked_div
| sym::unchecked_rem | sym::unchecked_shl |
sym::unchecked_shr => {
let target = target.unwrap();
let Ok([lhs, rhs]) =
take_array(args) else {
::rustc_middle::util::bug::bug_fmt(format_args!("Wrong arguments for {0} intrinsic",
intrinsic.name));
};
let bin_op =
match intrinsic.name {
sym::wrapping_add => BinOp::Add,
sym::wrapping_sub => BinOp::Sub,
sym::wrapping_mul => BinOp::Mul,
sym::three_way_compare => BinOp::Cmp,
sym::unchecked_add => BinOp::AddUnchecked,
sym::unchecked_sub => BinOp::SubUnchecked,
sym::unchecked_mul => BinOp::MulUnchecked,
sym::unchecked_div => BinOp::Div,
sym::unchecked_rem => BinOp::Rem,
sym::unchecked_shl => BinOp::ShlUnchecked,
sym::unchecked_shr => BinOp::ShrUnchecked,
_ =>
::rustc_middle::util::bug::bug_fmt(format_args!("unexpected intrinsic")),
};
block.statements.push(Statement::new(terminator.source_info,
StatementKind::Assign(Box::new((*destination,
Rvalue::BinaryOp(bin_op,
Box::new((lhs.node, rhs.node))))))));
terminator.kind = TerminatorKind::Goto { target };
}
sym::add_with_overflow | sym::sub_with_overflow |
sym::mul_with_overflow => {
let target = target.unwrap();
let Ok([lhs, rhs]) =
take_array(args) else {
::rustc_middle::util::bug::bug_fmt(format_args!("Wrong arguments for {0} intrinsic",
intrinsic.name));
};
let bin_op =
match intrinsic.name {
sym::add_with_overflow => BinOp::AddWithOverflow,
sym::sub_with_overflow => BinOp::SubWithOverflow,
sym::mul_with_overflow => BinOp::MulWithOverflow,
_ =>
::rustc_middle::util::bug::bug_fmt(format_args!("unexpected intrinsic")),
};
block.statements.push(Statement::new(terminator.source_info,
StatementKind::Assign(Box::new((*destination,
Rvalue::BinaryOp(bin_op,
Box::new((lhs.node, rhs.node))))))));
terminator.kind = TerminatorKind::Goto { target };
}
sym::read_via_copy => {
let Ok([arg]) =
take_array(args) else {
::rustc_middle::util::bug::span_bug_fmt(terminator.source_info.span,
format_args!("Wrong number of arguments"));
};
let derefed_place =
if let Some(place) = arg.node.place() &&
let Some(local) = place.as_local() {
tcx.mk_place_deref(local.into())
} else {
::rustc_middle::util::bug::span_bug_fmt(terminator.source_info.span,
format_args!("Only passing a local is supported"));
};
block.statements.push(Statement::new(terminator.source_info,
StatementKind::Assign(Box::new((*destination,
Rvalue::Use(Operand::Copy(derefed_place),
WithRetag::Yes))))));
terminator.kind =
match *target {
None => { TerminatorKind::Unreachable }
Some(target) => TerminatorKind::Goto { target },
}
}
sym::discriminant_value => {
let target = target.unwrap();
let Ok([arg]) =
take_array(args) else {
::rustc_middle::util::bug::span_bug_fmt(terminator.source_info.span,
format_args!("Wrong arguments for discriminant_value intrinsic"));
};
let arg = arg.node.place().unwrap();
let arg = tcx.mk_place_deref(arg);
block.statements.push(Statement::new(terminator.source_info,
StatementKind::Assign(Box::new((*destination,
Rvalue::Discriminant(arg))))));
terminator.kind = TerminatorKind::Goto { target };
}
sym::offset => {
let target = target.unwrap();
let Ok([ptr, delta]) =
take_array(args) else {
::rustc_middle::util::bug::span_bug_fmt(terminator.source_info.span,
format_args!("Wrong number of arguments for offset intrinsic"));
};
block.statements.push(Statement::new(terminator.source_info,
StatementKind::Assign(Box::new((*destination,
Rvalue::BinaryOp(BinOp::Offset,
Box::new((ptr.node, delta.node))))))));
terminator.kind = TerminatorKind::Goto { target };
}
sym::slice_get_unchecked => {
let target = target.unwrap();
let Ok([ptrish, index]) =
take_array(args) else {
::rustc_middle::util::bug::span_bug_fmt(terminator.source_info.span,
format_args!("Wrong number of arguments for {0:?}",
intrinsic));
};
let place = ptrish.node.place().unwrap();
if !!place.is_indirect() {
::core::panicking::panic("assertion failed: !place.is_indirect()")
};
let updated_place =
place.project_deeper(&[ProjectionElem::Deref,
ProjectionElem::Index(index.node.place().unwrap().as_local().unwrap())],
tcx);
let ret_ty = generic_args.type_at(0);
let rvalue =
match *ret_ty.kind() {
ty::RawPtr(_, Mutability::Not) => {
Rvalue::RawPtr(RawPtrKind::Const, updated_place)
}
ty::RawPtr(_, Mutability::Mut) => {
Rvalue::RawPtr(RawPtrKind::Mut, updated_place)
}
ty::Ref(region, _, Mutability::Not) => {
Rvalue::Ref(region, BorrowKind::Shared, updated_place)
}
ty::Ref(region, _, Mutability::Mut) =>
Rvalue::Ref(region,
BorrowKind::Mut { kind: MutBorrowKind::Default },
updated_place),
_ =>
::rustc_middle::util::bug::bug_fmt(format_args!("Unknown return type {0:?}",
ret_ty)),
};
block.statements.push(Statement::new(terminator.source_info,
StatementKind::Assign(Box::new((*destination, rvalue)))));
terminator.kind = TerminatorKind::Goto { target };
}
sym::transmute | sym::transmute_unchecked => {
let dst_ty = destination.ty(local_decls, tcx).ty;
let Ok([arg]) =
take_array(args) else {
::rustc_middle::util::bug::span_bug_fmt(terminator.source_info.span,
format_args!("Wrong number of arguments for transmute intrinsic"));
};
block.statements.push(Statement::new(terminator.source_info,
StatementKind::Assign(Box::new((*destination,
Rvalue::Cast(CastKind::Transmute, arg.node, dst_ty))))));
if let Some(target) = *target {
terminator.kind = TerminatorKind::Goto { target };
} else { terminator.kind = TerminatorKind::Unreachable; }
}
sym::aggregate_raw_ptr => {
let Ok([data, meta]) =
take_array(args) else {
::rustc_middle::util::bug::span_bug_fmt(terminator.source_info.span,
format_args!("Wrong number of arguments for aggregate_raw_ptr intrinsic"));
};
let target = target.unwrap();
let pointer_ty = generic_args.type_at(0);
let kind =
if let ty::RawPtr(pointee_ty, mutability) =
pointer_ty.kind() {
AggregateKind::RawPtr(*pointee_ty, *mutability)
} else {
::rustc_middle::util::bug::span_bug_fmt(terminator.source_info.span,
format_args!("Return type of aggregate_raw_ptr intrinsic must be a raw pointer"));
};
let fields = [data.node, meta.node];
block.statements.push(Statement::new(terminator.source_info,
StatementKind::Assign(Box::new((*destination,
Rvalue::Aggregate(Box::new(kind), fields.into()))))));
terminator.kind = TerminatorKind::Goto { target };
}
sym::ptr_metadata => {
let Ok([ptr]) =
take_array(args) else {
::rustc_middle::util::bug::span_bug_fmt(terminator.source_info.span,
format_args!("Wrong number of arguments for ptr_metadata intrinsic"));
};
let target = target.unwrap();
block.statements.push(Statement::new(terminator.source_info,
StatementKind::Assign(Box::new((*destination,
Rvalue::UnaryOp(UnOp::PtrMetadata, ptr.node))))));
terminator.kind = TerminatorKind::Goto { target };
}
_ => {}
}
}
}
}
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::Required
}
}
}
#[allow(unused_imports)]
use lower_intrinsics::LowerIntrinsics as _;
mod lower_slice_len {
use rustc_hir::def_id::DefId;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use crate::PassPolicy;
pub(super) struct LowerSliceLenCalls;
impl<'tcx> crate::MirPass<'tcx> for LowerSliceLenCalls {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 1)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let language_items = tcx.lang_items();
let Some(slice_len_fn_item_def_id) =
language_items.slice_len_fn() else { return; };
let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
for block in basic_blocks {
lower_slice_len_call(block, slice_len_fn_item_def_id);
}
}
}
fn lower_slice_len_call<'tcx>(block: &mut BasicBlockData<'tcx>,
slice_len_fn_item_def_id: DefId) {
let terminator = block.terminator();
if let TerminatorKind::Call {
func,
args,
destination,
target: Some(bb),
call_source: CallSource::Normal, .. } = &terminator.kind &&
let [arg] = &args[..] &&
let Some((fn_def_id, _)) = func.const_fn_def() &&
fn_def_id == slice_len_fn_item_def_id {
let r_value =
Rvalue::UnaryOp(UnOp::PtrMetadata, arg.node.clone());
let len_statement_kind =
StatementKind::Assign(Box::new((*destination, r_value)));
let add_statement =
Statement::new(terminator.source_info, len_statement_kind);
let new_terminator_kind = TerminatorKind::Goto { target: *bb };
block.statements.push(add_statement);
block.terminator_mut().kind = new_terminator_kind;
}
}
}
#[allow(unused_imports)]
use lower_slice_len::LowerSliceLenCalls as _;
mod match_branches {
use rustc_abi::Integer;
use rustc_const_eval::const_eval::mk_eval_cx_for_const_val;
use rustc_middle::mir::*;
use rustc_middle::ty::layout::{IntegerExt, TyAndLayout};
use rustc_middle::ty::util::Discr;
use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
use super::simplify::simplify_cfg;
use crate::PassPolicy;
use crate::patch::MirPatch;
use crate::unreachable_prop::remove_successors_from_switch;
pub(super) struct MatchBranchSimplification;
impl<'tcx> crate::MirPass<'tcx> for MatchBranchSimplification {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 2)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let typing_env = body.typing_env(tcx);
let mut changed = false;
for bb in body.basic_blocks.indices() {
if !candidate_match(body, bb) { continue; };
changed |= simplify_match(tcx, typing_env, body, bb)
}
if changed { simplify_cfg(tcx, body); }
}
}
struct SimplifyMatch<'tcx, 'a> {
tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
patch: MirPatch<'tcx>,
body: &'a Body<'tcx>,
switch_bb: BasicBlock,
discr: &'a Operand<'tcx>,
discr_local: Option<Local>,
discr_ty: Ty<'tcx>,
}
impl<'tcx, 'a> SimplifyMatch<'tcx, 'a> {
fn discr_local(&mut self) -> Local {
*self.discr_local.get_or_insert_with(||
{
let source_info =
self.body.basic_blocks[self.switch_bb].terminator().source_info;
self.patch.new_temp(self.discr_ty, source_info.span)
})
}
fn unify_if_equal_const(&self, dest: Place<'tcx>,
consts: &[(u128, &ConstOperand<'tcx>)],
otherwise: Option<&ConstOperand<'tcx>>)
-> Option<StatementKind<'tcx>> {
let (_, first_const, mut others) =
split_first_case(consts, otherwise);
let first_scalar_int =
first_const.const_.try_eval_scalar_int(self.tcx,
self.typing_env)?;
if others.all(|const_|
{
const_.const_.try_eval_scalar_int(self.tcx, self.typing_env)
== Some(first_scalar_int)
}) {
Some(StatementKind::Assign(Box::new((dest,
Rvalue::Use(Operand::Constant(Box::new(first_const.clone())),
WithRetag::No)))))
} else { None }
}
fn unify_by_eq_op(&mut self, dest: Place<'tcx>,
consts: &[(u128, &ConstOperand<'tcx>)],
otherwise: Option<&ConstOperand<'tcx>>)
-> Option<StatementKind<'tcx>> {
let (first_case, first_const, mut others) =
split_first_case(consts, otherwise);
if !first_const.ty().is_bool() { return None; }
let first_bool =
first_const.const_.try_eval_bool(self.tcx, self.typing_env)?;
if others.all(|const_|
{
const_.const_.try_eval_bool(self.tcx, self.typing_env) ==
Some(!first_bool)
}) {
let size =
self.tcx.layout_of(self.typing_env.as_query_input(self.discr_ty)).unwrap().size;
let const_cmp =
Operand::const_from_scalar(self.tcx, self.discr_ty,
rustc_const_eval::interpret::Scalar::from_uint(first_case,
size), rustc_span::DUMMY_SP);
let op = if first_bool { BinOp::Eq } else { BinOp::Ne };
let rval =
Rvalue::BinaryOp(op,
Box::new((Operand::Copy(Place::from(self.discr_local())),
const_cmp)));
Some(StatementKind::Assign(Box::new((dest, rval))))
} else { None }
}
fn unify_by_int_to_int(&mut self, dest: Place<'tcx>,
consts: &[(u128, &ConstOperand<'tcx>)])
-> Option<StatementKind<'tcx>> {
let (_, first_const) = consts[0];
if !first_const.ty().is_integral() { return None; }
let discr_layout =
self.tcx.layout_of(self.typing_env.as_query_input(self.discr_ty)).unwrap();
if consts.iter().all(|&(case, const_)|
{
let Some(scalar_int) =
const_.const_.try_eval_scalar_int(self.tcx,
self.typing_env) else { return false; };
can_cast(self.tcx, case, discr_layout, const_.ty(),
scalar_int)
}) {
let operand = Operand::Copy(Place::from(self.discr_local()));
let rval =
if first_const.ty() == self.discr_ty {
Rvalue::Use(operand, WithRetag::No)
} else {
Rvalue::Cast(CastKind::IntToInt, operand, first_const.ty())
};
Some(StatementKind::Assign(Box::new((dest, rval))))
} else { None }
}
fn unify_by_copy(&self, dest: Place<'tcx>,
rvals: &[(u128, &Rvalue<'tcx>)]) -> Option<StatementKind<'tcx>> {
let bbs = &self.body.basic_blocks;
let &Statement {
kind: StatementKind::Assign((discr_place,
Rvalue::Discriminant(copy_src_place))), .. } =
bbs[self.switch_bb].statements.last()? else { return None; };
if self.discr.place() != Some(discr_place) { return None; }
let src_ty = copy_src_place.ty(self.body.local_decls(), self.tcx);
if !src_ty.ty.is_enum() || src_ty.variant_index.is_some() {
return None;
}
let dest_ty = dest.ty(self.body.local_decls(), self.tcx);
if dest_ty.ty != src_ty.ty || dest_ty.variant_index.is_some() {
return None;
}
let ty::Adt(def, _) = dest_ty.ty.kind() else { return None; };
for &(case, rvalue) in rvals.iter() {
match rvalue {
Rvalue::Use(Operand::Constant(constant), _) if
let Const::Val(const_, ty) = constant.const_ => {
let (ecx, op) =
mk_eval_cx_for_const_val(self.tcx.at(constant.span),
self.typing_env, const_, ty)?;
let variant = ecx.read_discriminant(&op).discard_err()?;
if !def.variants()[variant].fields.is_empty() {
return None;
}
let Discr { val, .. } =
ty.discriminant_for_variant(self.tcx, variant)?;
if val != case { return None; }
}
Rvalue::Use(Operand::Copy(src_place), _) if
*src_place == copy_src_place => {}
Rvalue::Aggregate(AggregateKind::Adt(_, variant_index, _, _,
None), fields) if
fields.is_empty() &&
let Some(Discr { val, .. }) =
src_ty.ty.discriminant_for_variant(self.tcx, *variant_index)
&& val == case => {}
_ => return None,
}
}
Some(StatementKind::Assign(Box::new((dest,
Rvalue::Use(Operand::Copy(copy_src_place),
WithRetag::No)))))
}
fn try_unify_stmts(&mut self, index: usize,
stmts: &[(u128, &StatementKind<'tcx>)],
otherwise: Option<&StatementKind<'tcx>>)
-> Option<StatementKind<'tcx>> {
if let Some(new_stmt) = identical_stmts(stmts, otherwise) {
return Some(new_stmt);
}
let (dest, rvals, otherwise) =
candidate_assign(stmts, otherwise)?;
if let Some((consts, otherwise)) =
candidate_const(&rvals, otherwise) {
if let Some(new_stmt) =
self.unify_if_equal_const(dest, &consts, otherwise) {
return Some(new_stmt);
}
if let Some(new_stmt) =
self.unify_by_eq_op(dest, &consts, otherwise) {
return Some(new_stmt);
}
if otherwise.is_none() &&
let Some(new_stmt) = self.unify_by_int_to_int(dest, &consts)
{
return Some(new_stmt);
}
}
if index == 0 && dest.is_stable_offset() && otherwise.is_none() &&
let Some(new_stmt) = self.unify_by_copy(dest, &rvals) {
return Some(new_stmt);
}
None
}
}
fn candidate_match<'tcx>(body: &Body<'tcx>, switch_bb: BasicBlock)
-> bool {
use itertools::Itertools;
let targets =
match &body.basic_blocks[switch_bb].terminator().kind {
TerminatorKind::SwitchInt {
discr: Operand::Copy(_) | Operand::Move(_), targets, .. } =>
targets,
_ => return false,
};
if targets.all_targets().contains(&switch_bb) { return false; }
if !targets.is_distinct() { return false; }
targets.all_targets().iter().map(|&bb|
&body.basic_blocks[bb]).filter(|bb|
!bb.is_empty_unreachable()).map(|bb|
(bb.statements.len(), &bb.terminator().kind)).all_equal()
}
fn simplify_match<'tcx>(tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>, body: &mut Body<'tcx>,
switch_bb: BasicBlock) -> bool {
let (discr, targets) =
match &body.basic_blocks[switch_bb].terminator().kind {
TerminatorKind::SwitchInt { discr, targets, .. } =>
(discr, targets),
_ =>
::core::panicking::panic("internal error: entered unreachable code"),
};
let mut simplify_match =
SimplifyMatch {
tcx,
typing_env,
patch: MirPatch::new(body),
body,
switch_bb,
discr,
discr_local: None,
discr_ty: discr.ty(body.local_decls(), tcx),
};
let reachable_cases: Vec<_> =
targets.iter().filter(|&(_, bb)|
!body.basic_blocks[bb].is_empty_unreachable()).collect();
let mut new_stmts = Vec::new();
let otherwise =
if body.basic_blocks[targets.otherwise()].is_empty_unreachable() {
None
} else { Some(targets.otherwise()) };
match (reachable_cases.len(), otherwise.is_none()) {
(1, true) | (0, false) => {
let mut patch = simplify_match.patch;
remove_successors_from_switch(tcx, switch_bb, body,
&mut patch,
|bb| { body.basic_blocks[bb].is_empty_unreachable() });
patch.apply(body);
return true;
}
_ => {}
}
let Some(&(_, first_case_bb)) =
reachable_cases.first() else { return false; };
let stmt_len = body.basic_blocks[first_case_bb].statements.len();
let mut cases = Vec::with_capacity(stmt_len);
for index in 0..stmt_len {
cases.clear();
let otherwise =
otherwise.map(|bb|
&body.basic_blocks[bb].statements[index].kind);
for &(case, bb) in &reachable_cases {
cases.push((case,
&body.basic_blocks[bb].statements[index].kind));
}
let Some(new_stmt) =
simplify_match.try_unify_stmts(index, &cases,
otherwise) else { return false; };
new_stmts.push(new_stmt);
}
let discr = discr.clone();
let statement_index = body.basic_blocks[switch_bb].statements.len();
let parent_end = Location { block: switch_bb, statement_index };
let mut patch = simplify_match.patch;
if let Some(discr_local) = simplify_match.discr_local {
patch.add_statement(parent_end,
StatementKind::StorageLive(discr_local));
patch.add_assign(parent_end, Place::from(discr_local),
Rvalue::Use(discr, WithRetag::No));
}
for new_stmt in new_stmts {
patch.add_statement(parent_end, new_stmt);
}
if let Some(discr_local) = simplify_match.discr_local {
patch.add_statement(parent_end,
StatementKind::StorageDead(discr_local));
}
patch.patch_terminator(switch_bb,
body.basic_blocks[first_case_bb].terminator().kind.clone());
patch.apply(body);
true
}
fn can_cast(tcx: TyCtxt<'_>, src_val: impl Into<u128>,
src_layout: TyAndLayout<'_>, cast_ty: Ty<'_>,
target_scalar: ScalarInt) -> bool {
let from_scalar =
ScalarInt::try_from_uint(src_val.into(),
src_layout.size).unwrap();
let v =
match src_layout.ty.kind() {
ty::Uint(_) => from_scalar.to_uint(src_layout.size),
ty::Int(_) => from_scalar.to_int(src_layout.size) as u128,
_ => return false,
};
let size =
match *cast_ty.kind() {
ty::Int(t) => Integer::from_int_ty(&tcx, t).size(),
ty::Uint(t) => Integer::from_uint_ty(&tcx, t).size(),
_ => return false,
};
let v = size.truncate(v);
let cast_scalar = ScalarInt::try_from_uint(v, size).unwrap();
cast_scalar == target_scalar
}
fn candidate_assign<'tcx,
'a>(stmts: &'a [(u128, &'a StatementKind<'tcx>)],
otherwise: Option<&'a StatementKind<'tcx>>)
->
Option<(Place<'tcx>, Vec<(u128, &'a Rvalue<'tcx>)>,
Option<&'a Rvalue<'tcx>>)> {
let (_, first_stmt) = stmts[0];
let (dest, _) = first_stmt.as_assign()?;
let otherwise =
if let Some(otherwise) = otherwise {
let Some((otherwise_dest, rval)) =
otherwise.as_assign() else { return None; };
if otherwise_dest != dest { return None; }
Some(rval)
} else { None };
let rvals =
stmts.into_iter().map(|&(case, stmt)|
{
let (other_dest, rval) = stmt.as_assign()?;
if other_dest != dest { return None; }
Some((case, rval))
}).try_collect()?;
Some((*dest, rvals, otherwise))
}
fn candidate_const<'tcx,
'a>(rvals: &'a [(u128, &'a Rvalue<'tcx>)],
otherwise: Option<&'a Rvalue<'tcx>>)
->
Option<(Vec<(u128, &'a ConstOperand<'tcx>)>,
Option<&'a ConstOperand<'tcx>>)> {
let otherwise =
if let Some(otherwise) = otherwise {
let Rvalue::Use(Operand::Constant(const_), _) =
otherwise else { return None; };
Some(&**const_)
} else { None };
let consts =
rvals.into_iter().map(|&(case, rval)|
{
let Rvalue::Use(Operand::Constant(const_), _) =
rval else { return None };
Some((case, &**const_))
}).try_collect()?;
Some((consts, otherwise))
}
fn split_first_case<'a,
T>(stmts: &'a [(u128, &'a T)], otherwise: Option<&'a T>)
-> (u128, &'a T, impl Iterator<Item = &'a T>) {
let (first_case, first) = stmts[0];
(first_case, first,
stmts[1..].into_iter().map(|&(_, val)| val).chain(otherwise))
}
fn identical_stmts<'tcx>(stmts: &[(u128, &StatementKind<'tcx>)],
otherwise: Option<&StatementKind<'tcx>>)
-> Option<StatementKind<'tcx>> {
use itertools::Itertools;
let (_, first_stmt, others) = split_first_case(stmts, otherwise);
if std::iter::once(first_stmt).chain(others).all_equal() {
return Some(first_stmt.clone());
}
None
}
}
#[allow(unused_imports)]
use match_branches::MatchBranchSimplification as _;
mod mentioned_items {
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{self, Location, MentionedItem};
use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::{self, TyCtxt};
use rustc_span::Spanned;
use crate::PassPolicy;
pub(super) struct MentionedItems;
struct MentionedItemsVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
body: &'a mir::Body<'tcx>,
mentioned_items: Vec<Spanned<MentionedItem<'tcx>>>,
}
impl<'tcx> crate::MirPass<'tcx> for MentionedItems {
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::Required
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) {
let mut visitor =
MentionedItemsVisitor {
tcx,
body,
mentioned_items: Vec::new(),
};
visitor.visit_body(body);
body.set_mentioned_items(visitor.mentioned_items);
}
}
impl<'tcx> Visitor<'tcx> for MentionedItemsVisitor<'_, 'tcx> {
fn visit_terminator(&mut self, terminator: &mir::Terminator<'tcx>,
location: Location) {
self.super_terminator(terminator, location);
let span = || self.body.source_info(location).span;
match &terminator.kind {
mir::TerminatorKind::Call { func, .. } |
mir::TerminatorKind::TailCall { func, .. } => {
let callee_ty = func.ty(self.body, self.tcx);
self.mentioned_items.push(Spanned {
node: MentionedItem::Fn(callee_ty),
span: span(),
});
}
mir::TerminatorKind::Drop { place, .. } => {
let ty = place.ty(self.body, self.tcx).ty;
self.mentioned_items.push(Spanned {
node: MentionedItem::Drop(ty),
span: span(),
});
}
mir::TerminatorKind::InlineAsm { operands, .. } => {
for op in operands {
match *op {
mir::InlineAsmOperand::SymFn { ref value } => {
self.mentioned_items.push(Spanned {
node: MentionedItem::Fn(value.const_.ty()),
span: span(),
});
}
_ => {}
}
}
}
_ => {}
}
}
fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>,
location: Location) {
self.super_rvalue(rvalue, location);
let span = || self.body.source_info(location).span;
match *rvalue {
mir::Rvalue::Cast(mir::CastKind::PointerCoercion(PointerCoercion::Unsize,
_), ref operand, target_ty) => {
let source_ty = operand.ty(self.body, self.tcx);
let may_involve_vtable =
match (source_ty.builtin_deref(true).map(|t| t.kind()),
target_ty.builtin_deref(true).map(|t| t.kind())) {
(Some(ty::Array(..)), Some(ty::Str | ty::Slice(..))) =>
false,
_ => true,
};
if may_involve_vtable {
self.mentioned_items.push(Spanned {
node: MentionedItem::UnsizeCast { source_ty, target_ty },
span: span(),
});
}
}
mir::Rvalue::Cast(mir::CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(_),
_), ref operand, _) => {
let source_ty = operand.ty(self.body, self.tcx);
self.mentioned_items.push(Spanned {
node: MentionedItem::Closure(source_ty),
span: span(),
});
}
mir::Rvalue::Cast(mir::CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer(_),
_), ref operand, _) => {
let fn_ty = operand.ty(self.body, self.tcx);
self.mentioned_items.push(Spanned {
node: MentionedItem::Fn(fn_ty),
span: span(),
});
}
_ => {}
}
}
}
}
#[allow(unused_imports)]
use mentioned_items::MentionedItems as _;
mod multiple_return_terminators {
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use crate::{PassPolicy, simplify};
pub(super) struct MultipleReturnTerminators;
impl<'tcx> crate::MirPass<'tcx> for MultipleReturnTerminators {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 4)
}
fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let mut bbs_simple_returns =
DenseBitSet::new_empty(body.basic_blocks.len());
let bbs = body.basic_blocks_mut();
for (idx, bb) in bbs.iter_enumerated() {
if bb.statements.is_empty() &&
bb.terminator().kind == TerminatorKind::Return {
bbs_simple_returns.insert(idx);
}
}
for bb in bbs {
if let TerminatorKind::Goto { target } = bb.terminator().kind
&& bbs_simple_returns.contains(target) {
bb.terminator_mut().kind = TerminatorKind::Return;
}
}
simplify::remove_dead_blocks(body)
}
}
}
#[allow(unused_imports)]
use multiple_return_terminators::MultipleReturnTerminators as _;
mod post_drop_elaboration {
use rustc_const_eval::check_consts;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use crate::MirLint;
pub(super) struct CheckLiveDrops;
impl<'tcx> MirLint<'tcx> for CheckLiveDrops {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
check_consts::post_drop_elaboration::check_live_drops(tcx, body);
}
}
}
#[allow(unused_imports)]
use post_drop_elaboration::CheckLiveDrops as _;
mod prettify {
use rustc_index::bit_set::DenseBitSet;
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use crate::PassPolicy;
pub(super) struct ReorderBasicBlocks;
impl<'tcx> crate::MirPass<'tcx> for ReorderBasicBlocks {
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(false)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let rpo: IndexVec<BasicBlock, BasicBlock> =
body.basic_blocks.reverse_postorder().iter().copied().collect();
if rpo.iter().is_sorted() { return; }
let mut updater =
BasicBlockUpdater {
map: rpo.invert_bijective_mapping(),
tcx,
};
if true {
{
match (&updater.map[START_BLOCK], &START_BLOCK) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
updater.visit_body(body);
permute(body.basic_blocks.as_mut(), &updater.map);
}
}
pub(super) struct ReorderLocals;
impl<'tcx> crate::MirPass<'tcx> for ReorderLocals {
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(false)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let mut finder =
LocalFinder {
map: IndexVec::new(),
seen: DenseBitSet::new_empty(body.local_decls.len()),
};
for local in (0..=body.arg_count).map(Local::from_usize) {
finder.track(local);
}
for (bb, bbd) in body.basic_blocks.iter_enumerated() {
finder.visit_basic_block_data(bb, bbd);
}
for local in body.local_decls.indices() { finder.track(local); }
if finder.map.iter().is_sorted() { return; }
let mut updater =
LocalUpdater {
map: finder.map.invert_bijective_mapping(),
tcx,
};
for local in (0..=body.arg_count).map(Local::from_usize) {
if true {
{
match (&updater.map[local], &local) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};
}
updater.visit_body_preserves_cfg(body);
permute(&mut body.local_decls, &updater.map);
}
}
fn permute<I: rustc_index::Idx + Ord,
T>(data: &mut IndexVec<I, T>, map: &IndexSlice<I, I>) {
let mut enumerated: Vec<_> =
std::mem::take(data).into_iter_enumerated().collect();
enumerated.sort_by_key(|p| map[p.0]);
*data = enumerated.into_iter().map(|p| p.1).collect();
}
struct BasicBlockUpdater<'tcx> {
map: IndexVec<BasicBlock, BasicBlock>,
tcx: TyCtxt<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for BasicBlockUpdater<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>,
_location: Location) {
terminator.successors_mut(|succ| *succ = self.map[*succ]);
}
}
struct LocalFinder {
map: IndexVec<Local, Local>,
seen: DenseBitSet<Local>,
}
impl LocalFinder {
fn track(&mut self, l: Local) {
if self.seen.insert(l) { self.map.push(l); }
}
}
impl<'tcx> Visitor<'tcx> for LocalFinder {
fn visit_local(&mut self, l: Local, context: PlaceContext,
_location: Location) {
if context.is_use() { self.track(l); }
}
}
struct LocalUpdater<'tcx> {
map: IndexVec<Local, Local>,
tcx: TyCtxt<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_local(&mut self, l: &mut Local, _: PlaceContext,
_: Location) {
*l = self.map[*l];
}
}
}
#[allow(unused_imports)]
use prettify::ReorderBasicBlocks as _;
#[allow(unused_imports)]
use prettify::ReorderLocals as _;
mod promote_consts {
use std::cell::Cell;
use std::{assert_matches, cmp, iter, mem};
use either::{Left, Right};
use rustc_const_eval::check_consts::{ConstCx, qualifs};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::thin_vec::ThinVec;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_index::{IndexSlice, IndexVec};
use rustc_middle::mir::visit::{
MutVisitor, MutatingUseContext, PlaceContext, Visitor,
};
use rustc_middle::mir::*;
use rustc_middle::ty::{
self, GenericArgs, List, Ty, TyCtxt, TypeVisitableExt,
};
use rustc_middle::{bug, mir, span_bug};
use rustc_span::{Span, Spanned};
use tracing::{debug, instrument};
use crate::PassPolicy;
pub(super) struct PromoteTemps<'tcx> {
pub promoted_fragments: Cell<IndexVec<Promoted, Body<'tcx>>>,
}
#[automatically_derived]
impl<'tcx> ::core::default::Default for PromoteTemps<'tcx> {
#[inline]
fn default() -> PromoteTemps<'tcx> {
PromoteTemps {
promoted_fragments: ::core::default::Default::default(),
}
}
}
impl<'tcx> crate::MirPass<'tcx> for PromoteTemps<'tcx> {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
if let Err(_) = body.return_ty().error_reported() {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/promote_consts.rs:51",
"rustc_mir_transform::promote_consts",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/promote_consts.rs"),
::tracing_core::__macro_support::Option::Some(51u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::promote_consts"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("PromoteTemps: MIR had errors")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return;
}
if body.source.promoted.is_some() { return; }
let ccx = ConstCx::new(tcx, body);
let (mut temps, all_candidates) =
collect_temps_and_candidates(&ccx);
let promotable_candidates =
validate_candidates(&ccx, &mut temps, all_candidates);
let promoted =
promote_candidates(body, tcx, temps, promotable_candidates);
self.promoted_fragments.set(promoted);
}
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::Required
}
}
enum TempState {
Undefined,
Defined {
location: Location,
uses: usize,
valid: Result<(), ()>,
},
Unpromotable,
PromotedOut,
}
#[automatically_derived]
impl ::core::marker::Copy for TempState { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for TempState { }
#[automatically_derived]
impl ::core::clone::Clone for TempState {
#[inline]
fn clone(&self) -> TempState {
let _: ::core::clone::AssertParamIsClone<Location>;
let _: ::core::clone::AssertParamIsClone<usize>;
let _: ::core::clone::AssertParamIsClone<Result<(), ()>>;
*self
}
}
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for TempState { }
#[automatically_derived]
impl ::core::cmp::PartialEq for TempState {
#[inline]
fn eq(&self, other: &TempState) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(TempState::Defined {
location: __self_0, uses: __self_1, valid: __self_2 },
TempState::Defined {
location: __arg1_0, uses: __arg1_1, valid: __arg1_2 }) =>
__self_0 == __arg1_0 && __self_1 == __arg1_1 &&
__self_2 == __arg1_2,
_ => true,
}
}
}
#[automatically_derived]
impl ::core::cmp::Eq for TempState {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Location>;
let _: ::core::cmp::AssertParamIsEq<usize>;
let _: ::core::cmp::AssertParamIsEq<Result<(), ()>>;
}
}
#[automatically_derived]
impl ::core::fmt::Debug for TempState {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
TempState::Undefined =>
::core::fmt::Formatter::write_str(f, "Undefined"),
TempState::Defined {
location: __self_0, uses: __self_1, valid: __self_2 } =>
::core::fmt::Formatter::debug_struct_field3_finish(f,
"Defined", "location", __self_0, "uses", __self_1, "valid",
&__self_2),
TempState::Unpromotable =>
::core::fmt::Formatter::write_str(f, "Unpromotable"),
TempState::PromotedOut =>
::core::fmt::Formatter::write_str(f, "PromotedOut"),
}
}
}
struct Candidate {
location: Location,
}
#[automatically_derived]
impl ::core::marker::Copy for Candidate { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Candidate { }
#[automatically_derived]
impl ::core::clone::Clone for Candidate {
#[inline]
fn clone(&self) -> Candidate {
let _: ::core::clone::AssertParamIsClone<Location>;
*self
}
}
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for Candidate { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Candidate {
#[inline]
fn eq(&self, other: &Candidate) -> bool {
self.location == other.location
}
}
#[automatically_derived]
impl ::core::cmp::Eq for Candidate {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Location>;
}
}
#[automatically_derived]
impl ::core::fmt::Debug for Candidate {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f, "Candidate",
"location", &&self.location)
}
}
struct Collector<'a, 'tcx> {
ccx: &'a ConstCx<'a, 'tcx>,
temps: IndexVec<Local, TempState>,
candidates: Vec<Candidate>,
}
impl<'tcx> Visitor<'tcx> for Collector<'_, 'tcx> {
fn visit_local(&mut self, index: Local, context: PlaceContext,
location: Location) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("visit_local",
"rustc_mir_transform::promote_consts",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/promote_consts.rs"),
::tracing_core::__macro_support::Option::Some(104u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::promote_consts"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("index")
}> =
::tracing::__macro_support::FieldName::new("index");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("context")
}> =
::tracing::__macro_support::FieldName::new("context");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("location")
}> =
::tracing::__macro_support::FieldName::new("location");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&index)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&context)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&location)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
match self.ccx.body.local_kind(index) {
LocalKind::Arg => return,
LocalKind::Temp if
self.ccx.body.local_decls[index].is_user_variable() =>
return,
LocalKind::ReturnPointer | LocalKind::Temp => {}
}
if context.is_drop() || !context.is_use() {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/promote_consts.rs:117",
"rustc_mir_transform::promote_consts",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/promote_consts.rs"),
::tracing_core::__macro_support::Option::Some(117u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::promote_consts"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("is_drop")
}> =
::tracing::__macro_support::FieldName::new("is_drop");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("is_use")
}> =
::tracing::__macro_support::FieldName::new("is_use");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&context.is_drop()
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&context.is_use()
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return;
}
let temp = &mut self.temps[index];
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/promote_consts.rs:122",
"rustc_mir_transform::promote_consts",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/promote_consts.rs"),
::tracing_core::__macro_support::Option::Some(122u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::promote_consts"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("temp")
}> =
::tracing::__macro_support::FieldName::new("temp");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&temp)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
*temp =
match *temp {
TempState::Undefined =>
match context {
PlaceContext::MutatingUse(MutatingUseContext::Store |
MutatingUseContext::Call) => {
TempState::Defined { location, uses: 0, valid: Err(()) }
}
_ => TempState::Unpromotable,
},
TempState::Defined { ref mut uses, .. } => {
let allowed_use =
match context {
PlaceContext::MutatingUse(MutatingUseContext::Borrow) |
PlaceContext::NonMutatingUse(_) => true,
PlaceContext::MutatingUse(_) | PlaceContext::NonUse(_) =>
false,
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/promote_consts.rs:138",
"rustc_mir_transform::promote_consts",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/promote_consts.rs"),
::tracing_core::__macro_support::Option::Some(138u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::promote_consts"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("allowed_use")
}> =
::tracing::__macro_support::FieldName::new("allowed_use");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&allowed_use)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if allowed_use { *uses += 1; return; }
TempState::Unpromotable
}
TempState::Unpromotable | TempState::PromotedOut =>
TempState::Unpromotable,
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/promote_consts.rs:147",
"rustc_mir_transform::promote_consts",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/promote_consts.rs"),
::tracing_core::__macro_support::Option::Some(147u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::promote_consts"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("temp")
}> =
::tracing::__macro_support::FieldName::new("temp");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&temp)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
}
}
}
}
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>,
location: Location) {
self.super_rvalue(rvalue, location);
if let Rvalue::Ref(..) = *rvalue {
self.candidates.push(Candidate { location });
}
}
}
fn collect_temps_and_candidates<'tcx>(ccx: &ConstCx<'_, 'tcx>)
-> (IndexVec<Local, TempState>, Vec<Candidate>) {
let mut collector =
Collector {
temps: IndexVec::from_elem(TempState::Undefined,
&ccx.body.local_decls),
candidates: ::alloc::vec::Vec::new(),
ccx,
};
for (bb, data) in traversal::reverse_postorder(ccx.body) {
collector.visit_basic_block_data(bb, data);
}
(collector.temps, collector.candidates)
}
struct Validator<'a, 'tcx> {
ccx: &'a ConstCx<'a, 'tcx>,
temps: &'a mut IndexSlice<Local, TempState>,
promotion_safe_blocks: Option<FxHashSet<BasicBlock>>,
}
impl<'a, 'tcx> std::ops::Deref for Validator<'a, 'tcx> {
type Target = ConstCx<'a, 'tcx>;
fn deref(&self) -> &Self::Target { self.ccx }
}
struct Unpromotable;
impl<'tcx> Validator<'_, 'tcx> {
fn validate_candidate(&mut self, candidate: Candidate)
-> Result<(), Unpromotable> {
let Left(statement) =
self.body.stmt_at(candidate.location) else {
::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))
};
let Some((_, Rvalue::Ref(_, kind, place))) =
statement.kind.as_assign() else {
::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))
};
self.validate_local(place.local)?;
self.validate_ref(*kind, place)?;
if place.projection.contains(&ProjectionElem::Deref) {
return Err(Unpromotable);
}
Ok(())
}
fn qualif_local<Q: qualifs::Qualif>(&mut self, local: Local) -> bool {
let TempState::Defined { location: loc, .. } =
self.temps[local] else { return false; };
let stmt_or_term = self.body.stmt_at(loc);
match stmt_or_term {
Left(statement) => {
let Some((_, rhs)) =
statement.kind.as_assign() else {
::rustc_middle::util::bug::span_bug_fmt(statement.source_info.span,
format_args!("{0:?} is not an assignment", statement))
};
qualifs::in_rvalue::<Q,
_>(self.ccx, &mut |l| self.qualif_local::<Q>(l), rhs)
}
Right(terminator) => {
{
match terminator.kind {
TerminatorKind::Call { .. } => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"TerminatorKind::Call { .. }",
::core::option::Option::None);
}
}
};
let return_ty = self.body.local_decls[local].ty;
Q::in_any_value_of_ty(self.ccx, return_ty)
}
}
}
fn validate_local(&mut self, local: Local)
-> Result<(), Unpromotable> {
let TempState::Defined { location: loc, uses, valid } =
self.temps[local] else { return Err(Unpromotable); };
if self.qualif_local::<qualifs::NeedsDrop>(local) {
return Err(Unpromotable);
}
if valid.is_ok() { return Ok(()); }
let ok =
{
let stmt_or_term = self.body.stmt_at(loc);
match stmt_or_term {
Left(statement) => {
let Some((_, rhs)) =
statement.kind.as_assign() else {
::rustc_middle::util::bug::span_bug_fmt(statement.source_info.span,
format_args!("{0:?} is not an assignment", statement))
};
self.validate_rvalue(rhs)
}
Right(terminator) =>
match &terminator.kind {
TerminatorKind::Call { func, args, .. } => {
self.validate_call(func, args, loc.block)
}
TerminatorKind::Yield { .. } => Err(Unpromotable),
kind => {
::rustc_middle::util::bug::span_bug_fmt(terminator.source_info.span,
format_args!("{0:?} not promotable", kind));
}
},
}
};
self.temps[local] =
match ok {
Ok(()) =>
TempState::Defined { location: loc, uses, valid: Ok(()) },
Err(_) => TempState::Unpromotable,
};
ok
}
fn validate_place(&mut self, place: PlaceRef<'tcx>)
-> Result<(), Unpromotable> {
let Some((place_base, elem)) =
place.last_projection() else {
return self.validate_local(place.local);
};
match elem {
ProjectionElem::ConstantIndex { .. } |
ProjectionElem::Subslice { .. } |
ProjectionElem::UnwrapUnsafeBinder(_) => {}
ProjectionElem::PhantomDeref | ProjectionElem::OpaqueCast(..)
| ProjectionElem::Downcast(..) => {
return Err(Unpromotable);
}
ProjectionElem::Deref => {
if let Some(local) = place_base.as_local() &&
let TempState::Defined { location, .. } = self.temps[local]
&& let Left(def_stmt) = self.body.stmt_at(location) &&
let Some((_, Rvalue::Use(Operand::Constant(c), _))) =
def_stmt.kind.as_assign() &&
let Some(did) = c.check_static_ptr(self.tcx) &&
let Some(hir::ConstContext::Static(..)) = self.const_kind &&
!self.tcx.is_thread_local_static(did) &&
!self.tcx.is_foreign_item(did)
{} else { return Err(Unpromotable); }
}
ProjectionElem::Index(local) => {
if let TempState::Defined { location: loc, .. } =
self.temps[local] &&
let Left(statement) = self.body.stmt_at(loc) &&
let Some((_, Rvalue::Use(Operand::Constant(c), _))) =
statement.kind.as_assign() &&
self.should_evaluate_for_promotion_checks(c.const_) &&
let Some(idx) =
c.const_.try_eval_target_usize(self.tcx, self.typing_env) &&
let ty::Array(_, len) =
place_base.ty(self.body, self.tcx).ty.kind() &&
let Some(len) = len.try_to_target_usize(self.tcx) &&
idx < len {
self.validate_local(local)?;
} else { return Err(Unpromotable); }
}
ProjectionElem::Field(..) => {
let base_ty = place_base.ty(self.body, self.tcx).ty;
if base_ty.is_union() { return Err(Unpromotable); }
}
}
self.validate_place(place_base)
}
fn validate_operand(&mut self, operand: &Operand<'tcx>)
-> Result<(), Unpromotable> {
match operand {
Operand::Copy(place) | Operand::Move(place) =>
self.validate_place(place.as_ref()),
Operand::RuntimeChecks(_) => Err(Unpromotable),
Operand::Constant(c) => {
if let Some(def_id) = c.check_static_ptr(self.tcx) {
let is_static =
#[allow(non_exhaustive_omitted_patterns)] match self.const_kind
{
Some(hir::ConstContext::Static(_)) => true,
_ => false,
};
if !is_static { return Err(Unpromotable); }
let is_thread_local =
self.tcx.is_thread_local_static(def_id);
if is_thread_local { return Err(Unpromotable); }
}
Ok(())
}
}
}
fn validate_ref(&mut self, kind: BorrowKind, place: &Place<'tcx>)
-> Result<(), Unpromotable> {
match kind {
BorrowKind::Fake(_) | BorrowKind::Mut {
kind: MutBorrowKind::ClosureCapture } => {
return Err(Unpromotable);
}
BorrowKind::Shared => {
let has_mut_interior =
self.qualif_local::<qualifs::HasMutInterior>(place.local);
if has_mut_interior { return Err(Unpromotable); }
}
BorrowKind::Mut {
kind: MutBorrowKind::Default | MutBorrowKind::TwoPhaseBorrow
} => {
let ty = place.ty(self.body, self.tcx).ty;
let ty::Array(_, len) =
ty.kind() else { return Err(Unpromotable) };
let Some(0) =
len.try_to_target_usize(self.tcx) else {
return Err(Unpromotable)
};
}
}
Ok(())
}
fn validate_rvalue(&mut self, rvalue: &Rvalue<'tcx>)
-> Result<(), Unpromotable> {
match rvalue {
Rvalue::Use(_operand, WithRetag::No) => {
return Err(Unpromotable);
}
Rvalue::Use(operand, _) | Rvalue::Repeat(operand, _) |
Rvalue::WrapUnsafeBinder(operand, _) => {
self.validate_operand(operand)?;
}
Rvalue::CopyForDeref(place) => {
let op = &Operand::Copy(*place);
self.validate_operand(op)?
}
Rvalue::Discriminant(place) =>
self.validate_place(place.as_ref())?,
Rvalue::ThreadLocalRef(_) => return Err(Unpromotable),
Rvalue::Cast(CastKind::PointerExposeProvenance, _, _) =>
return Err(Unpromotable),
Rvalue::Cast(_, operand, _) => {
self.validate_operand(operand)?;
}
Rvalue::UnaryOp(op, operand) => {
match op { UnOp::Neg | UnOp::Not | UnOp::PtrMetadata => {} }
self.validate_operand(operand)?;
}
Rvalue::BinaryOp(op, (lhs, rhs)) => {
let op = *op;
let lhs_ty = lhs.ty(self.body, self.tcx);
if let ty::RawPtr(_, _) | ty::FnPtr(..) = lhs_ty.kind() {
{
match op {
BinOp::Eq | BinOp::Ne | BinOp::Le | BinOp::Lt | BinOp::Ge |
BinOp::Gt | BinOp::Offset => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"BinOp::Eq | BinOp::Ne | BinOp::Le | BinOp::Lt | BinOp::Ge | BinOp::Gt |\nBinOp::Offset",
::core::option::Option::None);
}
}
};
return Err(Unpromotable);
}
match op {
BinOp::Div | BinOp::Rem => {
if lhs_ty.is_integral() {
let sz = lhs_ty.primitive_size(self.tcx);
let rhs_val =
if let Operand::Constant(rhs_c) = rhs &&
self.should_evaluate_for_promotion_checks(rhs_c.const_) &&
let Some(rhs_val) =
rhs_c.const_.try_eval_scalar_int(self.tcx, self.typing_env)
&& rhs_val.to_uint(sz) != 0 {
rhs_val
} else { return Err(Unpromotable); };
if lhs_ty.is_signed() && rhs_val.to_int(sz) == -1 {
if let Operand::Constant(lhs_c) = lhs &&
self.should_evaluate_for_promotion_checks(lhs_c.const_) &&
let Some(lhs_val) =
lhs_c.const_.try_eval_scalar_int(self.tcx, self.typing_env)
&& let lhs_min = sz.signed_int_min() &&
lhs_val.to_int(sz) != lhs_min
{} else { return Err(Unpromotable); }
}
}
}
BinOp::Eq | BinOp::Ne | BinOp::Le | BinOp::Lt | BinOp::Ge |
BinOp::Gt | BinOp::Cmp | BinOp::Offset | BinOp::Add |
BinOp::AddUnchecked | BinOp::AddWithOverflow | BinOp::Sub |
BinOp::SubUnchecked | BinOp::SubWithOverflow | BinOp::Mul |
BinOp::MulUnchecked | BinOp::MulWithOverflow | BinOp::BitXor
| BinOp::BitAnd | BinOp::BitOr | BinOp::Shl |
BinOp::ShlUnchecked | BinOp::Shr | BinOp::ShrUnchecked => {}
}
self.validate_operand(lhs)?;
self.validate_operand(rhs)?;
}
Rvalue::RawPtr(_, place) => {
if let Some((place_base, ProjectionElem::Deref)) =
place.as_ref().last_projection() {
let base_ty = place_base.ty(self.body, self.tcx).ty;
if let ty::Ref(..) = base_ty.kind() {
return self.validate_place(place_base);
}
}
return Err(Unpromotable);
}
Rvalue::Ref(_, kind, place) => {
let mut place_simplified = place.as_ref();
if let Some((place_base, ProjectionElem::Deref)) =
place_simplified.last_projection() {
let base_ty = place_base.ty(self.body, self.tcx).ty;
if let ty::Ref(..) = base_ty.kind() {
place_simplified = place_base;
}
}
self.validate_place(place_simplified)?;
self.validate_ref(*kind, place)?;
}
Rvalue::Reborrow(..) => return Err(Unpromotable),
Rvalue::Aggregate(_, operands) => {
for o in operands { self.validate_operand(o)?; }
}
}
Ok(())
}
fn promotion_safe_blocks(body: &mir::Body<'tcx>)
-> FxHashSet<BasicBlock> {
let mut safe_blocks = FxHashSet::default();
let mut safe_block = START_BLOCK;
loop {
safe_blocks.insert(safe_block);
safe_block =
match body.basic_blocks[safe_block].terminator().kind {
TerminatorKind::Goto { target } => target,
TerminatorKind::Call { target: Some(target), .. } |
TerminatorKind::Drop { target, .. } => {
target
}
TerminatorKind::Assert { target, .. } => { target }
_ => { break; }
};
}
safe_blocks
}
fn is_promotion_safe_block(&mut self, block: BasicBlock) -> bool {
let body = self.body;
let safe_blocks =
self.promotion_safe_blocks.get_or_insert_with(||
Self::promotion_safe_blocks(body));
safe_blocks.contains(&block)
}
fn validate_call(&mut self, callee: &Operand<'tcx>,
args: &[Spanned<Operand<'tcx>>], block: BasicBlock)
-> Result<(), Unpromotable> {
self.validate_operand(callee)?;
for arg in args { self.validate_operand(&arg.node)?; }
let fn_ty = callee.ty(self.body, self.tcx);
if let ty::FnDef(def_id, _) = *fn_ty.kind() {
if self.tcx.is_promotable_const_fn(def_id) { return Ok(()); }
}
let promote_all_fn =
#[allow(non_exhaustive_omitted_patterns)] match self.const_kind
{
Some(hir::ConstContext::Static(_) |
hir::ConstContext::Const { allow_const_fn_promotion: true })
=> true,
_ => false,
};
if !promote_all_fn { return Err(Unpromotable); }
let is_const_fn =
match *fn_ty.kind() {
ty::FnDef(def_id, _) => self.tcx.is_const_fn(def_id),
_ => false,
};
if !is_const_fn { return Err(Unpromotable); }
if !self.is_promotion_safe_block(block) {
return Err(Unpromotable);
}
Ok(())
}
fn should_evaluate_for_promotion_checks(&self, constant: Const<'tcx>)
-> bool {
match constant {
Const::Ty(..) => false,
Const::Val(..) => true,
Const::Unevaluated(uc, _) => {
self.tcx.def_kind(uc.def) != DefKind::AnonConst ||
self.tcx.anon_const_kind(uc.def) !=
ty::AnonConstKind::NonTypeSystemInline
}
}
}
}
fn validate_candidates(ccx: &ConstCx<'_, '_>,
temps: &mut IndexSlice<Local, TempState>,
mut candidates: Vec<Candidate>) -> Vec<Candidate> {
let mut validator =
Validator { ccx, temps, promotion_safe_blocks: None };
candidates.retain(|&candidate|
validator.validate_candidate(candidate).is_ok());
candidates
}
struct Promoter<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
source: &'a mut Body<'tcx>,
promoted: Body<'tcx>,
temps: &'a mut IndexVec<Local, TempState>,
extra_statements: &'a mut Vec<(Location, Statement<'tcx>)>,
required_consts: Vec<ConstOperand<'tcx>>,
keep_original: bool,
add_to_required: bool,
}
impl<'a, 'tcx> Promoter<'a, 'tcx> {
fn new_block(&mut self) -> BasicBlock {
let span = self.promoted.span;
self.promoted.basic_blocks_mut().push(BasicBlockData::new(Some(Terminator {
source_info: SourceInfo::outermost(span),
kind: TerminatorKind::Return,
attributes: ThinVec::new(),
}), false))
}
fn assign(&mut self, dest: Local, rvalue: Rvalue<'tcx>, span: Span) {
let last = self.promoted.basic_blocks.last_index().unwrap();
let data = &mut self.promoted[last];
data.statements.push(Statement::new(SourceInfo::outermost(span),
StatementKind::Assign(Box::new((Place::from(dest),
rvalue)))));
}
fn is_temp_kind(&self, local: Local) -> bool {
self.source.local_kind(local) == LocalKind::Temp
}
fn promote_temp(&mut self, temp: Local) -> Local {
let old_keep_original = self.keep_original;
let loc =
match self.temps[temp] {
TempState::Defined { location, uses, .. } if uses > 0 => {
if uses > 1 { self.keep_original = true; }
location
}
state => {
::rustc_middle::util::bug::span_bug_fmt(self.promoted.span,
format_args!("{0:?} not promotable: {1:?}", temp, state));
}
};
if !self.keep_original {
self.temps[temp] = TempState::PromotedOut;
}
let num_stmts = self.source[loc.block].statements.len();
let new_temp =
self.promoted.local_decls.push(LocalDecl::new(self.source.local_decls[temp].ty,
self.source.local_decls[temp].source_info.span));
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/promote_consts.rs:803",
"rustc_mir_transform::promote_consts",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/promote_consts.rs"),
::tracing_core::__macro_support::Option::Some(803u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::promote_consts"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("promote({0:?} @ {1:?}/{2:?}, {3:?})",
temp, loc, num_stmts, self.keep_original) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};
if loc.statement_index < num_stmts {
let (mut rvalue, source_info) =
{
let statement =
&mut self.source[loc.block].statements[loc.statement_index];
let StatementKind::Assign((_, rhs)) =
&mut statement.kind else {
::rustc_middle::util::bug::span_bug_fmt(statement.source_info.span,
format_args!("{0:?} is not an assignment", statement));
};
(if self.keep_original {
rhs.clone()
} else {
let unit =
Rvalue::Use(Operand::Constant(Box::new(ConstOperand {
span: statement.source_info.span,
user_ty: None,
const_: Const::zero_sized(self.tcx.types.unit),
})), WithRetag::Yes);
mem::replace(rhs, unit)
}, statement.source_info)
};
self.visit_rvalue(&mut rvalue, loc);
self.assign(new_temp, rvalue, source_info.span);
} else {
let terminator =
if self.keep_original {
self.source[loc.block].terminator().clone()
} else {
let terminator = self.source[loc.block].terminator_mut();
let target =
match &terminator.kind {
TerminatorKind::Call { target: Some(target), .. } =>
*target,
kind => {
::rustc_middle::util::bug::span_bug_fmt(terminator.source_info.span,
format_args!("{0:?} not promotable", kind));
}
};
Terminator {
source_info: terminator.source_info,
kind: mem::replace(&mut terminator.kind,
TerminatorKind::Goto { target }),
attributes: ThinVec::new(),
}
};
match terminator.kind {
TerminatorKind::Call {
mut func, mut args, call_source: desugar, fn_span, .. } => {
self.add_to_required = true;
self.visit_operand(&mut func, loc);
for arg in &mut args {
self.visit_operand(&mut arg.node, loc);
}
let last = self.promoted.basic_blocks.last_index().unwrap();
let new_target = self.new_block();
*self.promoted[last].terminator_mut() =
Terminator {
kind: TerminatorKind::Call {
func,
args,
unwind: UnwindAction::Continue,
destination: Place::from(new_temp),
target: Some(new_target),
call_source: desugar,
fn_span,
},
source_info: SourceInfo::outermost(terminator.source_info.span),
..terminator
};
}
kind => {
::rustc_middle::util::bug::span_bug_fmt(terminator.source_info.span,
format_args!("{0:?} not promotable", kind));
}
};
};
self.keep_original = old_keep_original;
new_temp
}
fn promote_candidate(mut self, candidate: Candidate,
next_promoted_index: Promoted) -> Body<'tcx> {
let def = self.source.source.def_id();
let (mut rvalue, promoted_op) =
{
let promoted = &mut self.promoted;
let tcx = self.tcx;
let mut promoted_operand =
|ty, span|
{
promoted.span = span;
promoted.local_decls[RETURN_PLACE] =
LocalDecl::new(ty, span);
let args =
tcx.erase_and_anonymize_regions(GenericArgs::identity_for_item(tcx,
def));
let uneval =
mir::UnevaluatedConst {
def,
args,
promoted: Some(next_promoted_index),
};
ConstOperand {
span,
user_ty: None,
const_: Const::Unevaluated(uneval, ty),
}
};
let blocks = self.source.basic_blocks.as_mut();
let local_decls = &mut self.source.local_decls;
let loc = candidate.location;
let statement =
&mut blocks[loc.block].statements[loc.statement_index];
let StatementKind::Assign((_,
Rvalue::Ref(region, borrow_kind, place))) =
&mut statement.kind else {
::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))
};
if true {
if !region.is_erased() {
::core::panicking::panic("assertion failed: region.is_erased()")
};
};
let ty = local_decls[place.local].ty;
let span = statement.source_info.span;
let ref_ty =
Ty::new_ref(tcx, tcx.lifetimes.re_erased, ty,
borrow_kind.to_mutbl_lossy());
let mut projection =
::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[PlaceElem::Deref]));
projection.extend(place.projection);
place.projection = tcx.mk_place_elems(&projection);
let mut promoted_ref = LocalDecl::new(ref_ty, span);
promoted_ref.source_info = statement.source_info;
let promoted_ref = local_decls.push(promoted_ref);
{
match (&self.temps.push(TempState::Unpromotable),
&promoted_ref) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
let promoted_operand = promoted_operand(ref_ty, span);
let promoted_ref_statement =
Statement::new(statement.source_info,
StatementKind::Assign(Box::new((Place::from(promoted_ref),
Rvalue::Use(Operand::Constant(Box::new(promoted_operand)),
WithRetag::Yes)))));
self.extra_statements.push((loc, promoted_ref_statement));
(Rvalue::Ref(tcx.lifetimes.re_erased, *borrow_kind,
Place {
local: mem::replace(&mut place.local, promoted_ref),
projection: List::empty(),
}), promoted_operand)
};
{
match (&self.new_block(), &START_BLOCK) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
self.visit_rvalue(&mut rvalue,
Location { block: START_BLOCK, statement_index: usize::MAX });
let span = self.promoted.span;
self.assign(RETURN_PLACE, rvalue, span);
if self.add_to_required {
self.source.required_consts.as_mut().unwrap().push(promoted_op);
}
self.promoted.set_required_consts(self.required_consts);
self.promoted
}
}
impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_local(&mut self, local: &mut Local, _: PlaceContext,
_: Location) {
if self.is_temp_kind(*local) {
*local = self.promote_temp(*local);
}
}
fn visit_const_operand(&mut self, constant: &mut ConstOperand<'tcx>,
_location: Location) {
if constant.const_.is_required_const() {
self.required_consts.push(*constant);
}
}
}
fn promote_candidates<'tcx>(body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>,
mut temps: IndexVec<Local, TempState>, candidates: Vec<Candidate>)
-> IndexVec<Promoted, Body<'tcx>> {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/promote_consts.rs:1016",
"rustc_mir_transform::promote_consts",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/promote_consts.rs"),
::tracing_core::__macro_support::Option::Some(1016u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::promote_consts"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("promote_candidates")
}> =
::tracing::__macro_support::FieldName::new("promote_candidates");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&candidates)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if candidates.is_empty() { return IndexVec::new(); }
let mut promotions = IndexVec::new();
let mut extra_statements = ::alloc::vec::Vec::new();
for candidate in candidates.into_iter().rev() {
let Location { block, statement_index } = candidate.location;
if let StatementKind::Assign((place, _)) =
&body[block].statements[statement_index].kind &&
let Some(local) = place.as_local() {
if temps[local] == TempState::PromotedOut { continue; }
}
let initial_locals =
iter::once(LocalDecl::new(tcx.types.never,
body.span)).collect();
let mut scope =
body.source_scopes[body.source_info(candidate.location).scope].clone();
scope.parent_scope = None;
let mut promoted =
Body::new(body.source, IndexVec::new(),
IndexVec::from_elem_n(scope, 1), initial_locals,
IndexVec::new(), 0, ::alloc::vec::Vec::new(), body.span,
None, body.tainted_by_errors);
promoted.phase = MirPhase::Analysis(AnalysisPhase::Initial);
let promoter =
Promoter {
promoted,
tcx,
source: body,
temps: &mut temps,
extra_statements: &mut extra_statements,
keep_original: false,
add_to_required: false,
required_consts: Vec::new(),
};
let mut promoted =
promoter.promote_candidate(candidate,
promotions.next_index());
promoted.source.promoted = Some(promotions.next_index());
promotions.push(promoted);
}
extra_statements.sort_by_key(|&(loc, _)| cmp::Reverse(loc));
for (loc, statement) in extra_statements {
body[loc.block].statements.insert(loc.statement_index, statement);
}
let promoted = |index: Local| temps[index] == TempState::PromotedOut;
for block in body.basic_blocks_mut() {
block.retain_statements(|statement|
match &statement.kind {
StatementKind::Assign((place, _)) => {
if let Some(index) = place.as_local() {
!promoted(index)
} else { true }
}
StatementKind::StorageLive(index) |
StatementKind::StorageDead(index) => {
!promoted(*index)
}
_ => true,
});
let terminator = block.terminator_mut();
if let TerminatorKind::Drop { place, target, .. } =
&terminator.kind && let Some(index) = place.as_local() {
if promoted(index) {
terminator.kind = TerminatorKind::Goto { target: *target };
}
}
}
promotions
}
}
#[allow(unused_imports)]
use promote_consts::PromoteTemps as _;
mod ref_prop {
use std::borrow::Cow;
use rustc_data_structures::fx::FxHashSet;
use rustc_index::IndexVec;
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::bug;
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use rustc_mir_dataflow::Analysis;
use rustc_mir_dataflow::impls::{
MaybeStorageDead, always_storage_live_locals,
};
use tracing::{debug, instrument};
use crate::PassPolicy;
use crate::ssa::{SsaLocals, StorageLiveLocals};
pub(super) struct ReferencePropagation;
impl<'tcx> crate::MirPass<'tcx> for ReferencePropagation {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 2)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("run_pass",
"rustc_mir_transform::ref_prop", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs"),
::tracing_core::__macro_support::Option::Some(80u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::ref_prop"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs:82",
"rustc_mir_transform::ref_prop", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs"),
::tracing_core::__macro_support::Option::Some(82u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::ref_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&body.source.def_id())
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
move_to_copy_pointers(tcx, body);
while propagate_ssa(tcx, body) {}
}
}
}
}
}
fn move_to_copy_pointers<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let mut visitor =
MoveToCopyVisitor { tcx, local_decls: &body.local_decls };
for (bb, data) in
body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
visitor.visit_basic_block_data(bb, data);
}
struct MoveToCopyVisitor<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
local_decls: &'a IndexVec<Local, LocalDecl<'tcx>>,
}
impl<'a, 'tcx> MutVisitor<'tcx> for MoveToCopyVisitor<'a, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_operand(&mut self, operand: &mut Operand<'tcx>,
loc: Location) {
if let Operand::Move(place) = *operand {
if place.ty(self.local_decls, self.tcx).ty.is_any_ptr() {
*operand = Operand::Copy(place);
}
}
self.super_operand(operand, loc);
}
}
}
fn propagate_ssa<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool {
let typing_env = body.typing_env(tcx);
let ssa = SsaLocals::new(tcx, body, typing_env);
let mut replacer = compute_replacement(tcx, body, ssa);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs:125",
"rustc_mir_transform::ref_prop", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs"),
::tracing_core::__macro_support::Option::Some(125u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::ref_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("replacer.targets")
}> =
::tracing::__macro_support::FieldName::new("replacer.targets");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&replacer.targets)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs:126",
"rustc_mir_transform::ref_prop", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs"),
::tracing_core::__macro_support::Option::Some(126u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::ref_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("replacer.allowed_replacements")
}> =
::tracing::__macro_support::FieldName::new("replacer.allowed_replacements");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&replacer.allowed_replacements)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs:127",
"rustc_mir_transform::ref_prop", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs"),
::tracing_core::__macro_support::Option::Some(127u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::ref_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("replacer.storage_to_remove")
}> =
::tracing::__macro_support::FieldName::new("replacer.storage_to_remove");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&replacer.storage_to_remove)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
replacer.visit_body_preserves_cfg(body);
if replacer.any_replacement {
crate::simplify::remove_unused_definitions(body);
}
replacer.any_replacement
}
enum Value<'tcx> {
Unknown,
Pointer(Place<'tcx>, bool),
}
#[automatically_derived]
impl<'tcx> ::core::marker::Copy for Value<'tcx> { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl<'tcx> ::core::clone::TrivialClone for Value<'tcx> { }
#[automatically_derived]
impl<'tcx> ::core::clone::Clone for Value<'tcx> {
#[inline]
fn clone(&self) -> Value<'tcx> {
let _: ::core::clone::AssertParamIsClone<Place<'tcx>>;
let _: ::core::clone::AssertParamIsClone<bool>;
*self
}
}
#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for Value<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
Value::Unknown =>
::core::fmt::Formatter::write_str(f, "Unknown"),
Value::Pointer(__self_0, __self_1) =>
::core::fmt::Formatter::debug_tuple_field2_finish(f,
"Pointer", __self_0, &__self_1),
}
}
}
#[automatically_derived]
impl<'tcx> ::core::marker::StructuralPartialEq for Value<'tcx> { }
#[automatically_derived]
impl<'tcx> ::core::cmp::PartialEq for Value<'tcx> {
#[inline]
fn eq(&self, other: &Value<'tcx>) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(Value::Pointer(__self_0, __self_1),
Value::Pointer(__arg1_0, __arg1_1)) =>
__self_1 == __arg1_1 && __self_0 == __arg1_0,
_ => true,
}
}
}
#[automatically_derived]
impl<'tcx> ::core::cmp::Eq for Value<'tcx> {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<Place<'tcx>>;
let _: ::core::cmp::AssertParamIsEq<bool>;
}
}
#[doc = " For each local, save the place corresponding to `*local`."]
fn compute_replacement<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>,
ssa: SsaLocals) -> Replacer<'tcx> {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("compute_replacement",
"rustc_mir_transform::ref_prop", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs"),
::tracing_core::__macro_support::Option::Some(148u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::ref_prop"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: Replacer<'tcx> = loop {};
return __tracing_attr_fake_return;
}
{
let always_live_locals = always_storage_live_locals(body);
let storage_live =
StorageLiveLocals::new(body, &always_live_locals);
let mut maybe_dead =
MaybeStorageDead::new(Cow::Owned(always_live_locals)).iterate_to_fixpoint(tcx,
body, None).into_results_cursor(body);
let mut targets =
IndexVec::from_elem(Value::Unknown, &body.local_decls);
let mut storage_to_remove =
DenseBitSet::new_empty(body.local_decls.len());
let fully_replaceable_locals =
fully_replaceable_locals(&ssa);
let is_constant_place =
|place: Place<'_>|
{
if let Some((&PlaceElem::Deref, rest)) =
place.projection.split_first() {
ssa.is_ssa(place.local) &&
rest.iter().all(PlaceElem::is_stable_offset)
} else {
storage_live.has_single_storage(place.local) &&
place.projection[..].iter().all(PlaceElem::is_stable_offset)
}
};
let mut can_perform_opt =
|target: Place<'tcx>, loc: Location|
{
if target.is_indirect_first_projection() {
storage_to_remove.insert(target.local);
true
} else {
maybe_dead.seek_after_primary_effect(loc);
let maybe_dead = maybe_dead.get().contains(target.local);
!maybe_dead
}
};
for (local, rvalue, location) in ssa.assignments(body) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs:220",
"rustc_mir_transform::ref_prop", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs"),
::tracing_core::__macro_support::Option::Some(220u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::ref_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("local")
}> =
::tracing::__macro_support::FieldName::new("local");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&local)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let Value::Unknown =
targets[local] else {
::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))
};
let ty = body.local_decls[local].ty;
if !ty.is_any_ptr() {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs:229",
"rustc_mir_transform::ref_prop", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs"),
::tracing_core::__macro_support::Option::Some(229u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::ref_prop"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("not a reference or pointer")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
continue;
}
let needs_unique = ty.is_mutable_ptr();
if needs_unique && !fully_replaceable_locals.contains(local)
{
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs:238",
"rustc_mir_transform::ref_prop", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs"),
::tracing_core::__macro_support::Option::Some(238u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::ref_prop"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("not fully replaceable")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
continue;
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs:242",
"rustc_mir_transform::ref_prop", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs"),
::tracing_core::__macro_support::Option::Some(242u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::ref_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("rvalue")
}> =
::tracing::__macro_support::FieldName::new("rvalue");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&rvalue)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
match rvalue {
Rvalue::Use(Operand::Copy(place) | Operand::Move(place), _)
=> {
if let Some(rhs) = place.as_local() && ssa.is_ssa(rhs) {
let target = targets[rhs];
if !needs_unique &&
#[allow(non_exhaustive_omitted_patterns)] match target {
Value::Pointer(..) => true,
_ => false,
} {
targets[local] = target;
} else {
targets[local] =
Value::Pointer(tcx.mk_place_deref(rhs.into()),
needs_unique);
}
}
}
Rvalue::Ref(_, _, place) | Rvalue::RawPtr(_, place) => {
let mut place = *place;
if let Some((&PlaceElem::Deref, rest)) =
place.projection.split_first() &&
let Value::Pointer(target, inner_needs_unique) =
targets[place.local] && !inner_needs_unique &&
can_perform_opt(target, location) {
place = target.project_deeper(rest, tcx);
}
{
match (&place.local, &local) {
(left_val, right_val) => {
if *left_val == *right_val {
let kind = ::core::panicking::AssertKind::Ne;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
if is_constant_place(place) {
targets[local] = Value::Pointer(place, needs_unique);
}
}
_ => {}
}
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs:285",
"rustc_mir_transform::ref_prop", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs"),
::tracing_core::__macro_support::Option::Some(285u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::ref_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("targets")
}> =
::tracing::__macro_support::FieldName::new("targets");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&targets)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let mut finder =
ReplacementFinder {
targets,
can_perform_opt,
allowed_replacements: FxHashSet::default(),
};
let reachable_blocks = traversal::reachable_as_bitset(body);
for (bb, bbdata) in body.basic_blocks.iter_enumerated() {
if reachable_blocks.contains(bb) {
finder.visit_basic_block_data(bb, bbdata);
}
}
let allowed_replacements = finder.allowed_replacements;
return Replacer {
tcx,
targets: finder.targets,
remap_var_debug_infos: IndexVec::from_elem(None,
body.local_decls()),
storage_to_remove,
allowed_replacements,
any_replacement: false,
};
struct ReplacementFinder<'tcx, F> {
targets: IndexVec<Local, Value<'tcx>>,
can_perform_opt: F,
allowed_replacements: FxHashSet<(Local, Location)>,
}
impl<'tcx, F> Visitor<'tcx> for ReplacementFinder<'tcx, F>
where F: FnMut(Place<'tcx>, Location) -> bool {
fn visit_place(&mut self, place: &Place<'tcx>,
ctxt: PlaceContext, loc: Location) {
if #[allow(non_exhaustive_omitted_patterns)] match ctxt {
PlaceContext::NonUse(_) => true,
_ => false,
} {
return;
}
if !place.is_indirect_first_projection() { return; }
let mut place = place.as_ref();
loop {
if let Value::Pointer(target, needs_unique) =
self.targets[place.local] {
let perform_opt = (self.can_perform_opt)(target, loc);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs:332",
"rustc_mir_transform::ref_prop", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/ref_prop.rs"),
::tracing_core::__macro_support::Option::Some(332u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::ref_prop"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("place")
}> =
::tracing::__macro_support::FieldName::new("place");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("target")
}> =
::tracing::__macro_support::FieldName::new("target");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("needs_unique")
}> =
::tracing::__macro_support::FieldName::new("needs_unique");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("perform_opt")
}> =
::tracing::__macro_support::FieldName::new("perform_opt");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&place)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&target)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&needs_unique)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&perform_opt)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if let &[PlaceElem::Deref] = &target.projection[..] {
if !perform_opt {
::core::panicking::panic("assertion failed: perform_opt")
};
self.allowed_replacements.insert((target.local, loc));
place.local = target.local;
continue;
} else if perform_opt {
self.allowed_replacements.insert((target.local, loc));
} else if needs_unique {
self.targets[place.local] = Value::Unknown;
}
}
break;
}
}
}
}
}
}
}
fn fully_replaceable_locals(ssa: &SsaLocals) -> DenseBitSet<Local> {
let mut replaceable = DenseBitSet::new_empty(ssa.num_locals());
for local in ssa.locals() {
if ssa.num_direct_uses(local) == 0 { replaceable.insert(local); }
}
ssa.meet_copy_equivalence(&mut replaceable);
replaceable
}
struct Replacer<'tcx> {
tcx: TyCtxt<'tcx>,
targets: IndexVec<Local, Value<'tcx>>,
remap_var_debug_infos: IndexVec<Local, Option<Local>>,
storage_to_remove: DenseBitSet<Local>,
allowed_replacements: FxHashSet<(Local, Location)>,
any_replacement: bool,
}
impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_var_debug_info(&mut self,
debuginfo: &mut VarDebugInfo<'tcx>) {
if let VarDebugInfoContents::Place(ref mut place) =
debuginfo.value && place.projection.is_empty() {
let mut new_local = place.local;
while let Value::Pointer(target, _) = self.targets[new_local]
&& let &[PlaceElem::Deref] = &target.projection[..] {
new_local = target.local;
}
if place.local != new_local {
self.remap_var_debug_infos[place.local] = Some(new_local);
place.local = new_local;
self.any_replacement = true;
}
}
self.super_var_debug_info(debuginfo);
}
fn visit_statement_debuginfo(&mut self,
stmt_debuginfo: &mut StmtDebugInfo<'tcx>, location: Location) {
let local =
match stmt_debuginfo {
StmtDebugInfo::AssignRef(local, _) |
StmtDebugInfo::InvalidAssign(local) => local,
};
if let Some(target) = self.remap_var_debug_infos[*local] {
*local = target;
self.any_replacement = true;
}
self.super_statement_debuginfo(stmt_debuginfo, location);
}
fn visit_place(&mut self, place: &mut Place<'tcx>, ctxt: PlaceContext,
loc: Location) {
loop {
let Some((&PlaceElem::Deref, rest)) =
place.projection.split_first() else { return };
let Value::Pointer(target, _) =
self.targets[place.local] else { return };
let perform_opt =
match ctxt {
PlaceContext::NonUse(NonUseContext::VarDebugInfo) => {
target.projection.iter().all(|p| p.can_use_in_debuginfo())
}
PlaceContext::NonUse(_) => true,
_ =>
self.allowed_replacements.contains(&(target.local, loc)),
};
if !perform_opt { return; }
*place = target.project_deeper(rest, self.tcx);
self.any_replacement = true;
}
}
fn visit_statement(&mut self, stmt: &mut Statement<'tcx>,
loc: Location) {
match stmt.kind {
StatementKind::StorageLive(l) | StatementKind::StorageDead(l)
if self.storage_to_remove.contains(l) => {
stmt.make_nop(true);
}
_ => {}
}
self.super_statement(stmt, loc);
}
}
}
#[allow(unused_imports)]
use ref_prop::ReferencePropagation as _;
pub mod remove_noop_landing_pads {
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Instance, TyCtxt};
use tracing::{debug, instrument};
use crate::PassPolicy;
use crate::patch::MirPatch;
pub(super) struct RemoveNoopLandingPads;
impl<'tcx> crate::MirPass<'tcx> for RemoveNoopLandingPads {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.panic_strategy().unwinds())
}
fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("run_pass",
"rustc_mir_transform::remove_noop_landing_pads",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs"),
::tracing_core::__macro_support::Option::Some(21u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::remove_noop_landing_pads"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
let def_id = body.source.def_id();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs:24",
"rustc_mir_transform::remove_noop_landing_pads",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs"),
::tracing_core::__macro_support::Option::Some(24u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::remove_noop_landing_pads"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&def_id)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let has_resume =
body.basic_blocks.iter_enumerated().any(|(_bb, block)|
#[allow(non_exhaustive_omitted_patterns)] match block.terminator().kind
{
TerminatorKind::UnwindResume => true,
_ => false,
});
if !has_resume {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs:32",
"rustc_mir_transform::remove_noop_landing_pads",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs"),
::tracing_core::__macro_support::Option::Some(32u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::remove_noop_landing_pads"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("no resume block in MIR")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return;
}
let nop_landing_pads = find_noop_landing_pads(body, None);
if nop_landing_pads.is_empty() {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs:39",
"rustc_mir_transform::remove_noop_landing_pads",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs"),
::tracing_core::__macro_support::Option::Some(39u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::remove_noop_landing_pads"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("no nop landing pads in MIR")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
return;
}
let resume_block =
{
let mut patch = MirPatch::new(body);
let resume_block = patch.resume_block();
patch.apply(body);
resume_block
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs:50",
"rustc_mir_transform::remove_noop_landing_pads",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs"),
::tracing_core::__macro_support::Option::Some(50u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::remove_noop_landing_pads"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("resume_block")
}> =
::tracing::__macro_support::FieldName::new("resume_block");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&resume_block)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let basic_blocks = body.basic_blocks.as_mut();
for (bb, bbdata) in basic_blocks.iter_enumerated_mut() {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs:54",
"rustc_mir_transform::remove_noop_landing_pads",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs"),
::tracing_core::__macro_support::Option::Some(54u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::remove_noop_landing_pads"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("processing {0:?}",
bb) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if let Some(unwind) = bbdata.terminator_mut().unwind_mut()
&& let UnwindAction::Cleanup(unwind_bb) = *unwind &&
nop_landing_pads.contains(unwind_bb) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs:60",
"rustc_mir_transform::remove_noop_landing_pads",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs"),
::tracing_core::__macro_support::Option::Some(60u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::remove_noop_landing_pads"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!(" removing noop landing pad")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
*unwind = UnwindAction::Continue;
}
bbdata.terminator_mut().successors_mut(|target|
{
if *target != resume_block &&
nop_landing_pads.contains(*target) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs:66",
"rustc_mir_transform::remove_noop_landing_pads",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs"),
::tracing_core::__macro_support::Option::Some(66u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::remove_noop_landing_pads"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!(" folding noop jump to {0:?} to resume block",
target) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
*target = resume_block;
}
});
}
}
}
}
}
}
impl RemoveNoopLandingPads {
fn is_nop_landing_pad<'tcx>(&self, bbdata: &BasicBlockData<'tcx>,
body: &Body<'tcx>, nop_landing_pads: &DenseBitSet<BasicBlock>,
extra: Option<&ExtraInfo<'tcx>>) -> bool {
for stmt in &bbdata.statements {
match &stmt.kind {
StatementKind::FakeRead(..) | StatementKind::StorageLive(_)
| StatementKind::StorageDead(_) |
StatementKind::PlaceMention(..) |
StatementKind::AscribeUserType(..) |
StatementKind::Coverage(..) |
StatementKind::ConstEvalCounter |
StatementKind::BackwardIncompatibleDropHint { .. } |
StatementKind::Nop => {}
StatementKind::Assign((place,
Rvalue::Use(..) | Rvalue::Discriminant(_))) => {
if place.as_local().is_some() {} else { return false; }
}
StatementKind::Assign { .. } |
StatementKind::SetDiscriminant { .. } |
StatementKind::Intrinsic(..) => {
return false;
}
}
}
let terminator = bbdata.terminator();
match terminator.kind {
TerminatorKind::Goto { .. } | TerminatorKind::UnwindResume |
TerminatorKind::SwitchInt { .. } |
TerminatorKind::FalseEdge { .. } |
TerminatorKind::FalseUnwind { .. } => {
terminator.successors().all(|succ|
nop_landing_pads.contains(succ))
}
TerminatorKind::Drop { place, .. } => {
if let Some(extra) = extra {
let ty = place.ty(body, extra.tcx).ty;
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs:125",
"rustc_mir_transform::remove_noop_landing_pads",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs"),
::tracing_core::__macro_support::Option::Some(125u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::remove_noop_landing_pads"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("monomorphize: instance={0:?}",
extra.instance) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let ty =
extra.instance.instantiate_mir_and_normalize_erasing_regions(extra.tcx,
extra.typing_env, ty::EarlyBinder::bind(extra.tcx, ty));
let drop_fn = Instance::resolve_drop_glue(extra.tcx, ty);
if let ty::InstanceKind::Shim(ty::ShimKind::DropGlue(_,
None)) = drop_fn.def {
return terminator.successors().all(|succ|
nop_landing_pads.contains(succ));
}
}
false
}
TerminatorKind::CoroutineDrop | TerminatorKind::Yield { .. } |
TerminatorKind::Return | TerminatorKind::UnwindTerminate(_)
| TerminatorKind::Unreachable | TerminatorKind::Call { .. }
| TerminatorKind::TailCall { .. } | TerminatorKind::Assert {
.. } | TerminatorKind::InlineAsm { .. } => false,
}
}
}
pub struct ExtraInfo<'tcx> {
pub tcx: TyCtxt<'tcx>,
pub instance: Instance<'tcx>,
pub typing_env: ty::TypingEnv<'tcx>,
}
pub fn find_noop_landing_pads<'tcx>(body: &Body<'tcx>,
extra: Option<ExtraInfo<'tcx>>) -> DenseBitSet<BasicBlock> {
let mut nop_landing_pads =
DenseBitSet::new_empty(body.basic_blocks.len());
let postorder: Vec<_> =
traversal::postorder(body).map(|(bb, _)| bb).collect();
for bb in postorder {
let is_nop_landing_pad =
RemoveNoopLandingPads.is_nop_landing_pad(&body.basic_blocks[bb],
body, &nop_landing_pads, extra.as_ref());
if is_nop_landing_pad { nop_landing_pads.insert(bb); }
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs:182",
"rustc_mir_transform::remove_noop_landing_pads",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs"),
::tracing_core::__macro_support::Option::Some(182u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::remove_noop_landing_pads"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!(" is_nop_landing_pad({0:?}) = {1}",
bb, is_nop_landing_pad) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
}
nop_landing_pads
}
}
#[allow(unused_imports)]
use remove_noop_landing_pads::RemoveNoopLandingPads as _;
mod remove_place_mention {
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use tracing::trace;
use crate::PassPolicy;
pub(super) struct RemovePlaceMention;
impl<'tcx> crate::MirPass<'tcx> for RemovePlaceMention {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(!ctx.opts.unstable_opts.mir_preserve_ub)
}
fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_place_mention.rs:17",
"rustc_mir_transform::remove_place_mention",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_place_mention.rs"),
::tracing_core::__macro_support::Option::Some(17u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::remove_place_mention"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Running RemovePlaceMention on {0:?}",
body.source) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
for data in body.basic_blocks.as_mut_preserves_cfg() {
data.retain_statements(|statement|
match statement.kind {
StatementKind::PlaceMention(..) | StatementKind::Nop =>
false,
_ => true,
})
}
}
}
}
#[allow(unused_imports)]
use remove_place_mention::RemovePlaceMention as _;
mod remove_storage_markers {
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use tracing::trace;
use crate::PassPolicy;
pub(super) struct RemoveStorageMarkers;
impl<'tcx> crate::MirPass<'tcx> for RemoveStorageMarkers {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 1 &&
!ctx.emit_lifetime_markers())
}
fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_storage_markers.rs:17",
"rustc_mir_transform::remove_storage_markers",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_storage_markers.rs"),
::tracing_core::__macro_support::Option::Some(17u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::remove_storage_markers"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Running RemoveStorageMarkers on {0:?}",
body.source) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
for data in body.basic_blocks.as_mut_preserves_cfg() {
data.retain_statements(|statement|
match statement.kind {
StatementKind::StorageLive(..) |
StatementKind::StorageDead(..) | StatementKind::Nop =>
false,
_ => true,
})
}
}
}
}
#[allow(unused_imports)]
use remove_storage_markers::RemoveStorageMarkers as _;
mod remove_uninit_drops {
use rustc_abi::FieldIdx;
use rustc_index::bit_set::MixedBitSet;
use rustc_middle::mir::{Body, TerminatorKind};
use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, VariantDef};
use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
use rustc_mir_dataflow::move_paths::{
LookupResult, MoveData, MovePathIndex,
};
use rustc_mir_dataflow::{
Analysis, MaybeReachable, move_path_children_matching,
};
use crate::PassPolicy;
pub(super) struct RemoveUninitDrops;
impl<'tcx> crate::MirPass<'tcx> for RemoveUninitDrops {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let typing_env = body.typing_env(tcx);
let move_data =
MoveData::gather_moves(body, tcx,
|ty| ty.needs_drop(tcx, typing_env));
let mut maybe_inits =
MaybeInitializedPlaces::new(tcx, body,
&move_data).exclude_inactive_in_otherwise().iterate_to_fixpoint(tcx,
body,
Some("remove_uninit_drops")).into_results_cursor(body);
let mut to_remove = ::alloc::vec::Vec::new();
for (bb, block) in body.basic_blocks.iter_enumerated() {
let terminator = block.terminator();
let TerminatorKind::Drop { place, .. } =
&terminator.kind else { continue };
maybe_inits.seek_before_primary_effect(body.terminator_loc(bb));
let MaybeReachable::Reachable(maybe_inits) =
maybe_inits.get() else { continue };
let LookupResult::Exact(mpi) =
move_data.rev_lookup.find(place.as_ref()) else {
continue;
};
let should_keep =
is_needs_drop_and_init(tcx, typing_env, maybe_inits,
&move_data, place.ty(body, tcx).ty, mpi);
if !should_keep { to_remove.push(bb) }
}
for bb in to_remove {
let block = &mut body.basic_blocks_mut()[bb];
let TerminatorKind::Drop { target, .. } =
&block.terminator().kind else {
::core::panicking::panic("internal error: entered unreachable code")
};
block.terminator_mut().kind =
TerminatorKind::Goto { target: *target };
}
}
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::Required
}
}
fn is_needs_drop_and_init<'tcx>(tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
maybe_inits: &MixedBitSet<MovePathIndex>, move_data: &MoveData<'tcx>,
ty: Ty<'tcx>, mpi: MovePathIndex) -> bool {
if !maybe_inits.contains(mpi) || !ty.needs_drop(tcx, typing_env) {
return false;
}
let field_needs_drop_and_init =
|(f, f_ty, mpi)|
{
let child =
move_path_children_matching(move_data, mpi,
|x| x.is_field_to(f));
let Some(mpi) =
child else {
return Ty::needs_drop(f_ty, tcx, typing_env);
};
is_needs_drop_and_init(tcx, typing_env, maybe_inits,
move_data, f_ty, mpi)
};
match ty.kind() {
ty::Adt(adt, args) => {
let dont_elaborate =
adt.is_union() || adt.is_manually_drop() ||
adt.has_dtor(tcx);
if dont_elaborate { return true; }
adt.variants().iter_enumerated().any(|(vid, variant)|
{
let mpi =
if adt.is_enum() {
let downcast =
move_path_children_matching(move_data, mpi,
|x| x.is_downcast_to(vid));
let Some(dc_mpi) =
downcast else {
return variant_needs_drop(tcx, typing_env, args, variant);
};
dc_mpi
} else { mpi };
variant.fields.iter().enumerate().map(|(f, field)|
{
(FieldIdx::from_usize(f),
field.ty(tcx, args).skip_norm_wip(), mpi)
}).any(field_needs_drop_and_init)
})
}
ty::Tuple(fields) =>
fields.iter().enumerate().map(|(f, f_ty)|
(FieldIdx::from_usize(f), f_ty,
mpi)).any(field_needs_drop_and_init),
_ => true,
}
}
fn variant_needs_drop<'tcx>(tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>, args: GenericArgsRef<'tcx>,
variant: &VariantDef) -> bool {
variant.fields.iter().any(|field|
{
let f_ty = field.ty(tcx, args).skip_norm_wip();
f_ty.needs_drop(tcx, typing_env)
})
}
}
#[allow(unused_imports)]
use remove_uninit_drops::RemoveUninitDrops as _;
mod remove_unneeded_drops {
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use tracing::{debug, trace};
use super::simplify::simplify_cfg;
use crate::PassPolicy;
pub(super) struct RemoveUnneededDrops;
impl<'tcx> crate::MirPass<'tcx> for RemoveUnneededDrops {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs:19",
"rustc_mir_transform::remove_unneeded_drops",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs"),
::tracing_core::__macro_support::Option::Some(19u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::remove_unneeded_drops"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Running RemoveUnneededDrops on {0:?}",
body.source) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let typing_env = body.typing_env(tcx);
let mut should_simplify = false;
for block in body.basic_blocks.as_mut() {
let terminator = block.terminator_mut();
let TerminatorKind::Drop { place, target, .. } =
terminator.kind else { continue };
let ty = place.ty(&body.local_decls, tcx).ty;
if ty.needs_drop(tcx, typing_env) { continue; }
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs:31",
"rustc_mir_transform::remove_unneeded_drops",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs"),
::tracing_core::__macro_support::Option::Some(31u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::remove_unneeded_drops"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("SUCCESS: replacing `drop` with goto({0:?})",
target) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
terminator.kind = TerminatorKind::Goto { target };
should_simplify = true;
}
if should_simplify { simplify_cfg(tcx, body); }
}
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(true)
}
}
}
#[allow(unused_imports)]
use remove_unneeded_drops::RemoveUnneededDrops as _;
mod remove_zsts {
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty, TyCtxt};
use crate::PassPolicy;
pub(super) struct RemoveZsts;
impl<'tcx> crate::MirPass<'tcx> for RemoveZsts {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 1)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
if tcx.type_of(body.source.def_id()).instantiate_identity().skip_norm_wip().is_coroutine()
{
return;
}
let typing_env = body.typing_env(tcx);
let local_decls = &body.local_decls;
let mut replacer = Replacer { tcx, typing_env, local_decls };
for var_debug_info in &mut body.var_debug_info {
replacer.visit_var_debug_info(var_debug_info);
}
for (bb, data) in
body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut()
{
replacer.visit_basic_block_data(bb, data);
}
}
}
struct Replacer<'a, 'tcx> {
tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
local_decls: &'a LocalDecls<'tcx>,
}
fn trivially_zst<'tcx>(ty: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Option<bool> {
match ty.kind() {
ty::FnDef(..) | ty::Never => Some(true),
ty::Tuple(fields) if fields.is_empty() => Some(true),
ty::Array(_ty, len) if let Some(0) = len.try_to_target_usize(tcx)
=> Some(true),
ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) | ty::Float(..) |
ty::RawPtr(..) | ty::Ref(..) | ty::FnPtr(..) => Some(false),
ty::Coroutine(def_id, _) => {
if tcx.is_async_drop_in_place_coroutine(*def_id) {
Some(false)
} else { None }
}
_ => None,
}
}
impl<'tcx> Replacer<'_, 'tcx> {
fn known_to_be_zst(&self, ty: Ty<'tcx>) -> bool {
if let Some(is_zst) = trivially_zst(ty, self.tcx) {
is_zst
} else {
self.tcx.layout_of(self.typing_env.as_query_input(ty)).is_ok_and(|layout|
layout.is_zst())
}
}
fn make_zst(&self, ty: Ty<'tcx>) -> ConstOperand<'tcx> {
if true {
if !self.known_to_be_zst(ty) {
::core::panicking::panic("assertion failed: self.known_to_be_zst(ty)")
};
};
ConstOperand {
span: rustc_span::DUMMY_SP,
user_ty: None,
const_: Const::Val(ConstValue::ZeroSized, ty),
}
}
}
impl<'tcx> MutVisitor<'tcx> for Replacer<'_, 'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_var_debug_info(&mut self,
var_debug_info: &mut VarDebugInfo<'tcx>) {
match var_debug_info.value {
VarDebugInfoContents::Const(_) => {}
VarDebugInfoContents::Place(place) => {
let place_ty = place.ty(self.local_decls, self.tcx).ty;
if self.known_to_be_zst(place_ty) {
var_debug_info.value =
VarDebugInfoContents::Const(self.make_zst(place_ty))
}
}
}
}
fn visit_operand(&mut self, operand: &mut Operand<'tcx>,
_: Location) {
if let Operand::Constant(_) = operand { return; }
let op_ty = operand.ty(self.local_decls, self.tcx);
if self.known_to_be_zst(op_ty) {
*operand = Operand::Constant(Box::new(self.make_zst(op_ty)))
}
}
fn visit_statement(&mut self, statement: &mut Statement<'tcx>,
loc: Location) {
let place_for_ty =
match statement.kind {
StatementKind::Assign((place, ref rvalue)) => {
rvalue.is_safe_to_remove().then_some(place)
}
StatementKind::SetDiscriminant { ref place, variant_index: _
} | StatementKind::PlaceMention(ref place) => Some(**place),
StatementKind::AscribeUserType((place, _), _) |
StatementKind::FakeRead((_, place)) => {
Some(place)
}
StatementKind::StorageLive(local) |
StatementKind::StorageDead(local) => {
Some(local.into())
}
StatementKind::Coverage(_) | StatementKind::Intrinsic(_) |
StatementKind::Nop |
StatementKind::BackwardIncompatibleDropHint { .. } |
StatementKind::ConstEvalCounter => None,
};
if let Some(place_for_ty) = place_for_ty &&
let ty = place_for_ty.ty(self.local_decls, self.tcx).ty &&
self.known_to_be_zst(ty) {
statement.make_nop(true);
} else { self.super_statement(statement, loc); }
}
}
}
#[allow(unused_imports)]
use remove_zsts::RemoveZsts as _;
mod required_consts {
use rustc_middle::mir::visit::Visitor;
use rustc_middle::mir::{Body, ConstOperand, Location, traversal};
pub(super) struct RequiredConstsVisitor<'tcx> {
required_consts: Vec<ConstOperand<'tcx>>,
}
impl<'tcx> RequiredConstsVisitor<'tcx> {
pub(super) fn compute_required_consts(body: &mut Body<'tcx>) {
let mut visitor =
RequiredConstsVisitor { required_consts: Vec::new() };
for (bb, bb_data) in traversal::reverse_postorder(&body) {
visitor.visit_basic_block_data(bb, bb_data);
}
body.set_required_consts(visitor.required_consts);
}
}
impl<'tcx> Visitor<'tcx> for RequiredConstsVisitor<'tcx> {
fn visit_const_operand(&mut self, constant: &ConstOperand<'tcx>,
_: Location) {
if constant.const_.is_required_const() {
self.required_consts.push(*constant);
}
}
}
}
#[allow(unused_imports)]
use required_consts::RequiredConstsVisitor as _;
mod post_analysis_normalize {
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty, TyCtxt};
use crate::PassPolicy;
pub(super) struct PostAnalysisNormalize;
impl<'tcx> crate::MirPass<'tcx> for PostAnalysisNormalize {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let typing_env =
ty::TypingEnv::post_analysis(tcx, body.source.def_id());
PostAnalysisNormalizeVisitor {
tcx,
typing_env,
}.visit_body_preserves_cfg(body);
}
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::Required
}
}
struct PostAnalysisNormalizeVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for PostAnalysisNormalizeVisitor<'tcx> {
#[inline]
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
#[inline]
fn visit_place(&mut self, place: &mut Place<'tcx>,
_context: PlaceContext, _location: Location) {
if !self.tcx.next_trait_solver_globally() {
if place.projection.iter().any(|elem|
#[allow(non_exhaustive_omitted_patterns)] match elem {
ProjectionElem::OpaqueCast(_) => true,
_ => false,
}) {
place.projection =
self.tcx.mk_place_elems(&place.projection.into_iter().filter(|elem|
!#[allow(non_exhaustive_omitted_patterns)] match elem {
ProjectionElem::OpaqueCast(_) => true,
_ => false,
}).collect::<Vec<_>>());
};
}
self.super_place(place, _context, _location);
}
#[inline]
fn visit_const_operand(&mut self, constant: &mut ConstOperand<'tcx>,
location: Location) {
if let Ok(c) =
self.tcx.try_normalize_erasing_regions(self.typing_env,
ty::set_aliases_to_non_rigid(self.tcx, constant.const_)) {
constant.const_ = c;
}
self.super_const_operand(constant, location);
}
#[inline]
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
if let Ok(t) =
self.tcx.try_normalize_erasing_regions(self.typing_env,
ty::set_aliases_to_non_rigid(self.tcx, *ty)) {
*ty = t;
}
}
#[inline]
fn visit_args(&mut self, args: &mut ty::GenericArgsRef<'tcx>,
_: Location) {
if let Ok(a) =
self.tcx.try_normalize_erasing_regions(self.typing_env,
ty::set_aliases_to_non_rigid(self.tcx, *args)) {
*args = a;
}
}
}
}
#[allow(unused_imports)]
use post_analysis_normalize::PostAnalysisNormalize as _;
mod sanity_check {
use rustc_middle::mir::Body;
use rustc_middle::ty::TyCtxt;
use rustc_mir_dataflow::rustc_peek::sanity_check;
pub(super) struct SanityCheck;
impl<'tcx> crate::MirLint<'tcx> for SanityCheck {
fn run_lint(&self, tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
sanity_check(tcx, body);
}
}
}
#[allow(unused_imports)]
use sanity_check::SanityCheck as _;
pub mod simplify {
use itertools::Itertools as _;
use rustc_index::bit_set::DenseBitSet;
use rustc_index::{Idx, IndexSlice, IndexVec};
use rustc_middle::mir::visit::{
MutVisitor, MutatingUseContext, PlaceContext, Visitor,
};
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use rustc_mir_dataflow::debuginfo::debuginfo_locals;
use rustc_span::DUMMY_SP;
use smallvec::SmallVec;
use tracing::{debug, trace};
use crate::PassPolicy;
pub(super) enum SimplifyCfg {
Initial,
PromoteConsts,
RemoveFalseEdges,
PostAnalysis,
PreOptimizations,
Final,
MakeShim,
AfterUnreachableEnumBranching,
}
impl SimplifyCfg {
fn name(&self) -> &'static str {
match self {
SimplifyCfg::Initial => "SimplifyCfg-initial",
SimplifyCfg::PromoteConsts => "SimplifyCfg-promote-consts",
SimplifyCfg::RemoveFalseEdges =>
"SimplifyCfg-remove-false-edges",
SimplifyCfg::PostAnalysis => "SimplifyCfg-post-analysis",
SimplifyCfg::PreOptimizations =>
"SimplifyCfg-pre-optimizations",
SimplifyCfg::Final => "SimplifyCfg-final",
SimplifyCfg::MakeShim => "SimplifyCfg-make_shim",
SimplifyCfg::AfterUnreachableEnumBranching => {
"SimplifyCfg-after-unreachable-enum-branching"
}
}
}
}
pub(super) fn simplify_cfg<'tcx>(tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>) {
if CfgSimplifier::new(tcx, body).simplify() {
body.basic_blocks.invalidate_cfg_cache();
}
remove_dead_blocks(body);
body.basic_blocks.as_mut_preserves_cfg().shrink_to_fit();
}
impl<'tcx> crate::MirPass<'tcx> for SimplifyCfg {
fn name(&self) -> &'static str { self.name() }
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(true)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify.rs:103",
"rustc_mir_transform::simplify", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify.rs"),
::tracing_core::__macro_support::Option::Some(103u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::simplify"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("SimplifyCfg({0:?}) - simplifying {1:?}",
self.name(), body.source) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};
simplify_cfg(tcx, body);
}
}
struct CfgSimplifier<'a, 'tcx> {
preserve_switch_reads: bool,
basic_blocks: &'a mut IndexSlice<BasicBlock, BasicBlockData<'tcx>>,
pred_count: IndexVec<BasicBlock, u32>,
}
impl<'a, 'tcx> CfgSimplifier<'a, 'tcx> {
fn new(tcx: TyCtxt<'tcx>, body: &'a mut Body<'tcx>) -> Self {
let mut pred_count =
IndexVec::from_elem(0u32, &body.basic_blocks);
pred_count[START_BLOCK] = 1;
for (_, data) in traversal::preorder(body) {
if let Some(ref term) = data.terminator {
for tgt in term.successors() { pred_count[tgt] += 1; }
}
}
let preserve_switch_reads =
#[allow(non_exhaustive_omitted_patterns)] match body.phase {
MirPhase::Built | MirPhase::Analysis(_) => true,
_ => false,
} || tcx.sess.opts.unstable_opts.mir_preserve_ub;
let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
CfgSimplifier { preserve_switch_reads, basic_blocks, pred_count }
}
#[must_use]
fn simplify(mut self) -> bool {
self.strip_nops();
let mut merged_blocks: Vec<BasicBlock> = Vec::new();
let mut outer_changed = false;
loop {
let mut changed = false;
for bb in self.basic_blocks.indices() {
if self.pred_count[bb] == 0 { continue; }
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify.rs:159",
"rustc_mir_transform::simplify", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify.rs"),
::tracing_core::__macro_support::Option::Some(159u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::simplify"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("simplifying {0:?}",
bb) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let mut terminator =
self.basic_blocks[bb].terminator.take().expect("invalid terminator state");
terminator.successors_mut(|successor|
{ self.collapse_goto_chain(successor, &mut changed); });
let mut inner_changed = true;
merged_blocks.clear();
while inner_changed {
inner_changed = false;
inner_changed |= self.simplify_branch(&mut terminator);
inner_changed |=
self.merge_successor(&mut merged_blocks, &mut terminator);
changed |= inner_changed;
}
let statements_to_merge =
merged_blocks.iter().map(|&i|
self.basic_blocks[i].statements.len()).sum();
if statements_to_merge > 0 {
let mut statements =
std::mem::take(&mut self.basic_blocks[bb].statements);
statements.reserve(statements_to_merge);
let mut parent_bb_last_debuginfos =
std::mem::take(&mut self.basic_blocks[bb].after_last_stmt_debuginfos);
for &from in &merged_blocks {
if let Some(stmt) =
self.basic_blocks[from].statements.first_mut() {
stmt.debuginfos.prepend(&mut parent_bb_last_debuginfos);
}
statements.append(&mut self.basic_blocks[from].statements);
parent_bb_last_debuginfos =
std::mem::take(&mut self.basic_blocks[from].after_last_stmt_debuginfos);
}
self.basic_blocks[bb].statements = statements;
self.basic_blocks[bb].after_last_stmt_debuginfos =
parent_bb_last_debuginfos;
}
self.basic_blocks[bb].terminator = Some(terminator);
}
if !changed { break; }
outer_changed = true;
}
outer_changed
}
fn take_terminator_if_simple_goto(&mut self, bb: BasicBlock)
-> Option<Terminator<'tcx>> {
match self.basic_blocks[bb] {
BasicBlockData {
ref statements,
terminator: ref mut terminator
@
Some(Terminator { kind: TerminatorKind::Goto { .. }, .. }),
.. } if statements.is_empty() => terminator.take(),
_ => None,
}
}
fn collapse_goto_chain(&mut self, start: &mut BasicBlock,
changed: &mut bool) {
let mut terminators: SmallVec<[_; 1]> = Default::default();
let mut current = *start;
let mut trivial_goto_chain = true;
while let Some(terminator) =
self.take_terminator_if_simple_goto(current) {
let Terminator { kind: TerminatorKind::Goto { target }, .. } =
terminator else {
::core::panicking::panic("internal error: entered unreachable code");
};
trivial_goto_chain &= self.pred_count[target] == 1;
terminators.push((current, terminator));
current = target;
}
let last = current;
*changed |= *start != last;
*start = last;
while let Some((current, mut terminator)) = terminators.pop() {
let Terminator {
kind: TerminatorKind::Goto { ref mut target }, .. } =
terminator else {
::core::panicking::panic("internal error: entered unreachable code");
};
if trivial_goto_chain {
let mut pred_debuginfos =
std::mem::take(&mut self.basic_blocks[current].after_last_stmt_debuginfos);
let debuginfos =
if let Some(stmt) =
self.basic_blocks[last].statements.first_mut() {
&mut stmt.debuginfos
} else {
&mut self.basic_blocks[last].after_last_stmt_debuginfos
};
debuginfos.prepend(&mut pred_debuginfos);
}
*changed |= *target != last;
*target = last;
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify.rs:266",
"rustc_mir_transform::simplify", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify.rs"),
::tracing_core::__macro_support::Option::Some(266u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::simplify"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("collapsing goto chain from {0:?} to {1:?}",
current, target) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if self.pred_count[current] == 1 {
self.pred_count[current] = 0;
} else {
self.pred_count[*target] += 1;
self.pred_count[current] -= 1;
}
self.basic_blocks[current].terminator = Some(terminator);
}
}
fn merge_successor(&mut self, merged_blocks: &mut Vec<BasicBlock>,
terminator: &mut Terminator<'tcx>) -> bool {
let target =
match terminator.kind {
TerminatorKind::Goto { target } if
self.pred_count[target] == 1 => target,
_ => return false,
};
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify.rs:291",
"rustc_mir_transform::simplify", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify.rs"),
::tracing_core::__macro_support::Option::Some(291u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::simplify"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("merging block {0:?} into {1:?}",
target, terminator) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
*terminator =
match self.basic_blocks[target].terminator.take() {
Some(terminator) => terminator,
None => { return false; }
};
merged_blocks.push(target);
self.pred_count[target] = 0;
true
}
fn simplify_branch(&mut self, terminator: &mut Terminator<'tcx>)
-> bool {
if self.preserve_switch_reads { return false; }
let TerminatorKind::SwitchInt { .. } =
terminator.kind else { return false; };
let Ok(first_succ) =
terminator.successors().all_equal_value() else {
return false;
};
let count = terminator.successors().count();
self.pred_count[first_succ] -= (count - 1) as u32;
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify.rs:327",
"rustc_mir_transform::simplify", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify.rs"),
::tracing_core::__macro_support::Option::Some(327u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::simplify"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("simplifying branch {0:?}",
terminator) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
terminator.kind = TerminatorKind::Goto { target: first_succ };
true
}
fn strip_nops(&mut self) {
for blk in self.basic_blocks.iter_mut() { blk.strip_nops(); }
}
}
pub(super) fn simplify_duplicate_switch_targets(terminator:
&mut Terminator<'_>) {
if let TerminatorKind::SwitchInt { targets, .. } =
&mut terminator.kind {
let otherwise = targets.otherwise();
if targets.iter().any(|t| t.1 == otherwise) {
*targets =
SwitchTargets::new(targets.iter().filter(|t|
t.1 != otherwise), targets.otherwise());
}
}
}
pub(super) fn remove_dead_blocks(body: &mut Body<'_>) {
let should_deduplicate_unreachable =
|bbdata: &BasicBlockData<'_>|
{
bbdata.terminator.is_some() && bbdata.is_empty_unreachable()
&& !bbdata.is_cleanup
};
let reachable = traversal::reachable_as_bitset(body);
let empty_unreachable_blocks =
body.basic_blocks.iter_enumerated().filter(|(bb, bbdata)|
should_deduplicate_unreachable(bbdata) &&
reachable.contains(*bb)).count();
let num_blocks = body.basic_blocks.len();
if num_blocks == reachable.count() && empty_unreachable_blocks <= 1 {
return;
}
let basic_blocks = body.basic_blocks.as_mut();
let mut replacements: Vec<_> =
(0..num_blocks).map(BasicBlock::new).collect();
let mut orig_index = 0;
let mut used_index = 0;
let mut kept_unreachable = None;
let mut deduplicated_unreachable = false;
basic_blocks.raw.retain(|bbdata|
{
let orig_bb = BasicBlock::new(orig_index);
if !reachable.contains(orig_bb) {
orig_index += 1;
return false;
}
let used_bb = BasicBlock::new(used_index);
if should_deduplicate_unreachable(bbdata) {
let kept_unreachable =
*kept_unreachable.get_or_insert(used_bb);
if kept_unreachable != used_bb {
replacements[orig_index] = kept_unreachable;
deduplicated_unreachable = true;
orig_index += 1;
return false;
}
}
replacements[orig_index] = used_bb;
used_index += 1;
orig_index += 1;
true
});
if deduplicated_unreachable {
basic_blocks[kept_unreachable.unwrap()].terminator_mut().source_info
=
SourceInfo { span: DUMMY_SP, scope: OUTERMOST_SOURCE_SCOPE };
}
for block in basic_blocks {
block.terminator_mut().successors_mut(|target|
*target = replacements[target.index()]);
}
}
pub(super) enum SimplifyLocals { BeforeConstProp, AfterGVN, Final, }
impl<'tcx> crate::MirPass<'tcx> for SimplifyLocals {
fn name(&self) -> &'static str {
match &self {
SimplifyLocals::BeforeConstProp =>
"SimplifyLocals-before-const-prop",
SimplifyLocals::AfterGVN =>
"SimplifyLocals-after-value-numbering",
SimplifyLocals::Final => "SimplifyLocals-final",
}
}
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 1)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify.rs:437",
"rustc_mir_transform::simplify", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify.rs"),
::tracing_core::__macro_support::Option::Some(437u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::simplify"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("running SimplifyLocals on {0:?}",
body.source) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let mut used_locals = UsedLocals::new(body);
remove_unused_definitions_helper(&mut used_locals, body);
let map = make_local_map(&mut body.local_decls, &used_locals);
if map.iter().any(Option::is_none) {
let mut updater = LocalUpdater { map, tcx };
updater.visit_body_preserves_cfg(body);
body.local_decls.shrink_to_fit();
}
}
}
pub(super) fn remove_unused_definitions<'tcx>(body: &mut Body<'tcx>) {
let mut used_locals = UsedLocals::new(body);
remove_unused_definitions_helper(&mut used_locals, body);
}
fn make_local_map<V>(local_decls: &mut IndexVec<Local, V>,
used_locals: &UsedLocals) -> IndexVec<Local, Option<Local>> {
let mut map: IndexVec<Local, Option<Local>> =
IndexVec::from_elem(None, local_decls);
let mut used = Local::ZERO;
for alive_index in local_decls.indices() {
if !used_locals.is_used(alive_index) { continue; }
map[alive_index] = Some(used);
if alive_index != used { local_decls.swap(alive_index, used); }
used.increment_by(1);
}
local_decls.truncate(used.index());
map
}
struct UsedLocals {
increment: bool,
use_count: IndexVec<Local, u32>,
always_used: DenseBitSet<Local>,
}
impl UsedLocals {
fn new(body: &Body<'_>) -> Self {
let mut always_used = debuginfo_locals(body);
always_used.insert(RETURN_PLACE);
for arg in body.args_iter() { always_used.insert(arg); }
let mut this =
Self {
increment: true,
use_count: IndexVec::from_elem(0, &body.local_decls),
always_used,
};
this.visit_body(body);
this
}
fn is_used(&self, local: Local) -> bool {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify.rs:528",
"rustc_mir_transform::simplify", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify.rs"),
::tracing_core::__macro_support::Option::Some(528u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::simplify"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("is_used({0:?}): use_count: {1:?}, always_used: {2}",
local, self.use_count[local],
self.always_used.contains(local)) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};
self.always_used.contains(local) || self.use_count[local] != 0
}
fn statement_removed(&mut self, statement: &Statement<'_>) {
self.increment = false;
let location = Location::START;
self.visit_statement(statement, location);
}
fn visit_lhs(&mut self, place: &Place<'_>, location: Location) {
if place.is_indirect() {
self.visit_place(place,
PlaceContext::MutatingUse(MutatingUseContext::Store),
location);
} else {
self.super_projection(place.as_ref(),
PlaceContext::MutatingUse(MutatingUseContext::Projection),
location);
}
}
}
impl<'tcx> Visitor<'tcx> for UsedLocals {
fn visit_statement(&mut self, statement: &Statement<'tcx>,
location: Location) {
match statement.kind {
StatementKind::Intrinsic(..) | StatementKind::Coverage(..) |
StatementKind::FakeRead(..) |
StatementKind::PlaceMention(..) |
StatementKind::AscribeUserType(..) => {
self.super_statement(statement, location);
}
StatementKind::ConstEvalCounter | StatementKind::Nop |
StatementKind::StorageLive(..) |
StatementKind::StorageDead(..) => {}
StatementKind::Assign((ref place, ref rvalue)) => {
if rvalue.is_safe_to_remove() {
self.visit_lhs(place, location);
self.visit_rvalue(rvalue, location);
} else { self.super_statement(statement, location); }
}
StatementKind::SetDiscriminant { ref place, variant_index: _ }
| StatementKind::BackwardIncompatibleDropHint {
ref place, reason: _ } => {
self.visit_lhs(place, location);
}
}
}
fn visit_local(&mut self, local: Local, ctx: PlaceContext,
_location: Location) {
if #[allow(non_exhaustive_omitted_patterns)] match ctx {
PlaceContext::NonUse(_) => true,
_ => false,
} {
return;
}
if self.increment {
self.use_count[local] += 1;
} else {
{
match (&self.use_count[local], &0) {
(left_val, right_val) => {
if *left_val == *right_val {
let kind = ::core::panicking::AssertKind::Ne;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
self.use_count[local] -= 1;
}
}
}
fn remove_unused_definitions_helper(used_locals: &mut UsedLocals,
body: &mut Body<'_>) {
let mut modified = true;
while modified {
modified = false;
for data in body.basic_blocks.as_mut_preserves_cfg() {
for statement in data.statements.iter_mut() {
let keep_statement =
match &statement.kind {
StatementKind::StorageLive(local) |
StatementKind::StorageDead(local) => {
used_locals.is_used(*local)
}
StatementKind::Assign((place, _)) =>
used_locals.is_used(place.local),
StatementKind::SetDiscriminant { place, .. } |
StatementKind::BackwardIncompatibleDropHint { place, .. } =>
{
used_locals.is_used(place.local)
}
_ => continue,
};
if keep_statement { continue; }
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify.rs:637",
"rustc_mir_transform::simplify", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify.rs"),
::tracing_core::__macro_support::Option::Some(637u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::simplify"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("removing statement {0:?}",
statement) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
modified = true;
used_locals.statement_removed(statement);
statement.make_nop(true);
}
data.strip_nops();
}
}
}
struct LocalUpdater<'tcx> {
map: IndexVec<Local, Option<Local>>,
tcx: TyCtxt<'tcx>,
}
impl<'tcx> MutVisitor<'tcx> for LocalUpdater<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_statement_debuginfo(&mut self,
stmt_debuginfo: &mut StmtDebugInfo<'tcx>, location: Location) {
match stmt_debuginfo {
StmtDebugInfo::AssignRef(local, place) => {
if place.as_ref().accessed_locals().any(|local|
self.map[local].is_none()) {
*stmt_debuginfo = StmtDebugInfo::InvalidAssign(*local);
}
}
StmtDebugInfo::InvalidAssign(_) => {}
}
self.super_statement_debuginfo(stmt_debuginfo, location);
}
fn visit_local(&mut self, l: &mut Local, _: PlaceContext,
_: Location) {
*l = self.map[*l].unwrap();
}
}
pub(crate) struct UsedInStmtLocals {
pub(crate) locals: DenseBitSet<Local>,
}
impl UsedInStmtLocals {
pub(crate) fn new(body: &Body<'_>) -> Self {
let mut this =
Self {
locals: DenseBitSet::new_empty(body.local_decls.len()),
};
this.visit_body(body);
this
}
pub(crate) fn remove_unused_storage_annotations<'tcx>(&self,
body: &mut Body<'tcx>) {
for data in body.basic_blocks.as_mut_preserves_cfg() {
for statement in data.statements.iter_mut() {
let keep_statement =
match &statement.kind {
StatementKind::StorageLive(local) |
StatementKind::StorageDead(local) => {
self.locals.contains(*local)
}
_ => continue,
};
if keep_statement { continue; }
statement.make_nop(true);
}
}
}
}
impl<'tcx> Visitor<'tcx> for UsedInStmtLocals {
fn visit_local(&mut self, local: Local, context: PlaceContext,
_: Location) {
if #[allow(non_exhaustive_omitted_patterns)] match context {
PlaceContext::NonUse(_) => true,
_ => false,
} {
return;
}
self.locals.insert(local);
}
}
}
#[allow(unused_imports)]
use simplify::SimplifyCfg as _;
#[allow(unused_imports)]
use simplify::SimplifyLocals as _;
mod simplify_branches {
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use tracing::trace;
use crate::PassPolicy;
use crate::patch::MirPatch;
pub(super) enum SimplifyConstCondition {
AfterInstSimplify,
AfterConstProp,
Final,
}
impl<'tcx> crate::MirPass<'tcx> for SimplifyConstCondition {
fn name(&self) -> &'static str {
match self {
SimplifyConstCondition::AfterInstSimplify => {
"SimplifyConstCondition-after-inst-simplify"
}
SimplifyConstCondition::AfterConstProp =>
"SimplifyConstCondition-after-const-prop",
SimplifyConstCondition::Final =>
"SimplifyConstCondition-final",
}
}
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(true)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify_branches.rs:31",
"rustc_mir_transform::simplify_branches",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify_branches.rs"),
::tracing_core::__macro_support::Option::Some(31u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::simplify_branches"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Running SimplifyConstCondition on {0:?}",
body.source) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let typing_env = body.typing_env(tcx);
let mut patch = MirPatch::new(body);
fn try_get_const<'tcx,
'a>(operand: &'a Operand<'tcx>,
has_place_const:
Option<(Place<'tcx>, &'a ConstOperand<'tcx>)>)
-> Option<&'a ConstOperand<'tcx>> {
match operand {
Operand::Constant(const_operand) => Some(const_operand),
Operand::Copy(place) | Operand::Move(place) if
let Some((place_const, const_operand)) = has_place_const &&
place_const == *place => {
Some(const_operand)
}
Operand::Copy(_) | Operand::Move(_) |
Operand::RuntimeChecks(_) => None,
}
}
'blocks:
for (bb, block) in body.basic_blocks.iter_enumerated() {
let mut pre_place_const:
Option<(Place<'tcx>, &ConstOperand<'tcx>)> = None;
for (statement_index, stmt) in
block.statements.iter().enumerate() {
let has_place_const = pre_place_const.take();
if let StatementKind::Intrinsic(ref intrinsic) = stmt.kind
&& let NonDivergingIntrinsic::Assume(discr) = intrinsic &&
let Some(c) = try_get_const(discr, has_place_const) &&
let Some(constant) = c.const_.try_eval_bool(tcx, typing_env)
{
if constant {
patch.nop_statement(Location {
block: bb,
statement_index,
});
} else {
patch.patch_terminator(bb, TerminatorKind::Unreachable);
continue 'blocks;
}
} else if let StatementKind::Assign((lhs, ref rvalue)) =
stmt.kind &&
let Rvalue::Use(Operand::Constant(c), _) = rvalue {
pre_place_const = Some((lhs, c));
}
}
let terminator = block.terminator();
let terminator =
match terminator.kind {
TerminatorKind::SwitchInt { ref discr, ref targets, .. } if
let Some(c) = try_get_const(discr, pre_place_const.take())
&&
let Some(constant) = c.const_.try_eval_bits(tcx, typing_env)
=> {
let target = targets.target_for_value(constant);
TerminatorKind::Goto { target }
}
TerminatorKind::Assert { target, ref cond, expected, .. } if
let Some(c) = try_get_const(&cond, pre_place_const.take())
&&
let Some(constant) = c.const_.try_eval_bool(tcx, typing_env)
&& constant == expected => {
TerminatorKind::Goto { target }
}
_ => continue,
};
patch.patch_terminator(bb, terminator);
}
patch.apply(body);
}
}
}
#[allow(unused_imports)]
use simplify_branches::SimplifyConstCondition as _;
mod simplify_comparison_integral {
use std::iter;
use rustc_middle::bug;
use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::{
BasicBlock, BinOp, Body, Operand, Place, Rvalue, StatementKind,
SwitchTargets, TerminatorKind,
};
use rustc_middle::ty::{Ty, TyCtxt};
use tracing::trace;
use crate::PassPolicy;
use crate::ssa::SsaLocals;
pub(super) struct SimplifyComparisonIntegral;
impl<'tcx> crate::MirPass<'tcx> for SimplifyComparisonIntegral {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 2)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs:35",
"rustc_mir_transform::simplify_comparison_integral",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs"),
::tracing_core::__macro_support::Option::Some(35u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::simplify_comparison_integral"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("Running SimplifyComparisonIntegral on {0:?}",
body.source) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let typing_env = body.typing_env(tcx);
let ssa = SsaLocals::new(tcx, body, typing_env);
let helper = OptimizationFinder { body };
let opts = helper.find_optimizations(&ssa);
for opt in opts {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs:42",
"rustc_mir_transform::simplify_comparison_integral",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/simplify_comparison_integral.rs"),
::tracing_core::__macro_support::Option::Some(42u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::simplify_comparison_integral"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("SUCCESS: Applying {0:?}",
opt) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let bbs = &mut body.basic_blocks_mut();
let bb = &mut bbs[opt.bb_idx];
let new_value =
match opt.branch_value_scalar {
Scalar::Int(int) => {
let layout =
tcx.layout_of(typing_env.as_query_input(opt.branch_value_ty)).expect("if we have an evaluated constant we must know the layout");
int.to_bits(layout.size)
}
Scalar::Ptr(..) => continue,
};
const FALSE: u128 = 0;
let mut new_targets = opt.targets;
let first_value = new_targets.iter().next().unwrap().0;
let first_is_false_target = first_value == FALSE;
match opt.op {
BinOp::Eq => {
if first_is_false_target {
new_targets.all_targets_mut().swap(0, 1);
}
}
BinOp::Ne => {
if !first_is_false_target {
new_targets.all_targets_mut().swap(0, 1);
}
}
_ =>
::core::panicking::panic("internal error: entered unreachable code"),
}
let (_, rhs) =
bb.statements[opt.bin_op_stmt_idx].kind.as_assign_mut().unwrap();
use Operand::*;
match rhs {
Rvalue::BinaryOp(_, (left @ Move(_), Constant(_))) => {
*left = Copy(opt.to_switch_on);
}
Rvalue::BinaryOp(_, (Constant(_), right @ Move(_))) => {
*right = Copy(opt.to_switch_on);
}
_ => (),
}
let [bb_cond, bb_otherwise] =
match new_targets.all_targets() {
[a, b] => [*a, *b],
e =>
::rustc_middle::util::bug::bug_fmt(format_args!("expected 2 switch targets, got: {0:?}",
e)),
};
let targets =
SwitchTargets::new(iter::once((new_value, bb_cond)),
bb_otherwise);
let terminator = bb.terminator_mut();
terminator.kind =
TerminatorKind::SwitchInt {
discr: Operand::Copy(opt.to_switch_on),
targets,
};
}
}
}
struct OptimizationFinder<'a, 'tcx> {
body: &'a Body<'tcx>,
}
impl<'tcx> OptimizationFinder<'_, 'tcx> {
fn find_optimizations(&self, ssa: &SsaLocals)
-> Vec<OptimizationInfo<'tcx>> {
self.body.basic_blocks.iter_enumerated().filter_map(|(bb_idx, bb)|
{
let (discr, targets) = bb.terminator().kind.as_switch()?;
let place_switched_on = discr.place()?;
if !ssa.is_ssa(place_switched_on.local) ||
!place_switched_on.is_stable_offset() {
return None;
}
bb.statements.iter().enumerate().rev().find_map(|(stmt_idx,
stmt)|
{
match &stmt.kind {
rustc_middle::mir::StatementKind::Assign((lhs, rhs)) if
*lhs == place_switched_on => {
match rhs {
Rvalue::BinaryOp(op @ (BinOp::Eq | BinOp::Ne),
(left, right)) => {
let (branch_value_scalar, branch_value_ty, to_switch_on) =
find_branch_value_info(left, right, ssa)?;
if bb.statements[stmt_idx +
1..].iter().any(|stmt|
{
#[allow(non_exhaustive_omitted_patterns)]
match stmt.kind {
StatementKind::StorageLive(local) |
StatementKind::StorageDead(local) if
local == to_switch_on.local => true,
_ => false,
}
}) {
return None;
}
Some(OptimizationInfo {
bin_op_stmt_idx: stmt_idx,
bb_idx,
to_switch_on,
branch_value_scalar,
branch_value_ty,
op: *op,
targets: targets.clone(),
})
}
_ => None,
}
}
_ => None,
}
})
}).collect()
}
}
fn find_branch_value_info<'tcx>(left: &Operand<'tcx>,
right: &Operand<'tcx>, ssa: &SsaLocals)
-> Option<(Scalar, Ty<'tcx>, Place<'tcx>)> {
use Operand::*;
match (left, right) {
(Constant(branch_value), Copy(to_switch_on) | Move(to_switch_on))
|
(Copy(to_switch_on) | Move(to_switch_on),
Constant(branch_value)) => {
if !ssa.is_ssa(to_switch_on.local) ||
!to_switch_on.is_stable_offset() {
return None;
}
let branch_value_ty = branch_value.const_.ty();
if !branch_value_ty.is_integral() &&
!branch_value_ty.is_char() {
return None;
};
let branch_value_scalar =
branch_value.const_.try_to_scalar()?;
Some((branch_value_scalar, branch_value_ty, *to_switch_on))
}
_ => None,
}
}
struct OptimizationInfo<'tcx> {
bb_idx: BasicBlock,
bin_op_stmt_idx: usize,
to_switch_on: Place<'tcx>,
branch_value_scalar: Scalar,
branch_value_ty: Ty<'tcx>,
op: BinOp,
targets: SwitchTargets,
}
#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for OptimizationInfo<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
let names: &'static _ =
&["bb_idx", "bin_op_stmt_idx", "to_switch_on",
"branch_value_scalar", "branch_value_ty", "op", "targets"];
let values: &[&dyn ::core::fmt::Debug] =
&[&self.bb_idx, &self.bin_op_stmt_idx, &self.to_switch_on,
&self.branch_value_scalar, &self.branch_value_ty, &self.op,
&&self.targets];
::core::fmt::Formatter::debug_struct_fields_finish(f,
"OptimizationInfo", names, values)
}
}
}
#[allow(unused_imports)]
use simplify_comparison_integral::SimplifyComparisonIntegral as _;
mod single_use_consts {
use rustc_index::IndexVec;
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::bug;
use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use crate::PassPolicy;
use crate::strip_debuginfo::drop_invalid_debuginfos;
pub(super) struct SingleUseConsts;
impl<'tcx> crate::MirPass<'tcx> for SingleUseConsts {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 1)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let mut finder =
SingleUseConstsFinder {
ineligible_locals: DenseBitSet::new_empty(body.local_decls.len()),
locations: IndexVec::from_elem(LocationPair::new(),
&body.local_decls),
locals_in_debug_info: DenseBitSet::new_empty(body.local_decls.len()),
};
finder.ineligible_locals.insert_range(..Local::arg(body.arg_count));
finder.visit_body(body);
for (local, locations) in finder.locations.iter_enumerated() {
if finder.ineligible_locals.contains(local) { continue; }
let Some(init_loc) = locations.init_loc else { continue; };
let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
let init_statement_kind =
std::mem::replace(&mut basic_blocks[init_loc.block].statements[init_loc.statement_index].kind,
StatementKind::Nop);
let StatementKind::Assign(place_and_rvalue) =
init_statement_kind else {
::rustc_middle::util::bug::bug_fmt(format_args!("No longer an assign?"));
};
let (place, rvalue) = *place_and_rvalue;
{
match (&place.as_local(), &Some(local)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
let Rvalue::Use(operand, _) =
rvalue else {
::rustc_middle::util::bug::bug_fmt(format_args!("No longer a use?"))
};
let mut replacer =
LocalReplacer { tcx, local, operand: Some(operand) };
if finder.locals_in_debug_info.contains(local) {
for var_debug_info in &mut body.var_debug_info {
replacer.visit_var_debug_info(var_debug_info);
}
}
let Some(use_loc) = locations.use_loc else { continue };
let use_block = &mut basic_blocks[use_loc.block];
if let Some(use_statement) =
use_block.statements.get_mut(use_loc.statement_index) {
replacer.visit_statement(use_statement, use_loc);
} else {
replacer.visit_terminator(use_block.terminator_mut(),
use_loc);
}
if replacer.operand.is_some() {
::rustc_middle::util::bug::bug_fmt(format_args!("operand wasn\'t used replacing local {0:?} with locations {1:?} in body {2:#?}",
local, locations, body));
}
}
drop_invalid_debuginfos(body);
}
}
struct LocationPair {
init_loc: Option<Location>,
use_loc: Option<Location>,
}
#[automatically_derived]
impl ::core::marker::Copy for LocationPair { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for LocationPair { }
#[automatically_derived]
impl ::core::clone::Clone for LocationPair {
#[inline]
fn clone(&self) -> LocationPair {
let _: ::core::clone::AssertParamIsClone<Option<Location>>;
let _: ::core::clone::AssertParamIsClone<Option<Location>>;
*self
}
}
#[automatically_derived]
impl ::core::fmt::Debug for LocationPair {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"LocationPair", "init_loc", &self.init_loc, "use_loc",
&&self.use_loc)
}
}
impl LocationPair {
fn new() -> Self { Self { init_loc: None, use_loc: None } }
}
struct SingleUseConstsFinder {
ineligible_locals: DenseBitSet<Local>,
locations: IndexVec<Local, LocationPair>,
locals_in_debug_info: DenseBitSet<Local>,
}
impl<'tcx> Visitor<'tcx> for SingleUseConstsFinder {
fn visit_assign(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>,
location: Location) {
if let Some(local) = place.as_local() &&
let Rvalue::Use(operand, _) = rvalue &&
let Operand::Constant(_) = operand {
let locations = &mut self.locations[local];
if locations.init_loc.is_some() {
self.ineligible_locals.insert(local);
} else { locations.init_loc = Some(location); }
} else { self.super_assign(place, rvalue, location); }
}
fn visit_operand(&mut self, operand: &Operand<'tcx>,
location: Location) {
if let Some(place) = operand.place() &&
let Some(local) = place.as_local() {
let locations = &mut self.locations[local];
if locations.use_loc.is_some() {
self.ineligible_locals.insert(local);
} else { locations.use_loc = Some(location); }
} else { self.super_operand(operand, location); }
}
fn visit_statement(&mut self, statement: &Statement<'tcx>,
location: Location) {
match &statement.kind {
StatementKind::StorageLive(_) | StatementKind::StorageDead(_)
=> {}
_ => self.super_statement(statement, location),
}
}
fn visit_var_debug_info(&mut self,
var_debug_info: &VarDebugInfo<'tcx>) {
if let VarDebugInfoContents::Place(place) = &var_debug_info.value
&& let Some(local) = place.as_local() {
self.locals_in_debug_info.insert(local);
} else { self.super_var_debug_info(var_debug_info); }
}
fn visit_local(&mut self, local: Local, _context: PlaceContext,
_location: Location) {
self.ineligible_locals.insert(local);
}
}
struct LocalReplacer<'tcx> {
tcx: TyCtxt<'tcx>,
local: Local,
operand: Option<Operand<'tcx>>,
}
impl<'tcx> MutVisitor<'tcx> for LocalReplacer<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_operand(&mut self, operand: &mut Operand<'tcx>,
_location: Location) {
if let Operand::Copy(place) | Operand::Move(place) = operand &&
let Some(local) = place.as_local() && local == self.local {
*operand =
self.operand.take().unwrap_or_else(||
{
::rustc_middle::util::bug::bug_fmt(format_args!("there was a second use of the operand"));
});
}
}
fn visit_var_debug_info(&mut self,
var_debug_info: &mut VarDebugInfo<'tcx>) {
if let VarDebugInfoContents::Place(place) = &var_debug_info.value
&& let Some(local) = place.as_local() && local == self.local
{
let const_op =
*self.operand.as_ref().unwrap_or_else(||
{
::rustc_middle::util::bug::bug_fmt(format_args!("the operand was already stolen"));
}).constant().unwrap();
var_debug_info.value = VarDebugInfoContents::Const(const_op);
}
}
}
}
#[allow(unused_imports)]
use single_use_consts::SingleUseConsts as _;
mod sroa {
use rustc_abi::FieldIdx;
use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
use rustc_hir::attrs::lang_items::LangItem;
use rustc_index::IndexVec;
use rustc_index::bit_set::{DenseBitSet, GrowableBitSet};
use rustc_middle::bug;
use rustc_middle::mir::visit::*;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_mir_dataflow::value_analysis::{excluded_locals, iter_fields};
use tracing::{debug, instrument};
use crate::PassPolicy;
use crate::patch::MirPatch;
pub(super) struct ScalarReplacementOfAggregates;
impl<'tcx> crate::MirPass<'tcx> for ScalarReplacementOfAggregates {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 2)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("run_pass",
"rustc_mir_transform::sroa", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/sroa.rs"),
::tracing_core::__macro_support::Option::Some(23u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::sroa"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set_all(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/sroa.rs:25",
"rustc_mir_transform::sroa", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/sroa.rs"),
::tracing_core::__macro_support::Option::Some(25u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::sroa"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&body.source.def_id())
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if tcx.type_of(body.source.def_id()).instantiate_identity().skip_norm_wip().is_coroutine()
{
return;
}
let mut excluded = excluded_locals(body);
let typing_env = body.typing_env(tcx);
loop {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/sroa.rs:35",
"rustc_mir_transform::sroa", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/sroa.rs"),
::tracing_core::__macro_support::Option::Some(35u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::sroa"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("excluded")
}> =
::tracing::__macro_support::FieldName::new("excluded");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&excluded)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let escaping = escaping_locals(tcx, &excluded, body);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/sroa.rs:37",
"rustc_mir_transform::sroa", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/sroa.rs"),
::tracing_core::__macro_support::Option::Some(37u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::sroa"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("escaping")
}> =
::tracing::__macro_support::FieldName::new("escaping");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&escaping)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let replacements =
compute_flattening(tcx, typing_env, body, escaping);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/sroa.rs:39",
"rustc_mir_transform::sroa", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/sroa.rs"),
::tracing_core::__macro_support::Option::Some(39u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::sroa"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("replacements")
}> =
::tracing::__macro_support::FieldName::new("replacements");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&replacements)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let all_dead_locals =
replace_flattened_locals(tcx, body, replacements);
if !all_dead_locals.is_empty() {
excluded.union(&all_dead_locals);
excluded =
{
let mut growable = GrowableBitSet::from(excluded);
growable.ensure(body.local_decls.len());
growable.into()
};
} else { break; }
}
}
}
}
}
}
fn escaping_locals<'tcx>(tcx: TyCtxt<'tcx>, excluded: &DenseBitSet<Local>,
body: &Body<'tcx>) -> DenseBitSet<Local> {
let is_excluded_ty =
|ty: Ty<'tcx>|
{
if ty.is_union() || ty.is_enum() { return true; }
if let ty::Adt(def, _args) = ty.kind() &&
(def.repr().simd() || def.repr().scalable() ||
tcx.is_lang_item(def.did(), LangItem::DynMetadata)) {
return true;
}
false
};
let mut set = DenseBitSet::new_empty(body.local_decls.len());
set.insert_range(RETURN_PLACE..Local::arg(body.arg_count));
for (local, decl) in body.local_decls().iter_enumerated() {
if excluded.contains(local) || is_excluded_ty(decl.ty) {
set.insert(local);
}
}
let mut visitor = EscapeVisitor { set };
visitor.visit_body(body);
return visitor.set;
struct EscapeVisitor {
set: DenseBitSet<Local>,
}
impl<'tcx> Visitor<'tcx> for EscapeVisitor {
fn visit_local(&mut self, local: Local, _: PlaceContext,
_: Location) {
self.set.insert(local);
}
fn visit_place(&mut self, place: &Place<'tcx>,
context: PlaceContext, location: Location) {
if let &[PlaceElem::Field(..), ..] = &place.projection[..] {
return;
}
self.super_place(place, context, location);
}
fn visit_assign(&mut self, lvalue: &Place<'tcx>,
rvalue: &Rvalue<'tcx>, location: Location) {
if lvalue.as_local().is_some() {
match rvalue {
Rvalue::Aggregate(..) | Rvalue::Use(..) => {
self.visit_rvalue(rvalue, location);
return;
}
_ => {}
}
}
self.super_assign(lvalue, rvalue, location)
}
fn visit_statement(&mut self, statement: &Statement<'tcx>,
location: Location) {
match statement.kind {
StatementKind::StorageLive(..) |
StatementKind::StorageDead(..) => return,
_ => self.super_statement(statement, location),
}
}
fn visit_var_debug_info(&mut self, _: &VarDebugInfo<'tcx>) {}
}
}
struct ReplacementMap<'tcx> {
fragments: IndexVec<Local,
Option<IndexVec<FieldIdx, Option<(Ty<'tcx>, Local)>>>>,
}
#[automatically_derived]
impl<'tcx> ::core::default::Default for ReplacementMap<'tcx> {
#[inline]
fn default() -> ReplacementMap<'tcx> {
ReplacementMap { fragments: ::core::default::Default::default() }
}
}
#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for ReplacementMap<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field1_finish(f,
"ReplacementMap", "fragments", &&self.fragments)
}
}
impl<'tcx> ReplacementMap<'tcx> {
fn replace_place(&self, tcx: TyCtxt<'tcx>, place: PlaceRef<'tcx>)
-> Option<Place<'tcx>> {
let &[PlaceElem::Field(f, _), ref rest @ ..] =
place.projection else { return None; };
let fields = self.fragments[place.local].as_ref()?;
let (_, new_local) = fields[f]?;
Some(Place {
local: new_local,
projection: tcx.mk_place_elems(rest),
})
}
fn place_fragments(&self, place: Place<'tcx>)
-> Option<impl Iterator<Item = (FieldIdx, Ty<'tcx>, Local)>> {
let local = place.as_local()?;
let fields = self.fragments[local].as_ref()?;
Some(fields.iter_enumerated().filter_map(|(field, &opt_ty_local)|
{
let (ty, local) = opt_ty_local?;
Some((field, ty, local))
}))
}
}
fn compute_flattening<'tcx>(tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>, body: &mut Body<'tcx>,
escaping: DenseBitSet<Local>) -> ReplacementMap<'tcx> {
let mut fragments = IndexVec::from_elem(None, &body.local_decls);
for local in body.local_decls.indices() {
if escaping.contains(local) { continue; }
let decl = body.local_decls[local].clone();
let ty = decl.ty;
iter_fields(ty, tcx, typing_env,
|variant, field, field_ty|
{
if variant.is_some() { return; };
let new_local =
body.local_decls.push(LocalDecl {
ty: field_ty,
user_ty: None,
..decl.clone()
});
fragments.get_or_insert_with(local,
IndexVec::new).insert(field, (field_ty, new_local));
});
}
ReplacementMap { fragments }
}
fn replace_flattened_locals<'tcx>(tcx: TyCtxt<'tcx>,
body: &mut Body<'tcx>, replacements: ReplacementMap<'tcx>)
-> DenseBitSet<Local> {
let mut all_dead_locals =
DenseBitSet::new_empty(replacements.fragments.len());
for (local, replacements) in replacements.fragments.iter_enumerated()
{
if replacements.is_some() { all_dead_locals.insert(local); }
}
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/sroa.rs:222",
"rustc_mir_transform::sroa", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/sroa.rs"),
::tracing_core::__macro_support::Option::Some(222u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::sroa"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("all_dead_locals")
}> =
::tracing::__macro_support::FieldName::new("all_dead_locals");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&all_dead_locals)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if all_dead_locals.is_empty() { return all_dead_locals; }
let mut visitor =
ReplacementVisitor {
tcx,
local_decls: &body.local_decls,
replacements: &replacements,
all_dead_locals,
patch: MirPatch::new(body),
};
for (bb, data) in
body.basic_blocks.as_mut_preserves_cfg().iter_enumerated_mut() {
visitor.visit_basic_block_data(bb, data);
}
for scope in &mut body.source_scopes {
visitor.visit_source_scope_data(scope);
}
for (index, annotation) in
body.user_type_annotations.iter_enumerated_mut() {
visitor.visit_user_type_annotation(index, annotation);
}
visitor.expand_var_debug_info(&mut body.var_debug_info);
let ReplacementVisitor { patch, all_dead_locals, .. } = visitor;
patch.apply(body);
all_dead_locals
}
struct ReplacementVisitor<'tcx, 'll> {
tcx: TyCtxt<'tcx>,
local_decls: &'ll LocalDecls<'tcx>,
replacements: &'ll ReplacementMap<'tcx>,
all_dead_locals: DenseBitSet<Local>,
patch: MirPatch<'tcx>,
}
impl<'tcx> ReplacementVisitor<'tcx, '_> {
fn expand_var_debug_info(&mut self,
var_debug_info: &mut Vec<VarDebugInfo<'tcx>>) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("expand_var_debug_info",
"rustc_mir_transform::sroa", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/sroa.rs"),
::tracing_core::__macro_support::Option::Some(261u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::sroa"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("var_debug_info")
}> =
::tracing::__macro_support::FieldName::new("var_debug_info");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&var_debug_info)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
var_debug_info.flat_map_in_place(|mut var_debug_info|
{
let place =
match var_debug_info.value {
VarDebugInfoContents::Const(_) =>
return ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[var_debug_info])),
VarDebugInfoContents::Place(ref mut place) => place,
};
if let Some(repl) =
self.replacements.replace_place(self.tcx, place.as_ref()) {
*place = repl;
return ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[var_debug_info]));
}
let Some(parts) =
self.replacements.place_fragments(*place) else {
return ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[var_debug_info]));
};
let ty = place.ty(self.local_decls, self.tcx).ty;
parts.map(|(field, field_ty, replacement_local)|
{
let mut var_debug_info = var_debug_info.clone();
let composite =
var_debug_info.composite.get_or_insert_with(||
{
Box::new(VarDebugInfoFragment {
ty,
projection: Vec::new(),
})
});
composite.projection.push(PlaceElem::Field(field,
field_ty));
var_debug_info.value =
VarDebugInfoContents::Place(replacement_local.into());
var_debug_info
}).collect()
});
}
}
}
}
}
impl<'tcx, 'll> MutVisitor<'tcx> for ReplacementVisitor<'tcx, 'll> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_place(&mut self, place: &mut Place<'tcx>,
context: PlaceContext, location: Location) {
if let Some(repl) =
self.replacements.replace_place(self.tcx, place.as_ref()) {
*place = repl
} else { self.super_place(place, context, location) }
}
fn visit_statement(&mut self, statement: &mut Statement<'tcx>,
location: Location) {
{}
#[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("visit_statement",
"rustc_mir_transform::sroa", ::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/sroa.rs"),
::tracing_core::__macro_support::Option::Some(309u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::sroa"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("statement")
}> =
::tracing::__macro_support::FieldName::new("statement");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("location")
}> =
::tracing::__macro_support::FieldName::new("location");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
meta.fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&statement)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&location)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy
:: needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return: () = loop {};
return __tracing_attr_fake_return;
}
{
match statement.kind {
StatementKind::StorageLive(l) => {
if let Some(final_locals) =
self.replacements.place_fragments(l.into()) {
for (_, _, fl) in final_locals {
self.patch.add_statement(location,
StatementKind::StorageLive(fl));
}
statement.make_nop(true);
}
return;
}
StatementKind::StorageDead(l) => {
if let Some(final_locals) =
self.replacements.place_fragments(l.into()) {
for (_, _, fl) in final_locals {
self.patch.add_statement(location,
StatementKind::StorageDead(fl));
}
statement.make_nop(true);
}
return;
}
StatementKind::Assign((place,
Rvalue::Aggregate(_, ref mut operands))) => {
if let Some(local) = place.as_local() &&
let Some(final_locals) = &self.replacements.fragments[local]
{
let operands = std::mem::take(operands);
for (&opt_ty_local, mut operand) in
final_locals.iter().zip(operands) {
if let Some((_, new_local)) = opt_ty_local {
self.visit_operand(&mut operand, location);
let rvalue = Rvalue::Use(operand, WithRetag::Yes);
self.patch.add_statement(location,
StatementKind::Assign(Box::new((new_local.into(),
rvalue))));
}
}
statement.make_nop(true);
return;
}
}
StatementKind::Assign((place,
Rvalue::Use(Operand::Constant(_), retag))) => {
if let Some(final_locals) =
self.replacements.place_fragments(place) {
let location = location.successor_within_block();
for (field, ty, new_local) in final_locals {
let rplace = self.tcx.mk_place_field(place, field, ty);
let rvalue = Rvalue::Use(Operand::Move(rplace), retag);
self.patch.add_statement(location,
StatementKind::Assign(Box::new((new_local.into(),
rvalue))));
}
return;
}
}
StatementKind::Assign((lhs,
Rvalue::Use(ref op @
(Operand::Copy(rplace) | Operand::Move(rplace)), retag))) =>
{
let copy =
match *op {
Operand::Copy(_) => true,
Operand::Move(_) => false,
Operand::Constant(_) | Operand::RuntimeChecks(_) =>
::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached")),
};
if let Some(final_locals) =
self.replacements.place_fragments(lhs) {
for (field, ty, new_local) in final_locals {
let rplace = self.tcx.mk_place_field(rplace, field, ty);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/sroa.rs:406",
"rustc_mir_transform::sroa", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/sroa.rs"),
::tracing_core::__macro_support::Option::Some(406u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::sroa"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("rplace")
}> =
::tracing::__macro_support::FieldName::new("rplace");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&rplace)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let rplace =
self.replacements.replace_place(self.tcx,
rplace.as_ref()).unwrap_or(rplace);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/sroa.rs:411",
"rustc_mir_transform::sroa", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/sroa.rs"),
::tracing_core::__macro_support::Option::Some(411u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::sroa"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("rplace")
}> =
::tracing::__macro_support::FieldName::new("rplace");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&rplace)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let rvalue =
if copy {
Rvalue::Use(Operand::Copy(rplace), retag)
} else { Rvalue::Use(Operand::Move(rplace), retag) };
self.patch.add_statement(location,
StatementKind::Assign(Box::new((new_local.into(),
rvalue))));
}
statement.make_nop(true);
return;
}
}
_ => {}
}
self.super_statement(statement, location)
}
}
}
}
fn visit_local(&mut self, local: &mut Local, _: PlaceContext,
_: Location) {
if !!self.all_dead_locals.contains(*local) {
::core::panicking::panic("assertion failed: !self.all_dead_locals.contains(*local)")
};
}
}
}
#[allow(unused_imports)]
use sroa::ScalarReplacementOfAggregates as _;
mod strip_debuginfo {
use rustc_middle::mir::*;
use rustc_middle::ty::TyCtxt;
use rustc_mir_dataflow::debuginfo::debuginfo_locals;
use rustc_session::config::MirStripDebugInfo;
use crate::PassPolicy;
pub(super) struct StripDebugInfo;
impl<'tcx> crate::MirPass<'tcx> for StripDebugInfo {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.opts.unstable_opts.mir_strip_debuginfo !=
MirStripDebugInfo::None)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
match tcx.sess.opts.unstable_opts.mir_strip_debuginfo {
MirStripDebugInfo::None => return,
MirStripDebugInfo::AllLocals => {}
MirStripDebugInfo::LocalsInTinyFunctions if
let TerminatorKind::Return { .. } =
body.basic_blocks[START_BLOCK].terminator().kind => {}
MirStripDebugInfo::LocalsInTinyFunctions => return,
}
body.var_debug_info.retain(|vdi|
{
#[allow(non_exhaustive_omitted_patterns)]
match vdi.value {
VarDebugInfoContents::Place(place) if
place.local.as_usize() <= body.arg_count &&
place.local != RETURN_PLACE => true,
_ => false,
}
});
drop_invalid_debuginfos(body);
}
}
pub(super) fn drop_invalid_debuginfos(body: &mut Body<'_>) {
let debuginfo_locals = debuginfo_locals(body);
for data in body.basic_blocks.as_mut_preserves_cfg() {
for stmt in data.statements.iter_mut() {
stmt.debuginfos.retain_locals(&debuginfo_locals);
}
data.after_last_stmt_debuginfos.retain_locals(&debuginfo_locals);
}
}
}
#[allow(unused_imports)]
use strip_debuginfo::StripDebugInfo as _;
mod ssa_range_prop {
use rustc_abi::WrappingRange;
use rustc_const_eval::interpret::Scalar;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::graph::dominators::Dominators;
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::mir::visit::MutVisitor;
use rustc_middle::mir::{
BasicBlock, Body, Location, Operand, Place, TerminatorKind, *,
};
use rustc_middle::ty::{TyCtxt, TypingEnv};
use rustc_span::DUMMY_SP;
use crate::PassPolicy;
use crate::ssa::SsaLocals;
pub(super) struct SsaRangePropagation;
impl<'tcx> crate::MirPass<'tcx> for SsaRangePropagation {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 2)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let typing_env = body.typing_env(tcx);
let ssa = SsaLocals::new(tcx, body, typing_env);
let dominators = body.basic_blocks.dominators().clone();
let mut range_set =
RangeSet::new(tcx, typing_env, body, &ssa, &body.local_decls,
dominators);
let reverse_postorder =
body.basic_blocks.reverse_postorder().to_vec();
for bb in reverse_postorder {
let data = &mut body.basic_blocks.as_mut_preserves_cfg()[bb];
range_set.visit_basic_block_data(bb, data);
}
}
}
struct RangeSet<'tcx, 'body, 'a> {
tcx: TyCtxt<'tcx>,
typing_env: TypingEnv<'tcx>,
ssa: &'a SsaLocals,
local_decls: &'body LocalDecls<'tcx>,
dominators: Dominators<BasicBlock>,
ranges: FxHashMap<Place<'tcx>, Vec<(Location, WrappingRange)>>,
unique_predecessors: DenseBitSet<BasicBlock>,
}
impl<'tcx, 'body, 'a> RangeSet<'tcx, 'body, 'a> {
fn new(tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>,
body: &Body<'tcx>, ssa: &'a SsaLocals,
local_decls: &'body LocalDecls<'tcx>,
dominators: Dominators<BasicBlock>) -> Self {
let predecessors = body.basic_blocks.predecessors();
let mut unique_predecessors =
DenseBitSet::new_empty(body.basic_blocks.len());
for bb in body.basic_blocks.indices() {
if predecessors[bb].len() == 1 {
unique_predecessors.insert(bb);
}
}
RangeSet {
tcx,
typing_env,
ssa,
local_decls,
dominators,
ranges: FxHashMap::default(),
unique_predecessors,
}
}
fn insert_range(&mut self, place: Place<'tcx>, location: Location,
range: WrappingRange) {
if !self.is_ssa(place) {
::core::panicking::panic("assertion failed: self.is_ssa(place)")
};
self.ranges.entry(place).or_default().push((location, range));
}
fn get_range(&self, place: &Place<'tcx>, location: Location)
-> Option<WrappingRange> {
let Some(ranges) = self.ranges.get(place) else { return None; };
let (_, range) =
ranges.iter().find(|(range_loc, _)|
range_loc.dominates(location, &self.dominators))?;
Some(*range)
}
fn try_as_constant(&mut self, place: Place<'tcx>, location: Location)
-> Option<ConstOperand<'tcx>> {
if let Some(range) = self.get_range(&place, location) &&
range.start == range.end {
let ty = place.ty(self.local_decls, self.tcx).ty;
let layout =
self.tcx.layout_of(self.typing_env.as_query_input(ty)).ok()?;
let value =
ConstValue::Scalar(Scalar::from_uint(range.start,
layout.size));
let const_ = Const::Val(value, ty);
return Some(ConstOperand {
span: DUMMY_SP,
user_ty: None,
const_,
});
}
None
}
fn is_ssa(&self, place: Place<'tcx>) -> bool {
self.ssa.is_ssa(place.local) && place.is_stable_offset()
}
}
impl<'tcx> MutVisitor<'tcx> for RangeSet<'tcx, '_, '_> {
fn tcx(&self) -> TyCtxt<'tcx> { self.tcx }
fn visit_operand(&mut self, operand: &mut Operand<'tcx>,
location: Location) {
if let Some(place) = operand.place() &&
let Some(const_) = self.try_as_constant(place, location) {
*operand = Operand::Constant(Box::new(const_));
};
}
fn visit_statement(&mut self, statement: &mut Statement<'tcx>,
location: Location) {
self.super_statement(statement, location);
match &statement.kind {
StatementKind::Intrinsic(NonDivergingIntrinsic::Assume(operand))
if let Some(place) = operand.place() && self.is_ssa(place)
=> {
let successor = location.successor_within_block();
let range = WrappingRange { start: 1, end: 1 };
self.insert_range(place, successor, range);
}
_ => {}
}
}
fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>,
location: Location) {
self.super_terminator(terminator, location);
match &terminator.kind {
TerminatorKind::Assert { cond, expected, target, .. } if
let Some(place) = cond.place() && self.is_ssa(place) => {
let successor =
Location { block: *target, statement_index: 0 };
if location.strictly_dominates(successor, &self.dominators)
{
let val = *expected as u128;
let range = WrappingRange { start: val, end: val };
self.insert_range(place, successor, range);
}
}
TerminatorKind::SwitchInt { discr, targets } if
let Some(place) = discr.place() && self.is_ssa(place) &&
targets.all_targets().len() < 16 => {
let mut distinct_targets: FxHashMap<BasicBlock, u64> =
FxHashMap::default();
for (_, target) in targets.iter() {
let targets = distinct_targets.entry(target).or_default();
*targets += 1;
}
for (val, target) in targets.iter() {
if distinct_targets[&target] != 1 { continue; }
let successor =
Location { block: target, statement_index: 0 };
if self.unique_predecessors.contains(successor.block) {
{
match (&location.block, &successor.block) {
(left_val, right_val) => {
if *left_val == *right_val {
let kind = ::core::panicking::AssertKind::Ne;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
let range = WrappingRange { start: val, end: val };
self.insert_range(place, successor, range);
}
}
let otherwise =
Location { block: targets.otherwise(), statement_index: 0 };
if place.ty(self.local_decls, self.tcx).ty.is_bool() &&
let [val] = targets.all_values() &&
self.unique_predecessors.contains(otherwise.block) {
{
match (&location.block, &otherwise.block) {
(left_val, right_val) => {
if *left_val == *right_val {
let kind = ::core::panicking::AssertKind::Ne;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
let range =
if val.get() == 0 {
WrappingRange { start: 1, end: 1 }
} else { WrappingRange { start: 0, end: 0 } };
self.insert_range(place, otherwise, range);
}
}
_ => {}
}
}
}
}
#[allow(unused_imports)]
use ssa_range_prop::SsaRangePropagation as _;
mod unreachable_enum_branching {
use rustc_abi::Variants;
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::bug;
use rustc_middle::mir::{
BasicBlockData, Body, Local, Operand, Rvalue, StatementKind,
TerminatorKind,
};
use rustc_middle::ty::layout::TyAndLayout;
use rustc_middle::ty::{Ty, TyCtxt};
use tracing::trace;
use crate::PassPolicy;
use crate::patch::MirPatch;
pub(super) struct UnreachableEnumBranching;
fn get_discriminant_local(terminator: &TerminatorKind<'_>)
-> Option<Local> {
if let TerminatorKind::SwitchInt { discr: Operand::Move(p), .. } =
terminator {
p.as_local()
} else { None }
}
fn get_switched_on_type<'tcx>(block_data: &BasicBlockData<'tcx>,
tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> Option<Ty<'tcx>> {
let terminator = block_data.terminator();
let local = get_discriminant_local(&terminator.kind)?;
let stmt_before_term = block_data.statements.last()?;
if let StatementKind::Assign((l, Rvalue::Discriminant(place))) =
stmt_before_term.kind && l.as_local() == Some(local) {
let ty = place.ty(body, tcx).ty;
if ty.is_enum() { return Some(ty); }
}
None
}
fn variant_discriminants<'tcx>(layout: &TyAndLayout<'tcx>, ty: Ty<'tcx>,
tcx: TyCtxt<'tcx>) -> FxHashSet<u128> {
match &layout.variants {
Variants::Empty => { FxHashSet::default() }
Variants::Single { index } => {
let mut res = FxHashSet::default();
res.insert(ty.discriminant_for_variant(tcx,
*index).map_or(index.as_u32() as u128, |discr| discr.val));
res
}
Variants::Multiple { variants, .. } =>
variants.iter_enumerated().filter_map(|(idx, layout)|
{
(!layout.is_uninhabited()).then(||
ty.discriminant_for_variant(tcx, idx).unwrap().val)
}).collect(),
}
}
impl<'tcx> crate::MirPass<'tcx> for UnreachableEnumBranching {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 1)
}
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs:86",
"rustc_mir_transform::unreachable_enum_branching",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs"),
::tracing_core::__macro_support::Option::Some(86u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::unreachable_enum_branching"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("UnreachableEnumBranching starting for {0:?}",
body.source) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
let mut unreachable_targets = Vec::new();
let mut patch = MirPatch::new(body);
for (bb, bb_data) in body.basic_blocks.iter_enumerated() {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs:92",
"rustc_mir_transform::unreachable_enum_branching",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs"),
::tracing_core::__macro_support::Option::Some(92u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::unreachable_enum_branching"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("processing block {0:?}",
bb) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
if bb_data.is_cleanup { continue; }
let Some(discriminant_ty) =
get_switched_on_type(bb_data, tcx, body) else { continue };
let layout =
tcx.layout_of(body.typing_env(tcx).as_query_input(discriminant_ty));
let mut allowed_variants =
if let Ok(layout) = layout {
variant_discriminants(&layout, discriminant_ty, tcx)
} else if let Some(variant_range) =
discriminant_ty.variant_range(tcx) {
variant_range.map(|variant|
{
discriminant_ty.discriminant_for_variant(tcx,
variant).unwrap().val
}).collect()
} else { continue; };
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs:116",
"rustc_mir_transform::unreachable_enum_branching",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/unreachable_enum_branching.rs"),
::tracing_core::__macro_support::Option::Some(116u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform::unreachable_enum_branching"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("allowed_variants = {0:?}",
allowed_variants) as &dyn ::tracing::field::Value))])
});
} else { ; }
};
unreachable_targets.clear();
let TerminatorKind::SwitchInt { targets, discr } =
&bb_data.terminator().kind else {
::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))
};
for (index, (val, _)) in targets.iter().enumerate() {
if !allowed_variants.remove(&val) {
unreachable_targets.push(index);
}
}
let replace_otherwise_to_unreachable =
allowed_variants.len() <= 1 &&
!body.basic_blocks[targets.otherwise()].is_empty_unreachable();
if unreachable_targets.is_empty() &&
!replace_otherwise_to_unreachable {
continue;
}
let unreachable_block = patch.unreachable_no_cleanup_block();
let mut targets = targets.clone();
if replace_otherwise_to_unreachable {
let otherwise_is_last_variant = allowed_variants.len() == 1;
if otherwise_is_last_variant {
#[allow(rustc::potential_query_instability)]
let last_variant = *allowed_variants.iter().next().unwrap();
targets.add_target(last_variant, targets.otherwise());
}
unreachable_targets.push(targets.iter().count());
}
for index in unreachable_targets.iter() {
targets.all_targets_mut()[*index] = unreachable_block;
}
patch.patch_terminator(bb,
TerminatorKind::SwitchInt {
targets,
discr: discr.clone(),
});
}
patch.apply(body);
}
}
}
#[allow(unused_imports)]
use unreachable_enum_branching::UnreachableEnumBranching as _;
mod unreachable_prop {
use rustc_abi::Size;
use rustc_data_structures::fx::FxHashSet;
use rustc_middle::bug;
use rustc_middle::mir::interpret::Scalar;
use rustc_middle::mir::*;
use rustc_middle::ty::{self, TyCtxt};
use crate::PassPolicy;
use crate::patch::MirPatch;
pub(super) struct UnreachablePropagation;
impl crate::MirPass<'_> for UnreachablePropagation {
fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(ctx.mir_opt_level() >= 2)
}
fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
let mut patch = MirPatch::new(body);
let mut unreachable_blocks = FxHashSet::default();
for (bb, bb_data) in traversal::postorder(body) {
let terminator = bb_data.terminator();
let is_unreachable =
match &terminator.kind {
TerminatorKind::Unreachable => true,
TerminatorKind::Goto { target } if
unreachable_blocks.contains(target) => {
patch.patch_terminator(bb, TerminatorKind::Unreachable);
true
}
TerminatorKind::SwitchInt { .. } => {
remove_successors_from_switch(tcx, bb, body, &mut patch,
|bb| { unreachable_blocks.contains(&bb) })
}
_ => false,
};
if is_unreachable { unreachable_blocks.insert(bb); }
}
patch.apply(body);
#[allow(rustc::potential_query_instability)]
for bb in unreachable_blocks {
body.basic_blocks_mut()[bb].statements.clear();
}
}
}
pub(crate) fn remove_successors_from_switch<'tcx>(tcx: TyCtxt<'tcx>,
bb: BasicBlock, body: &Body<'tcx>, patch: &mut MirPatch<'tcx>,
is_unreachable_block: impl Fn(BasicBlock) -> bool) -> bool {
let terminator = body.basic_blocks[bb].terminator();
let TerminatorKind::SwitchInt { discr, targets } =
&terminator.kind else {
::rustc_middle::util::bug::bug_fmt(format_args!("impossible case reached"))
};
let source_info = terminator.source_info;
let location = body.terminator_loc(bb);
let discr_ty = discr.ty(body, tcx);
let discr_size =
Size::from_bits(match discr_ty.kind() {
ty::Uint(uint) =>
uint.normalize(tcx.sess.target.pointer_width).bit_width().unwrap(),
ty::Int(int) =>
int.normalize(tcx.sess.target.pointer_width).bit_width().unwrap(),
ty::Char => 32,
ty::Bool => 1,
other =>
::rustc_middle::util::bug::bug_fmt(format_args!("unhandled type: {0:?}",
other)),
});
let mut add_assumption =
|binop, value|
{
let local =
patch.new_temp(tcx.types.bool, source_info.span);
let value =
Operand::Constant(Box::new(ConstOperand {
span: source_info.span,
user_ty: None,
const_: Const::from_scalar(tcx,
Scalar::from_uint(value, discr_size), discr_ty),
}));
let cmp =
Rvalue::BinaryOp(binop, Box::new((discr.to_copy(), value)));
patch.add_assign(location, local.into(), cmp);
let assume =
NonDivergingIntrinsic::Assume(Operand::Move(local.into()));
patch.add_statement(location,
StatementKind::Intrinsic(Box::new(assume)));
};
let otherwise = targets.otherwise();
let otherwise_unreachable = is_unreachable_block(otherwise);
let reachable_iter =
targets.iter().filter(|&(value, bb)|
{
let is_unreachable = is_unreachable_block(bb);
if is_unreachable && !otherwise_unreachable {
add_assumption(BinOp::Ne, value);
}
!is_unreachable
});
let new_targets = SwitchTargets::new(reachable_iter, otherwise);
let num_targets = new_targets.all_targets().len();
let fully_unreachable = num_targets == 1 && otherwise_unreachable;
let terminator =
match (num_targets, otherwise_unreachable) {
(1, true) => TerminatorKind::Unreachable,
(1, false) => TerminatorKind::Goto { target: otherwise },
(2, true) => {
let (value, target) = new_targets.iter().next().unwrap();
add_assumption(BinOp::Eq, value);
TerminatorKind::Goto { target }
}
_ if num_targets == targets.all_targets().len() => {
return false;
}
_ =>
TerminatorKind::SwitchInt {
discr: discr.clone(),
targets: new_targets,
},
};
patch.patch_terminator(bb, terminator);
fully_unreachable
}
}
#[allow(unused_imports)]
use unreachable_prop::UnreachablePropagation as _;
mod validate {
use rustc_abi::{ExternAbi, FIRST_VARIANT, Size};
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::attrs::InlineAttr;
use rustc_hir::attrs::lang_items::LangItem;
use rustc_index::IndexVec;
use rustc_index::bit_set::DenseBitSet;
use rustc_infer::infer::TyCtxtInferExt;
use rustc_infer::traits::{Obligation, ObligationCause};
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;
use rustc_middle::ty::{
self, InstanceKind, ScalarInt, Ty, TyCtxt, TypeVisitableExt,
Unnormalized, Upcast, Variance,
};
use rustc_middle::{bug, span_bug};
use rustc_mir_dataflow::debuginfo::debuginfo_locals;
use rustc_trait_selection::traits::ObligationCtxt;
use crate::PassPolicy;
use crate::util::{self, most_packed_projection};
enum EdgeKind { Unwind, Normal, }
#[automatically_derived]
impl ::core::marker::Copy for EdgeKind { }
#[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for EdgeKind { }
#[automatically_derived]
impl ::core::clone::Clone for EdgeKind {
#[inline]
fn clone(&self) -> EdgeKind { *self }
}
#[automatically_derived]
impl ::core::fmt::Debug for EdgeKind {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
EdgeKind::Unwind => "Unwind",
EdgeKind::Normal => "Normal",
})
}
}
#[automatically_derived]
impl ::core::marker::StructuralPartialEq for EdgeKind { }
#[automatically_derived]
impl ::core::cmp::PartialEq for EdgeKind {
#[inline]
fn eq(&self, other: &EdgeKind) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}
#[automatically_derived]
impl ::core::cmp::Eq for EdgeKind {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}
pub(super) struct Validator {
pub when: String,
}
impl<'tcx> crate::MirPass<'tcx> for Validator {
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
if #[allow(non_exhaustive_omitted_patterns)] match body.source.instance
{
InstanceKind::Intrinsic(..) | InstanceKind::Virtual(..) =>
true,
_ => false,
} {
return;
}
let def_id = body.source.def_id();
let typing_env = body.typing_env(tcx);
let can_unwind =
if body.phase <= MirPhase::Runtime(RuntimePhase::Initial) {
true
} else if !tcx.def_kind(def_id).is_fn_like() {
true
} else {
let body_ty = tcx.type_of(def_id).skip_binder();
let body_abi =
match body_ty.kind() {
ty::FnDef(..) => body_ty.fn_sig(tcx).abi(),
ty::Closure(..) => ExternAbi::RustCall,
ty::CoroutineClosure(..) => ExternAbi::RustCall,
ty::Coroutine(..) => ExternAbi::Rust,
ty::Error(_) => return,
_ =>
::rustc_middle::util::bug::span_bug_fmt(body.span,
format_args!("unexpected body ty: {0}", body_ty)),
};
ty::layout::fn_can_unwind(tcx, Some(def_id), body_abi)
};
let mut cfg_checker =
CfgChecker {
when: &self.when,
body,
tcx,
unwind_edge_count: 0,
reachable_blocks: traversal::reachable_as_bitset(body),
value_cache: FxHashSet::default(),
can_unwind,
};
cfg_checker.visit_body(body);
cfg_checker.check_cleanup_control_flow();
for (location, msg) in validate_types(tcx, typing_env, body, body)
{
cfg_checker.fail(location, msg);
}
for (location, msg) in validate_debuginfos(body) {
cfg_checker.fail(location, msg);
}
if let MirPhase::Runtime(_) = body.phase &&
let ty::InstanceKind::Item(_) = body.source.instance &&
body.has_free_regions() {
cfg_checker.fail(Location::START,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Free regions in optimized {0} MIR",
body.phase.name()))
}));
}
}
fn policy(&self, _ctx: &crate::PassCtx<'_>) -> PassPolicy {
PassPolicy::optional(true)
}
}
struct CfgChecker<'a, 'tcx> {
when: &'a str,
body: &'a Body<'tcx>,
tcx: TyCtxt<'tcx>,
unwind_edge_count: usize,
reachable_blocks: DenseBitSet<BasicBlock>,
value_cache: FxHashSet<u128>,
can_unwind: bool,
}
impl<'a, 'tcx> CfgChecker<'a, 'tcx> {
#[track_caller]
fn fail(&self, location: Location, msg: impl AsRef<str>) {
if self.tcx.dcx().has_errors().is_none() {
::rustc_middle::util::bug::span_bug_fmt(self.body.source_info(location).span,
format_args!("broken MIR in {0:?} ({1}) at {2:?}:\n{3}",
self.body.source.instance, self.when, location,
msg.as_ref()));
}
}
fn check_edge(&mut self, location: Location, bb: BasicBlock,
edge_kind: EdgeKind) {
if bb == START_BLOCK {
self.fail(location, "start block must not have predecessors")
}
if let Some(bb) = self.body.basic_blocks.get(bb) {
let src = self.body.basic_blocks.get(location.block).unwrap();
match (src.is_cleanup, bb.is_cleanup, edge_kind) {
(false, false, EdgeKind::Normal) => {}
(true, true, EdgeKind::Normal) => {}
(false, true, EdgeKind::Unwind) => {
self.unwind_edge_count += 1;
}
_ =>
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?} edge to {1:?} violates unwind invariants (cleanup {2:?} -> {3:?})",
edge_kind, bb, src.is_cleanup, bb.is_cleanup))
})),
}
} else {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("encountered jump to invalid basic block {0:?}",
bb))
}))
}
}
fn check_cleanup_control_flow(&self) {
if self.unwind_edge_count <= 1 { return; }
let doms = self.body.basic_blocks.dominators();
let mut post_contract_node = FxHashMap::default();
let mut dom_path = ::alloc::vec::Vec::new();
let mut get_post_contract_node =
|mut bb|
{
let root =
loop {
if let Some(root) = post_contract_node.get(&bb) {
break *root;
}
let parent = doms.immediate_dominator(bb).unwrap();
dom_path.push(bb);
if !self.body.basic_blocks[parent].is_cleanup { break bb; }
bb = parent;
};
for bb in dom_path.drain(..) {
post_contract_node.insert(bb, root);
}
root
};
let mut parent =
IndexVec::from_elem(None, &self.body.basic_blocks);
for (bb, bb_data) in self.body.basic_blocks.iter_enumerated() {
if !bb_data.is_cleanup || !self.reachable_blocks.contains(bb)
{
continue;
}
let bb = get_post_contract_node(bb);
for s in bb_data.terminator().successors() {
let s = get_post_contract_node(s);
if s == bb { continue; }
let parent = &mut parent[bb];
match parent {
None => { *parent = Some(s); }
Some(e) if *e == s => (),
Some(e) =>
self.fail(Location { block: bb, statement_index: 0 },
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Cleanup control flow violation: The blocks dominated by {0:?} have edges to both {1:?} and {2:?}",
bb, s, *e))
})),
}
}
}
let mut stack = FxHashSet::default();
for (mut bb, parent) in parent.iter_enumerated_mut() {
stack.clear();
stack.insert(bb);
loop {
let Some(parent) = parent.take() else { break };
let no_cycle = stack.insert(parent);
if !no_cycle {
self.fail(Location { block: bb, statement_index: 0 },
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Cleanup control flow violation: Cycle involving edge {0:?} -> {1:?}",
bb, parent))
}));
break;
}
bb = parent;
}
}
}
fn check_unwind_edge(&mut self, location: Location,
unwind: UnwindAction) {
let is_cleanup =
self.body.basic_blocks[location.block].is_cleanup;
match unwind {
UnwindAction::Cleanup(unwind) => {
if is_cleanup {
self.fail(location,
"`UnwindAction::Cleanup` in cleanup block");
}
self.check_edge(location, unwind, EdgeKind::Unwind);
}
UnwindAction::Continue => {
if is_cleanup {
self.fail(location,
"`UnwindAction::Continue` in cleanup block");
}
if !self.can_unwind {
self.fail(location,
"`UnwindAction::Continue` in no-unwind function");
}
}
UnwindAction::Terminate(UnwindTerminateReason::InCleanup) => {
if !is_cleanup {
self.fail(location,
"`UnwindAction::Terminate(InCleanup)` in a non-cleanup block");
}
}
UnwindAction::Unreachable |
UnwindAction::Terminate(UnwindTerminateReason::Abi) => (),
}
}
fn is_critical_call_edge(&self, target: Option<BasicBlock>,
unwind: UnwindAction) -> bool {
let Some(target) = target else { return false };
#[allow(non_exhaustive_omitted_patterns)] (match unwind {
UnwindAction::Cleanup(_) | UnwindAction::Terminate(_) =>
true,
_ => false,
}) && self.body.basic_blocks.predecessors()[target].len() > 1
}
}
impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
fn visit_local(&mut self, local: Local, _context: PlaceContext,
location: Location) {
if self.body.local_decls.get(local).is_none() {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("local {0:?} has no corresponding declaration in `body.local_decls`",
local))
}));
}
}
fn visit_statement(&mut self, statement: &Statement<'tcx>,
location: Location) {
match &statement.kind {
StatementKind::AscribeUserType(..) => {
if self.body.phase >=
MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(location,
"`AscribeUserType` should have been removed after drop lowering phase");
}
}
StatementKind::FakeRead(..) => {
if self.body.phase >=
MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(location,
"`FakeRead` should have been removed after drop lowering phase");
}
}
StatementKind::SetDiscriminant { .. } => {
if self.body.phase <
MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(location,
"`SetDiscriminant`is not allowed until deaggregation");
}
}
StatementKind::Coverage(kind) => {
if self.body.phase >=
MirPhase::Analysis(AnalysisPhase::PostCleanup) &&
kind.is_removed_after_analysis() {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?} should have been removed after analysis",
kind))
}));
}
}
StatementKind::Assign(..) | StatementKind::StorageLive(_) |
StatementKind::StorageDead(_) | StatementKind::Intrinsic(_)
| StatementKind::ConstEvalCounter |
StatementKind::PlaceMention(..) |
StatementKind::BackwardIncompatibleDropHint { .. } |
StatementKind::Nop => {}
}
self.super_statement(statement, location);
}
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>,
location: Location) {
match &terminator.kind {
TerminatorKind::Goto { target } => {
self.check_edge(location, *target, EdgeKind::Normal);
}
TerminatorKind::SwitchInt { targets, discr: _ } => {
for (_, target) in targets.iter() {
self.check_edge(location, target, EdgeKind::Normal);
}
self.check_edge(location, targets.otherwise(),
EdgeKind::Normal);
self.value_cache.clear();
self.value_cache.extend(targets.iter().map(|(value, _)|
value));
let has_duplicates =
targets.iter().len() != self.value_cache.len();
if has_duplicates {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("duplicated values in `SwitchInt` terminator: {0:?}",
terminator.kind))
}));
}
}
TerminatorKind::Drop { target, unwind, drop, .. } => {
self.check_edge(location, *target, EdgeKind::Normal);
self.check_unwind_edge(location, *unwind);
if let Some(drop) = drop {
self.check_edge(location, *drop, EdgeKind::Normal);
if self.body.phase >=
MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(location,
"`async drop` should have been removed after drop elaboration");
}
}
}
TerminatorKind::Call { func, args, .. } |
TerminatorKind::TailCall { func, args, .. } => {
if let TerminatorKind::Call { target, unwind, destination,
.. } = terminator.kind {
if let Some(target) = target {
self.check_edge(location, target, EdgeKind::Normal);
}
self.check_unwind_edge(location, unwind);
if self.body.phase >=
MirPhase::Runtime(RuntimePhase::Optimized) &&
self.is_critical_call_edge(target, unwind) {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("encountered critical edge in `Call` terminator {0:?}",
terminator.kind))
}));
}
if most_packed_projection(self.tcx, &self.body.local_decls,
destination).is_some() {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("encountered packed place in `Call` terminator destination: {0:?}",
terminator.kind))
}));
}
}
for arg in args {
if let Operand::Move(place) = &arg.node {
if most_packed_projection(self.tcx, &self.body.local_decls,
*place).is_some() {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("encountered `Move` of a packed place in `Call` terminator: {0:?}",
terminator.kind))
}));
}
}
}
if let ty::FnDef(did, ..) =
*func.ty(&self.body.local_decls, self.tcx).kind() &&
self.body.phase >=
MirPhase::Runtime(RuntimePhase::Optimized) &&
#[allow(non_exhaustive_omitted_patterns)] match self.tcx.codegen_fn_attrs(did).inline
{
InlineAttr::Force { .. } => true,
_ => false,
} {
self.fail(location,
"`#[rustc_force_inline]`-annotated function not inlined");
}
}
TerminatorKind::Assert { target, unwind, .. } => {
self.check_edge(location, *target, EdgeKind::Normal);
self.check_unwind_edge(location, *unwind);
}
TerminatorKind::Yield { resume, drop, .. } => {
if self.body.coroutine.is_none() {
self.fail(location,
"`Yield` cannot appear outside coroutine bodies");
}
if self.body.phase >=
MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(location,
"`Yield` should have been replaced by coroutine lowering");
}
self.check_edge(location, *resume, EdgeKind::Normal);
if let Some(drop) = drop {
self.check_edge(location, *drop, EdgeKind::Normal);
}
}
TerminatorKind::FalseEdge { real_target, imaginary_target } =>
{
if self.body.phase >=
MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(location,
"`FalseEdge` should have been removed after drop elaboration");
}
self.check_edge(location, *real_target, EdgeKind::Normal);
self.check_edge(location, *imaginary_target,
EdgeKind::Normal);
}
TerminatorKind::FalseUnwind { real_target, unwind } => {
if self.body.phase >=
MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(location,
"`FalseUnwind` should have been removed after drop elaboration");
}
self.check_edge(location, *real_target, EdgeKind::Normal);
self.check_unwind_edge(location, *unwind);
}
TerminatorKind::InlineAsm { targets, unwind, .. } => {
for &target in targets {
self.check_edge(location, target, EdgeKind::Normal);
}
self.check_unwind_edge(location, *unwind);
}
TerminatorKind::CoroutineDrop => {
if self.body.coroutine.is_none() {
self.fail(location,
"`CoroutineDrop` cannot appear outside coroutine bodies");
}
if self.body.phase >=
MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(location,
"`CoroutineDrop` should have been replaced by coroutine lowering");
}
}
TerminatorKind::UnwindResume => {
let bb = location.block;
if !self.body.basic_blocks[bb].is_cleanup {
self.fail(location,
"Cannot `UnwindResume` from non-cleanup basic block")
}
if !self.can_unwind {
self.fail(location,
"Cannot `UnwindResume` in a function that cannot unwind")
}
}
TerminatorKind::UnwindTerminate(_) => {
let bb = location.block;
if !self.body.basic_blocks[bb].is_cleanup {
self.fail(location,
"Cannot `UnwindTerminate` from non-cleanup basic block")
}
}
TerminatorKind::Return => {
let bb = location.block;
if self.body.basic_blocks[bb].is_cleanup {
self.fail(location,
"Cannot `Return` from cleanup basic block")
}
}
TerminatorKind::Unreachable => {}
}
self.super_terminator(terminator, location);
}
fn visit_source_scope(&mut self, scope: SourceScope) {
if self.body.source_scopes.get(scope).is_none() {
self.tcx.dcx().span_bug(self.body.span,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("broken MIR in {0:?} ({1}):\ninvalid source scope {2:?}",
self.body.source.instance, self.when, scope))
}));
}
}
}
pub(super) fn validate_types<'tcx>(tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>, body: &Body<'tcx>,
caller_body: &Body<'tcx>) -> Vec<(Location, String)> {
let mut type_checker =
TypeChecker {
body,
caller_body,
tcx,
typing_env,
failures: Vec::new(),
};
{
let _guard = NoTrimmedGuard::new();
{ type_checker.visit_body(body); }
};
type_checker.failures
}
struct TypeChecker<'a, 'tcx> {
body: &'a Body<'tcx>,
caller_body: &'a Body<'tcx>,
tcx: TyCtxt<'tcx>,
typing_env: ty::TypingEnv<'tcx>,
failures: Vec<(Location, String)>,
}
impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
fn fail(&mut self, location: Location, msg: impl Into<String>) {
self.failures.push((location, msg.into()));
}
fn mir_assign_valid_types(&self, src: Ty<'tcx>, dest: Ty<'tcx>)
-> bool {
if src == dest { return true; }
if (src, dest).has_opaque_types() { return true; }
let variance =
if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial)
{
Variance::Invariant
} else { Variance::Covariant };
crate::util::relate_types(self.tcx, self.typing_env, variance,
src, dest)
}
fn predicate_must_hold_modulo_regions(&self,
pred: impl Upcast<TyCtxt<'tcx>, ty::Predicate<'tcx>>) -> bool {
let pred: ty::Predicate<'tcx> = pred.upcast(self.tcx);
if pred.has_opaque_types() { return true; }
let (infcx, param_env) =
self.tcx.infer_ctxt().build_with_typing_env(self.typing_env);
let ocx = ObligationCtxt::new(&infcx);
ocx.register_obligation(Obligation::new(self.tcx,
ObligationCause::dummy(), param_env, pred));
ocx.evaluate_obligations_error_on_ambiguity().no_errors()
}
}
impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
fn visit_operand(&mut self, operand: &Operand<'tcx>,
location: Location) {
if self.tcx.sess.opts.unstable_opts.validate_mir &&
self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) {
if let Operand::Copy(place) = operand {
let ty = place.ty(&self.body.local_decls, self.tcx).ty;
if !self.tcx.type_is_copy_modulo_regions(self.typing_env,
ty) {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`Operand::Copy` with non-`Copy` type {0}",
ty))
}));
}
}
}
self.super_operand(operand, location);
}
fn visit_projection_elem(&mut self, place_ref: PlaceRef<'tcx>,
elem: PlaceElem<'tcx>, context: PlaceContext,
location: Location) {
match elem {
ProjectionElem::Deref if
self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial)
=> {
let base_ty =
place_ref.ty(&self.body.local_decls, self.tcx).ty;
if base_ty.is_box() {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0} dereferenced after ElaborateBoxDerefs",
base_ty))
}))
}
}
ProjectionElem::Field(f, ty) => {
let parent_ty =
place_ref.ty(&self.body.local_decls, self.tcx);
let fail_out_of_bounds =
|this: &mut Self, location|
{
this.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Out of bounds field {0:?} for {1:?}",
f, parent_ty))
}));
};
let check_equal =
|this: &mut Self, location, f_ty|
{
if !this.mir_assign_valid_types(ty, f_ty) {
this.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Field projection `{0:?}.{1:?}` specified type `{2}`, but actual type is `{3}`",
place_ref, f, ty, f_ty))
}))
}
};
let kind =
match parent_ty.ty.kind() {
&ty::Alias(_, ty::AliasTy {
kind: ty::Opaque { def_id }, args, .. }) => {
self.tcx.type_of(def_id).instantiate(self.tcx,
args).skip_norm_wip().kind()
}
kind => kind,
};
match kind {
ty::Tuple(fields) => {
let Some(f_ty) =
fields.get(f.as_usize()) else {
fail_out_of_bounds(self, location);
return;
};
check_equal(self, location, *f_ty);
}
ty::Pat(base, _) => check_equal(self, location, *base),
ty::Adt(adt_def, args) => {
if self.tcx.is_lang_item(adt_def.did(),
LangItem::DynMetadata) {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("You can\'t project to field {0:?} of `DynMetadata` because layout is weird and thinks it doesn\'t have fields.",
f))
}));
}
if adt_def.repr().simd() || adt_def.repr().scalable() {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Projecting into SIMD type {0:?} is banned by MCP#838",
adt_def))
}));
}
let var = parent_ty.variant_index.unwrap_or(FIRST_VARIANT);
let Some(field) =
adt_def.variant(var).fields.get(f) else {
fail_out_of_bounds(self, location);
return;
};
check_equal(self, location,
field.ty(self.tcx, args).skip_norm_wip());
}
ty::Closure(_, args) => {
let args = args.as_closure();
let Some(&f_ty) =
args.upvar_tys().get(f.as_usize()) else {
fail_out_of_bounds(self, location);
return;
};
check_equal(self, location, f_ty);
}
ty::CoroutineClosure(_, args) => {
let args = args.as_coroutine_closure();
let Some(&f_ty) =
args.upvar_tys().get(f.as_usize()) else {
fail_out_of_bounds(self, location);
return;
};
check_equal(self, location, f_ty);
}
&ty::Coroutine(def_id, args) => {
let f_ty =
if let Some(var) = parent_ty.variant_index {
let layout =
if def_id == self.caller_body.source.def_id() {
self.caller_body.coroutine_layout_raw().or_else(||
self.tcx.coroutine_layout(def_id, args).ok())
} else if self.tcx.needs_coroutine_by_move_body_def_id(def_id)
&&
let ty::ClosureKind::FnOnce =
args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap()
&&
self.caller_body.source.def_id() ==
self.tcx.coroutine_by_move_body_def_id(def_id) {
self.caller_body.coroutine_layout_raw()
} else { self.tcx.coroutine_layout(def_id, args).ok() };
let Some(layout) =
layout else {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("No coroutine layout for {0:?}",
parent_ty))
}));
return;
};
let Some(&local) =
layout.variant_fields[var].get(f) else {
fail_out_of_bounds(self, location);
return;
};
let Some(f_ty) =
layout.field_tys.get(local) else {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Out of bounds local {0:?} for {1:?}",
local, parent_ty))
}));
return;
};
ty::EarlyBinder::bind(self.tcx,
f_ty.ty).instantiate(self.tcx, args).skip_norm_wip()
} else if let Some(&f_ty) =
args.as_coroutine().upvar_tys().get(f.index()) {
f_ty
} else { fail_out_of_bounds(self, location); return; };
check_equal(self, location, f_ty);
}
_ => {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?} does not have fields",
parent_ty.ty))
}));
}
}
}
ProjectionElem::Index(index) => {
let indexed_ty =
place_ref.ty(&self.body.local_decls, self.tcx).ty;
match indexed_ty.kind() {
ty::Array(_, _) | ty::Slice(_) => {}
_ =>
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?} cannot be indexed",
indexed_ty))
})),
}
let index_ty = self.body.local_decls[index].ty;
if index_ty != self.tcx.types.usize {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("bad index ({0} != usize)",
index_ty))
}))
}
}
ProjectionElem::ConstantIndex { offset, min_length, from_end }
=> {
let indexed_ty =
place_ref.ty(&self.body.local_decls, self.tcx).ty;
match indexed_ty.kind() {
ty::Array(_, _) => {
if from_end {
self.fail(location,
"arrays should not be indexed from end");
}
}
ty::Slice(_) => {}
_ =>
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?} cannot be indexed",
indexed_ty))
})),
}
if from_end {
if offset > min_length {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("constant index with offset -{0} out of bounds of min length {1}",
offset, min_length))
}));
}
} else {
if offset >= min_length {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("constant index with offset {0} out of bounds of min length {1}",
offset, min_length))
}));
}
}
}
ProjectionElem::Subslice { from, to, from_end } => {
let indexed_ty =
place_ref.ty(&self.body.local_decls, self.tcx).ty;
match indexed_ty.kind() {
ty::Array(_, _) => {
if from_end {
self.fail(location,
"arrays should not be subsliced from end");
}
}
ty::Slice(_) => {
if !from_end {
self.fail(location, "slices should be subsliced from end");
}
}
_ =>
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?} cannot be indexed",
indexed_ty))
})),
}
if !from_end && from > to {
self.fail(location, "backwards subslice {from}..{to}");
}
}
ProjectionElem::OpaqueCast(ty) if
self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial)
=> {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("explicit opaque type cast to `{0}` after `PostAnalysisNormalize`",
ty))
}))
}
ProjectionElem::UnwrapUnsafeBinder(unwrapped_ty) => {
let binder_ty =
place_ref.ty(&self.body.local_decls, self.tcx);
let ty::UnsafeBinder(binder_ty) =
*binder_ty.ty.kind() else {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("WrapUnsafeBinder does not produce a ty::UnsafeBinder"))
}));
return;
};
let binder_inner_ty =
self.tcx.instantiate_bound_regions_with_erased(*binder_ty);
if !self.mir_assign_valid_types(unwrapped_ty,
binder_inner_ty) {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Cannot unwrap unsafe binder {0:?} into type {1}",
binder_ty, unwrapped_ty))
}));
}
}
_ => {}
}
self.super_projection_elem(place_ref, elem, context, location);
}
fn visit_var_debug_info(&mut self, debuginfo: &VarDebugInfo<'tcx>) {
if let Some(VarDebugInfoFragment { ty, ref projection }) =
debuginfo.composite {
if ty.is_union() || ty.is_enum() {
self.fail(START_BLOCK.start_location(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid type {1} in debuginfo for {0:?}",
debuginfo.name, ty))
}));
}
if projection.is_empty() {
self.fail(START_BLOCK.start_location(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("invalid empty projection in debuginfo for {0:?}",
debuginfo.name))
}));
}
if projection.iter().any(|p|
!#[allow(non_exhaustive_omitted_patterns)] match p {
PlaceElem::Field(..) => true,
_ => false,
}) {
self.fail(START_BLOCK.start_location(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("illegal projection {0:?} in debuginfo for {1:?}",
projection, debuginfo.name))
}));
}
}
match debuginfo.value {
VarDebugInfoContents::Const(_) => {}
VarDebugInfoContents::Place(place) => {
if place.projection.iter().any(|p|
!p.can_use_in_debuginfo()) {
self.fail(START_BLOCK.start_location(),
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("illegal place {0:?} in debuginfo for {1:?}",
place, debuginfo.name))
}));
}
}
}
self.super_var_debug_info(debuginfo);
}
fn visit_place(&mut self, place: &Place<'tcx>, cntxt: PlaceContext,
location: Location) {
let _ = place.ty(&self.body.local_decls, self.tcx);
if self.body.phase >= MirPhase::Runtime(RuntimePhase::Initial) &&
place.projection.len() > 1 &&
cntxt != PlaceContext::NonUse(NonUseContext::VarDebugInfo)
&& place.projection[1..].contains(&ProjectionElem::Deref) {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("place {0:?} has deref as a later projection (it is only permitted as the first projection)",
place))
}));
}
let mut projections_iter = place.projection.iter();
while let Some(proj) = projections_iter.next() {
if #[allow(non_exhaustive_omitted_patterns)] match proj {
ProjectionElem::Downcast(..) => true,
_ => false,
} {
if !#[allow(non_exhaustive_omitted_patterns)] match projections_iter.next()
{
Some(ProjectionElem::Field(..)) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("place {0:?} has `Downcast` projection not followed by `Field`",
place))
}));
}
}
}
if let ClearCrossCrate::Set(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,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`DerefTemp` locals must only be dereferenced or directly assigned to"))
}));
}
}
if self.body.phase < MirPhase::Runtime(RuntimePhase::Initial) &&
let Some(i) =
place.projection.iter().position(|elem|
#[allow(non_exhaustive_omitted_patterns)] match elem {
ProjectionElem::Subslice { .. } => true,
_ => false,
}) && let Some(tail) = place.projection.get(i + 1..) &&
tail.iter().any(|elem|
{
#[allow(non_exhaustive_omitted_patterns)]
match elem {
ProjectionElem::ConstantIndex { .. } |
ProjectionElem::Subslice { .. } => true,
_ => false,
}
}) {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("place {0:?} has `ConstantIndex` or `Subslice` after `Subslice`",
place))
}));
}
self.super_place(place, cntxt, location);
}
fn visit_rvalue(&mut self, rvalue: &Rvalue<'tcx>,
location: Location) {
macro_rules! check_kinds {
($t:expr, $text:literal, $typat:pat) =>
{
if !matches!(($t).kind(), $typat)
{ self.fail(location, format!($text, $t)); }
};
}
match rvalue {
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) => {
for src in fields {
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx),
dest) {
self.fail(location, "array field has the wrong type");
}
}
}
AggregateKind::Adt(def_id, idx, args, _, Some(field)) => {
let adt_def = self.tcx.adt_def(def_id);
if !adt_def.is_union() {
::core::panicking::panic("assertion failed: adt_def.is_union()")
};
{
match (&idx, &FIRST_VARIANT) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
let dest_ty =
self.tcx.normalize_erasing_regions(self.typing_env,
adt_def.non_enum_variant().fields[field].ty(self.tcx,
args));
if let [field] = fields.raw.as_slice() {
let src_ty = field.ty(self.body, self.tcx);
if !self.mir_assign_valid_types(src_ty, dest_ty) {
self.fail(location, "union field has the wrong type");
}
} else {
self.fail(location,
"unions should have one initialized field");
}
}
AggregateKind::Adt(def_id, idx, args, _, None) => {
let adt_def = self.tcx.adt_def(def_id);
if !!adt_def.is_union() {
::core::panicking::panic("assertion failed: !adt_def.is_union()")
};
let variant = &adt_def.variants()[idx];
if variant.fields.len() != fields.len() {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("adt {2:?} has the wrong number of initialized fields, expected {0}, found {1}",
fields.len(), variant.fields.len(), def_id))
}));
}
for (src, dest) in std::iter::zip(fields, &variant.fields) {
let dest_ty =
self.tcx.normalize_erasing_regions(self.typing_env,
dest.ty(self.tcx, args));
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx),
dest_ty) {
self.fail(location, "adt field has the wrong type");
}
}
}
AggregateKind::Closure(_, args) => {
let upvars = args.as_closure().upvar_tys();
if upvars.len() != fields.len() {
self.fail(location,
"closure has the wrong number of initialized fields");
}
for (src, dest) in std::iter::zip(fields, upvars) {
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx),
dest) {
self.fail(location, "closure field has the wrong type");
}
}
}
AggregateKind::Coroutine(_, args) => {
let upvars = args.as_coroutine().upvar_tys();
if upvars.len() != fields.len() {
self.fail(location,
"coroutine has the wrong number of initialized fields");
}
for (src, dest) in std::iter::zip(fields, upvars) {
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx),
dest) {
self.fail(location, "coroutine field has the wrong type");
}
}
}
AggregateKind::CoroutineClosure(_, args) => {
let upvars = args.as_coroutine_closure().upvar_tys();
if upvars.len() != fields.len() {
self.fail(location,
"coroutine-closure has the wrong number of initialized fields");
}
for (src, dest) in std::iter::zip(fields, upvars) {
if !self.mir_assign_valid_types(src.ty(self.body, self.tcx),
dest) {
self.fail(location,
"coroutine-closure field has the wrong type");
}
}
}
AggregateKind::RawPtr(pointee_ty, mutability) => {
if !#[allow(non_exhaustive_omitted_patterns)] match self.body.phase
{
MirPhase::Runtime(_) => true,
_ => false,
} {
self.fail(location, "RawPtr should be in runtime MIR only");
}
if let [data_ptr, metadata] = fields.raw.as_slice() {
let data_ptr_ty = data_ptr.ty(self.body, self.tcx);
let metadata_ty = metadata.ty(self.body, self.tcx);
if let ty::RawPtr(in_pointee, in_mut) = data_ptr_ty.kind() {
if *in_mut != mutability {
self.fail(location,
"input and output mutability must match");
}
if !in_pointee.is_sized(self.tcx, self.typing_env) {
self.fail(location, "input pointer must be thin");
}
} else {
self.fail(location,
"first operand to raw pointer aggregate must be a raw pointer");
}
if pointee_ty.is_slice() {
if !self.mir_assign_valid_types(metadata_ty,
self.tcx.types.usize) {
self.fail(location, "slice metadata must be usize");
}
} else if pointee_ty.is_sized(self.tcx, self.typing_env) {
if metadata_ty != self.tcx.types.unit {
self.fail(location,
"metadata for pointer-to-thin must be unit");
}
}
} else {
self.fail(location,
"raw pointer aggregate must have 2 fields");
}
}
},
Rvalue::Ref(_, BorrowKind::Fake(_), _) => {
if self.body.phase >=
MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(location,
"`Assign` statement with a `Fake` borrow should have been removed in runtime MIR");
}
}
Rvalue::Ref(..) | Rvalue::Reborrow(..) => {}
Rvalue::BinaryOp(op, vals) => {
use BinOp::*;
let a = vals.0.ty(&self.body.local_decls, self.tcx);
let b = vals.1.ty(&self.body.local_decls, self.tcx);
if crate::util::binop_right_homogeneous(*op) {
if let Eq | Lt | Le | Ne | Ge | Gt = op {
if !self.mir_assign_valid_types(a, b) {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Cannot {0:?} compare incompatible types {1} and {2}",
op, a, b))
}));
}
} else if a != b {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Cannot perform binary op {0:?} on unequal types {1} and {2}",
op, a, b))
}));
}
}
match op {
Offset => {
if !#[allow(non_exhaustive_omitted_patterns)] match (a).kind()
{
ty::RawPtr(..) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Cannot offset non-pointer type {0:?}",
a))
}));
};
if b != self.tcx.types.isize && b != self.tcx.types.usize {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Cannot offset by non-isize type {0}",
b))
}));
}
}
Eq | Lt | Le | Ne | Ge | Gt => {
for x in [a, b] {
if !#[allow(non_exhaustive_omitted_patterns)] match (x).kind()
{
ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
ty::Float(..) | ty::RawPtr(..) | ty::FnPtr(..) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Cannot {1:?} compare type {0:?}",
x, op))
}));
}
}
}
Cmp => {
for x in [a, b] {
if !#[allow(non_exhaustive_omitted_patterns)] match (x).kind()
{
ty::Char | ty::Uint(..) | ty::Int(..) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Cannot three-way compare non-integer type {0:?}",
x))
}));
}
}
}
AddUnchecked | AddWithOverflow | SubUnchecked |
SubWithOverflow | MulUnchecked | MulWithOverflow | Shl |
ShlUnchecked | Shr | ShrUnchecked => {
for x in [a, b] {
if !#[allow(non_exhaustive_omitted_patterns)] match (x).kind()
{
ty::Uint(..) | ty::Int(..) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Cannot {1:?} non-integer type {0:?}",
x, op))
}));
}
}
}
BitAnd | BitOr | BitXor => {
for x in [a, b] {
if !#[allow(non_exhaustive_omitted_patterns)] match (x).kind()
{
ty::Uint(..) | ty::Int(..) | ty::Bool => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Cannot perform bitwise op {1:?} on type {0:?}",
x, op))
}));
}
}
}
Add | Sub | Mul | Div | Rem => {
for x in [a, b] {
if !#[allow(non_exhaustive_omitted_patterns)] match (x).kind()
{
ty::Uint(..) | ty::Int(..) | ty::Float(..) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Cannot perform arithmetic {1:?} on type {0:?}",
x, op))
}));
}
}
}
}
}
Rvalue::UnaryOp(op, operand) => {
let a = operand.ty(&self.body.local_decls, self.tcx);
match op {
UnOp::Neg => {
if !#[allow(non_exhaustive_omitted_patterns)] match (a).kind()
{
ty::Int(..) | ty::Float(..) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Cannot negate type {0:?}",
a))
}));
}
}
UnOp::Not => {
if !#[allow(non_exhaustive_omitted_patterns)] match (a).kind()
{
ty::Int(..) | ty::Uint(..) | ty::Bool => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Cannot binary not type {0:?}",
a))
}));
};
}
UnOp::PtrMetadata => {
if !#[allow(non_exhaustive_omitted_patterns)] match (a).kind()
{
ty::RawPtr(..) | ty::Ref(..) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Cannot PtrMetadata non-pointer non-reference type {0:?}",
a))
}));
};
}
}
}
Rvalue::Cast(kind, operand, target_type) => {
let op_ty = operand.ty(self.body, self.tcx);
match kind {
CastKind::PointerWithExposedProvenance |
CastKind::PointerExposeProvenance => {}
CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer(_),
_) => {
if !#[allow(non_exhaustive_omitted_patterns)] match (op_ty).kind()
{
ty::FnDef(..) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("CastKind::{1:?} input must be a fn item, not {0:?}",
op_ty, kind))
}));
};
if !#[allow(non_exhaustive_omitted_patterns)] match (target_type).kind()
{
ty::FnPtr(..) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("CastKind::{1:?} output must be a fn pointer, not {0:?}",
target_type, kind))
}));
};
}
CastKind::PointerCoercion(PointerCoercion::UnsafeFnPointer,
_) => {
if !#[allow(non_exhaustive_omitted_patterns)] match (op_ty).kind()
{
ty::FnPtr(..) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("CastKind::{1:?} input must be a fn pointer, not {0:?}",
op_ty, kind))
}));
};
if !#[allow(non_exhaustive_omitted_patterns)] match (target_type).kind()
{
ty::FnPtr(..) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("CastKind::{1:?} output must be a fn pointer, not {0:?}",
target_type, kind))
}));
};
}
CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(..),
_) => {
if !#[allow(non_exhaustive_omitted_patterns)] match (op_ty).kind()
{
ty::Closure(..) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("CastKind::{1:?} input must be a closure, not {0:?}",
op_ty, kind))
}));
};
if !#[allow(non_exhaustive_omitted_patterns)] match (target_type).kind()
{
ty::FnPtr(..) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("CastKind::{1:?} output must be a fn pointer, not {0:?}",
target_type, kind))
}));
};
}
CastKind::PointerCoercion(PointerCoercion::MutToConstPointer,
_) => {
if !#[allow(non_exhaustive_omitted_patterns)] match (op_ty).kind()
{
ty::RawPtr(_, Mutability::Mut) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("CastKind::{1:?} input must be a raw mut pointer, not {0:?}",
op_ty, kind))
}));
};
if !#[allow(non_exhaustive_omitted_patterns)] match (target_type).kind()
{
ty::RawPtr(_, Mutability::Not) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("CastKind::{1:?} output must be a raw const pointer, not {0:?}",
target_type, kind))
}));
};
if self.body.phase >=
MirPhase::Analysis(AnalysisPhase::PostCleanup) {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("After borrowck, MIR disallows {0:?}",
kind))
}));
}
}
CastKind::PointerCoercion(PointerCoercion::ArrayToPointer,
_) => {
if !#[allow(non_exhaustive_omitted_patterns)] match (op_ty).kind()
{
ty::RawPtr(..) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("CastKind::{1:?} input must be a raw pointer, not {0:?}",
op_ty, kind))
}));
};
if !#[allow(non_exhaustive_omitted_patterns)] match (target_type).kind()
{
ty::RawPtr(..) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("CastKind::{1:?} output must be a raw pointer, not {0:?}",
target_type, kind))
}));
};
if self.body.phase >=
MirPhase::Analysis(AnalysisPhase::PostCleanup) {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("After borrowck, MIR disallows {0:?}",
kind))
}));
}
}
CastKind::PointerCoercion(PointerCoercion::Unsize, _) => {
if !self.predicate_must_hold_modulo_regions(ty::TraitRef::new(self.tcx,
self.tcx.require_lang_item(LangItem::CoerceUnsized,
self.body.source_info(location).span),
[op_ty, *target_type])) {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Unsize coercion, but `{0}` isn\'t coercible to `{1}`",
op_ty, target_type))
}));
}
}
CastKind::IntToInt | CastKind::IntToFloat => {
let input_valid =
op_ty.is_integral() || op_ty.is_char() || op_ty.is_bool();
let target_valid =
target_type.is_numeric() || target_type.is_char();
if !input_valid || !target_valid {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Wrong cast kind {0:?} for the type {1}",
kind, op_ty))
}));
}
}
CastKind::FnPtrToPtr => {
if !#[allow(non_exhaustive_omitted_patterns)] match (op_ty).kind()
{
ty::FnPtr(..) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("CastKind::{1:?} input must be a fn pointer, not {0:?}",
op_ty, kind))
}));
};
if !#[allow(non_exhaustive_omitted_patterns)] match (target_type).kind()
{
ty::RawPtr(..) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("CastKind::{1:?} output must be a raw pointer, not {0:?}",
target_type, kind))
}));
};
}
CastKind::PtrToPtr => {
if !#[allow(non_exhaustive_omitted_patterns)] match (op_ty).kind()
{
ty::RawPtr(..) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("CastKind::{1:?} input must be a raw pointer, not {0:?}",
op_ty, kind))
}));
};
if !#[allow(non_exhaustive_omitted_patterns)] match (target_type).kind()
{
ty::RawPtr(..) => true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("CastKind::{1:?} output must be a raw pointer, not {0:?}",
target_type, kind))
}));
};
}
CastKind::FloatToFloat | CastKind::FloatToInt => {
if !op_ty.is_floating_point() || !target_type.is_numeric() {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Trying to cast non \'Float\' as {0:?} into {1:?}",
kind, target_type))
}));
}
}
CastKind::Transmute | CastKind::BoxDerefTransmute => {
if !self.tcx.normalize_erasing_regions(self.typing_env,
Unnormalized::new_wip(op_ty)).is_sized(self.tcx,
self.typing_env) {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Cannot transmute from non-`Sized` type {0}",
op_ty))
}));
}
if !self.tcx.normalize_erasing_regions(self.typing_env,
Unnormalized::new_wip(*target_type)).is_sized(self.tcx,
self.typing_env) {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Cannot transmute to non-`Sized` type {0:?}",
target_type))
}));
}
if #[allow(non_exhaustive_omitted_patterns)] match kind {
CastKind::BoxDerefTransmute => true,
_ => false,
} {
if !target_type.is_raw_ptr() {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Cannot BoxDerefTransmute to non-pointer type {0}",
target_type))
}));
}
}
}
CastKind::Subtype => {
if !util::sub_types(self.tcx, self.typing_env, op_ty,
*target_type) {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Failed subtyping {0} and {1}",
op_ty, target_type))
}))
}
}
}
}
Rvalue::Repeat(_, _) | Rvalue::ThreadLocalRef(_) |
Rvalue::RawPtr(_, _) | Rvalue::Discriminant(_) => {}
Rvalue::WrapUnsafeBinder(op, ty) => {
let unwrapped_ty = op.ty(self.body, self.tcx);
let ty::UnsafeBinder(binder_ty) =
*ty.kind() else {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("WrapUnsafeBinder does not produce a ty::UnsafeBinder"))
}));
return;
};
let binder_inner_ty =
self.tcx.instantiate_bound_regions_with_erased(*binder_ty);
if !self.mir_assign_valid_types(unwrapped_ty,
binder_inner_ty) {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Cannot wrap {0} into unsafe binder {1:?}",
unwrapped_ty, binder_ty))
}));
}
}
}
self.super_rvalue(rvalue, location);
}
fn visit_statement(&mut self, statement: &Statement<'tcx>,
location: Location) {
match &statement.kind {
StatementKind::Assign((dest, rvalue)) => {
let left_ty = dest.ty(&self.body.local_decls, self.tcx).ty;
let right_ty = rvalue.ty(&self.body.local_decls, self.tcx);
if !self.mir_assign_valid_types(right_ty, left_ty) {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("encountered `{0:?}` with incompatible types:\nleft-hand side has type: {1}\nright-hand side has type: {2}",
statement.kind, left_ty, right_ty))
}));
}
if let Some(local) = dest.as_local() &&
let ClearCrossCrate::Set(LocalInfo::DerefTemp) =
self.body.local_decls[local].local_info &&
!#[allow(non_exhaustive_omitted_patterns)] match rvalue {
Rvalue::CopyForDeref(_) => true,
_ => false,
} {
self.fail(location,
"assignment to a `DerefTemp` must use `CopyForDeref`")
}
}
StatementKind::AscribeUserType(..) => {
if self.body.phase >=
MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(location,
"`AscribeUserType` should have been removed after drop lowering phase");
}
}
StatementKind::FakeRead(..) => {
if self.body.phase >=
MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(location,
"`FakeRead` should have been removed after drop lowering phase");
}
}
StatementKind::Intrinsic(NonDivergingIntrinsic::Assume(op)) =>
{
let ty = op.ty(&self.body.local_decls, self.tcx);
if !ty.is_bool() {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`assume` argument must be `bool`, but got: `{0}`",
ty))
}));
}
}
StatementKind::Intrinsic(NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping {
src, dst, count })) => {
let src_ty = src.ty(&self.body.local_decls, self.tcx);
let op_src_ty =
if let Some(src_deref) = src_ty.builtin_deref(true) {
src_deref
} else {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Expected src to be ptr in copy_nonoverlapping, got: {0}",
src_ty))
}));
return;
};
let dst_ty = dst.ty(&self.body.local_decls, self.tcx);
let op_dst_ty =
if let Some(dst_deref) = dst_ty.builtin_deref(true) {
dst_deref
} else {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("Expected dst to be ptr in copy_nonoverlapping, got: {0}",
dst_ty))
}));
return;
};
if !self.mir_assign_valid_types(op_src_ty, op_dst_ty) {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("bad arg ({0} != {1})",
op_src_ty, op_dst_ty))
}));
}
let op_cnt_ty = count.ty(&self.body.local_decls, self.tcx);
if op_cnt_ty != self.tcx.types.usize {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("bad arg ({0} != usize)",
op_cnt_ty))
}))
}
}
StatementKind::SetDiscriminant { place, .. } => {
if self.body.phase <
MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(location,
"`SetDiscriminant`is not allowed until deaggregation");
}
let pty = place.ty(&self.body.local_decls, self.tcx).ty;
if !#[allow(non_exhaustive_omitted_patterns)] match pty.kind()
{
ty::Adt(..) | ty::Coroutine(..) |
ty::Alias(_, ty::AliasTy { kind: ty::Opaque { .. }, .. }) =>
true,
_ => false,
} {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("`SetDiscriminant` is only allowed on ADTs and coroutines, not {0}",
pty))
}));
}
}
StatementKind::StorageLive(_) | StatementKind::StorageDead(_)
| StatementKind::Coverage(_) |
StatementKind::ConstEvalCounter |
StatementKind::PlaceMention(..) |
StatementKind::BackwardIncompatibleDropHint { .. } |
StatementKind::Nop => {}
}
self.super_statement(statement, location);
}
fn visit_terminator(&mut self, terminator: &Terminator<'tcx>,
location: Location) {
match &terminator.kind {
TerminatorKind::SwitchInt { targets, discr } => {
let switch_ty = discr.ty(&self.body.local_decls, self.tcx);
let target_width = self.tcx.sess.target.pointer_width;
let size =
Size::from_bits(match switch_ty.kind() {
ty::Uint(uint) =>
uint.normalize(target_width).bit_width().unwrap(),
ty::Int(int) =>
int.normalize(target_width).bit_width().unwrap(),
ty::Char => 32,
ty::Bool => 1,
other =>
::rustc_middle::util::bug::bug_fmt(format_args!("unhandled type: {0:?}",
other)),
});
for (value, _) in targets.iter() {
if ScalarInt::try_from_uint(value, size).is_none() {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("the value {0:#x} is not a proper {1}",
value, switch_ty))
}))
}
}
}
TerminatorKind::Call { func, .. } | TerminatorKind::TailCall {
func, .. } => {
let func_ty = func.ty(&self.body.local_decls, self.tcx);
match func_ty.kind() {
ty::FnPtr(..) | ty::FnDef(..) => {}
_ =>
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("encountered non-callable type {1} in `{0}` terminator",
terminator.kind.name(), func_ty))
})),
}
if let TerminatorKind::TailCall { .. } = terminator.kind {}
}
TerminatorKind::Assert { cond, .. } => {
let cond_ty = cond.ty(&self.body.local_decls, self.tcx);
if cond_ty != self.tcx.types.bool {
self.fail(location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("encountered non-boolean condition of type {0} in `Assert` terminator",
cond_ty))
}));
}
}
TerminatorKind::Goto { .. } | TerminatorKind::Drop { .. } |
TerminatorKind::Yield { .. } | TerminatorKind::FalseEdge {
.. } | TerminatorKind::FalseUnwind { .. } |
TerminatorKind::InlineAsm { .. } |
TerminatorKind::CoroutineDrop | TerminatorKind::UnwindResume
| TerminatorKind::UnwindTerminate(_) |
TerminatorKind::Return | TerminatorKind::Unreachable => {}
}
self.super_terminator(terminator, location);
}
fn visit_local_decl(&mut self, local: Local,
local_decl: &LocalDecl<'tcx>) {
if let ClearCrossCrate::Set(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)> {
let mut debuginfo_checker =
DebuginfoChecker {
debuginfo_locals: debuginfo_locals(body),
failures: Vec::new(),
};
debuginfo_checker.visit_body(body);
debuginfo_checker.failures
}
struct DebuginfoChecker {
debuginfo_locals: DenseBitSet<Local>,
failures: Vec<(Location, String)>,
}
impl<'tcx> Visitor<'tcx> for DebuginfoChecker {
fn visit_statement_debuginfo(&mut self,
stmt_debuginfo: &StmtDebugInfo<'tcx>, location: Location) {
let local =
match stmt_debuginfo {
StmtDebugInfo::AssignRef(local, _) |
StmtDebugInfo::InvalidAssign(local) => *local,
};
if !self.debuginfo_locals.contains(local) {
self.failures.push((location,
::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0:?} is not in debuginfo",
local))
})));
}
}
}
}
#[allow(unused_imports)]
use validate::Validator as _;
static PASS_NAMES: LazyLock<FxIndexSet<&str>> =
LazyLock::new(||
{
let mut set = FxIndexSet::default();
set.extend(["AbortUnwindingCalls"]);
set.extend([add_call_guards::AddCallGuards::AllCallEdges.name(),
add_call_guards::AddCallGuards::CriticalCallEdges.name()]);
set.extend(["AddMovesForPackedDrops"]);
set.extend(["Subtyper"]);
set.extend(["CheckForceInline"]);
set.extend(["CheckCallRecursion"]);
set.extend(["CheckDropRecursion"]);
set.extend(["CheckAlignment"]);
set.extend(["CheckEnums"]);
set.extend(["CheckConstItemMutation"]);
set.extend(["CheckNull"]);
set.extend(["CheckPackedRef"]);
set.extend(["CheckMutRestriction"]);
set.extend(["CleanupPostBorrowck"]);
set.extend(["CopyProp"]);
set.extend(["StateTransform"]);
set.extend(["InstrumentCoverage"]);
set.extend(["CtfeLimit"]);
set.extend(["DataflowConstProp"]);
set.extend([dead_store_elimination::DeadStoreElimination::Initial.name(),
dead_store_elimination::DeadStoreElimination::Final.name()]);
set.extend(["Derefer"]);
set.extend(["DestinationPropagation"]);
set.extend(["EarlyOtherwiseBranch"]);
set.extend(["EraseDerefTemps"]);
set.extend(["ElaborateBoxDerefs"]);
set.extend(["ElaborateDrops"]);
set.extend(["FunctionItemReferences"]);
set.extend(["GVN"]);
set.extend(["Inline"]);
set.extend(["ForceInline"]);
set.extend(["ImpossibleClauses"]);
set.extend([instsimplify::InstSimplify::BeforeInline.name(),
instsimplify::InstSimplify::AfterSimplifyCfg.name()]);
set.extend(["JumpThreading"]);
set.extend(["KnownPanicsLint"]);
set.extend(["LintAndRemoveUninhabited"]);
set.extend(["LowerIntrinsics"]);
set.extend(["LowerSliceLenCalls"]);
set.extend(["MatchBranchSimplification"]);
set.extend(["MentionedItems"]);
set.extend(["MultipleReturnTerminators"]);
set.extend(["CheckLiveDrops"]);
set.extend(["ReorderBasicBlocks"]);
set.extend(["ReorderLocals"]);
set.extend(["PromoteTemps"]);
set.extend(["ReferencePropagation"]);
set.extend(["RemoveNoopLandingPads"]);
set.extend(["RemovePlaceMention"]);
set.extend(["RemoveStorageMarkers"]);
set.extend(["RemoveUninitDrops"]);
set.extend(["RemoveUnneededDrops"]);
set.extend(["RemoveZsts"]);
set.extend(["RequiredConstsVisitor"]);
set.extend(["PostAnalysisNormalize"]);
set.extend(["SanityCheck"]);
set.extend([simplify::SimplifyCfg::Initial.name(),
simplify::SimplifyCfg::PromoteConsts.name(),
simplify::SimplifyCfg::RemoveFalseEdges.name(),
simplify::SimplifyCfg::PostAnalysis.name(),
simplify::SimplifyCfg::PreOptimizations.name(),
simplify::SimplifyCfg::Final.name(),
simplify::SimplifyCfg::MakeShim.name(),
simplify::SimplifyCfg::AfterUnreachableEnumBranching.name()]);
set.extend([simplify::SimplifyLocals::BeforeConstProp.name(),
simplify::SimplifyLocals::AfterGVN.name(),
simplify::SimplifyLocals::Final.name()]);
set.extend([simplify_branches::SimplifyConstCondition::AfterInstSimplify.name(),
simplify_branches::SimplifyConstCondition::AfterConstProp.name(),
simplify_branches::SimplifyConstCondition::Final.name()]);
set.extend(["SimplifyComparisonIntegral"]);
set.extend(["SingleUseConsts"]);
set.extend(["ScalarReplacementOfAggregates"]);
set.extend(["StripDebugInfo"]);
set.extend(["SsaRangePropagation"]);
set.extend(["UnreachableEnumBranching"]);
set.extend(["UnreachablePropagation"]);
set.extend(["Validator"]);
set
});declare_passes! {
123 mod abort_unwinding_calls : AbortUnwindingCalls;
124 mod add_call_guards : AddCallGuards { AllCallEdges, CriticalCallEdges };
125 mod add_moves_for_packed_drops : AddMovesForPackedDrops;
126 mod add_subtyping_projections : Subtyper;
127 mod check_inline : CheckForceInline;
128 mod check_call_recursion : CheckCallRecursion, CheckDropRecursion;
129 mod check_alignment : CheckAlignment;
130 mod check_enums : CheckEnums;
131 mod check_const_item_mutation : CheckConstItemMutation;
132 mod check_null : CheckNull;
133 mod check_packed_ref : CheckPackedRef;
134 mod check_mut_restriction : CheckMutRestriction;
135 pub mod cleanup_post_borrowck : CleanupPostBorrowck;
137
138 mod copy_prop : CopyProp;
139 mod coroutine : StateTransform;
140 mod coverage : InstrumentCoverage;
141 mod ctfe_limit : CtfeLimit;
142 mod dataflow_const_prop : DataflowConstProp;
143 mod dead_store_elimination : DeadStoreElimination {
144 Initial,
145 Final
146 };
147 mod deref_separator : Derefer;
148 mod dest_prop : DestinationPropagation;
149 mod early_otherwise_branch : EarlyOtherwiseBranch;
150 mod erase_deref_temps : EraseDerefTemps;
151 mod elaborate_box_derefs : ElaborateBoxDerefs;
152 mod elaborate_drops : ElaborateDrops;
153 mod function_item_references : FunctionItemReferences;
154 mod gvn : GVN;
155 pub mod inline : Inline, ForceInline;
158 mod impossible_clauses : ImpossibleClauses;
159 mod instsimplify : InstSimplify { BeforeInline, AfterSimplifyCfg };
160 mod jump_threading : JumpThreading;
161 mod known_panics_lint : KnownPanicsLint;
162 mod lint_and_remove_uninhabited : LintAndRemoveUninhabited;
163 mod lower_intrinsics : LowerIntrinsics;
164 mod lower_slice_len : LowerSliceLenCalls;
165 mod match_branches : MatchBranchSimplification;
166 mod mentioned_items : MentionedItems;
167 mod multiple_return_terminators : MultipleReturnTerminators;
168 mod post_drop_elaboration : CheckLiveDrops;
169 mod prettify : ReorderBasicBlocks, ReorderLocals;
170 mod promote_consts : PromoteTemps;
171 mod ref_prop : ReferencePropagation;
172 pub mod remove_noop_landing_pads : RemoveNoopLandingPads;
173 mod remove_place_mention : RemovePlaceMention;
174 mod remove_storage_markers : RemoveStorageMarkers;
175 mod remove_uninit_drops : RemoveUninitDrops;
176 mod remove_unneeded_drops : RemoveUnneededDrops;
177 mod remove_zsts : RemoveZsts;
178 mod required_consts : RequiredConstsVisitor;
179 mod post_analysis_normalize : PostAnalysisNormalize;
180 mod sanity_check : SanityCheck;
181 pub mod simplify :
183 SimplifyCfg {
184 Initial,
185 PromoteConsts,
186 RemoveFalseEdges,
187 PostAnalysis,
188 PreOptimizations,
189 Final,
190 MakeShim,
191 AfterUnreachableEnumBranching
192 },
193 SimplifyLocals {
194 BeforeConstProp,
195 AfterGVN,
196 Final
197 };
198 mod simplify_branches : SimplifyConstCondition {
199 AfterInstSimplify,
200 AfterConstProp,
201 Final
202 };
203 mod simplify_comparison_integral : SimplifyComparisonIntegral;
204 mod single_use_consts : SingleUseConsts;
205 mod sroa : ScalarReplacementOfAggregates;
206 mod strip_debuginfo : StripDebugInfo;
207 mod ssa_range_prop: SsaRangePropagation;
208 mod unreachable_enum_branching : UnreachableEnumBranching;
209 mod unreachable_prop : UnreachablePropagation;
210 mod validate : Validator;
211}
212
213pub fn provide(providers: &mut Providers) {
214 coverage::query::provide(providers);
215 ffi_unwind_calls::provide(&mut providers.queries);
216 shim::provide(&mut providers.queries);
217 cross_crate_inline::provide(&mut providers.queries);
218 providers.queries = query::Providers {
219 mir_keys,
220 mir_built,
221 mir_const_qualif,
222 mir_promoted,
223 mir_drops_elaborated_and_const_checked,
224 mir_for_ctfe,
225 mir_coroutine_witnesses: coroutine::mir_coroutine_witnesses,
226 optimized_mir,
227 check_liveness: liveness::check_liveness,
228 is_mir_available,
229 mir_callgraph_cyclic: inline::cycle::mir_callgraph_cyclic,
230 mir_inliner_callees: inline::cycle::mir_inliner_callees,
231 promoted_mir,
232 deduced_param_attrs: deduce_param_attrs::deduced_param_attrs,
233 coroutine_by_move_body_def_id: coroutine::coroutine_by_move_body_def_id,
234 trivial_const: trivial_const::trivial_const_provider,
235 ..providers.queries
236 };
237}
238
239fn remap_mir_for_const_eval_select<'tcx>(
240 tcx: TyCtxt<'tcx>,
241 mut body: Body<'tcx>,
242 context: hir::Constness,
243) -> Body<'tcx> {
244 for bb in body.basic_blocks.as_mut().iter_mut() {
245 let terminator = bb.terminator.as_mut().expect("invalid terminator");
246 match terminator.kind {
247 TerminatorKind::Call {
248 func: Operand::Constant(ConstOperand { ref const_, .. }),
249 ref mut args,
250 destination,
251 target,
252 unwind,
253 fn_span,
254 ..
255 } if let ty::FnDef(def_id, _) = *const_.ty().kind()
256 && tcx.is_intrinsic(def_id, sym::const_eval_select) =>
257 {
258 let Ok([tupled_args, called_in_const, called_at_rt]) = take_array(args) else {
259 ::core::panicking::panic("internal error: entered unreachable code")unreachable!()
260 };
261 let ty = tupled_args.node.ty(&body.local_decls, tcx);
262 let fields = ty.tuple_fields();
263 let num_args = fields.len();
264 let func = match context {
265 hir::Constness::Const { .. } => called_in_const,
268 hir::Constness::NotConst => called_at_rt,
269 };
270 let (method, place): (fn(Place<'tcx>) -> Operand<'tcx>, Place<'tcx>) =
271 match tupled_args.node {
272 Operand::Constant(_) | Operand::RuntimeChecks(_) => {
273 let local = body.local_decls.push(LocalDecl::new(ty, fn_span));
277 bb.statements.push(Statement::new(
278 SourceInfo::outermost(fn_span),
279 StatementKind::Assign(Box::new((
280 local.into(),
281 Rvalue::Use(tupled_args.node.clone(), WithRetag::Yes),
282 ))),
283 ));
284 (Operand::Move, local.into())
285 }
286 Operand::Move(place) => (Operand::Move, place),
287 Operand::Copy(place) => (Operand::Copy, place),
288 };
289 let place_elems = place.projection;
290 let arguments = (0..num_args)
291 .map(|x| {
292 let mut place_elems = place_elems.to_vec();
293 place_elems.push(ProjectionElem::Field(x.into(), fields[x]));
294 let projection = tcx.mk_place_elems(&place_elems);
295 let place = Place { local: place.local, projection };
296 Spanned { node: method(place), span: DUMMY_SP }
297 })
298 .collect();
299 terminator.kind = TerminatorKind::Call {
300 func: func.node,
301 args: arguments,
302 destination,
303 target,
304 unwind,
305 call_source: CallSource::Misc,
306 fn_span,
307 };
308 }
309 _ => {}
310 }
311 }
312 body
313}
314
315fn take_array<T, const N: usize>(b: &mut Box<[T]>) -> Result<[T; N], Box<[T]>> {
316 let b: Box<[T; N]> = std::mem::take(b).try_into()?;
317 Ok(*b)
318}
319
320fn is_mir_available(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
321 tcx.mir_keys(()).contains(&def_id)
322}
323
324fn mir_keys(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LocalDefId> {
327 let mut set: FxIndexSet<_> = tcx.hir_body_owners().collect();
329
330 set.retain(|&def_id| !#[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(def_id) {
DefKind::GlobalAsm => true,
_ => false,
}matches!(tcx.def_kind(def_id), DefKind::GlobalAsm));
333
334 for body_owner in tcx.hir_body_owners() {
337 if let DefKind::Closure = tcx.def_kind(body_owner)
338 && tcx.needs_coroutine_by_move_body_def_id(body_owner.to_def_id())
339 {
340 set.insert(tcx.coroutine_by_move_body_def_id(body_owner).expect_local());
341 }
342 }
343
344 for item in tcx.hir_crate_items(()).free_items() {
347 if let DefKind::Struct | DefKind::Enum = tcx.def_kind(item.owner_id) {
348 for variant in tcx.adt_def(item.owner_id).variants() {
349 if let Some((CtorKind::Fn, ctor_def_id)) = variant.ctor {
350 set.insert(ctor_def_id.expect_local());
351 }
352 }
353 }
354 }
355
356 set
357}
358
359fn mir_const_qualif(tcx: TyCtxt<'_>, def: LocalDefId) -> ConstQualifs {
360 let body = &tcx.mir_built(def).borrow();
365 let ccx = check_consts::ConstCx::new(tcx, body);
366 match ccx.const_kind {
368 Some(ConstContext::Const { .. } | ConstContext::Static(_) | ConstContext::ConstFn) => {}
369 None => ::rustc_middle::util::bug::span_bug_fmt(tcx.def_span(def),
format_args!("`mir_const_qualif` should only be called on const fns and const items"))span_bug!(
370 tcx.def_span(def),
371 "`mir_const_qualif` should only be called on const fns and const items"
372 ),
373 }
374
375 if body.return_ty().references_error() {
376 tcx.dcx().span_delayed_bug(body.span, "mir_const_qualif: MIR had errors");
378 return Default::default();
379 }
380
381 let mut validator = check_consts::check::Checker::new(&ccx);
382 validator.check_body();
383
384 validator.qualifs_in_return_place()
387}
388
389fn mir_built(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
391 let mut body = tcx.build_mir_inner_impl(def);
394
395 if trivial_const::trivial_const(tcx, def, || &body).is_some() {
399 let body = tcx.alloc_steal_mir(body);
401 pass_manager::dump_mir_for_phase_change(tcx, &body.borrow());
402 return body;
403 }
404
405 pass_manager::dump_mir_for_phase_change(tcx, &body);
406
407 pm::run_passes(
408 tcx,
409 &mut body,
410 &[
411 &lint_and_remove_uninhabited::LintAndRemoveUninhabited,
414 &Lint(check_inline::CheckForceInline),
416 &Lint(check_call_recursion::CheckCallRecursion),
417 &Lint(check_packed_ref::CheckPackedRef),
418 &Lint(check_const_item_mutation::CheckConstItemMutation),
419 &Lint(check_mut_restriction::CheckMutRestriction),
420 &Lint(function_item_references::FunctionItemReferences),
421 &simplify::SimplifyCfg::Initial,
423 &Lint(sanity_check::SanityCheck),
424 ],
425 None,
426 );
427 tcx.alloc_steal_mir(body)
428}
429
430fn mir_promoted(
432 tcx: TyCtxt<'_>,
433 def: LocalDefId,
434) -> (&Steal<Body<'_>>, &Steal<IndexVec<Promoted, Body<'_>>>) {
435 if true {
if !!tcx.is_trivial_const(def) {
{
::core::panicking::panic_fmt(format_args!("Tried to get mir_promoted of a trivial const"));
}
};
};debug_assert!(!tcx.is_trivial_const(def), "Tried to get mir_promoted of a trivial const");
436 if true {
if !!tcx.is_constructor(def.to_def_id()) {
::core::panicking::panic("assertion failed: !tcx.is_constructor(def.to_def_id())")
};
};debug_assert!(!tcx.is_constructor(def.to_def_id()));
437
438 let const_qualifs = match tcx.def_kind(def) {
443 DefKind::Fn | DefKind::AssocFn | DefKind::Closure
444 if #[allow(non_exhaustive_omitted_patterns)] match tcx.constness(def) {
hir::Constness::Const { .. } => true,
_ => false,
}matches!(tcx.constness(def), hir::Constness::Const { .. }) =>
445 {
446 tcx.mir_const_qualif(def)
447 }
448 DefKind::AssocConst { .. }
449 | DefKind::Const { .. }
450 | DefKind::Static { .. }
451 | DefKind::AnonConst => tcx.mir_const_qualif(def),
452 _ => ConstQualifs::default(),
453 };
454
455 tcx.ensure_done().has_ffi_unwind_calls(def);
457
458 if tcx.needs_coroutine_by_move_body_def_id(def.to_def_id()) {
460 tcx.ensure_done().coroutine_by_move_body_def_id(def);
461 }
462
463 tcx.ensure_done().trivial_const(def);
465
466 let mut body = tcx.mir_built(def).steal();
467 if let Some(error_reported) = const_qualifs.tainted_by_errors {
468 body.tainted_by_errors = Some(error_reported);
469 }
470
471 RequiredConstsVisitor::compute_required_consts(&mut body);
474
475 let promote_pass = promote_consts::PromoteTemps::default();
477 pm::run_passes(
478 tcx,
479 &mut body,
480 &[&promote_pass, &simplify::SimplifyCfg::PromoteConsts, &coverage::InstrumentCoverage],
481 Some(MirPhase::Analysis(AnalysisPhase::Initial)),
482 );
483
484 lint_tail_expr_drop_order::run_lint(tcx, def, &body);
485
486 let promoted = promote_pass.promoted_fragments.into_inner();
487 (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted))
488}
489
490fn mir_for_ctfe(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &Body<'_> {
492 if true {
if !!tcx.is_trivial_const(def_id) {
{
::core::panicking::panic_fmt(format_args!("Tried to get mir_for_ctfe of a trivial const"));
}
};
};debug_assert!(!tcx.is_trivial_const(def_id), "Tried to get mir_for_ctfe of a trivial const");
493 tcx.arena.alloc(inner_mir_for_ctfe(tcx, def_id))
494}
495
496fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> {
497 if tcx.is_constructor(def.to_def_id()) {
498 return shim::build_adt_ctor(tcx, def.to_def_id());
503 }
504
505 let body = tcx.mir_drops_elaborated_and_const_checked(def);
506 let (body, always) = match tcx.hir_body_const_context(def) {
507 Some(hir::ConstContext::Const { .. } | hir::ConstContext::Static(_)) => {
510 (body.steal(), true)
511 }
512 Some(hir::ConstContext::ConstFn) => (body.borrow().clone(), false),
513 None => ::rustc_middle::util::bug::bug_fmt(format_args!("`mir_for_ctfe` called on non-const {0:?}",
def))bug!("`mir_for_ctfe` called on non-const {def:?}"),
514 };
515
516 let mut body = remap_mir_for_const_eval_select(tcx, body, hir::Constness::Const { always });
517 let passes: &[&dyn MirPass<'_>] = if #[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(def) {
DefKind::Fn | DefKind::AssocFn => true,
_ => false,
}matches!(tcx.def_kind(def), DefKind::Fn | DefKind::AssocFn)
519 && #[allow(non_exhaustive_omitted_patterns)] match tcx.constness(def) {
hir::Constness::Const { always: true } => true,
_ => false,
}matches!(tcx.constness(def), hir::Constness::Const { always: true })
520 {
521 &[&ctfe_limit::CtfeLimit, &mentioned_items::MentionedItems]
525 } else {
526 &[&ctfe_limit::CtfeLimit]
527 };
528 pm::run_passes(tcx, &mut body, passes, None);
529
530 body
531}
532
533fn mir_drops_elaborated_and_const_checked(tcx: TyCtxt<'_>, def: LocalDefId) -> &Steal<Body<'_>> {
537 if tcx.is_coroutine(def.to_def_id()) {
538 tcx.ensure_done().mir_coroutine_witnesses(def);
539 }
540
541 let tainted_by_errors = if !tcx.is_synthetic_mir(def) {
543 tcx.mir_borrowck(tcx.typeck_root_def_id_local(def)).err()
544 } else {
545 None
546 };
547
548 let is_fn_like = tcx.def_kind(def).is_fn_like();
549 if is_fn_like {
550 if pm::should_run_pass(&inline::Inline, &pm::PassCtx::for_body(tcx, def.to_def_id()))
552 || inline::ForceInline::should_run_pass_for_callee(tcx, def.to_def_id())
553 {
554 tcx.ensure_done().mir_inliner_callees(ty::InstanceKind::Item(def.to_def_id()));
555 }
556 }
557
558 tcx.ensure_done().check_liveness(def);
559
560 let (body, _) = tcx.mir_promoted(def);
561 let mut body = body.steal();
562
563 if let Some(error_reported) = tainted_by_errors {
564 body.tainted_by_errors = Some(error_reported);
565 }
566
567 let root = tcx.typeck_root_def_id_local(def);
568 if let Err(e) = tcx.check_transmutes(root) {
569 body.tainted_by_errors = Some(e);
570 }
571
572 match tcx.def_kind(root) {
577 DefKind::Fn
578 | DefKind::AssocFn
579 | DefKind::Static { .. }
580 | DefKind::Const { .. }
581 | DefKind::AssocConst { .. } => {
582 if let Err(guar) = tcx.ensure_result().check_well_formed(root) {
583 body.tainted_by_errors = Some(guar);
584 }
585 }
586 _ => {}
587 }
588
589 run_analysis_to_runtime_passes(tcx, &mut body);
590
591 tcx.alloc_steal_mir(body)
592}
593
594pub fn run_analysis_to_runtime_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
597 if !(body.phase == MirPhase::Analysis(AnalysisPhase::Initial)) {
::core::panicking::panic("assertion failed: body.phase == MirPhase::Analysis(AnalysisPhase::Initial)")
};assert!(body.phase == MirPhase::Analysis(AnalysisPhase::Initial));
598 let did = body.source.def_id();
599
600 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/lib.rs:600",
"rustc_mir_transform", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(600u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("analysis_mir_cleanup({0:?})",
did) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("analysis_mir_cleanup({:?})", did);
601 run_analysis_cleanup_passes(tcx, body);
602 if !(body.phase == MirPhase::Analysis(AnalysisPhase::PostCleanup)) {
::core::panicking::panic("assertion failed: body.phase == MirPhase::Analysis(AnalysisPhase::PostCleanup)")
};assert!(body.phase == MirPhase::Analysis(AnalysisPhase::PostCleanup));
603
604 if check_consts::post_drop_elaboration::checking_enabled(&ConstCx::new(tcx, body)) {
606 pm::run_passes(
607 tcx,
608 body,
609 &[
610 &remove_uninit_drops::RemoveUninitDrops,
611 &simplify::SimplifyCfg::RemoveFalseEdges,
612 &Lint(post_drop_elaboration::CheckLiveDrops),
613 ],
614 None,
615 );
616 }
617
618 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/lib.rs:618",
"rustc_mir_transform", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(618u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("runtime_mir_lowering({0:?})",
did) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("runtime_mir_lowering({:?})", did);
619 run_runtime_lowering_passes(tcx, body);
620 if !(body.phase == MirPhase::Runtime(RuntimePhase::Initial)) {
::core::panicking::panic("assertion failed: body.phase == MirPhase::Runtime(RuntimePhase::Initial)")
};assert!(body.phase == MirPhase::Runtime(RuntimePhase::Initial));
621
622 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/lib.rs:622",
"rustc_mir_transform", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(622u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("runtime_mir_cleanup({0:?})",
did) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("runtime_mir_cleanup({:?})", did);
623 run_runtime_cleanup_passes(tcx, body);
624 if !(body.phase == MirPhase::Runtime(RuntimePhase::PostCleanup)) {
::core::panicking::panic("assertion failed: body.phase == MirPhase::Runtime(RuntimePhase::PostCleanup)")
};assert!(body.phase == MirPhase::Runtime(RuntimePhase::PostCleanup));
625}
626
627fn run_analysis_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
631 let passes: &[&dyn MirPass<'tcx>] = &[
632 &impossible_clauses::ImpossibleClauses,
633 &cleanup_post_borrowck::CleanupPostBorrowck,
634 &remove_noop_landing_pads::RemoveNoopLandingPads,
635 &simplify::SimplifyCfg::PostAnalysis,
636 &deref_separator::Derefer,
637 ];
638
639 pm::run_passes(tcx, body, passes, Some(MirPhase::Analysis(AnalysisPhase::PostCleanup)));
640}
641
642fn run_runtime_lowering_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
644 let passes: &[&dyn MirPass<'tcx>] = &[
645 &add_call_guards::CriticalCallEdges,
647 &post_analysis_normalize::PostAnalysisNormalize,
649 &add_subtyping_projections::Subtyper,
651 &elaborate_drops::ElaborateDrops,
652 &Lint(check_call_recursion::CheckDropRecursion),
654 &abort_unwinding_calls::AbortUnwindingCalls,
658 &add_moves_for_packed_drops::AddMovesForPackedDrops,
661 &erase_deref_temps::EraseDerefTemps,
662 &elaborate_box_derefs::ElaborateBoxDerefs,
663 &coroutine::StateTransform,
664 &Lint(known_panics_lint::KnownPanicsLint),
665 ];
666 pm::run_passes_no_validate(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::Initial)));
667}
668
669fn run_runtime_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
671 let passes: &[&dyn MirPass<'tcx>] = &[
672 &lower_intrinsics::LowerIntrinsics,
673 &remove_place_mention::RemovePlaceMention,
674 &simplify::SimplifyCfg::PreOptimizations,
675 ];
676
677 pm::run_passes(tcx, body, passes, Some(MirPhase::Runtime(RuntimePhase::PostCleanup)));
678
679 for decl in &mut body.local_decls {
682 decl.local_info = ClearCrossCrate::Clear;
683 }
684}
685
686pub(crate) fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
687 fn o1<T>(x: T) -> WithMinOptLevel<T> {
688 WithMinOptLevel(1, x)
689 }
690
691 pm::run_passes(
693 tcx,
694 body,
695 &[
696 &check_alignment::CheckAlignment,
698 &check_null::CheckNull,
699 &check_enums::CheckEnums,
700 &lower_slice_len::LowerSliceLenCalls,
705 &instsimplify::InstSimplify::BeforeInline,
708 &inline::ForceInline,
710 &inline::Inline,
712 &remove_storage_markers::RemoveStorageMarkers,
717 &remove_zsts::RemoveZsts,
719 &remove_unneeded_drops::RemoveUnneededDrops,
720 &unreachable_enum_branching::UnreachableEnumBranching,
723 &unreachable_prop::UnreachablePropagation,
724 &o1(simplify::SimplifyCfg::AfterUnreachableEnumBranching),
725 &multiple_return_terminators::MultipleReturnTerminators,
726 &instsimplify::InstSimplify::AfterSimplifyCfg,
730 &o1(simplify_branches::SimplifyConstCondition::AfterInstSimplify),
739 &ref_prop::ReferencePropagation,
740 &sroa::ScalarReplacementOfAggregates,
741 &simplify::SimplifyLocals::BeforeConstProp,
742 &dead_store_elimination::DeadStoreElimination::Initial,
743 &gvn::GVN,
744 &simplify::SimplifyLocals::AfterGVN,
745 &ssa_range_prop::SsaRangePropagation,
748 &match_branches::MatchBranchSimplification,
749 &dataflow_const_prop::DataflowConstProp,
750 &single_use_consts::SingleUseConsts,
751 &o1(simplify_branches::SimplifyConstCondition::AfterConstProp),
752 &jump_threading::JumpThreading,
753 &early_otherwise_branch::EarlyOtherwiseBranch,
754 &simplify_comparison_integral::SimplifyComparisonIntegral,
755 &o1(simplify_branches::SimplifyConstCondition::Final),
756 &o1(remove_noop_landing_pads::RemoveNoopLandingPads),
757 &o1(simplify::SimplifyCfg::Final),
758 &strip_debuginfo::StripDebugInfo,
760 ©_prop::CopyProp,
761 &dead_store_elimination::DeadStoreElimination::Final,
762 &dest_prop::DestinationPropagation,
763 &simplify::SimplifyLocals::Final,
764 &multiple_return_terminators::MultipleReturnTerminators,
765 &add_call_guards::CriticalCallEdges,
767 &prettify::ReorderBasicBlocks,
769 &prettify::ReorderLocals,
770 ],
771 Some(MirPhase::Runtime(RuntimePhase::Optimized)),
772 );
773}
774
775fn optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> &Body<'_> {
777 if tcx.is_constructor(did.to_def_id()) {
778 return tcx.mir_for_ctfe(did);
783 }
784
785 tcx.arena.alloc(inner_optimized_mir(tcx, did))
786}
787
788fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
789 match tcx.hir_body_const_context(did) {
790 Some(hir::ConstContext::ConstFn) => tcx.ensure_done().mir_for_ctfe(did),
794 None => {}
795 Some(other) => {
::core::panicking::panic_fmt(format_args!("do not use `optimized_mir` for constants: {0:?}",
other));
}panic!("do not use `optimized_mir` for constants: {other:?}"),
796 }
797 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/lib.rs:797",
"rustc_mir_transform", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_mir_transform/src/lib.rs"),
::tracing_core::__macro_support::Option::Some(797u32),
::tracing_core::__macro_support::Option::Some("rustc_mir_transform"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("about to call mir_drops_elaborated...")
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("about to call mir_drops_elaborated...");
798 let body = tcx.mir_drops_elaborated_and_const_checked(did).steal();
799 let mut body = remap_mir_for_const_eval_select(tcx, body, hir::Constness::NotConst);
800
801 if body.tainted_by_errors.is_some() {
802 return body;
803 }
804
805 mentioned_items::MentionedItems.run_pass(tcx, &mut body);
809
810 if let TerminatorKind::Unreachable = body.basic_blocks[START_BLOCK].terminator().kind
814 && body.basic_blocks[START_BLOCK].statements.is_empty()
815 {
816 return body;
817 }
818
819 run_optimization_passes(tcx, &mut body);
820
821 body
822}
823
824fn promoted_mir(tcx: TyCtxt<'_>, def: LocalDefId) -> &IndexVec<Promoted, Body<'_>> {
827 if tcx.is_constructor(def.to_def_id()) {
828 return tcx.arena.alloc(IndexVec::new());
829 }
830
831 if !tcx.is_synthetic_mir(def) {
832 tcx.ensure_done().mir_borrowck(tcx.typeck_root_def_id_local(def));
833 }
834 let mut promoted = tcx.mir_promoted(def).1.steal();
835
836 for body in &mut promoted {
837 run_analysis_to_runtime_passes(tcx, body);
838 }
839
840 tcx.arena.alloc(promoted)
841}