diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index fee24f0bae8ca..2f306809f1fd6 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -10,12 +10,11 @@ use crate::ty::codec::{TyDecoder, TyEncoder}; use crate::ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use crate::ty::print::{FmtPrinter, Printer}; use crate::ty::subst::{Subst, SubstsRef}; -use crate::ty::{ - self, AdtDef, CanonicalUserTypeAnnotations, List, Region, Ty, TyCtxt, UserTypeAnnotationIndex, -}; +use crate::ty::{self, List, Ty, TyCtxt}; +use crate::ty::{AdtDef, InstanceDef, Region, UserTypeAnnotationIndex}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, Namespace}; -use rustc_hir::def_id::DefId; +use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX}; use rustc_hir::{self, GeneratorKind}; use rustc_target::abi::VariantIdx; @@ -112,6 +111,38 @@ impl MirPhase { } } +/// Where a specific `mir::Body` comes from. +#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(HashStable, TyEncodable, TyDecodable, TypeFoldable)] +pub struct MirSource<'tcx> { + pub instance: InstanceDef<'tcx>, + + /// If `Some`, this is a promoted rvalue within the parent function. + pub promoted: Option, +} + +impl<'tcx> MirSource<'tcx> { + pub fn item(def_id: DefId) -> Self { + MirSource { + instance: InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)), + promoted: None, + } + } + + pub fn from_instance(instance: InstanceDef<'tcx>) -> Self { + MirSource { instance, promoted: None } + } + + pub fn with_opt_param(self) -> ty::WithOptConstParam { + self.instance.with_opt_param() + } + + #[inline] + pub fn def_id(&self) -> DefId { + self.instance.def_id() + } +} + /// The lowered representation of a single function. #[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable)] pub struct Body<'tcx> { @@ -126,6 +157,8 @@ pub struct Body<'tcx> { /// us to see the difference and forego optimization on the inlined promoted items. pub phase: MirPhase, + pub source: MirSource<'tcx>, + /// A list of source scopes; these are referenced by statements /// and used for debuginfo. Indexed by a `SourceScope`. pub source_scopes: IndexVec, @@ -151,7 +184,7 @@ pub struct Body<'tcx> { pub local_decls: LocalDecls<'tcx>, /// User type annotations. - pub user_type_annotations: CanonicalUserTypeAnnotations<'tcx>, + pub user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>, /// The number of arguments this function takes. /// @@ -209,10 +242,11 @@ pub struct Body<'tcx> { impl<'tcx> Body<'tcx> { pub fn new( + source: MirSource<'tcx>, basic_blocks: IndexVec>, source_scopes: IndexVec, local_decls: LocalDecls<'tcx>, - user_type_annotations: CanonicalUserTypeAnnotations<'tcx>, + user_type_annotations: ty::CanonicalUserTypeAnnotations<'tcx>, arg_count: usize, var_debug_info: Vec>, span: Span, @@ -228,6 +262,7 @@ impl<'tcx> Body<'tcx> { let mut body = Body { phase: MirPhase::Build, + source, basic_blocks, source_scopes, yield_ty: None, @@ -257,6 +292,7 @@ impl<'tcx> Body<'tcx> { pub fn new_cfg_only(basic_blocks: IndexVec>) -> Self { let mut body = Body { phase: MirPhase::Build, + source: MirSource::item(DefId::local(CRATE_DEF_INDEX)), basic_blocks, source_scopes: IndexVec::new(), yield_ty: None, diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index a6b62097d5b18..9bb1c0ed7ded5 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -22,7 +22,8 @@ pub struct Instance<'tcx> { pub substs: SubstsRef<'tcx>, } -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, TyEncodable, TyDecodable, HashStable)] +#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(TyEncodable, TyDecodable, HashStable, TypeFoldable)] pub enum InstanceDef<'tcx> { /// A user-defined callable item. /// diff --git a/compiler/rustc_mir/src/borrow_check/mod.rs b/compiler/rustc_mir/src/borrow_check/mod.rs index e4237482f47fa..37e2730025d11 100644 --- a/compiler/rustc_mir/src/borrow_check/mod.rs +++ b/compiler/rustc_mir/src/borrow_check/mod.rs @@ -17,7 +17,7 @@ use rustc_middle::mir::{AggregateKind, BasicBlock, BorrowCheckResult, BorrowKind use rustc_middle::mir::{Field, ProjectionElem, Promoted, Rvalue, Statement, StatementKind}; use rustc_middle::mir::{InlineAsmOperand, Terminator, TerminatorKind}; use rustc_middle::ty::query::Providers; -use rustc_middle::ty::{self, InstanceDef, ParamEnv, RegionVid, TyCtxt}; +use rustc_middle::ty::{self, ParamEnv, RegionVid, TyCtxt}; use rustc_session::lint::builtin::{MUTABLE_BORROW_RESERVATION_CONFLICT, UNUSED_MUT}; use rustc_span::{Span, Symbol, DUMMY_SP}; @@ -36,7 +36,6 @@ use crate::dataflow::indexes::{BorrowIndex, InitIndex, MoveOutIndex, MovePathInd use crate::dataflow::move_paths::{InitLocation, LookupResult, MoveData, MoveError}; use crate::dataflow::MoveDataParamEnv; use crate::dataflow::{Analysis, BorrowckFlowState as Flows, BorrowckResults}; -use crate::transform::MirSource; use self::diagnostics::{AccessKind, RegionName}; use self::location::LocationTable; @@ -236,13 +235,7 @@ fn do_mir_borrowck<'a, 'tcx>( // Dump MIR results into a file, if that is enabled. This let us // write unit-tests, as well as helping with debugging. - nll::dump_mir_results( - infcx, - MirSource { instance: InstanceDef::Item(def.to_global()), promoted: None }, - &body, - ®ioncx, - &opt_closure_req, - ); + nll::dump_mir_results(infcx, &body, ®ioncx, &opt_closure_req); // We also have a `#[rustc_regions]` annotation that causes us to dump // information. diff --git a/compiler/rustc_mir/src/borrow_check/nll.rs b/compiler/rustc_mir/src/borrow_check/nll.rs index 66a17cba6bb01..44125885f2a12 100644 --- a/compiler/rustc_mir/src/borrow_check/nll.rs +++ b/compiler/rustc_mir/src/borrow_check/nll.rs @@ -9,7 +9,7 @@ use rustc_middle::mir::{ BasicBlock, Body, ClosureOutlivesSubject, ClosureRegionRequirements, LocalKind, Location, Promoted, }; -use rustc_middle::ty::{self, InstanceDef, RegionKind, RegionVid}; +use rustc_middle::ty::{self, RegionKind, RegionVid}; use rustc_span::symbol::sym; use std::env; use std::fmt::Debug; @@ -24,7 +24,6 @@ use polonius_engine::{Algorithm, Output}; use crate::dataflow::impls::MaybeInitializedPlaces; use crate::dataflow::move_paths::{InitKind, InitLocation, MoveData}; use crate::dataflow::ResultsCursor; -use crate::transform::MirSource; use crate::util as mir_util; use crate::util::pretty; @@ -72,8 +71,7 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( // Replace all remaining regions with fresh inference variables. renumber::renumber_mir(infcx, body, promoted); - let source = MirSource { instance: InstanceDef::Item(def.to_global()), promoted: None }; - mir_util::dump_mir(infcx.tcx, None, "renumber", &0, source, body, |_, _| Ok(())); + mir_util::dump_mir(infcx.tcx, None, "renumber", &0, body, |_, _| Ok(())); universal_regions } @@ -315,16 +313,15 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( pub(super) fn dump_mir_results<'a, 'tcx>( infcx: &InferCtxt<'a, 'tcx>, - source: MirSource<'tcx>, body: &Body<'tcx>, regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option>, ) { - if !mir_util::dump_enabled(infcx.tcx, "nll", source.def_id()) { + if !mir_util::dump_enabled(infcx.tcx, "nll", body.source.def_id()) { return; } - mir_util::dump_mir(infcx.tcx, None, "nll", &0, source, body, |pass_where, out| { + mir_util::dump_mir(infcx.tcx, None, "nll", &0, body, |pass_where, out| { match pass_where { // Before the CFG, dump out the values for each region variable. PassWhere::BeforeCFG => { @@ -352,14 +349,14 @@ pub(super) fn dump_mir_results<'a, 'tcx>( // Also dump the inference graph constraints as a graphviz file. let _: io::Result<()> = try { let mut file = - pretty::create_dump_file(infcx.tcx, "regioncx.all.dot", None, "nll", &0, source)?; + pretty::create_dump_file(infcx.tcx, "regioncx.all.dot", None, "nll", &0, body.source)?; regioncx.dump_graphviz_raw_constraints(&mut file)?; }; // Also dump the inference graph constraints as a graphviz file. let _: io::Result<()> = try { let mut file = - pretty::create_dump_file(infcx.tcx, "regioncx.scc.dot", None, "nll", &0, source)?; + pretty::create_dump_file(infcx.tcx, "regioncx.scc.dot", None, "nll", &0, body.source)?; regioncx.dump_graphviz_scc_constraints(&mut file)?; }; } diff --git a/compiler/rustc_mir/src/shim.rs b/compiler/rustc_mir/src/shim.rs index 7e4d189f0b737..5431d22e70320 100644 --- a/compiler/rustc_mir/src/shim.rs +++ b/compiler/rustc_mir/src/shim.rs @@ -78,8 +78,6 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<' run_passes( tcx, &mut result, - instance, - None, MirPhase::Const, &[&[ &add_moves_for_packed_drops::AddMovesForPackedDrops, @@ -163,7 +161,9 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) block(&mut blocks, TerminatorKind::Goto { target: return_block }); block(&mut blocks, TerminatorKind::Return); - let mut body = new_body(blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span); + let source = MirSource::from_instance(ty::InstanceDef::DropGlue(def_id, ty)); + let mut body = + new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span); if let Some(..) = ty { // The first argument (index 0), but add 1 for the return value. @@ -202,12 +202,14 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) } fn new_body<'tcx>( + source: MirSource<'tcx>, basic_blocks: IndexVec>, local_decls: IndexVec>, arg_count: usize, span: Span, ) -> Body<'tcx> { Body::new( + source, basic_blocks, IndexVec::from_elem_n( SourceScopeData { span, parent_scope: None, local_data: ClearCrossCrate::Clear }, @@ -344,7 +346,11 @@ impl CloneShimBuilder<'tcx> { } fn into_mir(self) -> Body<'tcx> { - new_body(self.blocks, self.local_decls, self.sig.inputs().len(), self.span) + let source = MirSource::from_instance(ty::InstanceDef::CloneShim( + self.def_id, + self.sig.inputs_and_output[0], + )); + new_body(source, self.blocks, self.local_decls, self.sig.inputs().len(), self.span) } fn source_info(&self) -> SourceInfo { @@ -834,7 +840,8 @@ fn build_call_shim<'tcx>( block(&mut blocks, vec![], TerminatorKind::Resume, true); } - let mut body = new_body(blocks, local_decls, sig.inputs().len(), span); + let mut body = + new_body(MirSource::from_instance(instance), blocks, local_decls, sig.inputs().len(), span); if let Abi::RustCall = sig.abi { body.spread_arg = Some(Local::new(sig.inputs().len())); @@ -897,18 +904,16 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { is_cleanup: false, }; - let body = - new_body(IndexVec::from_elem_n(start_block, 1), local_decls, sig.inputs().len(), span); - - crate::util::dump_mir( - tcx, - None, - "mir_map", - &0, - crate::transform::MirSource::item(ctor_id), - &body, - |_, _| Ok(()), + let source = MirSource::item(ctor_id); + let body = new_body( + source, + IndexVec::from_elem_n(start_block, 1), + local_decls, + sig.inputs().len(), + span, ); + crate::util::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(())); + body } diff --git a/compiler/rustc_mir/src/transform/add_call_guards.rs b/compiler/rustc_mir/src/transform/add_call_guards.rs index 33859115359e0..1dddaeb89e684 100644 --- a/compiler/rustc_mir/src/transform/add_call_guards.rs +++ b/compiler/rustc_mir/src/transform/add_call_guards.rs @@ -1,4 +1,4 @@ -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -31,7 +31,7 @@ pub use self::AddCallGuards::*; */ impl<'tcx> MirPass<'tcx> for AddCallGuards { - fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { self.add_call_guards(body); } } diff --git a/compiler/rustc_mir/src/transform/add_moves_for_packed_drops.rs b/compiler/rustc_mir/src/transform/add_moves_for_packed_drops.rs index a02d0f655600d..977bc85310079 100644 --- a/compiler/rustc_mir/src/transform/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir/src/transform/add_moves_for_packed_drops.rs @@ -2,7 +2,7 @@ use rustc_hir::def_id::DefId; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use crate::util; use crate::util::patch::MirPatch; @@ -40,9 +40,9 @@ use crate::util::patch::MirPatch; pub struct AddMovesForPackedDrops; impl<'tcx> MirPass<'tcx> for AddMovesForPackedDrops { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { - debug!("add_moves_for_packed_drops({:?} @ {:?})", src, body.span); - add_moves_for_packed_drops(tcx, body, src.def_id()); + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + debug!("add_moves_for_packed_drops({:?} @ {:?})", body.source, body.span); + add_moves_for_packed_drops(tcx, body, body.source.def_id()); } } diff --git a/compiler/rustc_mir/src/transform/add_retag.rs b/compiler/rustc_mir/src/transform/add_retag.rs index 0c596ba71549f..eec704e6cb775 100644 --- a/compiler/rustc_mir/src/transform/add_retag.rs +++ b/compiler/rustc_mir/src/transform/add_retag.rs @@ -4,7 +4,7 @@ //! of MIR building, and only after this pass we think of the program has having the //! normal MIR semantics. -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::{self, Ty, TyCtxt}; @@ -58,13 +58,13 @@ fn may_be_reference(ty: Ty<'tcx>) -> bool { } impl<'tcx> MirPass<'tcx> for AddRetag { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { if !tcx.sess.opts.debugging_opts.mir_emit_retag { return; } // We need an `AllCallEdges` pass before we can do any work. - super::add_call_guards::AllCallEdges.run_pass(tcx, src, body); + super::add_call_guards::AllCallEdges.run_pass(tcx, body); let (span, arg_count) = (body.span, body.arg_count); let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); diff --git a/compiler/rustc_mir/src/transform/check_const_item_mutation.rs b/compiler/rustc_mir/src/transform/check_const_item_mutation.rs index b6d57b899ddab..4d4e9b989171a 100644 --- a/compiler/rustc_mir/src/transform/check_const_item_mutation.rs +++ b/compiler/rustc_mir/src/transform/check_const_item_mutation.rs @@ -6,12 +6,12 @@ use rustc_middle::ty::TyCtxt; use rustc_session::lint::builtin::CONST_ITEM_MUTATION; use rustc_span::def_id::DefId; -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; pub struct CheckConstItemMutation; impl<'tcx> MirPass<'tcx> for CheckConstItemMutation { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let mut checker = ConstMutationChecker { body, tcx, target_local: None }; checker.visit_body(&body); } diff --git a/compiler/rustc_mir/src/transform/check_packed_ref.rs b/compiler/rustc_mir/src/transform/check_packed_ref.rs index 043b2d0d1703e..ee88daa83e783 100644 --- a/compiler/rustc_mir/src/transform/check_packed_ref.rs +++ b/compiler/rustc_mir/src/transform/check_packed_ref.rs @@ -3,14 +3,14 @@ use rustc_middle::mir::*; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::lint::builtin::UNALIGNED_REFERENCES; -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use crate::util; pub struct CheckPackedRef; impl<'tcx> MirPass<'tcx> for CheckPackedRef { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { - let param_env = tcx.param_env(src.instance.def_id()); + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let param_env = tcx.param_env(body.source.def_id()); let source_info = SourceInfo::outermost(body.span); let mut checker = PackedRefChecker { body, tcx, param_env, source_info }; checker.visit_body(&body); diff --git a/compiler/rustc_mir/src/transform/cleanup_post_borrowck.rs b/compiler/rustc_mir/src/transform/cleanup_post_borrowck.rs index 3f3d247a8294f..8ff0fae768618 100644 --- a/compiler/rustc_mir/src/transform/cleanup_post_borrowck.rs +++ b/compiler/rustc_mir/src/transform/cleanup_post_borrowck.rs @@ -18,7 +18,7 @@ //! [`ForMatchGuard`]: rustc_middle::mir::FakeReadCause::ForMatchGuard //! [`Nop`]: rustc_middle::mir::StatementKind::Nop -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::{Body, BorrowKind, Location, Rvalue}; use rustc_middle::mir::{Statement, StatementKind}; @@ -31,7 +31,7 @@ pub struct DeleteNonCodegenStatements<'tcx> { } impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let mut delete = DeleteNonCodegenStatements { tcx }; delete.visit_body(body); body.user_type_annotations.raw.clear(); diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs index 0f04ead94dd33..14b310cda939e 100644 --- a/compiler/rustc_mir/src/transform/const_prop.rs +++ b/compiler/rustc_mir/src/transform/const_prop.rs @@ -32,7 +32,7 @@ use crate::interpret::{ InterpCx, LocalState, LocalValue, MemPlace, Memory, MemoryKind, OpTy, Operand as InterpOperand, PlaceTy, Pointer, ScalarMaybeUninit, StackPopCleanup, }; -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; /// The maximum number of bytes that we'll allocate space for a local or the return value. /// Needed for #66397, because otherwise we eval into large places and that can cause OOM or just @@ -60,30 +60,31 @@ macro_rules! throw_machine_stop_str { pub struct ConstProp; impl<'tcx> MirPass<'tcx> for ConstProp { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // will be evaluated by miri and produce its errors there - if source.promoted.is_some() { + if body.source.promoted.is_some() { return; } use rustc_middle::hir::map::blocks::FnLikeNode; - let hir_id = tcx.hir().local_def_id_to_hir_id(source.def_id().expect_local()); + let def_id = body.source.def_id().expect_local(); + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id); let is_fn_like = FnLikeNode::from_node(tcx.hir().get(hir_id)).is_some(); - let is_assoc_const = tcx.def_kind(source.def_id()) == DefKind::AssocConst; + let is_assoc_const = tcx.def_kind(def_id.to_def_id()) == DefKind::AssocConst; // Only run const prop on functions, methods, closures and associated constants if !is_fn_like && !is_assoc_const { // skip anon_const/statics/consts because they'll be evaluated by miri anyway - trace!("ConstProp skipped for {:?}", source.def_id()); + trace!("ConstProp skipped for {:?}", def_id); return; } - let is_generator = tcx.type_of(source.def_id()).is_generator(); + let is_generator = tcx.type_of(def_id.to_def_id()).is_generator(); // FIXME(welseywiser) const prop doesn't work on generators because of query cycles // computing their layout. if is_generator { - trace!("ConstProp skipped for generator {:?}", source.def_id()); + trace!("ConstProp skipped for generator {:?}", def_id); return; } @@ -114,7 +115,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp { // the normalization code (leading to cycle errors), since // it's usually never invoked in this way. let predicates = tcx - .predicates_of(source.def_id()) + .predicates_of(def_id.to_def_id()) .predicates .iter() .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); @@ -122,20 +123,21 @@ impl<'tcx> MirPass<'tcx> for ConstProp { tcx, traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(), ) { - trace!("ConstProp skipped for {:?}: found unsatisfiable predicates", source.def_id()); + trace!("ConstProp skipped for {:?}: found unsatisfiable predicates", def_id); return; } - trace!("ConstProp starting for {:?}", source.def_id()); + trace!("ConstProp starting for {:?}", def_id); let dummy_body = &Body::new( + body.source, body.basic_blocks().clone(), body.source_scopes.clone(), body.local_decls.clone(), Default::default(), body.arg_count, Default::default(), - tcx.def_span(source.def_id()), + tcx.def_span(def_id), body.generator_kind, ); @@ -143,10 +145,10 @@ impl<'tcx> MirPass<'tcx> for ConstProp { // constants, instead of just checking for const-folding succeeding. // That would require an uniform one-def no-mutation analysis // and RPO (or recursing when needing the value of a local). - let mut optimization_finder = ConstPropagator::new(body, dummy_body, tcx, source); + let mut optimization_finder = ConstPropagator::new(body, dummy_body, tcx); optimization_finder.visit_body(body); - trace!("ConstProp done for {:?}", source.def_id()); + trace!("ConstProp done for {:?}", def_id); } } @@ -346,9 +348,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { body: &Body<'tcx>, dummy_body: &'mir Body<'tcx>, tcx: TyCtxt<'tcx>, - source: MirSource<'tcx>, ) -> ConstPropagator<'mir, 'tcx> { - let def_id = source.def_id(); + let def_id = body.source.def_id(); let substs = &InternalSubsts::identity_for_item(tcx, def_id); let param_env = tcx.param_env_reveal_all_normalized(def_id); diff --git a/compiler/rustc_mir/src/transform/copy_prop.rs b/compiler/rustc_mir/src/transform/copy_prop.rs index 74194467b38c5..4f44bb7b20476 100644 --- a/compiler/rustc_mir/src/transform/copy_prop.rs +++ b/compiler/rustc_mir/src/transform/copy_prop.rs @@ -19,7 +19,7 @@ //! (non-mutating) use of `SRC`. These restrictions are conservative and may be relaxed in the //! future. -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use crate::util::def_use::DefUseAnalysis; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::{ @@ -30,7 +30,7 @@ use rustc_middle::ty::TyCtxt; pub struct CopyPropagation; impl<'tcx> MirPass<'tcx> for CopyPropagation { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let opts = &tcx.sess.opts.debugging_opts; // We only run when the MIR optimization level is > 1. // This avoids a slow pass, and messing up debug info. diff --git a/compiler/rustc_mir/src/transform/deaggregator.rs b/compiler/rustc_mir/src/transform/deaggregator.rs index 66989a902447d..5bd7256c666c6 100644 --- a/compiler/rustc_mir/src/transform/deaggregator.rs +++ b/compiler/rustc_mir/src/transform/deaggregator.rs @@ -1,4 +1,4 @@ -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use crate::util::expand_aggregate; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -6,7 +6,7 @@ use rustc_middle::ty::TyCtxt; pub struct Deaggregator; impl<'tcx> MirPass<'tcx> for Deaggregator { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut(); let local_decls = &*local_decls; for bb in basic_blocks { diff --git a/compiler/rustc_mir/src/transform/dest_prop.rs b/compiler/rustc_mir/src/transform/dest_prop.rs index 97d261760772b..0982bcfb0ca5b 100644 --- a/compiler/rustc_mir/src/transform/dest_prop.rs +++ b/compiler/rustc_mir/src/transform/dest_prop.rs @@ -99,7 +99,7 @@ use crate::dataflow::impls::{MaybeInitializedLocals, MaybeLiveLocals}; use crate::dataflow::Analysis; use crate::{ - transform::{MirPass, MirSource}, + transform::MirPass, util::{dump_mir, PassWhere}, }; use itertools::Itertools; @@ -126,16 +126,18 @@ const MAX_BLOCKS: usize = 250; pub struct DestinationPropagation; impl<'tcx> MirPass<'tcx> for DestinationPropagation { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // Only run at mir-opt-level=2 or higher for now (we don't fix up debuginfo and remove // storage statements at the moment). if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 { return; } + let def_id = body.source.def_id(); + let candidates = find_candidates(tcx, body); if candidates.is_empty() { - debug!("{:?}: no dest prop candidates, done", source.def_id()); + debug!("{:?}: no dest prop candidates, done", def_id); return; } @@ -152,7 +154,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { let relevant = relevant_locals.count(); debug!( "{:?}: {} locals ({} relevant), {} blocks", - source.def_id(), + def_id, body.local_decls.len(), relevant, body.basic_blocks().len() @@ -160,23 +162,21 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { if relevant > MAX_LOCALS { warn!( "too many candidate locals in {:?} ({}, max is {}), not optimizing", - source.def_id(), - relevant, - MAX_LOCALS + def_id, relevant, MAX_LOCALS ); return; } if body.basic_blocks().len() > MAX_BLOCKS { warn!( "too many blocks in {:?} ({}, max is {}), not optimizing", - source.def_id(), + def_id, body.basic_blocks().len(), MAX_BLOCKS ); return; } - let mut conflicts = Conflicts::build(tcx, body, source, &relevant_locals); + let mut conflicts = Conflicts::build(tcx, body, &relevant_locals); let mut replacements = Replacements::new(body.local_decls.len()); for candidate @ CandidateAssignment { dest, src, loc } in candidates { @@ -192,7 +192,7 @@ impl<'tcx> MirPass<'tcx> for DestinationPropagation { } if !tcx.consider_optimizing(|| { - format!("DestinationPropagation {:?} {:?}", source.def_id(), candidate) + format!("DestinationPropagation {:?} {:?}", def_id, candidate) }) { break; } @@ -398,7 +398,6 @@ impl Conflicts<'a> { fn build<'tcx>( tcx: TyCtxt<'tcx>, body: &'_ Body<'tcx>, - source: MirSource<'tcx>, relevant_locals: &'a BitSet, ) -> Self { // We don't have to look out for locals that have their address taken, since @@ -409,7 +408,7 @@ impl Conflicts<'a> { body.local_decls.len(), ); - let def_id = source.def_id(); + let def_id = body.source.def_id(); let mut init = MaybeInitializedLocals .into_engine(tcx, body, def_id) .iterate_to_fixpoint() @@ -420,58 +419,49 @@ impl Conflicts<'a> { .into_results_cursor(body); let mut reachable = None; - dump_mir( - tcx, - None, - "DestinationPropagation-dataflow", - &"", - source, - body, - |pass_where, w| { - let reachable = - reachable.get_or_insert_with(|| traversal::reachable_as_bitset(body)); - - match pass_where { - PassWhere::BeforeLocation(loc) if reachable.contains(loc.block) => { - init.seek_before_primary_effect(loc); - live.seek_after_primary_effect(loc); - - writeln!(w, " // init: {:?}", init.get())?; - writeln!(w, " // live: {:?}", live.get())?; - } - PassWhere::AfterTerminator(bb) if reachable.contains(bb) => { - let loc = body.terminator_loc(bb); - init.seek_after_primary_effect(loc); - live.seek_before_primary_effect(loc); + dump_mir(tcx, None, "DestinationPropagation-dataflow", &"", body, |pass_where, w| { + let reachable = reachable.get_or_insert_with(|| traversal::reachable_as_bitset(body)); - writeln!(w, " // init: {:?}", init.get())?; - writeln!(w, " // live: {:?}", live.get())?; - } + match pass_where { + PassWhere::BeforeLocation(loc) if reachable.contains(loc.block) => { + init.seek_before_primary_effect(loc); + live.seek_after_primary_effect(loc); - PassWhere::BeforeBlock(bb) if reachable.contains(bb) => { - init.seek_to_block_start(bb); - live.seek_to_block_start(bb); + writeln!(w, " // init: {:?}", init.get())?; + writeln!(w, " // live: {:?}", live.get())?; + } + PassWhere::AfterTerminator(bb) if reachable.contains(bb) => { + let loc = body.terminator_loc(bb); + init.seek_after_primary_effect(loc); + live.seek_before_primary_effect(loc); - writeln!(w, " // init: {:?}", init.get())?; - writeln!(w, " // live: {:?}", live.get())?; - } + writeln!(w, " // init: {:?}", init.get())?; + writeln!(w, " // live: {:?}", live.get())?; + } - PassWhere::BeforeCFG | PassWhere::AfterCFG | PassWhere::AfterLocation(_) => {} + PassWhere::BeforeBlock(bb) if reachable.contains(bb) => { + init.seek_to_block_start(bb); + live.seek_to_block_start(bb); - PassWhere::BeforeLocation(_) | PassWhere::AfterTerminator(_) => { - writeln!(w, " // init: ")?; - writeln!(w, " // live: ")?; - } + writeln!(w, " // init: {:?}", init.get())?; + writeln!(w, " // live: {:?}", live.get())?; + } - PassWhere::BeforeBlock(_) => { - writeln!(w, " // init: ")?; - writeln!(w, " // live: ")?; - } + PassWhere::BeforeCFG | PassWhere::AfterCFG | PassWhere::AfterLocation(_) => {} + + PassWhere::BeforeLocation(_) | PassWhere::AfterTerminator(_) => { + writeln!(w, " // init: ")?; + writeln!(w, " // live: ")?; } - Ok(()) - }, - ); + PassWhere::BeforeBlock(_) => { + writeln!(w, " // init: ")?; + writeln!(w, " // live: ")?; + } + } + + Ok(()) + }); let mut this = Self { relevant_locals, diff --git a/compiler/rustc_mir/src/transform/dump_mir.rs b/compiler/rustc_mir/src/transform/dump_mir.rs index 5ce6f4fa7414e..5b6edf17d06ab 100644 --- a/compiler/rustc_mir/src/transform/dump_mir.rs +++ b/compiler/rustc_mir/src/transform/dump_mir.rs @@ -5,7 +5,7 @@ use std::fmt; use std::fs::File; use std::io; -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use crate::util as mir_util; use rustc_middle::mir::Body; use rustc_middle::ty::TyCtxt; @@ -18,7 +18,7 @@ impl<'tcx> MirPass<'tcx> for Marker { Cow::Borrowed(self.0) } - fn run_pass(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body: &mut Body<'tcx>) {} + fn run_pass(&self, _tcx: TyCtxt<'tcx>, _body: &mut Body<'tcx>) {} } pub struct Disambiguator { @@ -36,17 +36,15 @@ pub fn on_mir_pass<'tcx>( tcx: TyCtxt<'tcx>, pass_num: &dyn fmt::Display, pass_name: &str, - source: MirSource<'tcx>, body: &Body<'tcx>, is_after: bool, ) { - if mir_util::dump_enabled(tcx, pass_name, source.def_id()) { + if mir_util::dump_enabled(tcx, pass_name, body.source.def_id()) { mir_util::dump_mir( tcx, Some(pass_num), pass_name, &Disambiguator { is_after }, - source, body, |_, _| Ok(()), ); diff --git a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs index 7a9089d0f3675..a45b0e86fffc2 100644 --- a/compiler/rustc_mir/src/transform/early_otherwise_branch.rs +++ b/compiler/rustc_mir/src/transform/early_otherwise_branch.rs @@ -1,7 +1,4 @@ -use crate::{ - transform::{MirPass, MirSource}, - util::patch::MirPatch, -}; +use crate::{transform::MirPass, util::patch::MirPatch}; use rustc_middle::mir::*; use rustc_middle::ty::{Ty, TyCtxt}; use std::{borrow::Cow, fmt::Debug}; @@ -28,11 +25,11 @@ use super::simplify::simplify_cfg; pub struct EarlyOtherwiseBranch; impl<'tcx> MirPass<'tcx> for EarlyOtherwiseBranch { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { if tcx.sess.opts.debugging_opts.mir_opt_level < 1 { return; } - trace!("running EarlyOtherwiseBranch on {:?}", source); + trace!("running EarlyOtherwiseBranch on {:?}", body.source); // we are only interested in this bb if the terminator is a switchInt let bbs_with_switch = body.basic_blocks().iter_enumerated().filter(|(_, bb)| is_switch(bb.terminator())); diff --git a/compiler/rustc_mir/src/transform/elaborate_drops.rs b/compiler/rustc_mir/src/transform/elaborate_drops.rs index a8b2ee5705f1f..f59050f58385c 100644 --- a/compiler/rustc_mir/src/transform/elaborate_drops.rs +++ b/compiler/rustc_mir/src/transform/elaborate_drops.rs @@ -5,7 +5,7 @@ use crate::dataflow::on_lookup_result_bits; use crate::dataflow::MoveDataParamEnv; use crate::dataflow::{on_all_children_bits, on_all_drop_children_bits}; use crate::dataflow::{Analysis, ResultsCursor}; -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use crate::util::elaborate_drops::{elaborate_drop, DropFlagState, Unwind}; use crate::util::elaborate_drops::{DropElaborator, DropFlagMode, DropStyle}; use crate::util::patch::MirPatch; @@ -21,11 +21,11 @@ use std::fmt; pub struct ElaborateDrops; impl<'tcx> MirPass<'tcx> for ElaborateDrops { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { - debug!("elaborate_drops({:?} @ {:?})", src, body.span); + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + debug!("elaborate_drops({:?} @ {:?})", body.source, body.span); - let def_id = src.def_id(); - let param_env = tcx.param_env_reveal_all_normalized(src.def_id()); + let def_id = body.source.def_id(); + let param_env = tcx.param_env_reveal_all_normalized(def_id); let move_data = match MoveData::gather_moves(body, tcx, param_env) { Ok(move_data) => move_data, Err((move_data, _)) => { diff --git a/compiler/rustc_mir/src/transform/generator.rs b/compiler/rustc_mir/src/transform/generator.rs index 1fffcf8151537..7c3a0502decf5 100644 --- a/compiler/rustc_mir/src/transform/generator.rs +++ b/compiler/rustc_mir/src/transform/generator.rs @@ -55,7 +55,7 @@ use crate::dataflow::impls::{ use crate::dataflow::{self, Analysis}; use crate::transform::no_landing_pads::no_landing_pads; use crate::transform::simplify; -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use crate::util::dump_mir; use crate::util::expand_aggregate; use crate::util::storage; @@ -451,11 +451,10 @@ struct LivenessInfo { fn locals_live_across_suspend_points( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, - source: MirSource<'tcx>, always_live_locals: &storage::AlwaysLiveLocals, movable: bool, ) -> LivenessInfo { - let def_id = source.def_id(); + let def_id = body.source.def_id(); let body_ref: &Body<'_> = &body; // Calculate when MIR locals have live storage. This gives us an upper bound of their @@ -915,7 +914,6 @@ fn elaborate_generator_drops<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, body: &mut fn create_generator_drop_shim<'tcx>( tcx: TyCtxt<'tcx>, transform: &TransformVisitor<'tcx>, - source: MirSource<'tcx>, gen_ty: Ty<'tcx>, body: &mut Body<'tcx>, drop_clean: BasicBlock, @@ -968,7 +966,7 @@ fn create_generator_drop_shim<'tcx>( // unrelated code from the resume part of the function simplify::remove_dead_blocks(&mut body); - dump_mir(tcx, None, "generator_drop", &0, source, &body, |_, _| Ok(())); + dump_mir(tcx, None, "generator_drop", &0, &body, |_, _| Ok(())); body } @@ -1070,7 +1068,6 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool { fn create_generator_resume_function<'tcx>( tcx: TyCtxt<'tcx>, transform: TransformVisitor<'tcx>, - source: MirSource<'tcx>, body: &mut Body<'tcx>, can_return: bool, ) { @@ -1142,7 +1139,7 @@ fn create_generator_resume_function<'tcx>( // unrelated code from the drop part of the function simplify::remove_dead_blocks(body); - dump_mir(tcx, None, "generator_resume", &0, source, body, |_, _| Ok(())); + dump_mir(tcx, None, "generator_resume", &0, body, |_, _| Ok(())); } fn insert_clean_drop(body: &mut Body<'_>) -> BasicBlock { @@ -1239,7 +1236,7 @@ fn create_cases<'tcx>( } impl<'tcx> MirPass<'tcx> for StateTransform { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let yield_ty = if let Some(yield_ty) = body.yield_ty { yield_ty } else { @@ -1249,7 +1246,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { assert!(body.generator_drop.is_none()); - let def_id = source.def_id(); + let def_id = body.source.def_id(); // The first argument is the generator type passed by value let gen_ty = body.local_decls.raw[1].ty; @@ -1307,7 +1304,7 @@ impl<'tcx> MirPass<'tcx> for StateTransform { let always_live_locals = storage::AlwaysLiveLocals::new(&body); let liveness_info = - locals_live_across_suspend_points(tcx, body, source, &always_live_locals, movable); + locals_live_across_suspend_points(tcx, body, &always_live_locals, movable); sanitize_witness(tcx, body, def_id, interior, &upvars, &liveness_info.saved_locals); @@ -1356,23 +1353,22 @@ impl<'tcx> MirPass<'tcx> for StateTransform { // This is expanded to a drop ladder in `elaborate_generator_drops`. let drop_clean = insert_clean_drop(body); - dump_mir(tcx, None, "generator_pre-elab", &0, source, body, |_, _| Ok(())); + dump_mir(tcx, None, "generator_pre-elab", &0, body, |_, _| Ok(())); // Expand `drop(generator_struct)` to a drop ladder which destroys upvars. // If any upvars are moved out of, drop elaboration will handle upvar destruction. // However we need to also elaborate the code generated by `insert_clean_drop`. elaborate_generator_drops(tcx, def_id, body); - dump_mir(tcx, None, "generator_post-transform", &0, source, body, |_, _| Ok(())); + dump_mir(tcx, None, "generator_post-transform", &0, body, |_, _| Ok(())); // Create a copy of our MIR and use it to create the drop shim for the generator - let drop_shim = - create_generator_drop_shim(tcx, &transform, source, gen_ty, body, drop_clean); + let drop_shim = create_generator_drop_shim(tcx, &transform, gen_ty, body, drop_clean); body.generator_drop = Some(box drop_shim); // Create the Generator::resume function - create_generator_resume_function(tcx, transform, source, body, can_return); + create_generator_resume_function(tcx, transform, body, can_return); } } diff --git a/compiler/rustc_mir/src/transform/inline.rs b/compiler/rustc_mir/src/transform/inline.rs index 4e7cacc2f4af7..ced8a2289d577 100644 --- a/compiler/rustc_mir/src/transform/inline.rs +++ b/compiler/rustc_mir/src/transform/inline.rs @@ -12,7 +12,7 @@ use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyC use rustc_target::spec::abi::Abi; use super::simplify::{remove_dead_blocks, CfgSimplifier}; -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use std::collections::VecDeque; use std::iter; @@ -37,7 +37,7 @@ struct CallSite<'tcx> { } impl<'tcx> MirPass<'tcx> for Inline { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 { if tcx.sess.opts.debugging_opts.instrument_coverage { // The current implementation of source code coverage injects code region counters @@ -45,7 +45,7 @@ impl<'tcx> MirPass<'tcx> for Inline { // based function. debug!("function inlining is disabled when compiling with `instrument_coverage`"); } else { - Inliner { tcx, source, codegen_fn_attrs: tcx.codegen_fn_attrs(source.def_id()) } + Inliner { tcx, codegen_fn_attrs: tcx.codegen_fn_attrs(body.source.def_id()) } .run_pass(body); } } @@ -54,7 +54,6 @@ impl<'tcx> MirPass<'tcx> for Inline { struct Inliner<'tcx> { tcx: TyCtxt<'tcx>, - source: MirSource<'tcx>, codegen_fn_attrs: &'tcx CodegenFnAttrs, } @@ -74,11 +73,15 @@ impl Inliner<'tcx> { let mut callsites = VecDeque::new(); - let param_env = self.tcx.param_env_reveal_all_normalized(self.source.def_id()); + let def_id = caller_body.source.def_id(); + + let param_env = self.tcx.param_env_reveal_all_normalized(def_id); // Only do inlining into fn bodies. - let id = self.tcx.hir().local_def_id_to_hir_id(self.source.def_id().expect_local()); - if self.tcx.hir().body_owner_kind(id).is_fn_or_closure() && self.source.promoted.is_none() { + let self_hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + if self.tcx.hir().body_owner_kind(self_hir_id).is_fn_or_closure() + && caller_body.source.promoted.is_none() + { for (bb, bb_data) in caller_body.basic_blocks().iter_enumerated() { if let Some(callsite) = self.get_valid_function_call(bb, bb_data, caller_body, param_env) @@ -104,8 +107,6 @@ impl Inliner<'tcx> { let callee_body = if let Some(callee_def_id) = callsite.callee.as_local() { let callee_hir_id = self.tcx.hir().local_def_id_to_hir_id(callee_def_id); - let self_hir_id = - self.tcx.hir().local_def_id_to_hir_id(self.source.def_id().expect_local()); // Avoid a cycle here by only using `optimized_mir` only if we have // a lower `HirId` than the callee. This ensures that the callee will // not inline us. This trick only works without incremental compilation. @@ -178,7 +179,7 @@ impl Inliner<'tcx> { // Simplify if we inlined anything. if changed { - debug!("running simplify cfg on {:?}", self.source); + debug!("running simplify cfg on {:?}", caller_body.source); CfgSimplifier::new(caller_body).simplify(); remove_dead_blocks(caller_body); } @@ -300,7 +301,7 @@ impl Inliner<'tcx> { // FIXME: Give a bonus to functions with only a single caller - let param_env = tcx.param_env(self.source.def_id()); + let param_env = tcx.param_env(callee_body.source.def_id()); let mut first_block = true; let mut cost = 0; @@ -430,7 +431,7 @@ impl Inliner<'tcx> { match terminator.kind { // FIXME: Handle inlining of diverging calls TerminatorKind::Call { args, destination: Some(destination), cleanup, .. } => { - debug!("inlined {:?} into {:?}", callsite.callee, self.source); + debug!("inlined {:?} into {:?}", callsite.callee, caller_body.source); let mut local_map = IndexVec::with_capacity(callee_body.local_decls.len()); let mut scope_map = IndexVec::with_capacity(callee_body.source_scopes.len()); diff --git a/compiler/rustc_mir/src/transform/instcombine.rs b/compiler/rustc_mir/src/transform/instcombine.rs index 3ed0aea1404d4..1a8e281d417df 100644 --- a/compiler/rustc_mir/src/transform/instcombine.rs +++ b/compiler/rustc_mir/src/transform/instcombine.rs @@ -1,6 +1,6 @@ //! Performs various peephole optimizations. -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::Mutability; use rustc_index::vec::Idx; @@ -19,7 +19,7 @@ use std::mem; pub struct InstCombine; impl<'tcx> MirPass<'tcx> for InstCombine { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // First, find optimization opportunities. This is done in a pre-pass to keep the MIR // read-only so that we can do global analyses on the MIR in the process (e.g. // `Place::ty()`). diff --git a/compiler/rustc_mir/src/transform/instrument_coverage.rs b/compiler/rustc_mir/src/transform/instrument_coverage.rs index a5b30a25a9bdf..388fb90651c5f 100644 --- a/compiler/rustc_mir/src/transform/instrument_coverage.rs +++ b/compiler/rustc_mir/src/transform/instrument_coverage.rs @@ -1,4 +1,4 @@ -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use crate::util::pretty; use crate::util::spanview::{ source_range_no_file, statement_kind_name, terminator_kind_name, write_spanview_document, @@ -74,16 +74,11 @@ fn coverageinfo_from_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> CoverageInfo } impl<'tcx> MirPass<'tcx> for InstrumentCoverage { - fn run_pass( - &self, - tcx: TyCtxt<'tcx>, - mir_source: MirSource<'tcx>, - mir_body: &mut mir::Body<'tcx>, - ) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, mir_body: &mut mir::Body<'tcx>) { // If the InstrumentCoverage pass is called on promoted MIRs, skip them. // See: https://github.com/rust-lang/rust/pull/73011#discussion_r438317601 - if mir_source.promoted.is_none() { - Instrumentor::new(&self.name(), tcx, mir_source, mir_body).inject_counters(); + if mir_body.source.promoted.is_none() { + Instrumentor::new(&self.name(), tcx, mir_body).inject_counters(); } } } @@ -97,7 +92,6 @@ struct CoverageRegion { struct Instrumentor<'a, 'tcx> { pass_name: &'a str, tcx: TyCtxt<'tcx>, - mir_source: MirSource<'tcx>, mir_body: &'a mut mir::Body<'tcx>, hir_body: &'tcx rustc_hir::Body<'tcx>, function_source_hash: Option, @@ -106,17 +100,11 @@ struct Instrumentor<'a, 'tcx> { } impl<'a, 'tcx> Instrumentor<'a, 'tcx> { - fn new( - pass_name: &'a str, - tcx: TyCtxt<'tcx>, - mir_source: MirSource<'tcx>, - mir_body: &'a mut mir::Body<'tcx>, - ) -> Self { - let hir_body = hir_body(tcx, mir_source.def_id()); + fn new(pass_name: &'a str, tcx: TyCtxt<'tcx>, mir_body: &'a mut mir::Body<'tcx>) -> Self { + let hir_body = hir_body(tcx, mir_body.source.def_id()); Self { pass_name, tcx, - mir_source, mir_body, hir_body, function_source_hash: None, @@ -156,7 +144,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { fn inject_counters(&mut self) { let tcx = self.tcx; - let def_id = self.mir_source.def_id(); + let def_id = self.mir_body.source.def_id(); let mir_body = &self.mir_body; let body_span = self.hir_body.value.span; debug!( @@ -239,9 +227,15 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> { } if let Some(span_viewables) = span_viewables { - let mut file = - pretty::create_dump_file(tcx, "html", None, self.pass_name, &0, self.mir_source) - .expect("Unexpected error creating MIR spanview HTML file"); + let mut file = pretty::create_dump_file( + tcx, + "html", + None, + self.pass_name, + &0, + self.mir_body.source, + ) + .expect("Unexpected error creating MIR spanview HTML file"); write_spanview_document(tcx, def_id, span_viewables, &mut file) .expect("Unexpected IO error dumping coverage spans as HTML"); } diff --git a/compiler/rustc_mir/src/transform/match_branches.rs b/compiler/rustc_mir/src/transform/match_branches.rs index c1d574d6ef290..dad3812c5cd74 100644 --- a/compiler/rustc_mir/src/transform/match_branches.rs +++ b/compiler/rustc_mir/src/transform/match_branches.rs @@ -1,4 +1,4 @@ -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -37,8 +37,8 @@ pub struct MatchBranchSimplification; /// ``` impl<'tcx> MirPass<'tcx> for MatchBranchSimplification { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { - let param_env = tcx.param_env(src.def_id()); + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let param_env = tcx.param_env(body.source.def_id()); let bbs = body.basic_blocks_mut(); 'outer: for bb_idx in bbs.indices() { let (discr, val, switch_ty, first, second) = match bbs[bb_idx].terminator().kind { diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index 67193814a40cb..d8bc00c5f3f92 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -9,7 +9,7 @@ use rustc_middle::mir::visit::Visitor as _; use rustc_middle::mir::{traversal, Body, ConstQualifs, MirPhase, Promoted}; use rustc_middle::ty::query::Providers; use rustc_middle::ty::steal::Steal; -use rustc_middle::ty::{self, InstanceDef, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{self, TyCtxt, TypeFoldable}; use rustc_span::{Span, Symbol}; use std::borrow::Cow; @@ -49,6 +49,8 @@ pub mod uninhabited_enum_branching; pub mod unreachable_prop; pub mod validate; +pub use rustc_middle::mir::MirSource; + pub(crate) fn provide(providers: &mut Providers) { self::check_unsafety::provide(providers); *providers = Providers { @@ -132,33 +134,6 @@ fn mir_keys(tcx: TyCtxt<'_>, krate: CrateNum) -> FxHashSet { set } -/// Where a specific `mir::Body` comes from. -#[derive(Debug, Copy, Clone)] -pub struct MirSource<'tcx> { - pub instance: InstanceDef<'tcx>, - - /// If `Some`, this is a promoted rvalue within the parent function. - pub promoted: Option, -} - -impl<'tcx> MirSource<'tcx> { - pub fn item(def_id: DefId) -> Self { - MirSource { - instance: InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)), - promoted: None, - } - } - - pub fn with_opt_param(self) -> ty::WithOptConstParam { - self.instance.with_opt_param() - } - - #[inline] - pub fn def_id(&self) -> DefId { - self.instance.def_id() - } -} - /// Generates a default name for the pass based on the name of the /// type `T`. pub fn default_name() -> Cow<'static, str> { @@ -174,19 +149,16 @@ pub trait MirPass<'tcx> { default_name::() } - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>); + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>); } pub fn run_passes( tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, - instance: InstanceDef<'tcx>, - promoted: Option, mir_phase: MirPhase, passes: &[&[&dyn MirPass<'tcx>]], ) { let phase_index = mir_phase.phase_index(); - let source = MirSource { instance, promoted }; let validate = tcx.sess.opts.debugging_opts.validate_mir; if body.phase >= mir_phase { @@ -195,7 +167,7 @@ pub fn run_passes( if validate { validate::Validator { when: format!("input to phase {:?}", mir_phase), mir_phase } - .run_pass(tcx, source, body); + .run_pass(tcx, body); } let mut index = 0; @@ -205,13 +177,12 @@ pub fn run_passes( tcx, &format_args!("{:03}-{:03}", phase_index, index), &pass.name(), - source, body, is_after, ); }; run_hooks(body, index, false); - pass.run_pass(tcx, source, body); + pass.run_pass(tcx, body); run_hooks(body, index, true); if validate { @@ -219,7 +190,7 @@ pub fn run_passes( when: format!("after {} in phase {:?}", pass.name(), mir_phase), mir_phase, } - .run_pass(tcx, source, body); + .run_pass(tcx, body); } index += 1; @@ -235,7 +206,7 @@ pub fn run_passes( if mir_phase == MirPhase::Optimization { validate::Validator { when: format!("end of phase {:?}", mir_phase), mir_phase } - .run_pass(tcx, source, body); + .run_pass(tcx, body); } } @@ -292,21 +263,11 @@ fn mir_const<'tcx>( let mut body = tcx.mir_built(def).steal(); - util::dump_mir( - tcx, - None, - "mir_map", - &0, - MirSource { instance: InstanceDef::Item(def.to_global()), promoted: None }, - &body, - |_, _| Ok(()), - ); + util::dump_mir(tcx, None, "mir_map", &0, &body, |_, _| Ok(())); run_passes( tcx, &mut body, - InstanceDef::Item(def.to_global()), - None, MirPhase::Const, &[&[ // MIR-level lints. @@ -359,14 +320,7 @@ fn mir_promoted( &[] }; - run_passes( - tcx, - &mut body, - InstanceDef::Item(def.to_global()), - None, - MirPhase::ConstPromotion, - &[promote, opt_coverage], - ); + run_passes(tcx, &mut body, MirPhase::ConstPromotion, &[promote, opt_coverage]); let promoted = promote_pass.promoted_fragments.into_inner(); (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted)) @@ -391,19 +345,14 @@ fn mir_drops_elaborated_and_const_checked<'tcx>( let (body, _) = tcx.mir_promoted(def); let mut body = body.steal(); - run_post_borrowck_cleanup_passes(tcx, &mut body, def.did, None); + run_post_borrowck_cleanup_passes(tcx, &mut body); check_consts::post_drop_elaboration::check_live_drops(tcx, def.did, &body); tcx.alloc_steal_mir(body) } /// After this series of passes, no lifetime analysis based on borrowing can be done. -fn run_post_borrowck_cleanup_passes<'tcx>( - tcx: TyCtxt<'tcx>, - body: &mut Body<'tcx>, - def_id: LocalDefId, - promoted: Option, -) { - debug!("post_borrowck_cleanup({:?})", def_id); +fn run_post_borrowck_cleanup_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + debug!("post_borrowck_cleanup({:?})", body.source.def_id()); let post_borrowck_cleanup: &[&dyn MirPass<'tcx>] = &[ // Remove all things only needed by analysis @@ -428,22 +377,10 @@ fn run_post_borrowck_cleanup_passes<'tcx>( &deaggregator::Deaggregator, ]; - run_passes( - tcx, - body, - InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id())), - promoted, - MirPhase::DropLowering, - &[post_borrowck_cleanup], - ); + run_passes(tcx, body, MirPhase::DropLowering, &[post_borrowck_cleanup]); } -fn run_optimization_passes<'tcx>( - tcx: TyCtxt<'tcx>, - body: &mut Body<'tcx>, - def_id: LocalDefId, - promoted: Option, -) { +fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { let mir_opt_level = tcx.sess.opts.debugging_opts.mir_opt_level; // Lowering generator control-flow and variables has to happen before we do anything else @@ -502,8 +439,6 @@ fn run_optimization_passes<'tcx>( run_passes( tcx, body, - InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id())), - promoted, MirPhase::GeneratorLowering, &[ if mir_opt_level > 0 { @@ -519,8 +454,6 @@ fn run_optimization_passes<'tcx>( run_passes( tcx, body, - InstanceDef::Item(ty::WithOptConstParam::unknown(def_id.to_def_id())), - promoted, MirPhase::Optimization, &[ if mir_opt_level > 0 { optimizations } else { no_optimizations }, @@ -558,7 +491,7 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) } let mut body = tcx.mir_drops_elaborated_and_const_checked(def).steal(); - run_optimization_passes(tcx, &mut body, def.did, None); + run_optimization_passes(tcx, &mut body); debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR"); @@ -581,9 +514,9 @@ fn promoted_mir<'tcx>( let (_, promoted) = tcx.mir_promoted(def); let mut promoted = promoted.steal(); - for (p, mut body) in promoted.iter_enumerated_mut() { - run_post_borrowck_cleanup_passes(tcx, &mut body, def.did, Some(p)); - run_optimization_passes(tcx, &mut body, def.did, Some(p)); + for body in &mut promoted { + run_post_borrowck_cleanup_passes(tcx, body); + run_optimization_passes(tcx, body); } debug_assert!(!promoted.has_free_regions(), "Free regions in promoted MIR"); diff --git a/compiler/rustc_mir/src/transform/multiple_return_terminators.rs b/compiler/rustc_mir/src/transform/multiple_return_terminators.rs index 3c9c8454f7470..c37b54a3190f8 100644 --- a/compiler/rustc_mir/src/transform/multiple_return_terminators.rs +++ b/compiler/rustc_mir/src/transform/multiple_return_terminators.rs @@ -1,7 +1,7 @@ //! This pass removes jumps to basic blocks containing only a return, and replaces them with a //! return instead. -use crate::transform::{simplify, MirPass, MirSource}; +use crate::transform::{simplify, MirPass}; use rustc_index::bit_set::BitSet; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -9,7 +9,7 @@ use rustc_middle::ty::TyCtxt; pub struct MultipleReturnTerminators; impl<'tcx> MirPass<'tcx> for MultipleReturnTerminators { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { if tcx.sess.opts.debugging_opts.mir_opt_level < 3 { return; } diff --git a/compiler/rustc_mir/src/transform/no_landing_pads.rs b/compiler/rustc_mir/src/transform/no_landing_pads.rs index 1d83733e4cd30..83954c93c04a1 100644 --- a/compiler/rustc_mir/src/transform/no_landing_pads.rs +++ b/compiler/rustc_mir/src/transform/no_landing_pads.rs @@ -1,7 +1,7 @@ //! This pass removes the unwind branch of all the terminators when the no-landing-pads option is //! specified. -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -18,7 +18,7 @@ impl<'tcx> NoLandingPads<'tcx> { } impl<'tcx> MirPass<'tcx> for NoLandingPads<'tcx> { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { no_landing_pads(tcx, body) } } diff --git a/compiler/rustc_mir/src/transform/nrvo.rs b/compiler/rustc_mir/src/transform/nrvo.rs index 3673b6a4aa223..7e05d66074bb1 100644 --- a/compiler/rustc_mir/src/transform/nrvo.rs +++ b/compiler/rustc_mir/src/transform/nrvo.rs @@ -4,7 +4,7 @@ use rustc_middle::mir::visit::{MutVisitor, NonUseContext, PlaceContext, Visitor} use rustc_middle::mir::{self, BasicBlock, Local, Location}; use rustc_middle::ty::TyCtxt; -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; /// This pass looks for MIR that always copies the same local into the return place and eliminates /// the copy by renaming all uses of that local to `_0`. @@ -31,7 +31,7 @@ use crate::transform::{MirPass, MirSource}; pub struct RenameReturnPlace; impl<'tcx> MirPass<'tcx> for RenameReturnPlace { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut mir::Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut mir::Body<'tcx>) { if tcx.sess.opts.debugging_opts.mir_opt_level == 0 { return; } @@ -39,14 +39,14 @@ impl<'tcx> MirPass<'tcx> for RenameReturnPlace { let returned_local = match local_eligible_for_nrvo(body) { Some(l) => l, None => { - debug!("`{:?}` was ineligible for NRVO", src.def_id()); + debug!("`{:?}` was ineligible for NRVO", body.source.def_id()); return; } }; debug!( "`{:?}` was eligible for NRVO, making {:?} the return place", - src.def_id(), + body.source.def_id(), returned_local ); diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs index 89f7531b3a7ff..7ad659bddbe3d 100644 --- a/compiler/rustc_mir/src/transform/promote_consts.rs +++ b/compiler/rustc_mir/src/transform/promote_consts.rs @@ -32,7 +32,7 @@ use std::{cmp, iter, mem}; use crate::const_eval::{is_const_fn, is_unstable_const_fn}; use crate::transform::check_consts::{is_lang_panic_fn, qualifs, ConstCx}; -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; /// A `MirPass` for promotion. /// @@ -47,7 +47,7 @@ pub struct PromoteTemps<'tcx> { } impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // There's not really any point in promoting errorful MIR. // // This does not include MIR that failed const-checking, which we still try to promote. @@ -56,11 +56,11 @@ impl<'tcx> MirPass<'tcx> for PromoteTemps<'tcx> { return; } - if src.promoted.is_some() { + if body.source.promoted.is_some() { return; } - let def = src.with_opt_param().expect_local(); + let def = body.source.with_opt_param().expect_local(); let mut rpo = traversal::reverse_postorder(body); let ccx = ConstCx::new(tcx, def.did, body); @@ -1167,6 +1167,7 @@ pub fn promote_candidates<'tcx>( let initial_locals = iter::once(LocalDecl::new(tcx.types.never, body.span)).collect(); let mut promoted = Body::new( + body.source, // `promoted` gets filled in below IndexVec::new(), // FIXME: maybe try to filter this to avoid blowing up // memory usage? @@ -1190,7 +1191,8 @@ pub fn promote_candidates<'tcx>( }; //FIXME(oli-obk): having a `maybe_push()` method on `IndexVec` might be nice - if let Some(promoted) = promoter.promote_candidate(def, candidate, promotions.len()) { + if let Some(mut promoted) = promoter.promote_candidate(def, candidate, promotions.len()) { + promoted.source.promoted = Some(promotions.next_index()); promotions.push(promoted); } } diff --git a/compiler/rustc_mir/src/transform/remove_noop_landing_pads.rs b/compiler/rustc_mir/src/transform/remove_noop_landing_pads.rs index 4079f0110e2c0..b45c533d2c002 100644 --- a/compiler/rustc_mir/src/transform/remove_noop_landing_pads.rs +++ b/compiler/rustc_mir/src/transform/remove_noop_landing_pads.rs @@ -1,4 +1,4 @@ -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use crate::util::patch::MirPatch; use rustc_index::bit_set::BitSet; use rustc_middle::mir::*; @@ -20,7 +20,7 @@ pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) } impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads { - fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { remove_noop_landing_pads(tcx, body); } } diff --git a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs index b9f29786c64ea..cfee656eda413 100644 --- a/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs +++ b/compiler/rustc_mir/src/transform/remove_unneeded_drops.rs @@ -1,6 +1,6 @@ //! This pass replaces a drop of a type that does not need dropping, with a goto -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use rustc_hir::def_id::LocalDefId; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; @@ -11,13 +11,13 @@ use super::simplify::simplify_cfg; pub struct RemoveUnneededDrops; impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { - trace!("Running RemoveUnneededDrops on {:?}", source); + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + trace!("Running RemoveUnneededDrops on {:?}", body.source); let mut opt_finder = RemoveUnneededDropsOptimizationFinder { tcx, body, optimizations: vec![], - def_id: source.def_id().expect_local(), + def_id: body.source.def_id().expect_local(), }; opt_finder.visit_body(body); let should_simplify = !opt_finder.optimizations.is_empty(); diff --git a/compiler/rustc_mir/src/transform/rustc_peek.rs b/compiler/rustc_mir/src/transform/rustc_peek.rs index 015af44b80f6f..366041581c2a8 100644 --- a/compiler/rustc_mir/src/transform/rustc_peek.rs +++ b/compiler/rustc_mir/src/transform/rustc_peek.rs @@ -5,7 +5,7 @@ use rustc_span::symbol::sym; use rustc_span::Span; use rustc_target::spec::abi::Abi; -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use rustc_hir::def_id::DefId; use rustc_index::bit_set::BitSet; use rustc_middle::mir::{self, Body, Local, Location}; @@ -23,9 +23,9 @@ use crate::dataflow::{Analysis, JoinSemiLattice, Results, ResultsCursor}; pub struct SanityCheck; impl<'tcx> MirPass<'tcx> for SanityCheck { - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { use crate::dataflow::has_rustc_mir_with; - let def_id = src.def_id(); + let def_id = body.source.def_id(); if !tcx.has_attr(def_id, sym::rustc_mir) { debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); return; diff --git a/compiler/rustc_mir/src/transform/simplify.rs b/compiler/rustc_mir/src/transform/simplify.rs index 3fc8e6d4b04b8..f0c87bcf513cd 100644 --- a/compiler/rustc_mir/src/transform/simplify.rs +++ b/compiler/rustc_mir/src/transform/simplify.rs @@ -27,7 +27,7 @@ //! naively generate still contains the `_a = ()` write in the unreachable block "after" the //! return. -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use rustc_index::bit_set::BitSet; use rustc_index::vec::{Idx, IndexVec}; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; @@ -59,7 +59,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyCfg { Cow::Borrowed(&self.label) } - fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body); simplify_cfg(body); } @@ -318,8 +318,8 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) { pub struct SimplifyLocals; impl<'tcx> MirPass<'tcx> for SimplifyLocals { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { - trace!("running SimplifyLocals on {:?}", source); + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + trace!("running SimplifyLocals on {:?}", body.source); // First, we're going to get a count of *actual* uses for every `Local`. // Take a look at `DeclMarker::visit_local()` to see exactly what is ignored. diff --git a/compiler/rustc_mir/src/transform/simplify_branches.rs b/compiler/rustc_mir/src/transform/simplify_branches.rs index 4c30a0946bccf..161856a38ee03 100644 --- a/compiler/rustc_mir/src/transform/simplify_branches.rs +++ b/compiler/rustc_mir/src/transform/simplify_branches.rs @@ -1,6 +1,6 @@ //! A pass that simplifies branches when their condition is known. -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -21,8 +21,8 @@ impl<'tcx> MirPass<'tcx> for SimplifyBranches { Cow::Borrowed(&self.label) } - fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { - let param_env = tcx.param_env(src.def_id()); + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let param_env = tcx.param_env(body.source.def_id()); for block in body.basic_blocks_mut() { let terminator = block.terminator_mut(); terminator.kind = match terminator.kind { diff --git a/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs b/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs index 9b460c9ecb1be..9f837cf78a608 100644 --- a/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs +++ b/compiler/rustc_mir/src/transform/simplify_comparison_integral.rs @@ -1,4 +1,4 @@ -use super::{MirPass, MirSource}; +use super::MirPass; use rustc_middle::{ mir::{ interpret::Scalar, BasicBlock, BinOp, Body, Operand, Place, Rvalue, Statement, @@ -24,8 +24,8 @@ use rustc_middle::{ pub struct SimplifyComparisonIntegral; impl<'tcx> MirPass<'tcx> for SimplifyComparisonIntegral { - fn run_pass(&self, _: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { - trace!("Running SimplifyComparisonIntegral on {:?}", source); + fn run_pass(&self, _: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + trace!("Running SimplifyComparisonIntegral on {:?}", body.source); let helper = OptimizationFinder { body }; let opts = helper.find_optimizations(); diff --git a/compiler/rustc_mir/src/transform/simplify_try.rs b/compiler/rustc_mir/src/transform/simplify_try.rs index b2c889bfd05e8..e6b7345d6e488 100644 --- a/compiler/rustc_mir/src/transform/simplify_try.rs +++ b/compiler/rustc_mir/src/transform/simplify_try.rs @@ -9,7 +9,7 @@ //! //! into just `x`. -use crate::transform::{simplify, MirPass, MirSource}; +use crate::transform::{simplify, MirPass}; use itertools::Itertools as _; use rustc_index::{bit_set::BitSet, vec::IndexVec}; use rustc_middle::mir::visit::{NonUseContext, PlaceContext, Visitor}; @@ -367,13 +367,15 @@ fn optimization_applies<'tcx>( } impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { // FIXME(77359): This optimization can result in unsoundness. if !tcx.sess.opts.debugging_opts.unsound_mir_opts { return; } + let source = body.source; trace!("running SimplifyArmIdentity on {:?}", source); + let local_uses = LocalUseCounter::get_local_uses(body); let (basic_blocks, local_decls, debug_info) = body.basic_blocks_local_decls_mut_and_var_debug_info(); @@ -528,8 +530,8 @@ fn match_variant_field_place<'tcx>(place: Place<'tcx>) -> Option<(Local, VarFiel pub struct SimplifyBranchSame; impl<'tcx> MirPass<'tcx> for SimplifyBranchSame { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { - trace!("Running SimplifyBranchSame on {:?}", source); + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + trace!("Running SimplifyBranchSame on {:?}", body.source); let finder = SimplifyBranchSameOptimizationFinder { body, tcx }; let opts = finder.find(); diff --git a/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs b/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs index 4cca4d223c0cb..a6bfa0c7409f2 100644 --- a/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs +++ b/compiler/rustc_mir/src/transform/uninhabited_enum_branching.rs @@ -1,6 +1,6 @@ //! A pass that eliminates branches on uninhabited enum variants. -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use rustc_middle::mir::{ BasicBlock, BasicBlockData, Body, Local, Operand, Rvalue, StatementKind, TerminatorKind, }; @@ -66,12 +66,12 @@ fn variant_discriminants<'tcx>( } impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { - if source.promoted.is_some() { + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + if body.source.promoted.is_some() { return; } - trace!("UninhabitedEnumBranching starting for {:?}", source); + trace!("UninhabitedEnumBranching starting for {:?}", body.source); let basic_block_count = body.basic_blocks().len(); @@ -86,7 +86,7 @@ impl<'tcx> MirPass<'tcx> for UninhabitedEnumBranching { continue; }; - let layout = tcx.layout_of(tcx.param_env(source.def_id()).and(discriminant_ty)); + let layout = tcx.layout_of(tcx.param_env(body.source.def_id()).and(discriminant_ty)); let allowed_variants = if let Ok(layout) = layout { variant_discriminants(&layout, discriminant_ty, tcx) diff --git a/compiler/rustc_mir/src/transform/unreachable_prop.rs b/compiler/rustc_mir/src/transform/unreachable_prop.rs index fa362c66fb289..c6426a06ea155 100644 --- a/compiler/rustc_mir/src/transform/unreachable_prop.rs +++ b/compiler/rustc_mir/src/transform/unreachable_prop.rs @@ -3,7 +3,7 @@ //! post-order traversal of the blocks. use crate::transform::simplify; -use crate::transform::{MirPass, MirSource}; +use crate::transform::MirPass; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::*; use rustc_middle::ty::TyCtxt; @@ -12,7 +12,7 @@ use std::borrow::Cow; pub struct UnreachablePropagation; impl MirPass<'_> for UnreachablePropagation { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { if tcx.sess.opts.debugging_opts.mir_opt_level < 3 { // Enable only under -Zmir-opt-level=3 as in some cases (check the deeply-nested-opt // perf benchmark) LLVM may spend quite a lot of time optimizing the generated code. diff --git a/compiler/rustc_mir/src/transform/validate.rs b/compiler/rustc_mir/src/transform/validate.rs index ba7554cf02bde..0c3580584ff26 100644 --- a/compiler/rustc_mir/src/transform/validate.rs +++ b/compiler/rustc_mir/src/transform/validate.rs @@ -4,7 +4,7 @@ use crate::dataflow::impls::MaybeStorageLive; use crate::dataflow::{Analysis, ResultsCursor}; use crate::util::storage::AlwaysLiveLocals; -use super::{MirPass, MirSource}; +use super::MirPass; use rustc_middle::mir::visit::{PlaceContext, Visitor}; use rustc_middle::mir::{ AggregateKind, BasicBlock, Body, BorrowKind, Local, Location, MirPhase, Operand, Rvalue, @@ -31,8 +31,8 @@ pub struct Validator { } impl<'tcx> MirPass<'tcx> for Validator { - fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { - let def_id = source.def_id(); + fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let def_id = body.source.def_id(); let param_env = tcx.param_env(def_id); let mir_phase = self.mir_phase; @@ -42,7 +42,7 @@ impl<'tcx> MirPass<'tcx> for Validator { .iterate_to_fixpoint() .into_results_cursor(body); - TypeChecker { when: &self.when, source, body, tcx, param_env, mir_phase, storage_liveness } + TypeChecker { when: &self.when, body, tcx, param_env, mir_phase, storage_liveness } .visit_body(body); } } @@ -141,7 +141,6 @@ pub fn equal_up_to_regions( struct TypeChecker<'a, 'tcx> { when: &'a str, - source: MirSource<'tcx>, body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, @@ -158,7 +157,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { span, &format!( "broken MIR in {:?} ({}) at {:?}:\n{}", - self.source.instance, + self.body.source.instance, self.when, location, msg.as_ref() diff --git a/compiler/rustc_mir/src/util/graphviz.rs b/compiler/rustc_mir/src/util/graphviz.rs index 4511962d68f03..c10724ad40456 100644 --- a/compiler/rustc_mir/src/util/graphviz.rs +++ b/compiler/rustc_mir/src/util/graphviz.rs @@ -22,7 +22,7 @@ where for def_id in def_ids { let body = &tcx.optimized_mir(def_id); - write_mir_fn_graphviz(tcx, def_id, body, use_subgraphs, w)?; + write_mir_fn_graphviz(tcx, body, use_subgraphs, w)?; } if use_subgraphs { @@ -41,7 +41,6 @@ pub fn graphviz_safe_def_name(def_id: DefId) -> String { /// Write a graphviz DOT graph of the MIR. pub fn write_mir_fn_graphviz<'tcx, W>( tcx: TyCtxt<'tcx>, - def_id: DefId, body: &Body<'_>, subgraph: bool, w: &mut W, @@ -49,6 +48,7 @@ pub fn write_mir_fn_graphviz<'tcx, W>( where W: Write, { + let def_id = body.source.def_id(); let kind = if subgraph { "subgraph" } else { "digraph" }; let cluster = if subgraph { "cluster_" } else { "" }; // Prints a border around MIR let def_name = graphviz_safe_def_name(def_id); diff --git a/compiler/rustc_mir/src/util/pretty.rs b/compiler/rustc_mir/src/util/pretty.rs index 49c644a20bf82..ad871fde00f78 100644 --- a/compiler/rustc_mir/src/util/pretty.rs +++ b/compiler/rustc_mir/src/util/pretty.rs @@ -75,17 +75,16 @@ pub fn dump_mir<'tcx, F>( pass_num: Option<&dyn Display>, pass_name: &str, disambiguator: &dyn Display, - source: MirSource<'tcx>, body: &Body<'tcx>, extra_data: F, ) where F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>, { - if !dump_enabled(tcx, pass_name, source.def_id()) { + if !dump_enabled(tcx, pass_name, body.source.def_id()) { return; } - dump_matched_mir_node(tcx, pass_num, pass_name, disambiguator, source, body, extra_data); + dump_matched_mir_node(tcx, pass_num, pass_name, disambiguator, body, extra_data); } pub fn dump_enabled<'tcx>(tcx: TyCtxt<'tcx>, pass_name: &str, def_id: DefId) -> bool { @@ -113,20 +112,20 @@ fn dump_matched_mir_node<'tcx, F>( pass_num: Option<&dyn Display>, pass_name: &str, disambiguator: &dyn Display, - source: MirSource<'tcx>, body: &Body<'tcx>, mut extra_data: F, ) where F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>, { let _: io::Result<()> = try { - let mut file = create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, source)?; + let mut file = + create_dump_file(tcx, "mir", pass_num, pass_name, disambiguator, body.source)?; let def_path = ty::print::with_forced_impl_filename_line(|| { // see notes on #41697 above - tcx.def_path_str(source.def_id()) + tcx.def_path_str(body.source.def_id()) }); write!(file, "// MIR for `{}", def_path)?; - match source.promoted { + match body.source.promoted { None => write!(file, "`")?, Some(promoted) => write!(file, "::{:?}`", promoted)?, } @@ -137,24 +136,24 @@ fn dump_matched_mir_node<'tcx, F>( writeln!(file)?; extra_data(PassWhere::BeforeCFG, &mut file)?; write_user_type_annotations(tcx, body, &mut file)?; - write_mir_fn(tcx, source, body, &mut extra_data, &mut file)?; + write_mir_fn(tcx, body, &mut extra_data, &mut file)?; extra_data(PassWhere::AfterCFG, &mut file)?; }; if tcx.sess.opts.debugging_opts.dump_mir_graphviz { let _: io::Result<()> = try { let mut file = - create_dump_file(tcx, "dot", pass_num, pass_name, disambiguator, source)?; - write_mir_fn_graphviz(tcx, source.def_id(), body, false, &mut file)?; + create_dump_file(tcx, "dot", pass_num, pass_name, disambiguator, body.source)?; + write_mir_fn_graphviz(tcx, body, false, &mut file)?; }; } if let Some(spanview) = tcx.sess.opts.debugging_opts.dump_mir_spanview { let _: io::Result<()> = try { let mut file = - create_dump_file(tcx, "html", pass_num, pass_name, disambiguator, source)?; - if source.def_id().is_local() { - write_mir_fn_spanview(tcx, source.def_id(), body, spanview, &mut file)?; + create_dump_file(tcx, "html", pass_num, pass_name, disambiguator, body.source)?; + if body.source.def_id().is_local() { + write_mir_fn_spanview(tcx, body.source.def_id(), body, spanview, &mut file)?; } }; } @@ -263,15 +262,11 @@ pub fn write_mir_pretty<'tcx>( writeln!(w)?; } - write_mir_fn(tcx, MirSource::item(def_id), body, &mut |_, _| Ok(()), w)?; + write_mir_fn(tcx, body, &mut |_, _| Ok(()), w)?; - for (i, body) in tcx.promoted_mir(def_id).iter_enumerated() { + for body in tcx.promoted_mir(def_id) { writeln!(w)?; - let src = MirSource { - instance: ty::InstanceDef::Item(ty::WithOptConstParam::unknown(def_id)), - promoted: Some(i), - }; - write_mir_fn(tcx, src, body, &mut |_, _| Ok(()), w)?; + write_mir_fn(tcx, body, &mut |_, _| Ok(()), w)?; } } Ok(()) @@ -280,7 +275,6 @@ pub fn write_mir_pretty<'tcx>( /// Write out a human-readable textual representation for the given function. pub fn write_mir_fn<'tcx, F>( tcx: TyCtxt<'tcx>, - src: MirSource<'tcx>, body: &Body<'tcx>, extra_data: &mut F, w: &mut dyn Write, @@ -288,7 +282,7 @@ pub fn write_mir_fn<'tcx, F>( where F: FnMut(PassWhere, &mut dyn Write) -> io::Result<()>, { - write_mir_intro(tcx, src, body, w)?; + write_mir_intro(tcx, body, w)?; for block in body.basic_blocks().indices() { extra_data(PassWhere::BeforeBlock(block), w)?; write_basic_block(tcx, block, body, extra_data, w)?; @@ -548,11 +542,10 @@ fn write_scope_tree( /// local variables (both user-defined bindings and compiler temporaries). pub fn write_mir_intro<'tcx>( tcx: TyCtxt<'tcx>, - src: MirSource<'tcx>, body: &Body<'_>, w: &mut dyn Write, ) -> io::Result<()> { - write_mir_sig(tcx, src, body, w)?; + write_mir_sig(tcx, body, w)?; writeln!(w, "{{")?; // construct a scope tree and write it out @@ -850,25 +843,21 @@ fn write_allocation_bytes( Ok(()) } -fn write_mir_sig( - tcx: TyCtxt<'_>, - src: MirSource<'tcx>, - body: &Body<'_>, - w: &mut dyn Write, -) -> io::Result<()> { +fn write_mir_sig(tcx: TyCtxt<'_>, body: &Body<'_>, w: &mut dyn Write) -> io::Result<()> { use rustc_hir::def::DefKind; - trace!("write_mir_sig: {:?}", src.instance); - let kind = tcx.def_kind(src.def_id()); + trace!("write_mir_sig: {:?}", body.source.instance); + let def_id = body.source.def_id(); + let kind = tcx.def_kind(def_id); let is_function = match kind { DefKind::Fn | DefKind::AssocFn | DefKind::Ctor(..) => true, - _ => tcx.is_closure(src.def_id()), + _ => tcx.is_closure(def_id), }; - match (kind, src.promoted) { + match (kind, body.source.promoted) { (_, Some(i)) => write!(w, "{:?} in ", i)?, (DefKind::Const | DefKind::AssocConst, _) => write!(w, "const ")?, (DefKind::Static, _) => { - write!(w, "static {}", if tcx.is_mutable_static(src.def_id()) { "mut " } else { "" })? + write!(w, "static {}", if tcx.is_mutable_static(def_id) { "mut " } else { "" })? } (_, _) if is_function => write!(w, "fn ")?, (DefKind::AnonConst, _) => {} // things like anon const, not an item @@ -877,10 +866,10 @@ fn write_mir_sig( ty::print::with_forced_impl_filename_line(|| { // see notes on #41697 elsewhere - write!(w, "{}", tcx.def_path_str(src.def_id())) + write!(w, "{}", tcx.def_path_str(def_id)) })?; - if src.promoted.is_none() && is_function { + if body.source.promoted.is_none() && is_function { write!(w, "(")?; // fn argument types. diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index aa96ae8759154..72814e3373bbb 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -29,7 +29,13 @@ crate fn mir_built<'tcx>( return tcx.mir_built(def); } - tcx.alloc_steal_mir(mir_build(tcx, def)) + let mut body = mir_build(tcx, def); + if def.const_param_did.is_some() { + assert!(matches!(body.source.instance, ty::InstanceDef::Item(_))); + body.source = MirSource::from_instance(ty::InstanceDef::Item(def.to_global())); + } + + tcx.alloc_steal_mir(body) } /// Construct the MIR for a given `DefId`. @@ -296,6 +302,7 @@ struct Builder<'a, 'tcx> { hir: Cx<'a, 'tcx>, cfg: CFG<'tcx>, + def_id: DefId, fn_span: Span, arg_count: usize, generator_kind: Option, @@ -597,6 +604,7 @@ where let mut builder = Builder::new( hir, + fn_def_id.to_def_id(), span_with_body, arguments.len(), safety, @@ -675,8 +683,9 @@ fn construct_const<'a, 'tcx>( ) -> Body<'tcx> { let tcx = hir.tcx(); let owner_id = tcx.hir().body_owner(body_id); + let def_id = tcx.hir().local_def_id(owner_id); let span = tcx.hir().span(owner_id); - let mut builder = Builder::new(hir, span, 0, Safety::Safe, const_ty, const_ty_span, None); + let mut builder = Builder::new(hir, def_id.to_def_id(), span, 0, Safety::Safe, const_ty, const_ty_span, None); let mut block = START_BLOCK; let ast_expr = &tcx.hir().body(body_id).value; @@ -705,6 +714,7 @@ fn construct_const<'a, 'tcx>( fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'tcx> { let tcx = hir.tcx(); let owner_id = tcx.hir().body_owner(body_id); + let def_id = tcx.hir().local_def_id(owner_id); let span = tcx.hir().span(owner_id); let ty = tcx.ty_error(); let num_params = match hir.body_owner_kind { @@ -722,7 +732,7 @@ fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'t hir::BodyOwnerKind::Const => 0, hir::BodyOwnerKind::Static(_) => 0, }; - let mut builder = Builder::new(hir, span, num_params, Safety::Safe, ty, span, None); + let mut builder = Builder::new(hir, def_id.to_def_id(), span, num_params, Safety::Safe, ty, span, None); let source_info = builder.source_info(span); // Some MIR passes will expect the number of parameters to match the // function declaration. @@ -740,6 +750,7 @@ fn construct_error<'a, 'tcx>(hir: Cx<'a, 'tcx>, body_id: hir::BodyId) -> Body<'t impl<'a, 'tcx> Builder<'a, 'tcx> { fn new( hir: Cx<'a, 'tcx>, + def_id: DefId, span: Span, arg_count: usize, safety: Safety, @@ -750,6 +761,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let lint_level = LintLevel::Explicit(hir.root_lint_level); let mut builder = Builder { hir, + def_id, cfg: CFG { basic_blocks: IndexVec::new() }, fn_span: span, arg_count, @@ -790,6 +802,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } Body::new( + MirSource::item(self.def_id), self.cfg.basic_blocks, self.source_scopes, self.local_decls,