From 666180c3242169fa40ec462617e96ebf831fc62d Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sun, 4 Aug 2019 16:20:00 -0400 Subject: [PATCH 01/10] Move 'tcx lifetime on MirPass --- src/librustc_mir/transform/add_call_guards.rs | 4 ++-- src/librustc_mir/transform/add_moves_for_packed_drops.rs | 4 ++-- src/librustc_mir/transform/add_retag.rs | 4 ++-- src/librustc_mir/transform/cleanup_post_borrowck.rs | 4 ++-- src/librustc_mir/transform/const_prop.rs | 4 ++-- src/librustc_mir/transform/copy_prop.rs | 4 ++-- src/librustc_mir/transform/deaggregator.rs | 4 ++-- src/librustc_mir/transform/dump_mir.rs | 4 ++-- src/librustc_mir/transform/elaborate_drops.rs | 4 ++-- src/librustc_mir/transform/erase_regions.rs | 4 ++-- src/librustc_mir/transform/generator.rs | 4 ++-- src/librustc_mir/transform/inline.rs | 4 ++-- src/librustc_mir/transform/instcombine.rs | 4 ++-- src/librustc_mir/transform/mod.rs | 8 ++++---- src/librustc_mir/transform/no_landing_pads.rs | 4 ++-- src/librustc_mir/transform/qualify_consts.rs | 4 ++-- src/librustc_mir/transform/remove_noop_landing_pads.rs | 4 ++-- src/librustc_mir/transform/rustc_peek.rs | 4 ++-- src/librustc_mir/transform/simplify.rs | 8 ++++---- src/librustc_mir/transform/simplify_branches.rs | 4 ++-- src/librustc_mir/transform/uniform_array_move_out.rs | 8 ++++---- 21 files changed, 48 insertions(+), 48 deletions(-) diff --git a/src/librustc_mir/transform/add_call_guards.rs b/src/librustc_mir/transform/add_call_guards.rs index c08c33bc6ff8b..15ecc6c37920b 100644 --- a/src/librustc_mir/transform/add_call_guards.rs +++ b/src/librustc_mir/transform/add_call_guards.rs @@ -30,8 +30,8 @@ pub use self::AddCallGuards::*; * */ -impl MirPass for AddCallGuards { - fn run_pass<'tcx>(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for AddCallGuards { + fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { self.add_call_guards(body); } } diff --git a/src/librustc_mir/transform/add_moves_for_packed_drops.rs b/src/librustc_mir/transform/add_moves_for_packed_drops.rs index 426e16698d74d..052631ddff371 100644 --- a/src/librustc_mir/transform/add_moves_for_packed_drops.rs +++ b/src/librustc_mir/transform/add_moves_for_packed_drops.rs @@ -39,8 +39,8 @@ use crate::util; pub struct AddMovesForPackedDrops; -impl MirPass for AddMovesForPackedDrops { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { +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()); } diff --git a/src/librustc_mir/transform/add_retag.rs b/src/librustc_mir/transform/add_retag.rs index 524a19e3434f3..0fd75cd57b2ac 100644 --- a/src/librustc_mir/transform/add_retag.rs +++ b/src/librustc_mir/transform/add_retag.rs @@ -65,8 +65,8 @@ fn may_be_reference<'tcx>(ty: Ty<'tcx>) -> bool { } } -impl MirPass for AddRetag { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for AddRetag { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { if !tcx.sess.opts.debugging_opts.mir_emit_retag { return; } diff --git a/src/librustc_mir/transform/cleanup_post_borrowck.rs b/src/librustc_mir/transform/cleanup_post_borrowck.rs index 6ee14160bbd1b..ede1cb62f9451 100644 --- a/src/librustc_mir/transform/cleanup_post_borrowck.rs +++ b/src/librustc_mir/transform/cleanup_post_borrowck.rs @@ -26,8 +26,8 @@ pub struct CleanupNonCodegenStatements; pub struct DeleteNonCodegenStatements; -impl MirPass for CleanupNonCodegenStatements { - fn run_pass<'tcx>(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements { + fn run_pass(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { let mut delete = DeleteNonCodegenStatements; delete.visit_body(body); } diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 98d8ca58ee164..ac442a496e535 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -33,8 +33,8 @@ use crate::transform::{MirPass, MirSource}; pub struct ConstProp; -impl MirPass for ConstProp { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for ConstProp { + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { // will be evaluated by miri and produce its errors there if source.promoted.is_some() { return; diff --git a/src/librustc_mir/transform/copy_prop.rs b/src/librustc_mir/transform/copy_prop.rs index 7c9eeb5a57741..f3a523a813413 100644 --- a/src/librustc_mir/transform/copy_prop.rs +++ b/src/librustc_mir/transform/copy_prop.rs @@ -29,8 +29,8 @@ use crate::util::def_use::DefUseAnalysis; pub struct CopyPropagation; -impl MirPass for CopyPropagation { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for CopyPropagation { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { // We only run when the MIR optimization level is > 1. // This avoids a slow pass, and messing up debug info. if tcx.sess.opts.debugging_opts.mir_opt_level <= 1 { diff --git a/src/librustc_mir/transform/deaggregator.rs b/src/librustc_mir/transform/deaggregator.rs index 1b42a0dffb894..1fc7ce09aa647 100644 --- a/src/librustc_mir/transform/deaggregator.rs +++ b/src/librustc_mir/transform/deaggregator.rs @@ -5,8 +5,8 @@ use crate::util::expand_aggregate; pub struct Deaggregator; -impl MirPass for Deaggregator { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for Deaggregator { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'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/src/librustc_mir/transform/dump_mir.rs b/src/librustc_mir/transform/dump_mir.rs index a6fb555f20bd0..ed0eff943a165 100644 --- a/src/librustc_mir/transform/dump_mir.rs +++ b/src/librustc_mir/transform/dump_mir.rs @@ -13,12 +13,12 @@ use crate::util as mir_util; pub struct Marker(pub &'static str); -impl MirPass for Marker { +impl<'tcx> MirPass<'tcx> for Marker { fn name(&self) -> Cow<'_, str> { Cow::Borrowed(self.0) } - fn run_pass<'tcx>(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body: &mut Body<'tcx>) { + fn run_pass(&self, _tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, _body: &mut Body<'tcx>) { } } diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 4480d1e0a05b8..7a5c00c859629 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -20,8 +20,8 @@ use syntax_pos::Span; pub struct ElaborateDrops; -impl MirPass for ElaborateDrops { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { +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); let def_id = src.def_id(); diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs index 5a29ea21a7a04..21ca339eb968b 100644 --- a/src/librustc_mir/transform/erase_regions.rs +++ b/src/librustc_mir/transform/erase_regions.rs @@ -49,8 +49,8 @@ impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> { pub struct EraseRegions; -impl MirPass for EraseRegions { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for EraseRegions { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { EraseRegionsVisitor::new(tcx).visit_body(body); } } diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index f694188024031..d87331195dd24 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -1115,8 +1115,8 @@ where }).collect() } -impl MirPass for StateTransform { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for StateTransform { + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { let yield_ty = if let Some(yield_ty) = body.yield_ty { yield_ty } else { diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index bc7bd39be488e..57aac2b0eac99 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -37,8 +37,8 @@ struct CallSite<'tcx> { location: SourceInfo, } -impl MirPass for Inline { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for Inline { + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>) { if tcx.sess.opts.debugging_opts.mir_opt_level >= 2 { Inliner { tcx, source }.run_pass(body); } diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs index b2d063a1f4e10..abe41606e8079 100644 --- a/src/librustc_mir/transform/instcombine.rs +++ b/src/librustc_mir/transform/instcombine.rs @@ -11,8 +11,8 @@ use crate::transform::{MirPass, MirSource}; pub struct InstCombine; -impl MirPass for InstCombine { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for InstCombine { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { // We only run when optimizing MIR (at any level). if tcx.sess.opts.debugging_opts.mir_opt_level == 0 { return diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 61d0b1f3485b6..255635b933385 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -137,12 +137,12 @@ pub fn default_name() -> Cow<'static, str> { /// A streamlined trait that you can implement to create a pass; the /// pass will be named after the type, and it will consist of a main /// loop that goes over each available MIR and applies `run_pass`. -pub trait MirPass { +pub trait MirPass<'tcx> { fn name(&self) -> Cow<'_, str> { default_name::() } - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>); + fn run_pass(&self, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, body: &mut Body<'tcx>); } pub fn run_passes( @@ -150,7 +150,7 @@ pub fn run_passes( body: &mut Body<'tcx>, instance: InstanceDef<'tcx>, mir_phase: MirPhase, - passes: &[&dyn MirPass], + passes: &[&dyn MirPass<'tcx>], ) { let phase_index = mir_phase.phase_index(); @@ -164,7 +164,7 @@ pub fn run_passes( promoted, }; let mut index = 0; - let mut run_pass = |pass: &dyn MirPass| { + let mut run_pass = |pass: &dyn MirPass<'tcx>| { let run_hooks = |body: &_, index, is_after| { dump_mir::on_mir_pass(tcx, &format_args!("{:03}-{:03}", phase_index, index), &pass.name(), source, body, is_after); diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs index 841db80fc7dbb..762bb5d44839f 100644 --- a/src/librustc_mir/transform/no_landing_pads.rs +++ b/src/librustc_mir/transform/no_landing_pads.rs @@ -8,8 +8,8 @@ use crate::transform::{MirPass, MirSource}; pub struct NoLandingPads; -impl MirPass for NoLandingPads { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for NoLandingPads { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { no_landing_pads(tcx, body) } } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 649cccc36c346..1fe45a2c4240b 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1572,8 +1572,8 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> (u8, &BitSet) { pub struct QualifyAndPromoteConstants; -impl MirPass for QualifyAndPromoteConstants { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { // There's not really any point in promoting errorful MIR. if body.return_ty().references_error() { tcx.sess.delay_span_bug(body.span, "QualifyAndPromoteConstants: MIR had errors"); diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index adba9097d12df..73089a2106f6b 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -18,8 +18,8 @@ pub fn remove_noop_landing_pads<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) RemoveNoopLandingPads.remove_nop_landing_pads(body) } -impl MirPass for RemoveNoopLandingPads { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _src: MirSource<'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>) { remove_noop_landing_pads(tcx, body); } } diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 598de3a77e61c..1d3bf247387a7 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -23,8 +23,8 @@ use crate::dataflow::has_rustc_mir_with; pub struct SanityCheck; -impl MirPass for SanityCheck { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for SanityCheck { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { let def_id = src.def_id(); if !tcx.has_attr(def_id, sym::rustc_mir) { debug!("skipping rustc_peek::SanityCheck on {}", tcx.def_path_str(def_id)); diff --git a/src/librustc_mir/transform/simplify.rs b/src/librustc_mir/transform/simplify.rs index 2eed9d453f233..d4599ee08aa46 100644 --- a/src/librustc_mir/transform/simplify.rs +++ b/src/librustc_mir/transform/simplify.rs @@ -52,12 +52,12 @@ pub fn simplify_cfg(body: &mut Body<'_>) { body.basic_blocks_mut().raw.shrink_to_fit(); } -impl MirPass for SimplifyCfg { +impl<'tcx> MirPass<'tcx> for SimplifyCfg { fn name(&self) -> Cow<'_, str> { Cow::Borrowed(&self.label) } - fn run_pass<'tcx>(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, _tcx: TyCtxt<'tcx>, _src: MirSource<'tcx>, body: &mut Body<'tcx>) { debug!("SimplifyCfg({:?}) - simplifying {:?}", self.label, body); simplify_cfg(body); } @@ -292,8 +292,8 @@ pub fn remove_dead_blocks(body: &mut Body<'_>) { pub struct SimplifyLocals; -impl MirPass for SimplifyLocals { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for SimplifyLocals { + fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut Body<'tcx>) { let mut marker = DeclMarker { locals: BitSet::new_empty(body.local_decls.len()) }; marker.visit_body(body); // Return pointer and arguments are always live diff --git a/src/librustc_mir/transform/simplify_branches.rs b/src/librustc_mir/transform/simplify_branches.rs index 9ffa3db4c2eb0..0a509666d34ae 100644 --- a/src/librustc_mir/transform/simplify_branches.rs +++ b/src/librustc_mir/transform/simplify_branches.rs @@ -14,12 +14,12 @@ impl SimplifyBranches { } } -impl MirPass for SimplifyBranches { +impl<'tcx> MirPass<'tcx> for SimplifyBranches { fn name(&self) -> Cow<'_, str> { Cow::Borrowed(&self.label) } - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { let param_env = tcx.param_env(src.def_id()); for block in body.basic_blocks_mut() { let terminator = block.terminator_mut(); diff --git a/src/librustc_mir/transform/uniform_array_move_out.rs b/src/librustc_mir/transform/uniform_array_move_out.rs index 60489e7fa3668..8199a252e78b0 100644 --- a/src/librustc_mir/transform/uniform_array_move_out.rs +++ b/src/librustc_mir/transform/uniform_array_move_out.rs @@ -36,8 +36,8 @@ use crate::util::patch::MirPatch; pub struct UniformArrayMoveOut; -impl MirPass for UniformArrayMoveOut { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for UniformArrayMoveOut { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { let mut patch = MirPatch::new(body); let param_env = tcx.param_env(src.def_id()); { @@ -184,8 +184,8 @@ impl<'a, 'tcx> UniformArrayMoveOutVisitor<'a, 'tcx> { pub struct RestoreSubsliceArrayMoveOut; -impl MirPass for RestoreSubsliceArrayMoveOut { - fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { +impl<'tcx> MirPass<'tcx> for RestoreSubsliceArrayMoveOut { + fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { let mut patch = MirPatch::new(body); let param_env = tcx.param_env(src.def_id()); { From 73814654b29604ded9dff105e4156639980d2f2c Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sun, 4 Aug 2019 16:20:21 -0400 Subject: [PATCH 02/10] Move promoted out of mir::Body --- src/librustc/arena.rs | 10 +++ src/librustc/mir/mod.rs | 9 -- src/librustc/query/mod.rs | 14 +++- src/librustc/ty/context.rs | 12 ++- src/librustc_metadata/cstore_impl.rs | 9 ++ src/librustc_metadata/decoder.rs | 10 ++- src/librustc_metadata/encoder.rs | 64 +++++++++------ src/librustc_metadata/schema.rs | 2 + src/librustc_mir/borrow_check/mod.rs | 13 ++- src/librustc_mir/borrow_check/nll/mod.rs | 8 +- src/librustc_mir/borrow_check/nll/renumber.rs | 19 +++-- .../borrow_check/nll/type_check/mod.rs | 11 ++- src/librustc_mir/build/mod.rs | 1 - src/librustc_mir/const_eval.rs | 2 +- src/librustc_mir/monomorphize/collector.rs | 33 ++++---- src/librustc_mir/shim.rs | 4 - src/librustc_mir/transform/const_prop.rs | 28 ++----- src/librustc_mir/transform/inline.rs | 9 +- src/librustc_mir/transform/mod.rs | 82 ++++++++++++++++--- src/librustc_mir/transform/promote_consts.rs | 20 +++-- src/librustc_mir/transform/qualify_consts.rs | 19 ++++- 21 files changed, 253 insertions(+), 126 deletions(-) diff --git a/src/librustc/arena.rs b/src/librustc/arena.rs index e8c3914e695ad..a38dbbdd50c57 100644 --- a/src/librustc/arena.rs +++ b/src/librustc/arena.rs @@ -25,6 +25,16 @@ macro_rules! arena_types { [] adt_def: rustc::ty::AdtDef, [] steal_mir: rustc::ty::steal::Steal>, [] mir: rustc::mir::Body<$tcx>, + [] steal_promoted: rustc::ty::steal::Steal< + rustc_data_structures::indexed_vec::IndexVec< + rustc::mir::Promoted, + rustc::mir::Body<$tcx> + > + >, + [] promoted: rustc_data_structures::indexed_vec::IndexVec< + rustc::mir::Promoted, + rustc::mir::Body<$tcx> + >, [] tables: rustc::ty::TypeckTables<$tcx>, [] const_allocs: rustc::mir::interpret::Allocation, [] vtable_method: Option<( diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 11701a6637744..66f5eaeeda1c7 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -108,11 +108,6 @@ pub struct Body<'tcx> { /// needn't) be tracked across crates. pub source_scope_local_data: ClearCrossCrate>, - /// Rvalues promoted from this function, such as borrows of constants. - /// Each of them is the Body of a constant with the fn's type parameters - /// in scope, but a separate set of locals. - pub promoted: IndexVec>, - /// Yields type of the function, if it is a generator. pub yield_ty: Option>, @@ -174,7 +169,6 @@ impl<'tcx> Body<'tcx> { basic_blocks: IndexVec>, source_scopes: IndexVec, source_scope_local_data: ClearCrossCrate>, - promoted: IndexVec>, yield_ty: Option>, local_decls: LocalDecls<'tcx>, user_type_annotations: CanonicalUserTypeAnnotations<'tcx>, @@ -196,7 +190,6 @@ impl<'tcx> Body<'tcx> { basic_blocks, source_scopes, source_scope_local_data, - promoted, yield_ty, generator_drop: None, generator_layout: None, @@ -418,7 +411,6 @@ impl_stable_hash_for!(struct Body<'tcx> { basic_blocks, source_scopes, source_scope_local_data, - promoted, yield_ty, generator_drop, generator_layout, @@ -3032,7 +3024,6 @@ BraceStructTypeFoldableImpl! { basic_blocks, source_scopes, source_scope_local_data, - promoted, yield_ty, generator_drop, generator_layout, diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index 5ab1b90642a6a..e1dbaeb5b173d 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -110,7 +110,7 @@ rustc_queries! { no_hash } - query mir_validated(_: DefId) -> &'tcx Steal> { + query mir_validated(_: DefId) -> (&'tcx Steal>, &'tcx Steal>>) { no_hash } @@ -125,7 +125,17 @@ rustc_queries! { } } - query promoted_mir(key: DefId) -> &'tcx IndexVec> { } + query promoted_mir(key: DefId) -> &'tcx IndexVec> { + cache_on_disk_if { key.is_local() } + load_cached(tcx, id) { + let promoted: Option< + rustc_data_structures::indexed_vec::IndexVec< + crate::mir::Promoted, + crate::mir::Body<'tcx> + >> = tcx.queries.on_disk_cache.try_load_query_result(tcx, id); + promoted.map(|p| &*tcx.arena.alloc(p)) + } + } } TypeChecking { diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index e72efdb057ab1..9f316e93111a3 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -21,7 +21,7 @@ use crate::middle::cstore::EncodedMetadata; use crate::middle::lang_items; use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault}; use crate::middle::stability; -use crate::mir::{Body, interpret, ProjectionKind}; +use crate::mir::{Body, interpret, ProjectionKind, Promoted}; use crate::mir::interpret::{ConstValue, Allocation, Scalar}; use crate::ty::subst::{Kind, InternalSubsts, SubstsRef, Subst}; use crate::ty::ReprOptions; @@ -1096,6 +1096,16 @@ impl<'tcx> TyCtxt<'tcx> { self.arena.alloc(Steal::new(mir)) } + pub fn alloc_steal_promoted(self, promoted: IndexVec>) -> + &'tcx Steal>> { + self.arena.alloc(Steal::new(promoted)) + } + + pub fn intern_promoted(self, promoted: IndexVec>) -> + &'tcx IndexVec> { + self.arena.alloc(promoted) + } + pub fn alloc_adt_def( self, did: DefId, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index a66da32fa4d75..7aeeef00ea934 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -136,6 +136,15 @@ provide! { <'tcx> tcx, def_id, other, cdata, mir } + promoted_mir => { + let promoted = cdata.maybe_get_promoted_mir(tcx, def_id.index).unwrap_or_else(|| { + bug!("get_promoted_mir: missing promoted MIR for `{:?}`", def_id) + }); + + let promoted = tcx.arena.alloc(promoted); + + promoted + } mir_const_qualif => { (cdata.mir_const_qualif(def_id.index), tcx.arena.alloc(BitSet::new_empty(0))) } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index da96728d2dec9..128e30be79929 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -3,6 +3,7 @@ use crate::cstore::{self, CrateMetadata, MetadataBlob, NativeLibrary, ForeignModule, FullProcMacro}; use crate::schema::*; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::sync::{Lrc, ReadGuard}; use rustc::hir::map::{DefKey, DefPath, DefPathData, DefPathHash}; use rustc::hir; @@ -17,7 +18,7 @@ use rustc::mir::interpret::AllocDecodingSession; use rustc::session::Session; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::codec::TyDecoder; -use rustc::mir::Body; +use rustc::mir::{Body, Promoted}; use rustc::util::captures::Captures; use std::io; @@ -923,6 +924,13 @@ impl<'a, 'tcx> CrateMetadata { } } + pub fn maybe_get_promoted_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Option>> { + match self.is_proc_macro(id) { + true => None, + false => self.entry(id).promoted_mir.map(|promoted| promoted.decode((self, tcx)),) + } + } + pub fn mir_const_qualif(&self, id: DefIndex) -> u8 { match self.entry(id).kind { EntryKind::Const(qualif, _) | diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index df3320c64a960..f3863fd788ae0 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -8,6 +8,7 @@ use rustc::hir::def_id::{CrateNum, CRATE_DEF_INDEX, DefIndex, DefId, LocalDefId, use rustc::hir::GenericParamKind; use rustc::hir::map::definitions::DefPathTable; use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::indexed_vec::IndexVec; use rustc::middle::dependency_format::Linkage; use rustc::middle::exported_symbols::{ExportedSymbol, SymbolExportLevel, metadata_symbol_name}; @@ -623,6 +624,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: self.encode_optimized_mir(def_id), + promoted_mir: self.encode_promoted_mir(def_id), } } @@ -677,6 +679,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: self.encode_optimized_mir(def_id), + promoted_mir: self.encode_promoted_mir(def_id), } } @@ -713,7 +716,8 @@ impl EncodeContext<'tcx> { predicates: None, predicates_defined_on: None, - mir: None + mir: None, + promoted_mir: None, } } @@ -748,6 +752,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: None, + promoted_mir: None, } } @@ -808,6 +813,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: self.encode_optimized_mir(def_id), + promoted_mir: self.encode_promoted_mir(def_id), } } @@ -923,6 +929,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: self.encode_optimized_mir(def_id), + promoted_mir: self.encode_promoted_mir(def_id), } } @@ -1022,6 +1029,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: if mir { self.encode_optimized_mir(def_id) } else { None }, + promoted_mir: if mir { self.encode_promoted_mir(def_id) } else { None }, } } @@ -1052,6 +1060,16 @@ impl EncodeContext<'tcx> { } } + fn encode_promoted_mir(&mut self, def_id: DefId) -> Option>>> { + debug!("EncodeContext::encode_promoted_mir({:?})", def_id); + if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) { + let promoted = self.tcx.promoted_mir(def_id); + Some(self.lazy(promoted)) + } else { + None + } + } + // Encodes the inherent implementations of a structure, enumeration, or trait. fn encode_inherent_implementations(&mut self, def_id: DefId) -> Lazy<[DefIndex]> { debug!("EncodeContext::encode_inherent_implementations({:?})", def_id); @@ -1202,6 +1220,20 @@ impl EncodeContext<'tcx> { hir::ItemKind::Use(..) => bug!("cannot encode info for item {:?}", item), }; + let mir = match item.node { + hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => true, + hir::ItemKind::Fn(_, header, ..) => { + let generics = tcx.generics_of(def_id); + let needs_inline = + (generics.requires_monomorphization(tcx) || + tcx.codegen_fn_attrs(def_id).requests_inline()) && + !self.metadata_output_only(); + let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; + needs_inline || header.constness == hir::Constness::Const || always_encode_mir + } + _ => false, + }; + Entry { kind, visibility: self.lazy(ty::Visibility::from_hir(&item.vis, item.hir_id, tcx)), @@ -1301,29 +1333,8 @@ impl EncodeContext<'tcx> { _ => None, // not *wrong* for other kinds of items, but not needed }, - mir: match item.node { - hir::ItemKind::Static(..) => { - self.encode_optimized_mir(def_id) - } - hir::ItemKind::Const(..) => self.encode_optimized_mir(def_id), - hir::ItemKind::Fn(_, header, ..) => { - let generics = tcx.generics_of(def_id); - let needs_inline = - (generics.requires_monomorphization(tcx) || - tcx.codegen_fn_attrs(def_id).requests_inline()) && - !self.metadata_output_only(); - let always_encode_mir = self.tcx.sess.opts.debugging_opts.always_encode_mir; - if needs_inline - || header.constness == hir::Constness::Const - || always_encode_mir - { - self.encode_optimized_mir(def_id) - } else { - None - } - } - _ => None, - }, + mir: if mir { self.encode_optimized_mir(def_id) } else { None }, + promoted_mir: if mir { self.encode_promoted_mir(def_id) } else { None }, } } @@ -1350,6 +1361,7 @@ impl EncodeContext<'tcx> { predicates: None, predicates_defined_on: None, mir: None, + promoted_mir: None, } } @@ -1376,6 +1388,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: None, + promoted_mir: None, } } @@ -1436,6 +1449,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: self.encode_optimized_mir(def_id), + promoted_mir: self.encode_promoted_mir(def_id), } } @@ -1464,6 +1478,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: self.encode_optimized_mir(def_id), + promoted_mir: self.encode_promoted_mir(def_id), } } @@ -1675,6 +1690,7 @@ impl EncodeContext<'tcx> { predicates_defined_on: None, mir: None, + promoted_mir: None, } } } diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index f37877b437e15..72a4b527c93d0 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -11,6 +11,7 @@ use rustc::session::CrateDisambiguator; use rustc::session::config::SymbolManglingVersion; use rustc::ty::{self, Ty, ReprOptions}; use rustc_target::spec::{PanicStrategy, TargetTriple}; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::svh::Svh; use syntax::{ast, attr}; @@ -231,6 +232,7 @@ pub struct Entry<'tcx> { pub predicates_defined_on: Option>>, pub mir: Option>>, + pub promoted_mir: Option>>>, } #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index de27aec2b2990..05b396681ac06 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -13,7 +13,7 @@ use rustc::mir::{ ClearCrossCrate, Local, Location, Body, Mutability, Operand, Place, PlaceBase, PlaceRef, Static, StaticKind }; -use rustc::mir::{Field, Projection, ProjectionElem, Rvalue, Statement, StatementKind}; +use rustc::mir::{Field, Projection, ProjectionElem, Promoted, Rvalue, Statement, StatementKind}; use rustc::mir::{Terminator, TerminatorKind}; use rustc::ty::query::Providers; use rustc::ty::{self, TyCtxt}; @@ -22,6 +22,7 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, Level}; use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::graph::dominators::Dominators; +use rustc_data_structures::indexed_vec::IndexVec; use smallvec::SmallVec; use std::collections::BTreeMap; @@ -86,12 +87,13 @@ pub fn provide(providers: &mut Providers<'_>) { } fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> BorrowCheckResult<'_> { - let input_body = tcx.mir_validated(def_id); + let (input_body, promoted) = tcx.mir_validated(def_id); debug!("run query mir_borrowck: {}", tcx.def_path_str(def_id)); let opt_closure_req = tcx.infer_ctxt().enter(|infcx| { let input_body: &Body<'_> = &input_body.borrow(); - do_mir_borrowck(&infcx, input_body, def_id) + let promoted: &IndexVec<_, _> = &promoted.borrow(); + do_mir_borrowck(&infcx, input_body, promoted, def_id) }); debug!("mir_borrowck done"); @@ -101,6 +103,7 @@ fn mir_borrowck(tcx: TyCtxt<'_>, def_id: DefId) -> BorrowCheckResult<'_> { fn do_mir_borrowck<'a, 'tcx>( infcx: &InferCtxt<'a, 'tcx>, input_body: &Body<'tcx>, + input_promoted: &IndexVec>, def_id: DefId, ) -> BorrowCheckResult<'tcx> { debug!("do_mir_borrowck(def_id = {:?})", def_id); @@ -147,7 +150,8 @@ fn do_mir_borrowck<'a, 'tcx>( // be modified (in place) to contain non-lexical lifetimes. It // will have a lifetime tied to the inference context. let mut body: Body<'tcx> = input_body.clone(); - let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body); + let mut promoted: IndexVec> = input_promoted.clone(); + let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body, &mut promoted); let body = &body; // no further changes let location_table = &LocationTable::new(body); @@ -184,6 +188,7 @@ fn do_mir_borrowck<'a, 'tcx>( def_id, free_regions, body, + &promoted, &upvars, location_table, param_env, diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index d65cdde303ca0..11ec154e5b5c1 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -11,8 +11,9 @@ use crate::transform::MirSource; use crate::borrow_check::Upvar; use rustc::hir::def_id::DefId; use rustc::infer::InferCtxt; -use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Local, Body}; +use rustc::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, Local, Body, Promoted}; use rustc::ty::{self, RegionKind, RegionVid}; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_errors::Diagnostic; use std::fmt::Debug; use std::env; @@ -52,6 +53,7 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( def_id: DefId, param_env: ty::ParamEnv<'tcx>, body: &mut Body<'tcx>, + promoted: &mut IndexVec>, ) -> UniversalRegions<'tcx> { debug!("replace_regions_in_mir(def_id={:?})", def_id); @@ -59,7 +61,7 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>( let universal_regions = UniversalRegions::new(infcx, def_id, param_env); // Replace all remaining regions with fresh inference variables. - renumber::renumber_mir(infcx, body); + renumber::renumber_mir(infcx, body, promoted); let source = MirSource::item(def_id); mir_util::dump_mir(infcx.tcx, None, "renumber", &0, source, body, |_, _| Ok(())); @@ -75,6 +77,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( def_id: DefId, universal_regions: UniversalRegions<'tcx>, body: &Body<'tcx>, + promoted: &IndexVec>, upvars: &[Upvar], location_table: &LocationTable, param_env: ty::ParamEnv<'tcx>, @@ -105,6 +108,7 @@ pub(in crate::borrow_check) fn compute_regions<'cx, 'tcx>( infcx, param_env, body, + promoted, def_id, &universal_regions, location_table, diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index c1d1185cf177a..4e3ffb7af1601 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -1,16 +1,18 @@ use rustc::ty::subst::SubstsRef; use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, Ty, TypeFoldable}; -use rustc::mir::{Location, Body}; +use rustc::mir::{Location, Body, Promoted}; use rustc::mir::visit::{MutVisitor, TyContext}; use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; +use rustc_data_structures::indexed_vec::IndexVec; /// Replaces all free regions appearing in the MIR with fresh /// inference variables, returning the number of variables created. -pub fn renumber_mir<'tcx>(infcx: &InferCtxt<'_, 'tcx>, body: &mut Body<'tcx>) { +pub fn renumber_mir<'tcx>(infcx: &InferCtxt<'_, 'tcx>, body: &mut Body<'tcx>, promoted: &mut IndexVec>) { debug!("renumber_mir()"); debug!("renumber_mir: body.arg_count={:?}", body.arg_count); let mut visitor = NLLVisitor { infcx }; + visitor.visit_promoted(promoted); visitor.visit_body(body); } @@ -41,17 +43,16 @@ impl<'a, 'tcx> NLLVisitor<'a, 'tcx> { { renumber_regions(self.infcx, value) } -} -impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> { - fn visit_body(&mut self, body: &mut Body<'tcx>) { - for promoted in body.promoted.iter_mut() { - self.visit_body(promoted); + fn visit_promoted(&mut self, promoted: &mut IndexVec>) { + debug!("visiting promoted mir"); + for body in promoted.iter_mut() { + self.visit_body(body); } - - self.super_body(body); } +} +impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> { fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) { debug!("visit_ty(ty={:?}, ty_context={:?})", ty, ty_context); diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 9ff0c6ca6a546..4b4477756bacc 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -112,6 +112,7 @@ pub(crate) fn type_check<'tcx>( infcx: &InferCtxt<'_, 'tcx>, param_env: ty::ParamEnv<'tcx>, body: &Body<'tcx>, + promoted: &IndexVec>, mir_def_id: DefId, universal_regions: &Rc>, location_table: &LocationTable, @@ -157,6 +158,7 @@ pub(crate) fn type_check<'tcx>( mir_def_id, param_env, body, + promoted, ®ion_bound_pairs, implicit_region_bound, &mut borrowck_context, @@ -180,6 +182,7 @@ fn type_check_internal<'a, 'tcx, R>( mir_def_id: DefId, param_env: ty::ParamEnv<'tcx>, body: &'a Body<'tcx>, + promoted: &'a IndexVec>, region_bound_pairs: &'a RegionBoundPairs<'tcx>, implicit_region_bound: ty::Region<'tcx>, borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>, @@ -197,7 +200,7 @@ fn type_check_internal<'a, 'tcx, R>( universal_region_relations, ); let errors_reported = { - let mut verifier = TypeVerifier::new(&mut checker, body); + let mut verifier = TypeVerifier::new(&mut checker, body, promoted); verifier.visit_body(body); verifier.errors_reported }; @@ -254,6 +257,7 @@ enum FieldAccessError { struct TypeVerifier<'a, 'b, 'tcx> { cx: &'a mut TypeChecker<'b, 'tcx>, body: &'b Body<'tcx>, + promoted: &'b IndexVec>, last_span: Span, mir_def_id: DefId, errors_reported: bool, @@ -380,9 +384,10 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { - fn new(cx: &'a mut TypeChecker<'b, 'tcx>, body: &'b Body<'tcx>) -> Self { + fn new(cx: &'a mut TypeChecker<'b, 'tcx>, body: &'b Body<'tcx>, promoted: &'b IndexVec>) -> Self { TypeVerifier { body, + promoted, mir_def_id: cx.mir_def_id, cx, last_span: body.span, @@ -442,7 +447,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { match kind { StaticKind::Promoted(promoted) => { if !self.errors_reported { - let promoted_body = &self.body.promoted[*promoted]; + let promoted_body = &self.promoted[*promoted]; self.sanitize_promoted(promoted_body, location); let promoted_ty = promoted_body.return_ty(); diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 4e970aee42cf4..3e3558fc60062 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -763,7 +763,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.cfg.basic_blocks, self.source_scopes, ClearCrossCrate::Set(self.source_scope_local_data), - IndexVec::new(), yield_ty, self.local_decls, self.canonical_user_type_annotations, diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 76ee76a74562b..4ab5c9cc1c498 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -667,7 +667,7 @@ pub fn const_eval_raw_provider<'tcx>( let res = ecx.load_mir(cid.instance.def); res.map(|body| { if let Some(index) = cid.promoted { - &body.promoted[index] + &tcx.promoted_mir(def_id)[index] } else { body } diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 12d763bb7910a..9d80163f30f9d 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -185,7 +185,7 @@ use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind, Instance}; use rustc::ty::print::obsolete::DefPathBasedNames; use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast}; use rustc::session::config::EntryFnType; -use rustc::mir::{self, Location, PlaceBase, Promoted, Static, StaticKind}; +use rustc::mir::{self, Location, PlaceBase, Static, StaticKind}; use rustc::mir::visit::Visitor as MirVisitor; use rustc::mir::mono::{MonoItem, InstantiationMode}; use rustc::mir::interpret::{Scalar, GlobalId, GlobalAlloc, ErrorHandled}; @@ -1222,6 +1222,7 @@ fn collect_neighbours<'tcx>( instance: Instance<'tcx>, output: &mut Vec>, ) { + debug!("collect_neighbours: {:?}", instance.def_id()); let body = tcx.instance_mir(instance.def); MirNeighborCollector { @@ -1230,20 +1231,22 @@ fn collect_neighbours<'tcx>( output, param_substs: instance.substs, }.visit_body(&body); - let param_env = ty::ParamEnv::reveal_all(); - for i in 0..body.promoted.len() { - use rustc_data_structures::indexed_vec::Idx; - let i = Promoted::new(i); - let cid = GlobalId { - instance, - promoted: Some(i), - }; - match tcx.const_eval(param_env.and(cid)) { - Ok(val) => collect_const(tcx, val, instance.substs, output), - Err(ErrorHandled::Reported) => {}, - Err(ErrorHandled::TooGeneric) => span_bug!( - body.promoted[i].span, "collection encountered polymorphic constant", - ), + + if let ty::InstanceDef::Item(def_id) = instance.def { + let param_env = ty::ParamEnv::reveal_all(); + let promoted = tcx.promoted_mir(def_id); + for (promoted, promoted_body) in promoted.iter_enumerated() { + let cid = GlobalId { + instance, + promoted: Some(promoted), + }; + match tcx.const_eval(param_env.and(cid)) { + Ok(val) => collect_const(tcx, val, instance.substs, output), + Err(ErrorHandled::Reported) => {}, + Err(ErrorHandled::TooGeneric) => span_bug!( + promoted_body.span, "collection encountered polymorphic constant", + ), + } } } } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 3e02f6c3725fd..9d31015f84558 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -201,7 +201,6 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) SourceScopeData { span: span, parent_scope: None }, 1 ), ClearCrossCrate::Clear, - IndexVec::new(), None, local_decls_for_sig(&sig, span), IndexVec::new(), @@ -369,7 +368,6 @@ impl CloneShimBuilder<'tcx> { SourceScopeData { span: self.span, parent_scope: None }, 1 ), ClearCrossCrate::Clear, - IndexVec::new(), None, self.local_decls, IndexVec::new(), @@ -813,7 +811,6 @@ fn build_call_shim<'tcx>( SourceScopeData { span: span, parent_scope: None }, 1 ), ClearCrossCrate::Clear, - IndexVec::new(), None, local_decls, IndexVec::new(), @@ -900,7 +897,6 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> &Body<'_> { SourceScopeData { span: span, parent_scope: None }, 1 ), ClearCrossCrate::Clear, - IndexVec::new(), None, local_decls, IndexVec::new(), diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index ac442a496e535..790595b4feef9 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -8,7 +8,7 @@ use rustc::mir::{ AggregateKind, Constant, Location, Place, PlaceBase, Body, Operand, Rvalue, Local, NullOp, UnOp, StatementKind, Statement, LocalKind, Static, StaticKind, TerminatorKind, Terminator, ClearCrossCrate, SourceInfo, BinOp, ProjectionElem, - SourceScope, SourceScopeLocalData, LocalDecl, Promoted, + SourceScope, SourceScopeLocalData, LocalDecl, }; use rustc::mir::visit::{ Visitor, PlaceContext, MutatingUseContext, MutVisitor, NonMutatingUseContext, @@ -64,17 +64,12 @@ impl<'tcx> MirPass<'tcx> for ConstProp { &mut body.source_scope_local_data, ClearCrossCrate::Clear ); - let promoted = std::mem::replace( - &mut body.promoted, - IndexVec::new() - ); let dummy_body = &Body::new( body.basic_blocks().clone(), Default::default(), ClearCrossCrate::Clear, - Default::default(), None, body.local_decls.clone(), Default::default(), @@ -92,22 +87,17 @@ impl<'tcx> MirPass<'tcx> for ConstProp { body, dummy_body, source_scope_local_data, - promoted, tcx, source ); optimization_finder.visit_body(body); // put back the data we stole from `mir` - let (source_scope_local_data, promoted) = optimization_finder.release_stolen_data(); + let source_scope_local_data = optimization_finder.release_stolen_data(); std::mem::replace( &mut body.source_scope_local_data, source_scope_local_data ); - std::mem::replace( - &mut body.promoted, - promoted - ); trace!("ConstProp done for {:?}", source.def_id()); } @@ -124,7 +114,6 @@ struct ConstPropagator<'mir, 'tcx> { param_env: ParamEnv<'tcx>, source_scope_local_data: ClearCrossCrate>, local_decls: IndexVec>, - promoted: IndexVec>, } impl<'mir, 'tcx> LayoutOf for ConstPropagator<'mir, 'tcx> { @@ -155,7 +144,6 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { body: &Body<'tcx>, dummy_body: &'mir Body<'tcx>, source_scope_local_data: ClearCrossCrate>, - promoted: IndexVec>, tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, ) -> ConstPropagator<'mir, 'tcx> { @@ -184,17 +172,11 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { source_scope_local_data, //FIXME(wesleywiser) we can't steal this because `Visitor::super_visit_body()` needs it local_decls: body.local_decls.clone(), - promoted, } } - fn release_stolen_data( - self, - ) -> ( - ClearCrossCrate>, - IndexVec>, - ) { - (self.source_scope_local_data, self.promoted) + fn release_stolen_data(self) -> ClearCrossCrate> { + self.source_scope_local_data } fn get_const(&self, local: Local) -> Option> { @@ -318,7 +300,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { // cannot use `const_eval` here, because that would require having the MIR // for the current function available, but we're producing said MIR right now let res = self.use_ecx(source_info, |this| { - let body = &this.promoted[*promoted]; + let body = &this.tcx.promoted_mir(this.source.def_id())[*promoted]; eval_promoted(this.tcx, cid, body, this.param_env) })?; trace!("evaluated promoted {:?} to {:?}", promoted, res); diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 57aac2b0eac99..19a8769ce1633 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -394,7 +394,7 @@ impl Inliner<'tcx> { let mut local_map = IndexVec::with_capacity(callee_body.local_decls.len()); let mut scope_map = IndexVec::with_capacity(callee_body.source_scopes.len()); - let mut promoted_map = IndexVec::with_capacity(callee_body.promoted.len()); + let promoted_map = IndexVec::with_capacity(self.tcx.promoted_mir(callsite.callee).len()); for mut scope in callee_body.source_scopes.iter().cloned() { if scope.parent_scope.is_none() { @@ -420,9 +420,10 @@ impl Inliner<'tcx> { local_map.push(idx); } - promoted_map.extend( - callee_body.promoted.iter().cloned().map(|p| caller_body.promoted.push(p)) - ); + //TODO fixme + //promoted_map.extend( + // self.tcx.promoted_mir(callsite.callee).iter().cloned().map(|p| caller_body.promoted.push(p)) + //); // If the call is something like `a[*i] = f(i)`, where // `i : &mut usize`, then just duplicating the `a[*i]` diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index 255635b933385..a78e78331ee3f 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -184,13 +184,6 @@ pub fn run_passes( }; run_passes(body, None); - - for (index, promoted_body) in body.promoted.iter_enumerated_mut() { - run_passes(promoted_body, Some(index)); - - //Let's make sure we don't miss any nested instances - assert!(promoted_body.promoted.is_empty()) - } } fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { @@ -207,7 +200,7 @@ fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { tcx.alloc_steal_mir(body) } -fn mir_validated(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Steal> { +fn mir_validated(tcx: TyCtxt<'tcx>, def_id: DefId) -> (&'tcx Steal>, &'tcx Steal>>) { let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); if let hir::BodyOwnerKind::Const = tcx.hir().body_owner_kind(hir_id) { // Ensure that we compute the `mir_const_qualif` for constants at @@ -216,12 +209,14 @@ fn mir_validated(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Steal> { } let mut body = tcx.mir_const(def_id).steal(); + let qualify_and_promote_pass = qualify_consts::QualifyAndPromoteConstants::default(); run_passes(tcx, &mut body, InstanceDef::Item(def_id), MirPhase::Validated, &[ // What we need to run borrowck etc. - &qualify_consts::QualifyAndPromoteConstants, + &qualify_and_promote_pass, &simplify::SimplifyCfg::new("qualify-consts"), ]); - tcx.alloc_steal_mir(body) + let promoted = qualify_and_promote_pass.promoted.into_inner(); + (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted.unwrap_or_else(|| IndexVec::new()))) } fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { @@ -241,7 +236,8 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { tcx.ensure().borrowck(def_id); } - let mut body = tcx.mir_validated(def_id).steal(); + let (body, _) = tcx.mir_validated(def_id); + let mut body = body.steal(); run_passes(tcx, &mut body, InstanceDef::Item(def_id), MirPhase::Optimized, &[ // Remove all things only needed by analysis &no_landing_pads::NoLandingPads, @@ -297,6 +293,66 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { } fn promoted_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx IndexVec> { - let body = tcx.optimized_mir(def_id); - &body.promoted + if tcx.is_constructor(def_id) { + return tcx.intern_promoted(IndexVec::new()); + } + + tcx.ensure().mir_borrowck(def_id); + let (_, promoted) = tcx.mir_validated(def_id); + let mut promoted = promoted.steal(); + + for mut body in promoted.iter_mut() { + run_passes(tcx, &mut body, InstanceDef::Item(def_id), MirPhase::Optimized, &[ + // Remove all things only needed by analysis + &no_landing_pads::NoLandingPads, + &simplify_branches::SimplifyBranches::new("initial"), + &remove_noop_landing_pads::RemoveNoopLandingPads, + &cleanup_post_borrowck::CleanupNonCodegenStatements, + + &simplify::SimplifyCfg::new("early-opt"), + + // These next passes must be executed together + &add_call_guards::CriticalCallEdges, + &elaborate_drops::ElaborateDrops, + &no_landing_pads::NoLandingPads, + // AddMovesForPackedDrops needs to run after drop + // elaboration. + &add_moves_for_packed_drops::AddMovesForPackedDrops, + // AddRetag needs to run after ElaborateDrops, and it needs + // an AllCallEdges pass right before it. Otherwise it should + // run fairly late, but before optimizations begin. + &add_call_guards::AllCallEdges, + &add_retag::AddRetag, + + &simplify::SimplifyCfg::new("elaborate-drops"), + + // No lifetime analysis based on borrowing can be done from here on out. + + // From here on out, regions are gone. + &erase_regions::EraseRegions, + + // Optimizations begin. + &uniform_array_move_out::RestoreSubsliceArrayMoveOut, + &inline::Inline, + + // Lowering generator control-flow and variables + // has to happen before we do anything else to them. + &generator::StateTransform, + + &instcombine::InstCombine, + &const_prop::ConstProp, + &simplify_branches::SimplifyBranches::new("after-const-prop"), + &deaggregator::Deaggregator, + ©_prop::CopyPropagation, + &simplify_branches::SimplifyBranches::new("after-copy-prop"), + &remove_noop_landing_pads::RemoveNoopLandingPads, + &simplify::SimplifyCfg::new("final"), + &simplify::SimplifyLocals, + + &add_call_guards::CriticalCallEdges, + &dump_mir::Marker("PreCodegen"), + ]); + } + + tcx.intern_promoted(promoted) } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 3090b63a7e993..7015e2c087faa 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -293,10 +293,10 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { new_temp } - fn promote_candidate(mut self, candidate: Candidate) { + fn promote_candidate(mut self, candidate: Candidate, next_promoted_id: usize) -> Option> { let mut operand = { let promoted = &mut self.promoted; - let promoted_id = Promoted::new(self.source.promoted.len()); + let promoted_id = Promoted::new(next_promoted_id); let mut promoted_place = |ty, span| { promoted.span = span; promoted.local_decls[RETURN_PLACE] = LocalDecl::new_return_place(ty, span); @@ -353,7 +353,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { // a function requiring a constant argument and as that constant value // providing a value whose computation contains another call to a function // requiring a constant argument. - TerminatorKind::Goto { .. } => return, + TerminatorKind::Goto { .. } => return None, _ => bug!() } } @@ -368,7 +368,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let span = self.promoted.span; self.assign(RETURN_PLACE, Rvalue::Use(operand), span); - self.source.promoted.push(self.promoted); + Some(self.promoted) } } @@ -389,10 +389,12 @@ pub fn promote_candidates<'tcx>( tcx: TyCtxt<'tcx>, mut temps: IndexVec, candidates: Vec, -) { +) -> IndexVec> { // Visit candidates in reverse, in case they're nested. debug!("promote_candidates({:?})", candidates); + let mut promotions = IndexVec::new(); + for candidate in candidates.into_iter().rev() { match candidate { Candidate::Repeat(Location { block, statement_index }) | @@ -426,7 +428,6 @@ pub fn promote_candidates<'tcx>( // memory usage? body.source_scopes.clone(), body.source_scope_local_data.clone(), - IndexVec::new(), None, initial_locals, IndexVec::new(), @@ -440,7 +441,10 @@ pub fn promote_candidates<'tcx>( temps: &mut temps, keep_original: false }; - promoter.promote_candidate(candidate); + + if let Some(promoted) = promoter.promote_candidate(candidate, promotions.len()) { + promotions.push(promoted); + } } // Eliminate assignments to, and drops of promoted temps. @@ -474,4 +478,6 @@ pub fn promote_candidates<'tcx>( _ => {} } } + + promotions } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 1fe45a2c4240b..dd4db479cc00b 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -25,6 +25,7 @@ use syntax::feature_gate::{emit_feature_err, GateIssue}; use syntax::symbol::sym; use syntax_pos::{Span, DUMMY_SP}; +use std::cell::Cell; use std::fmt; use std::ops::{Deref, Index, IndexMut}; use std::usize; @@ -1570,9 +1571,19 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> (u8, &BitSet) { Checker::new(tcx, def_id, body, Mode::Const).check_const() } -pub struct QualifyAndPromoteConstants; +pub struct QualifyAndPromoteConstants<'tcx> { + pub promoted: Cell>>>, +} + +impl<'tcx> Default for QualifyAndPromoteConstants<'tcx> { + fn default() -> Self { + QualifyAndPromoteConstants { + promoted: Cell::new(None), + } + } +} -impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants { +impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { fn run_pass(&self, tcx: TyCtxt<'tcx>, src: MirSource<'tcx>, body: &mut Body<'tcx>) { // There's not really any point in promoting errorful MIR. if body.return_ty().references_error() { @@ -1649,7 +1660,9 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants { }; // Do the actual promotion, now that we know what's viable. - promote_consts::promote_candidates(body, tcx, temps, candidates); + self.promoted.set( + Some(promote_consts::promote_candidates(body, tcx, temps, candidates)) + ); } else { if !body.control_flow_destroyed.is_empty() { let mut locals = body.vars_iter(); From f13faf58d92d2d6154acc8cf50bf5d237a3a4118 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 5 Aug 2019 20:01:59 -0400 Subject: [PATCH 03/10] Remove eval_promoted const-prop hack --- src/librustc_mir/const_eval.rs | 23 +++------------------- src/librustc_mir/interpret/eval_context.rs | 6 +++++- src/librustc_mir/transform/const_prop.rs | 7 ++----- 3 files changed, 10 insertions(+), 26 deletions(-) diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 4ab5c9cc1c498..67d63e52b2bfa 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -49,17 +49,6 @@ pub(crate) fn mk_eval_cx<'mir, 'tcx>( InterpCx::new(tcx.at(span), param_env, CompileTimeInterpreter::new(), Default::default()) } -pub(crate) fn eval_promoted<'mir, 'tcx>( - tcx: TyCtxt<'tcx>, - cid: GlobalId<'tcx>, - body: &'mir mir::Body<'tcx>, - param_env: ty::ParamEnv<'tcx>, -) -> InterpResult<'tcx, MPlaceTy<'tcx>> { - let span = tcx.def_span(cid.instance.def_id()); - let mut ecx = mk_eval_cx(tcx, span, param_env); - eval_body_using_ecx(&mut ecx, cid, body, param_env) -} - fn op_to_const<'tcx>( ecx: &CompileTimeEvalContext<'_, 'tcx>, op: OpTy<'tcx>, @@ -360,7 +349,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, } } // This is a const fn. Call it. - Ok(Some(match ecx.load_mir(instance.def) { + Ok(Some(match ecx.load_mir(instance.def, None) { Ok(body) => body, Err(err) => { if let err_unsup!(NoMirFor(ref path)) = err.kind { @@ -664,14 +653,8 @@ pub fn const_eval_raw_provider<'tcx>( Default::default() ); - let res = ecx.load_mir(cid.instance.def); - res.map(|body| { - if let Some(index) = cid.promoted { - &tcx.promoted_mir(def_id)[index] - } else { - body - } - }).and_then( + let res = ecx.load_mir(cid.instance.def, cid.promoted); + res.and_then( |body| eval_body_using_ecx(&mut ecx, cid, body, key.param_env) ).and_then(|place| { Ok(RawConst { diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs index 6f48396cdd7cf..ac01d436bdc9b 100644 --- a/src/librustc_mir/interpret/eval_context.rs +++ b/src/librustc_mir/interpret/eval_context.rs @@ -294,6 +294,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { pub fn load_mir( &self, instance: ty::InstanceDef<'tcx>, + promoted: Option, ) -> InterpResult<'tcx, &'tcx mir::Body<'tcx>> { // do not continue if typeck errors occurred (can only occur in local crate) let did = instance.def_id(); @@ -303,7 +304,10 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> { { throw_inval!(TypeckError) } - trace!("load mir {:?}", instance); + trace!("load mir(instance={:?}, promoted={:?})", instance, promoted); + if let Some(promoted) = promoted { + return Ok(&self.tcx.promoted_mir(did)[promoted]); + } match instance { ty::InstanceDef::Item(def_id) => if self.tcx.is_mir_available(did) { Ok(self.tcx.optimized_mir(did)) diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 790595b4feef9..9aeef16ba1e38 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -27,7 +27,7 @@ use crate::interpret::{ ImmTy, MemoryKind, StackPopCleanup, LocalValue, LocalState, }; use crate::const_eval::{ - CompileTimeInterpreter, error_to_const_error, eval_promoted, mk_eval_cx, + CompileTimeInterpreter, error_to_const_error, mk_eval_cx, }; use crate::transform::{MirPass, MirSource}; @@ -297,11 +297,8 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { instance, promoted: Some(*promoted), }; - // cannot use `const_eval` here, because that would require having the MIR - // for the current function available, but we're producing said MIR right now let res = self.use_ecx(source_info, |this| { - let body = &this.tcx.promoted_mir(this.source.def_id())[*promoted]; - eval_promoted(this.tcx, cid, body, this.param_env) + this.ecx.const_eval_raw(cid) })?; trace!("evaluated promoted {:?} to {:?}", promoted, res); res.into() From 4d62545687d0c10577eb75c058c0662e6b261395 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Mon, 5 Aug 2019 21:11:55 -0400 Subject: [PATCH 04/10] Move def_id out add substsref --- src/librustc/mir/mod.rs | 18 ++++---- src/librustc/mir/visit.rs | 2 +- src/librustc_codegen_ssa/mir/block.rs | 6 ++- src/librustc_codegen_ssa/mir/place.rs | 21 +++++++--- .../borrow_check/error_reporting.rs | 8 ++-- src/librustc_mir/borrow_check/mod.rs | 9 ++-- .../borrow_check/mutability_errors.rs | 5 ++- .../borrow_check/nll/type_check/mod.rs | 8 ++-- src/librustc_mir/borrow_check/place_ext.rs | 4 +- .../borrow_check/places_conflict.rs | 8 ++-- src/librustc_mir/build/expr/as_place.rs | 3 +- src/librustc_mir/interpret/place.rs | 6 +-- src/librustc_mir/monomorphize/collector.rs | 41 +++++++++---------- src/librustc_mir/transform/check_unsafety.rs | 4 +- src/librustc_mir/transform/const_prop.rs | 2 +- src/librustc_mir/transform/inline.rs | 24 ++++------- src/librustc_mir/transform/promote_consts.rs | 41 +++++++++++++++---- src/librustc_mir/transform/qualify_consts.rs | 16 ++++---- .../transform/qualify_min_const_fn.rs | 4 +- 19 files changed, 134 insertions(+), 96 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 66f5eaeeda1c7..69e98583b191c 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1732,20 +1732,22 @@ pub enum PlaceBase<'tcx> { #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub struct Static<'tcx> { pub ty: Ty<'tcx>, - pub kind: StaticKind, + pub kind: StaticKind<'tcx>, + pub def_id: DefId, } #[derive( Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, RustcEncodable, RustcDecodable, )] -pub enum StaticKind { - Promoted(Promoted), - Static(DefId), +pub enum StaticKind<'tcx> { + Promoted(Promoted, SubstsRef<'tcx>), + Static, } impl_stable_hash_for!(struct Static<'tcx> { ty, - kind + kind, + def_id }); /// The `Projection` data structure defines things of the form `base.x`, `*b` or `b[index]`. @@ -2106,10 +2108,12 @@ impl Debug for PlaceBase<'_> { fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result { match *self { PlaceBase::Local(id) => write!(fmt, "{:?}", id), - PlaceBase::Static(box self::Static { ty, kind: StaticKind::Static(def_id) }) => { + PlaceBase::Static(box self::Static { ty, kind: StaticKind::Static, def_id }) => { write!(fmt, "({}: {:?})", ty::tls::with(|tcx| tcx.def_path_str(def_id)), ty) } - PlaceBase::Static(box self::Static { ty, kind: StaticKind::Promoted(promoted) }) => { + PlaceBase::Static(box self::Static { + ty, kind: StaticKind::Promoted(promoted, _), def_id: _ + }) => { write!(fmt, "({:?}: {:?})", promoted, ty) } } diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index 2d16e7bcc8371..ac0e784d8bd12 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -708,7 +708,7 @@ macro_rules! make_mir_visitor { PlaceBase::Local(local) => { self.visit_local(local, context, location); } - PlaceBase::Static(box Static { kind: _, ty }) => { + PlaceBase::Static(box Static { kind: _, ty, def_id: _ }) => { self.visit_ty(& $($mutability)? *ty, TyContext::Location(location)); } } diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs index dbce5ce4896a7..d2a7571fde1e2 100644 --- a/src/librustc_codegen_ssa/mir/block.rs +++ b/src/librustc_codegen_ssa/mir/block.rs @@ -609,8 +609,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Operand::Copy( Place { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(promoted), + kind: StaticKind::Promoted(promoted, _), ty, + def_id: _, }), projection: None, } @@ -618,8 +619,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::Operand::Move( Place { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(promoted), + kind: StaticKind::Promoted(promoted, _), ty, + def_id: _, }), projection: None, } diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index a632838ba2442..f7b94ea134cfc 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -1,4 +1,5 @@ -use rustc::ty::{self, Ty}; +use rustc::ty::{self, Instance, Ty}; +use rustc::ty::subst::Subst; use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; use rustc::mir; use rustc::mir::tcx::PlaceTy; @@ -454,16 +455,25 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::PlaceRef { base: mir::PlaceBase::Static(box mir::Static { ty, - kind: mir::StaticKind::Promoted(promoted), + kind: mir::StaticKind::Promoted(promoted, substs), + def_id, }), projection: None, } => { + debug!("promoted={:?}, def_id={:?}, substs={:?}, self_substs={:?}", promoted, def_id, substs, self.instance.substs); let param_env = ty::ParamEnv::reveal_all(); + let instance = Instance::new(*def_id, substs.subst(bx.tcx(), self.instance.substs)); + debug!("instance: {:?}", instance); let cid = mir::interpret::GlobalId { - instance: self.instance, + instance: instance, promoted: Some(*promoted), }; - let layout = cx.layout_of(self.monomorphize(&ty)); + let mono_ty = tcx.subst_and_normalize_erasing_regions( + instance.substs, + param_env, + ty, + ); + let layout = cx.layout_of(mono_ty); match bx.tcx().const_eval(param_env.and(cid)) { Ok(val) => match val.val { mir::interpret::ConstValue::ByRef { alloc, offset } => { @@ -487,7 +497,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { mir::PlaceRef { base: mir::PlaceBase::Static(box mir::Static { ty, - kind: mir::StaticKind::Static(def_id), + kind: mir::StaticKind::Static, + def_id, }), projection: None, } => { diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 99899aa390c4a..251d4b727c754 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -159,7 +159,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. }), projection: None, @@ -169,7 +169,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Static(def_id), + kind: StaticKind::Static, + def_id, .. }), projection: None, @@ -440,7 +441,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { pub fn is_place_thread_local(&self, place_ref: PlaceRef<'cx, 'tcx>) -> bool { if let PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Static(def_id), + kind: StaticKind::Static, + def_id, .. }), projection: None, diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 05b396681ac06..33cec78f3dfd5 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1467,13 +1467,13 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { assert!(root_place.projection.is_none()); let (might_be_alive, will_be_dropped) = match root_place.base { PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. }) => { (true, false) } PlaceBase::Static(box Static { - kind: StaticKind::Static(_), + kind: StaticKind::Static, .. }) => { // Thread-locals might be dropped after the function exits, but @@ -2155,7 +2155,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // `Place::Promoted` if the promotion weren't 100% legal. So we just forward this PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. }), projection: None, @@ -2167,7 +2167,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }), PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Static(def_id), + kind: StaticKind::Static, + def_id, .. }), projection: None, diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 937c6383be341..091b3eeb05f6c 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -149,7 +149,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. }), projection: None, @@ -158,7 +158,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Static(def_id), + kind: StaticKind::Static, + def_id, .. }), projection: None, diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 4b4477756bacc..35dd5b5d7eb19 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -421,7 +421,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { let mut place_ty = match place_base { PlaceBase::Local(index) => PlaceTy::from_ty(self.body.local_decls[*index].ty), - PlaceBase::Static(box Static { kind, ty: sty }) => { + PlaceBase::Static(box Static { kind, ty: sty, def_id }) => { let sty = self.sanitize_type(place, sty); let check_err = |verifier: &mut TypeVerifier<'a, 'b, 'tcx>, @@ -445,7 +445,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { }; }; match kind { - StaticKind::Promoted(promoted) => { + StaticKind::Promoted(promoted, _) => { if !self.errors_reported { let promoted_body = &self.promoted[*promoted]; self.sanitize_promoted(promoted_body, location); @@ -454,7 +454,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { check_err(self, place, promoted_ty, sty); } } - StaticKind::Static(def_id) => { + StaticKind::Static => { let ty = self.tcx().type_of(*def_id); let ty = self.cx.normalize(ty, location); @@ -471,7 +471,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { let is_promoted = match place { Place { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. }), projection: None, diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs index 72d5588c34120..5caba637ccc4a 100644 --- a/src/librustc_mir/borrow_check/place_ext.rs +++ b/src/librustc_mir/borrow_check/place_ext.rs @@ -46,9 +46,9 @@ impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { } } } - PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. }) => + PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_, _), .. }) => false, - PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. }) => { + PlaceBase::Static(box Static{ kind: StaticKind::Static, def_id, .. }) => { tcx.is_mutable_static(*def_id) } }; diff --git a/src/librustc_mir/borrow_check/places_conflict.rs b/src/librustc_mir/borrow_check/places_conflict.rs index 4dd2794f11301..4f469174b392d 100644 --- a/src/librustc_mir/borrow_check/places_conflict.rs +++ b/src/librustc_mir/borrow_check/places_conflict.rs @@ -329,11 +329,11 @@ fn place_base_conflict<'tcx>( } (PlaceBase::Static(s1), PlaceBase::Static(s2)) => { match (&s1.kind, &s2.kind) { - (StaticKind::Static(def_id_1), StaticKind::Static(def_id_2)) => { - if def_id_1 != def_id_2 { + (StaticKind::Static, StaticKind::Static) => { + if s1.def_id != s2.def_id { debug!("place_element_conflict: DISJOINT-STATIC"); Overlap::Disjoint - } else if tcx.is_mutable_static(*def_id_1) { + } else if tcx.is_mutable_static(s1.def_id) { // We ignore mutable statics - they can only be unsafe code. debug!("place_element_conflict: IGNORE-STATIC-MUT"); Overlap::Disjoint @@ -342,7 +342,7 @@ fn place_base_conflict<'tcx>( Overlap::EqualOrDisjoint } }, - (StaticKind::Promoted(promoted_1), StaticKind::Promoted(promoted_2)) => { + (StaticKind::Promoted(promoted_1, _), StaticKind::Promoted(promoted_2, _)) => { if promoted_1 == promoted_2 { if let ty::Array(_, len) = s1.ty.sty { if let Some(0) = len.try_eval_usize(tcx, param_env) { diff --git a/src/librustc_mir/build/expr/as_place.rs b/src/librustc_mir/build/expr/as_place.rs index 7005f274e0e7d..98cf4bba1c75f 100644 --- a/src/librustc_mir/build/expr/as_place.rs +++ b/src/librustc_mir/build/expr/as_place.rs @@ -126,7 +126,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::StaticRef { id } => block.and(Place { base: PlaceBase::Static(Box::new(Static { ty: expr.ty, - kind: StaticKind::Static(id), + kind: StaticKind::Static, + def_id: id, })), projection: None, }), diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 85f9cbd37589a..23c9e7fdf67ce 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -585,7 +585,7 @@ where use rustc::mir::StaticKind; Ok(match place_static.kind { - StaticKind::Promoted(promoted) => { + StaticKind::Promoted(promoted, _) => { let instance = self.frame().instance; self.const_eval_raw(GlobalId { instance, @@ -593,11 +593,11 @@ where })? } - StaticKind::Static(def_id) => { + StaticKind::Static => { let ty = place_static.ty; assert!(!ty.needs_subst()); let layout = self.layout_of(ty)?; - let instance = ty::Instance::mono(*self.tcx, def_id); + let instance = ty::Instance::mono(*self.tcx, place_static.def_id); let cid = GlobalId { instance, promoted: None diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 9d80163f30f9d..512ace1a4728c 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -180,7 +180,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::def_id::{DefId, LOCAL_CRATE}; use rustc::mir::interpret::{AllocId, ConstValue}; use rustc::middle::lang_items::{ExchangeMallocFnLangItem, StartFnLangItem}; -use rustc::ty::subst::{InternalSubsts, SubstsRef}; +use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc::ty::{self, TypeFoldable, Ty, TyCtxt, GenericParamDefKind, Instance}; use rustc::ty::print::obsolete::DefPathBasedNames; use rustc::ty::adjustment::{CustomCoerceUnsized, PointerCast}; @@ -661,7 +661,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { _context: mir::visit::PlaceContext, location: Location) { match place_base { - PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. }) => { + PlaceBase::Static(box Static { kind: StaticKind::Static, def_id, .. }) => { debug!("visiting static {:?} @ {:?}", def_id, location); let tcx = self.tcx; @@ -670,8 +670,23 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { self.output.push(MonoItem::Static(*def_id)); } } - PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. }) => { - // FIXME: should we handle promoteds here instead of eagerly in collect_neighbours? + PlaceBase::Static(box Static { kind: StaticKind::Promoted(promoted, substs), def_id, .. }) => { + debug!("collecting promoted(def_id: {:?}, promoted: {:?}, substs: {:?})", def_id, promoted, substs); + debug!("param_substs: {:?}", self.param_substs); + let param_env = ty::ParamEnv::reveal_all(); + let cid = GlobalId { + instance: Instance::new(*def_id, substs.subst(self.tcx, self.param_substs)), + promoted: Some(*promoted), + }; + debug!("cid: {:?}", cid); + match self.tcx.const_eval(param_env.and(cid)) { + Ok(val) => collect_const(self.tcx, val, substs, self.output), + Err(ErrorHandled::Reported) => {}, + Err(ErrorHandled::TooGeneric) => { + let span = self.tcx.promoted_mir(*def_id)[*promoted].span; + span_bug!(span, "collection encountered polymorphic constant") + }, + } } PlaceBase::Local(_) => { // Locals have no relevance for collector @@ -1231,24 +1246,6 @@ fn collect_neighbours<'tcx>( output, param_substs: instance.substs, }.visit_body(&body); - - if let ty::InstanceDef::Item(def_id) = instance.def { - let param_env = ty::ParamEnv::reveal_all(); - let promoted = tcx.promoted_mir(def_id); - for (promoted, promoted_body) in promoted.iter_enumerated() { - let cid = GlobalId { - instance, - promoted: Some(promoted), - }; - match tcx.const_eval(param_env.and(cid)) { - Ok(val) => collect_const(tcx, val, instance.substs, output), - Err(ErrorHandled::Reported) => {}, - Err(ErrorHandled::TooGeneric) => span_bug!( - promoted_body.span, "collection encountered polymorphic constant", - ), - } - } - } } fn def_id_to_string(tcx: TyCtxt<'_>, def_id: DefId) -> String { diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index d5c5267a119d3..539922c54d12d 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -205,10 +205,10 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { PlaceBase::Local(..) => { // Locals are safe. } - PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. }) => { + PlaceBase::Static(box Static { kind: StaticKind::Promoted(_, _), .. }) => { bug!("unsafety checking should happen before promotion") } - PlaceBase::Static(box Static { kind: StaticKind::Static(def_id), .. }) => { + PlaceBase::Static(box Static { kind: StaticKind::Static, def_id, .. }) => { if self.tcx.is_mutable_static(*def_id) { self.require_unsafe("use of mutable static", "mutable statics can be mutated by multiple threads: aliasing \ diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 9aeef16ba1e38..b6146b6b7227d 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -285,7 +285,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> { place.iterate(|place_base, place_projection| { let mut eval = match place_base { PlaceBase::Local(loc) => self.get_const(*loc).clone()?, - PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted), ..}) => { + PlaceBase::Static(box Static {kind: StaticKind::Promoted(promoted, _), ..}) => { let generics = self.tcx.generics_of(self.source.def_id()); if generics.requires_monomorphization(self.tcx) { // FIXME: can't handle code with generics diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 19a8769ce1633..533e08f5e1fd3 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -394,7 +394,6 @@ impl Inliner<'tcx> { let mut local_map = IndexVec::with_capacity(callee_body.local_decls.len()); let mut scope_map = IndexVec::with_capacity(callee_body.source_scopes.len()); - let promoted_map = IndexVec::with_capacity(self.tcx.promoted_mir(callsite.callee).len()); for mut scope in callee_body.source_scopes.iter().cloned() { if scope.parent_scope.is_none() { @@ -420,11 +419,6 @@ impl Inliner<'tcx> { local_map.push(idx); } - //TODO fixme - //promoted_map.extend( - // self.tcx.promoted_mir(callsite.callee).iter().cloned().map(|p| caller_body.promoted.push(p)) - //); - // If the call is something like `a[*i] = f(i)`, where // `i : &mut usize`, then just duplicating the `a[*i]` // Place could result in two different locations if `f` @@ -485,12 +479,12 @@ impl Inliner<'tcx> { args: &args, local_map, scope_map, - promoted_map, - _callsite: callsite, + callsite, destination: dest, return_block, cleanup_block: cleanup, - in_cleanup_block: false + in_cleanup_block: false, + tcx: self.tcx, }; @@ -645,12 +639,12 @@ struct Integrator<'a, 'tcx> { args: &'a [Local], local_map: IndexVec, scope_map: IndexVec, - promoted_map: IndexVec, - _callsite: CallSite<'tcx>, + callsite: CallSite<'tcx>, destination: Place<'tcx>, return_block: BasicBlock, cleanup_block: Option, in_cleanup_block: bool, + tcx: TyCtxt<'tcx>, } impl<'a, 'tcx> Integrator<'a, 'tcx> { @@ -701,14 +695,14 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { }, Place { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(promoted), + kind: StaticKind::Promoted(_, substs), .. }), projection: None, } => { - if let Some(p) = self.promoted_map.get(*promoted).cloned() { - *promoted = p; - } + let adjusted_substs = substs.subst(self.tcx, self.callsite.substs); + debug!("replacing substs {:?} with {:?}", substs, adjusted_substs); + *substs = adjusted_substs; }, _ => self.super_place(place, _ctxt, _location) } diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index 7015e2c087faa..cb0ce77d5c014 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -12,9 +12,11 @@ //! initialization and can otherwise silence errors, if //! move analysis runs after promotion on broken MIR. +use rustc::hir::def_id::DefId; use rustc::mir::*; use rustc::mir::visit::{PlaceContext, MutatingUseContext, MutVisitor, Visitor}; use rustc::mir::traversal::ReversePostorder; +use rustc::ty::subst::InternalSubsts; use rustc::ty::TyCtxt; use syntax_pos::Span; @@ -293,17 +295,18 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { new_temp } - fn promote_candidate(mut self, candidate: Candidate, next_promoted_id: usize) -> Option> { + fn promote_candidate(mut self, def_id: DefId, candidate: Candidate, next_promoted_id: usize) -> Option> { let mut operand = { let promoted = &mut self.promoted; let promoted_id = Promoted::new(next_promoted_id); - let mut promoted_place = |ty, span| { + let mut promoted_place = |ty, substs, span| { promoted.span = span; promoted.local_decls[RETURN_PLACE] = LocalDecl::new_return_place(ty, span); Place { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(promoted_id), - ty + kind: StaticKind::Promoted(promoted_id, substs), + ty, + def_id, }), projection: None, } @@ -319,7 +322,14 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let span = statement.source_info.span; Operand::Move(Place { - base: mem::replace(&mut place.base, promoted_place(ty, span).base), + base: mem::replace( + &mut place.base, + promoted_place( + ty, + InternalSubsts::identity_for_item(self.tcx, def_id), + span, + ).base + ), projection: None, }) } @@ -332,7 +342,16 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { StatementKind::Assign(_, box Rvalue::Repeat(ref mut operand, _)) => { let ty = operand.ty(local_decls, self.tcx); let span = statement.source_info.span; - mem::replace(operand, Operand::Copy(promoted_place(ty, span))) + mem::replace( + operand, + Operand::Copy( + promoted_place( + ty, + InternalSubsts::identity_for_item(self.tcx, def_id), + span, + ) + ) + ) } _ => bug!() } @@ -343,7 +362,12 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { TerminatorKind::Call { ref mut args, .. } => { let ty = args[index].ty(local_decls, self.tcx); let span = terminator.source_info.span; - let operand = Operand::Copy(promoted_place(ty, span)); + let operand = + Operand::Copy( + promoted_place( + ty, + InternalSubsts::identity_for_item(self.tcx, def_id), + span)); mem::replace(&mut args[index], operand) } // We expected a `TerminatorKind::Call` for which we'd like to promote an @@ -385,6 +409,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> { } pub fn promote_candidates<'tcx>( + def_id: DefId, body: &mut Body<'tcx>, tcx: TyCtxt<'tcx>, mut temps: IndexVec, @@ -442,7 +467,7 @@ pub fn promote_candidates<'tcx>( keep_original: false }; - if let Some(promoted) = promoter.promote_candidate(candidate, promotions.len()) { + if let Some(promoted) = promoter.promote_candidate(def_id, candidate, promotions.len()) { promotions.push(promoted); } } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index dd4db479cc00b..70a394ad98330 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -223,7 +223,7 @@ trait Qualif { } => Self::in_local(cx, *local), PlaceRef { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. }), projection: None, @@ -434,13 +434,13 @@ impl Qualif for IsNotPromotable { fn in_static(cx: &ConstCx<'_, 'tcx>, static_: &Static<'tcx>) -> bool { match static_.kind { - StaticKind::Promoted(_) => unreachable!(), - StaticKind::Static(def_id) => { + StaticKind::Promoted(_, _) => unreachable!(), + StaticKind::Static => { // Only allow statics (not consts) to refer to other statics. let allowed = cx.mode == Mode::Static || cx.mode == Mode::StaticMut; !allowed || - cx.tcx.get_attrs(def_id).iter().any( + cx.tcx.get_attrs(static_.def_id).iter().any( |attr| attr.check_name(sym::thread_local) ) } @@ -873,7 +873,7 @@ impl<'a, 'tcx> Checker<'a, 'tcx> { dest_projection = &proj.base; }, (&PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_), + kind: StaticKind::Promoted(..), .. }), None) => bug!("promoteds don't exist yet during promotion"), (&PlaceBase::Static(box Static{ kind: _, .. }), None) => { @@ -1028,10 +1028,10 @@ impl<'a, 'tcx> Visitor<'tcx> for Checker<'a, 'tcx> { self.super_place_base(place_base, context, location); match place_base { PlaceBase::Local(_) => {} - PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_), .. }) => { + PlaceBase::Static(box Static{ kind: StaticKind::Promoted(_, _), .. }) => { unreachable!() } - PlaceBase::Static(box Static{ kind: StaticKind::Static(def_id), .. }) => { + PlaceBase::Static(box Static{ kind: StaticKind::Static, def_id, .. }) => { if self.tcx .get_attrs(*def_id) .iter() @@ -1661,7 +1661,7 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { // Do the actual promotion, now that we know what's viable. self.promoted.set( - Some(promote_consts::promote_candidates(body, tcx, temps, candidates)) + Some(promote_consts::promote_candidates(def_id, body, tcx, temps, candidates)) ); } else { if !body.control_flow_destroyed.is_empty() { diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index 334d0cee9fbe7..56093527aee24 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -264,11 +264,11 @@ fn check_place( } match place_base { - PlaceBase::Static(box Static { kind: StaticKind::Static(_), .. }) => { + PlaceBase::Static(box Static { kind: StaticKind::Static, .. }) => { Err((span, "cannot access `static` items in const fn".into())) } PlaceBase::Local(_) - | PlaceBase::Static(box Static { kind: StaticKind::Promoted(_), .. }) => Ok(()), + | PlaceBase::Static(box Static { kind: StaticKind::Promoted(_, _), .. }) => Ok(()), } }) } From 34fe28bc67817db6743654f8eef8bbf8244f57bf Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Wed, 14 Aug 2019 08:08:17 -0400 Subject: [PATCH 05/10] Fix tidy --- src/librustc/query/mod.rs | 6 +++++- src/librustc_codegen_ssa/mir/place.rs | 1 - src/librustc_metadata/decoder.rs | 3 ++- src/librustc_metadata/encoder.rs | 3 ++- src/librustc_mir/borrow_check/mod.rs | 3 ++- src/librustc_mir/borrow_check/nll/renumber.rs | 6 +++++- src/librustc_mir/borrow_check/nll/type_check/mod.rs | 6 +++++- src/librustc_mir/monomorphize/collector.rs | 9 +++++---- src/librustc_mir/transform/mod.rs | 10 +++++++--- src/librustc_mir/transform/promote_consts.rs | 7 ++++++- 10 files changed, 39 insertions(+), 15 deletions(-) diff --git a/src/librustc/query/mod.rs b/src/librustc/query/mod.rs index e1dbaeb5b173d..c4f7ca51f4a7a 100644 --- a/src/librustc/query/mod.rs +++ b/src/librustc/query/mod.rs @@ -110,7 +110,11 @@ rustc_queries! { no_hash } - query mir_validated(_: DefId) -> (&'tcx Steal>, &'tcx Steal>>) { + query mir_validated(_: DefId) -> + ( + &'tcx Steal>, + &'tcx Steal>> + ) { no_hash } diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index f7b94ea134cfc..b08093c3a71eb 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -460,7 +460,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { }), projection: None, } => { - debug!("promoted={:?}, def_id={:?}, substs={:?}, self_substs={:?}", promoted, def_id, substs, self.instance.substs); let param_env = ty::ParamEnv::reveal_all(); let instance = Instance::new(*def_id, substs.subst(bx.tcx(), self.instance.substs)); debug!("instance: {:?}", instance); diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 128e30be79929..2add8bf918398 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -924,7 +924,8 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn maybe_get_promoted_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> Option>> { + pub fn maybe_get_promoted_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> + Option>> { match self.is_proc_macro(id) { true => None, false => self.entry(id).promoted_mir.map(|promoted| promoted.decode((self, tcx)),) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index f3863fd788ae0..0b8d2438752fa 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1060,7 +1060,8 @@ impl EncodeContext<'tcx> { } } - fn encode_promoted_mir(&mut self, def_id: DefId) -> Option>>> { + fn encode_promoted_mir(&mut self, def_id: DefId) -> + Option>>> { debug!("EncodeContext::encode_promoted_mir({:?})", def_id); if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) { let promoted = self.tcx.promoted_mir(def_id); diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 33cec78f3dfd5..8ded539e7205a 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -151,7 +151,8 @@ fn do_mir_borrowck<'a, 'tcx>( // will have a lifetime tied to the inference context. let mut body: Body<'tcx> = input_body.clone(); let mut promoted: IndexVec> = input_promoted.clone(); - let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body, &mut promoted); + let free_regions = + nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body, &mut promoted); let body = &body; // no further changes let location_table = &LocationTable::new(body); diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index 4e3ffb7af1601..c6a5c6fdfd0f2 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -7,7 +7,11 @@ use rustc_data_structures::indexed_vec::IndexVec; /// Replaces all free regions appearing in the MIR with fresh /// inference variables, returning the number of variables created. -pub fn renumber_mir<'tcx>(infcx: &InferCtxt<'_, 'tcx>, body: &mut Body<'tcx>, promoted: &mut IndexVec>) { +pub fn renumber_mir<'tcx>( + infcx: &InferCtxt<'_, 'tcx>, + body: &mut Body<'tcx>, + promoted: &mut IndexVec>, +) { debug!("renumber_mir()"); debug!("renumber_mir: body.arg_count={:?}", body.arg_count); diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 35dd5b5d7eb19..da1f64b05151b 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -384,7 +384,11 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { - fn new(cx: &'a mut TypeChecker<'b, 'tcx>, body: &'b Body<'tcx>, promoted: &'b IndexVec>) -> Self { + fn new( + cx: &'a mut TypeChecker<'b, 'tcx>, + body: &'b Body<'tcx>, + promoted: &'b IndexVec>, + ) -> Self { TypeVerifier { body, promoted, diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs index 512ace1a4728c..11f9df625285f 100644 --- a/src/librustc_mir/monomorphize/collector.rs +++ b/src/librustc_mir/monomorphize/collector.rs @@ -670,15 +670,16 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> { self.output.push(MonoItem::Static(*def_id)); } } - PlaceBase::Static(box Static { kind: StaticKind::Promoted(promoted, substs), def_id, .. }) => { - debug!("collecting promoted(def_id: {:?}, promoted: {:?}, substs: {:?})", def_id, promoted, substs); - debug!("param_substs: {:?}", self.param_substs); + PlaceBase::Static(box Static { + kind: StaticKind::Promoted(promoted, substs), + def_id, + .. + }) => { let param_env = ty::ParamEnv::reveal_all(); let cid = GlobalId { instance: Instance::new(*def_id, substs.subst(self.tcx, self.param_substs)), promoted: Some(*promoted), }; - debug!("cid: {:?}", cid); match self.tcx.const_eval(param_env.and(cid)) { Ok(val) => collect_const(self.tcx, val, substs, self.output), Err(ErrorHandled::Reported) => {}, diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index a78e78331ee3f..f59ad6bae0298 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -200,7 +200,10 @@ fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { tcx.alloc_steal_mir(body) } -fn mir_validated(tcx: TyCtxt<'tcx>, def_id: DefId) -> (&'tcx Steal>, &'tcx Steal>>) { +fn mir_validated( + tcx: TyCtxt<'tcx>, + def_id: DefId, +) -> (&'tcx Steal>, &'tcx Steal>>) { let hir_id = tcx.hir().as_local_hir_id(def_id).unwrap(); if let hir::BodyOwnerKind::Const = tcx.hir().body_owner_kind(hir_id) { // Ensure that we compute the `mir_const_qualif` for constants at @@ -215,8 +218,9 @@ fn mir_validated(tcx: TyCtxt<'tcx>, def_id: DefId) -> (&'tcx Steal>, &qualify_and_promote_pass, &simplify::SimplifyCfg::new("qualify-consts"), ]); - let promoted = qualify_and_promote_pass.promoted.into_inner(); - (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted.unwrap_or_else(|| IndexVec::new()))) + let promoted = + qualify_and_promote_pass.promoted.into_inner().unwrap_or_else(|| IndexVec::new()); + (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted)) } fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs index cb0ce77d5c014..fd5b6c2a32825 100644 --- a/src/librustc_mir/transform/promote_consts.rs +++ b/src/librustc_mir/transform/promote_consts.rs @@ -295,7 +295,12 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { new_temp } - fn promote_candidate(mut self, def_id: DefId, candidate: Candidate, next_promoted_id: usize) -> Option> { + fn promote_candidate( + mut self, + def_id: DefId, + candidate: Candidate, + next_promoted_id: usize, + ) -> Option> { let mut operand = { let promoted = &mut self.promoted; let promoted_id = Promoted::new(next_promoted_id); From 9fdf5b555181ee6438a9cb01bb38ae5a52049475 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Wed, 14 Aug 2019 08:16:06 -0400 Subject: [PATCH 06/10] Remove unnecessary Option --- src/librustc_mir/transform/mod.rs | 3 +-- src/librustc_mir/transform/qualify_consts.rs | 6 +++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index f59ad6bae0298..c9bcdbe1bef50 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -218,8 +218,7 @@ fn mir_validated( &qualify_and_promote_pass, &simplify::SimplifyCfg::new("qualify-consts"), ]); - let promoted = - qualify_and_promote_pass.promoted.into_inner().unwrap_or_else(|| IndexVec::new()); + let promoted = qualify_and_promote_pass.promoted.into_inner(); (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted)) } diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index 70a394ad98330..7f8ae88342934 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1572,13 +1572,13 @@ fn mir_const_qualif(tcx: TyCtxt<'_>, def_id: DefId) -> (u8, &BitSet) { } pub struct QualifyAndPromoteConstants<'tcx> { - pub promoted: Cell>>>, + pub promoted: Cell>>, } impl<'tcx> Default for QualifyAndPromoteConstants<'tcx> { fn default() -> Self { QualifyAndPromoteConstants { - promoted: Cell::new(None), + promoted: Cell::new(IndexVec::new()), } } } @@ -1661,7 +1661,7 @@ impl<'tcx> MirPass<'tcx> for QualifyAndPromoteConstants<'tcx> { // Do the actual promotion, now that we know what's viable. self.promoted.set( - Some(promote_consts::promote_candidates(def_id, body, tcx, temps, candidates)) + promote_consts::promote_candidates(def_id, body, tcx, temps, candidates) ); } else { if !body.control_flow_destroyed.is_empty() { From e63b9920302e860b4f50968eb332f534d62b8055 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Thu, 15 Aug 2019 06:39:31 -0400 Subject: [PATCH 07/10] Resolve PR comments --- src/librustc_metadata/decoder.rs | 7 +- src/librustc_metadata/encoder.rs | 6 +- src/librustc_mir/borrow_check/nll/renumber.rs | 13 +- src/librustc_mir/shim.rs | 2 +- src/librustc_mir/transform/mod.rs | 153 +++++++----------- src/librustc_mir/transform/promote_consts.rs | 31 ++-- 6 files changed, 81 insertions(+), 131 deletions(-) diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 2add8bf918398..5b9cb966af235 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -924,8 +924,11 @@ impl<'a, 'tcx> CrateMetadata { } } - pub fn maybe_get_promoted_mir(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> - Option>> { + pub fn maybe_get_promoted_mir( + &self, + tcx: TyCtxt<'tcx>, + id: DefIndex, + ) -> Option>> { match self.is_proc_macro(id) { true => None, false => self.entry(id).promoted_mir.map(|promoted| promoted.decode((self, tcx)),) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index 0b8d2438752fa..1797d77461567 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -1060,8 +1060,10 @@ impl EncodeContext<'tcx> { } } - fn encode_promoted_mir(&mut self, def_id: DefId) -> - Option>>> { + fn encode_promoted_mir( + &mut self, + def_id: DefId, + ) -> Option>>> { debug!("EncodeContext::encode_promoted_mir({:?})", def_id); if self.tcx.mir_keys(LOCAL_CRATE).contains(&def_id) { let promoted = self.tcx.promoted_mir(def_id); diff --git a/src/librustc_mir/borrow_check/nll/renumber.rs b/src/librustc_mir/borrow_check/nll/renumber.rs index c6a5c6fdfd0f2..c479c38f30c7e 100644 --- a/src/librustc_mir/borrow_check/nll/renumber.rs +++ b/src/librustc_mir/borrow_check/nll/renumber.rs @@ -16,7 +16,11 @@ pub fn renumber_mir<'tcx>( debug!("renumber_mir: body.arg_count={:?}", body.arg_count); let mut visitor = NLLVisitor { infcx }; - visitor.visit_promoted(promoted); + + for body in promoted.iter_mut() { + visitor.visit_body(body); + } + visitor.visit_body(body); } @@ -47,13 +51,6 @@ impl<'a, 'tcx> NLLVisitor<'a, 'tcx> { { renumber_regions(self.infcx, value) } - - fn visit_promoted(&mut self, promoted: &mut IndexVec>) { - debug!("visiting promoted mir"); - for body in promoted.iter_mut() { - self.visit_body(body); - } - } } impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> { diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 9d31015f84558..aa83255bf62f4 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -112,7 +112,7 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> &'tcx }; debug!("make_shim({:?}) = untransformed {:?}", instance, result); - run_passes(tcx, &mut result, instance, MirPhase::Const, &[ + run_passes(tcx, &mut result, instance, None, MirPhase::Const, &[ &add_moves_for_packed_drops::AddMovesForPackedDrops, &no_landing_pads::NoLandingPads, &remove_noop_landing_pads::RemoveNoopLandingPads, diff --git a/src/librustc_mir/transform/mod.rs b/src/librustc_mir/transform/mod.rs index c9bcdbe1bef50..ac291c2996d06 100644 --- a/src/librustc_mir/transform/mod.rs +++ b/src/librustc_mir/transform/mod.rs @@ -149,41 +149,38 @@ 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 run_passes = |body: &mut Body<'tcx>, promoted| { - if body.phase >= mir_phase { - return; - } + if body.phase >= mir_phase { + return; + } - let source = MirSource { - instance, - promoted, - }; - let mut index = 0; - let mut run_pass = |pass: &dyn MirPass<'tcx>| { - let run_hooks = |body: &_, index, is_after| { - dump_mir::on_mir_pass(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); - run_hooks(body, index, true); - - index += 1; + let source = MirSource { + instance, + promoted, + }; + let mut index = 0; + let mut run_pass = |pass: &dyn MirPass<'tcx>| { + let run_hooks = |body: &_, index, is_after| { + dump_mir::on_mir_pass(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); + run_hooks(body, index, true); - for pass in passes { - run_pass(*pass); - } - - body.phase = mir_phase; + index += 1; }; - run_passes(body, None); + for pass in passes { + run_pass(*pass); + } + + body.phase = mir_phase; } fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { @@ -191,7 +188,7 @@ fn mir_const(tcx: TyCtxt<'_>, def_id: DefId) -> &Steal> { let _ = tcx.unsafety_check_result(def_id); let mut body = tcx.mir_built(def_id).steal(); - run_passes(tcx, &mut body, InstanceDef::Item(def_id), MirPhase::Const, &[ + run_passes(tcx, &mut body, InstanceDef::Item(def_id), None, MirPhase::Const, &[ // What we need to do constant evaluation. &simplify::SimplifyCfg::new("initial"), &rustc_peek::SanityCheck, @@ -213,7 +210,7 @@ fn mir_validated( let mut body = tcx.mir_const(def_id).steal(); let qualify_and_promote_pass = qualify_consts::QualifyAndPromoteConstants::default(); - run_passes(tcx, &mut body, InstanceDef::Item(def_id), MirPhase::Validated, &[ + run_passes(tcx, &mut body, InstanceDef::Item(def_id), None, MirPhase::Validated, &[ // What we need to run borrowck etc. &qualify_and_promote_pass, &simplify::SimplifyCfg::new("qualify-consts"), @@ -222,26 +219,13 @@ fn mir_validated( (tcx.alloc_steal_mir(body), tcx.alloc_steal_promoted(promoted)) } -fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { - if tcx.is_constructor(def_id) { - // There's no reason to run all of the MIR passes on constructors when - // we can just output the MIR we want directly. This also saves const - // qualification and borrow checking the trouble of special casing - // constructors. - return shim::build_adt_ctor(tcx, def_id); - } - - // (Mir-)Borrowck uses `mir_validated`, so we have to force it to - // execute before we can steal. - tcx.ensure().mir_borrowck(def_id); - - if tcx.use_ast_borrowck() { - tcx.ensure().borrowck(def_id); - } - - let (body, _) = tcx.mir_validated(def_id); - let mut body = body.steal(); - run_passes(tcx, &mut body, InstanceDef::Item(def_id), MirPhase::Optimized, &[ +fn run_optimization_passes<'tcx>( + tcx: TyCtxt<'tcx>, + body: &mut Body<'tcx>, + def_id: DefId, + promoted: Option, +) { + run_passes(tcx, body, InstanceDef::Item(def_id), promoted, MirPhase::Optimized, &[ // Remove all things only needed by analysis &no_landing_pads::NoLandingPads, &simplify_branches::SimplifyBranches::new("initial"), @@ -292,6 +276,28 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { &add_call_guards::CriticalCallEdges, &dump_mir::Marker("PreCodegen"), ]); +} + +fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &Body<'_> { + if tcx.is_constructor(def_id) { + // There's no reason to run all of the MIR passes on constructors when + // we can just output the MIR we want directly. This also saves const + // qualification and borrow checking the trouble of special casing + // constructors. + return shim::build_adt_ctor(tcx, def_id); + } + + // (Mir-)Borrowck uses `mir_validated`, so we have to force it to + // execute before we can steal. + tcx.ensure().mir_borrowck(def_id); + + if tcx.use_ast_borrowck() { + tcx.ensure().borrowck(def_id); + } + + let (body, _) = tcx.mir_validated(def_id); + let mut body = body.steal(); + run_optimization_passes(tcx, &mut body, def_id, None); tcx.arena.alloc(body) } @@ -304,57 +310,8 @@ fn promoted_mir<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx IndexVec Promoter<'a, 'tcx> { let mut operand = { let promoted = &mut self.promoted; let promoted_id = Promoted::new(next_promoted_id); - let mut promoted_place = |ty, substs, span| { + let tcx = self.tcx; + let mut promoted_place = |ty, span| { promoted.span = span; promoted.local_decls[RETURN_PLACE] = LocalDecl::new_return_place(ty, span); Place { base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(promoted_id, substs), + kind: + StaticKind::Promoted( + promoted_id, + InternalSubsts::identity_for_item(tcx, def_id), + ), ty, def_id, }), @@ -329,11 +334,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { Operand::Move(Place { base: mem::replace( &mut place.base, - promoted_place( - ty, - InternalSubsts::identity_for_item(self.tcx, def_id), - span, - ).base + promoted_place(ty, span).base ), projection: None, }) @@ -349,13 +350,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { let span = statement.source_info.span; mem::replace( operand, - Operand::Copy( - promoted_place( - ty, - InternalSubsts::identity_for_item(self.tcx, def_id), - span, - ) - ) + Operand::Copy(promoted_place(ty, span)) ) } _ => bug!() @@ -367,12 +362,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { TerminatorKind::Call { ref mut args, .. } => { let ty = args[index].ty(local_decls, self.tcx); let span = terminator.source_info.span; - let operand = - Operand::Copy( - promoted_place( - ty, - InternalSubsts::identity_for_item(self.tcx, def_id), - span)); + let operand = Operand::Copy(promoted_place(ty, span)); mem::replace(&mut args[index], operand) } // We expected a `TerminatorKind::Call` for which we'd like to promote an @@ -472,6 +462,7 @@ pub fn promote_candidates<'tcx>( keep_original: false }; + //FIXME(oli-obk): having a `maybe_push()` method on `IndexVec` might be nice if let Some(promoted) = promoter.promote_candidate(def_id, candidate, promotions.len()) { promotions.push(promoted); } From 84556502e69e1741938610e4af5800fe0cee9975 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Fri, 16 Aug 2019 20:31:28 -0400 Subject: [PATCH 08/10] Handle statics in `Subst::subst()` by implementing `TypeFoldable` --- src/librustc/mir/mod.rs | 58 +++++++++++++++++++++++++-- src/librustc_codegen_ssa/mir/place.rs | 11 +---- src/librustc_mir/transform/inline.rs | 15 ------- 3 files changed, 56 insertions(+), 28 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 69e98583b191c..60efeaab97602 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1729,7 +1729,7 @@ pub enum PlaceBase<'tcx> { } /// We store the normalized type to avoid requiring normalization when reading MIR -#[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable)] pub struct Static<'tcx> { pub ty: Ty<'tcx>, pub kind: StaticKind<'tcx>, @@ -1737,7 +1737,7 @@ pub struct Static<'tcx> { } #[derive( - Clone, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, RustcEncodable, RustcDecodable, + Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, HashStable, RustcEncodable, RustcDecodable, )] pub enum StaticKind<'tcx> { Promoted(Promoted, SubstsRef<'tcx>), @@ -3221,13 +3221,63 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> { impl<'tcx> TypeFoldable<'tcx> for Place<'tcx> { fn super_fold_with>(&self, folder: &mut F) -> Self { Place { - base: self.base.clone(), + base: self.base.fold_with(folder), projection: self.projection.fold_with(folder), } } fn super_visit_with>(&self, visitor: &mut V) -> bool { - self.projection.visit_with(visitor) + self.base.visit_with(visitor) || self.projection.visit_with(visitor) + } +} + +impl<'tcx> TypeFoldable<'tcx> for PlaceBase<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + match self { + PlaceBase::Local(local) => PlaceBase::Local(local.fold_with(folder)), + PlaceBase::Static(static_) => PlaceBase::Static(static_.fold_with(folder)), + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + match self { + PlaceBase::Local(local) => local.visit_with(visitor), + PlaceBase::Static(static_) => (**static_).visit_with(visitor), + } + } +} + +impl<'tcx> TypeFoldable<'tcx> for Static<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + Static { + ty: self.ty.fold_with(folder), + kind: self.kind.fold_with(folder), + def_id: self.def_id, + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + let Static { ty, kind, def_id: _ } = self; + + ty.visit_with(visitor) || kind.visit_with(visitor) + } +} + +impl<'tcx> TypeFoldable<'tcx> for StaticKind<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + match self { + StaticKind::Promoted(promoted, substs) => + StaticKind::Promoted(promoted.fold_with(folder), substs.fold_with(folder)), + StaticKind::Static => StaticKind::Static + } + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + match self { + StaticKind::Promoted(promoted, substs) => + promoted.visit_with(visitor) || substs.visit_with(visitor), + StaticKind::Static => { false } + } } } diff --git a/src/librustc_codegen_ssa/mir/place.rs b/src/librustc_codegen_ssa/mir/place.rs index b08093c3a71eb..ac72928a89677 100644 --- a/src/librustc_codegen_ssa/mir/place.rs +++ b/src/librustc_codegen_ssa/mir/place.rs @@ -1,5 +1,4 @@ use rustc::ty::{self, Instance, Ty}; -use rustc::ty::subst::Subst; use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx, HasTyCtxt}; use rustc::mir; use rustc::mir::tcx::PlaceTy; @@ -461,18 +460,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { projection: None, } => { let param_env = ty::ParamEnv::reveal_all(); - let instance = Instance::new(*def_id, substs.subst(bx.tcx(), self.instance.substs)); - debug!("instance: {:?}", instance); + let instance = Instance::new(*def_id, self.monomorphize(substs)); let cid = mir::interpret::GlobalId { instance: instance, promoted: Some(*promoted), }; - let mono_ty = tcx.subst_and_normalize_erasing_regions( - instance.substs, - param_env, - ty, - ); - let layout = cx.layout_of(mono_ty); + let layout = cx.layout_of(self.monomorphize(&ty)); match bx.tcx().const_eval(param_env.and(cid)) { Ok(val) => match val.val { mir::interpret::ConstValue::ByRef { alloc, offset } => { diff --git a/src/librustc_mir/transform/inline.rs b/src/librustc_mir/transform/inline.rs index 533e08f5e1fd3..f31303c642faa 100644 --- a/src/librustc_mir/transform/inline.rs +++ b/src/librustc_mir/transform/inline.rs @@ -479,12 +479,10 @@ impl Inliner<'tcx> { args: &args, local_map, scope_map, - callsite, destination: dest, return_block, cleanup_block: cleanup, in_cleanup_block: false, - tcx: self.tcx, }; @@ -639,12 +637,10 @@ struct Integrator<'a, 'tcx> { args: &'a [Local], local_map: IndexVec, scope_map: IndexVec, - callsite: CallSite<'tcx>, destination: Place<'tcx>, return_block: BasicBlock, cleanup_block: Option, in_cleanup_block: bool, - tcx: TyCtxt<'tcx>, } impl<'a, 'tcx> Integrator<'a, 'tcx> { @@ -693,17 +689,6 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Integrator<'a, 'tcx> { // Return pointer; update the place itself *place = self.destination.clone(); }, - Place { - base: PlaceBase::Static(box Static { - kind: StaticKind::Promoted(_, substs), - .. - }), - projection: None, - } => { - let adjusted_substs = substs.subst(self.tcx, self.callsite.substs); - debug!("replacing substs {:?} with {:?}", substs, adjusted_substs); - *substs = adjusted_substs; - }, _ => self.super_place(place, _ctxt, _location) } } From 5c45420bdad8d3bf950ff3c46e1856348a7ddc7b Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Sun, 4 Aug 2019 22:23:32 -0400 Subject: [PATCH 09/10] Changed tests --- src/test/incremental/hashes/for_loops.rs | 2 +- src/test/ui/consts/array-literal-index-oob.rs | 1 - .../ui/consts/array-literal-index-oob.stderr | 8 +---- .../ui/consts/const-eval/issue-43197.stderr | 8 ++--- .../ui/consts/const-eval/promoted_errors.rs | 6 ++-- .../consts/const-eval/promoted_errors.stderr | 30 ++++++------------- 6 files changed, 17 insertions(+), 38 deletions(-) diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs index ca45d36a6b0e4..5d0b8b867b22f 100644 --- a/src/test/incremental/hashes/for_loops.rs +++ b/src/test/incremental/hashes/for_loops.rs @@ -94,7 +94,7 @@ pub fn change_iterable() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, optimized_mir")] +#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] #[rustc_clean(cfg="cfail3")] pub fn change_iterable() { let mut _x = 0; diff --git a/src/test/ui/consts/array-literal-index-oob.rs b/src/test/ui/consts/array-literal-index-oob.rs index 76013c77de0c2..492182921ba34 100644 --- a/src/test/ui/consts/array-literal-index-oob.rs +++ b/src/test/ui/consts/array-literal-index-oob.rs @@ -2,5 +2,4 @@ fn main() { &{[1, 2, 3][4]}; //~^ ERROR index out of bounds //~| ERROR reaching this expression at runtime will panic or abort - //~| ERROR this expression will panic at runtime } diff --git a/src/test/ui/consts/array-literal-index-oob.stderr b/src/test/ui/consts/array-literal-index-oob.stderr index 18a09fdda7be4..0ddc2a0e79cd3 100644 --- a/src/test/ui/consts/array-literal-index-oob.stderr +++ b/src/test/ui/consts/array-literal-index-oob.stderr @@ -6,12 +6,6 @@ LL | &{[1, 2, 3][4]}; | = note: `#[deny(const_err)]` on by default -error: this expression will panic at runtime - --> $DIR/array-literal-index-oob.rs:2:5 - | -LL | &{[1, 2, 3][4]}; - | ^^^^^^^^^^^^^^^ index out of bounds: the len is 3 but the index is 4 - error: reaching this expression at runtime will panic or abort --> $DIR/array-literal-index-oob.rs:2:7 | @@ -20,5 +14,5 @@ LL | &{[1, 2, 3][4]}; | | | index out of bounds: the len is 3 but the index is 4 -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-eval/issue-43197.stderr b/src/test/ui/consts/const-eval/issue-43197.stderr index 478e453fe0834..d971d825f278c 100644 --- a/src/test/ui/consts/const-eval/issue-43197.stderr +++ b/src/test/ui/consts/const-eval/issue-43197.stderr @@ -21,16 +21,16 @@ LL | const Y: u32 = foo(0-1); | attempt to subtract with overflow error[E0080]: evaluation of constant expression failed - --> $DIR/issue-43197.rs:12:26 + --> $DIR/issue-43197.rs:12:23 | LL | println!("{} {}", X, Y); - | ^ referenced constant has errors + | ^ referenced constant has errors error[E0080]: evaluation of constant expression failed - --> $DIR/issue-43197.rs:12:23 + --> $DIR/issue-43197.rs:12:26 | LL | println!("{} {}", X, Y); - | ^ referenced constant has errors + | ^ referenced constant has errors error: aborting due to 2 previous errors diff --git a/src/test/ui/consts/const-eval/promoted_errors.rs b/src/test/ui/consts/const-eval/promoted_errors.rs index fa8859cbb3bb6..cd989731452b3 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.rs +++ b/src/test/ui/consts/const-eval/promoted_errors.rs @@ -7,15 +7,13 @@ fn main() { let _x = 0u32 - 1; //~^ ERROR this expression will panic at runtime [const_err] println!("{}", 1/(1-1)); - //~^ ERROR this expression will panic at runtime [const_err] - //~| ERROR attempt to divide by zero [const_err] + //~^ ERROR attempt to divide by zero [const_err] //~| ERROR reaching this expression at runtime will panic or abort [const_err] let _x = 1/(1-1); //~^ ERROR const_err //~| ERROR const_err println!("{}", 1/(false as u32)); - //~^ ERROR this expression will panic at runtime [const_err] - //~| ERROR attempt to divide by zero [const_err] + //~^ ERROR attempt to divide by zero [const_err] //~| ERROR reaching this expression at runtime will panic or abort [const_err] let _x = 1/(false as u32); //~^ ERROR const_err diff --git a/src/test/ui/consts/const-eval/promoted_errors.stderr b/src/test/ui/consts/const-eval/promoted_errors.stderr index 12407accf096f..40d5c73e86679 100644 --- a/src/test/ui/consts/const-eval/promoted_errors.stderr +++ b/src/test/ui/consts/const-eval/promoted_errors.stderr @@ -16,59 +16,47 @@ error: attempt to divide by zero LL | println!("{}", 1/(1-1)); | ^^^^^^^ -error: this expression will panic at runtime +error: reaching this expression at runtime will panic or abort --> $DIR/promoted_errors.rs:9:20 | LL | println!("{}", 1/(1-1)); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:13:14 + --> $DIR/promoted_errors.rs:12:14 | LL | let _x = 1/(1-1); | ^^^^^^^ error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:13:14 + --> $DIR/promoted_errors.rs:12:14 | LL | let _x = 1/(1-1); | ^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:16:20 + --> $DIR/promoted_errors.rs:15:20 | LL | println!("{}", 1/(false as u32)); | ^^^^^^^^^^^^^^^^ -error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:16:20 +error: reaching this expression at runtime will panic or abort + --> $DIR/promoted_errors.rs:15:20 | LL | println!("{}", 1/(false as u32)); | ^^^^^^^^^^^^^^^^ attempt to divide by zero error: attempt to divide by zero - --> $DIR/promoted_errors.rs:20:14 + --> $DIR/promoted_errors.rs:18:14 | LL | let _x = 1/(false as u32); | ^^^^^^^^^^^^^^^^ error: this expression will panic at runtime - --> $DIR/promoted_errors.rs:20:14 + --> $DIR/promoted_errors.rs:18:14 | LL | let _x = 1/(false as u32); | ^^^^^^^^^^^^^^^^ attempt to divide by zero -error: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:16:20 - | -LL | println!("{}", 1/(false as u32)); - | ^^^^^^^^^^^^^^^^ attempt to divide by zero - -error: reaching this expression at runtime will panic or abort - --> $DIR/promoted_errors.rs:9:20 - | -LL | println!("{}", 1/(1-1)); - | ^^^^^^^ attempt to divide by zero - -error: aborting due to 11 previous errors +error: aborting due to 9 previous errors From d6bf776bc69c766aa70c39f28f6c70ab7faf32b7 Mon Sep 17 00:00:00 2001 From: Wesley Wiser Date: Wed, 21 Aug 2019 21:38:23 -0400 Subject: [PATCH 10/10] Fix incremental tests --- .../persist/dirty_clean.rs | 27 ++++++++++++++----- src/test/incremental/hashes/for_loops.rs | 2 +- src/test/incremental/hashes/inherent_impls.rs | 12 ++++++--- 3 files changed, 31 insertions(+), 10 deletions(-) diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs index e569a9bc7df40..837aa9360c895 100644 --- a/src/librustc_incremental/persist/dirty_clean.rs +++ b/src/librustc_incremental/persist/dirty_clean.rs @@ -24,6 +24,7 @@ use rustc::hir::itemlikevisit::ItemLikeVisitor; use rustc::hir::intravisit; use rustc::ich::{ATTR_DIRTY, ATTR_CLEAN}; use rustc::ty::TyCtxt; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashSet; use syntax::ast::{self, Attribute, NestedMetaItem}; use syntax::symbol::{Symbol, sym}; @@ -71,6 +72,7 @@ const BASE_IMPL: &[&str] = &[ /// code, i.e., functions+methods const BASE_MIR: &[&str] = &[ label_strs::optimized_mir, + label_strs::promoted_mir, label_strs::mir_built, ]; @@ -472,11 +474,10 @@ impl DirtyCleanVisitor<'tcx> { fn assert_dirty(&self, item_span: Span, dep_node: DepNode) { debug!("assert_dirty({:?})", dep_node); - let dep_node_index = self.tcx.dep_graph.dep_node_index_of(&dep_node); - let current_fingerprint = self.tcx.dep_graph.fingerprint_of(dep_node_index); + let current_fingerprint = self.get_fingerprint(&dep_node); let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node); - if Some(current_fingerprint) == prev_fingerprint { + if current_fingerprint == prev_fingerprint { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( item_span, @@ -484,14 +485,28 @@ impl DirtyCleanVisitor<'tcx> { } } + fn get_fingerprint(&self, dep_node: &DepNode) -> Option { + if self.tcx.dep_graph.dep_node_exists(dep_node) { + let dep_node_index = self.tcx.dep_graph.dep_node_index_of(dep_node); + Some(self.tcx.dep_graph.fingerprint_of(dep_node_index)) + } else { + None + } + } + fn assert_clean(&self, item_span: Span, dep_node: DepNode) { debug!("assert_clean({:?})", dep_node); - let dep_node_index = self.tcx.dep_graph.dep_node_index_of(&dep_node); - let current_fingerprint = self.tcx.dep_graph.fingerprint_of(dep_node_index); + let current_fingerprint = self.get_fingerprint(&dep_node); let prev_fingerprint = self.tcx.dep_graph.prev_fingerprint_of(&dep_node); - if Some(current_fingerprint) != prev_fingerprint { + // if the node wasn't previously evaluated and now is (or vice versa), + // then the node isn't actually clean or dirty. + if (current_fingerprint == None) ^ (prev_fingerprint == None) { + return; + } + + if current_fingerprint != prev_fingerprint { let dep_node_str = self.dep_node_str(&dep_node); self.tcx.sess.span_err( item_span, diff --git a/src/test/incremental/hashes/for_loops.rs b/src/test/incremental/hashes/for_loops.rs index 5d0b8b867b22f..70820dfaea4a0 100644 --- a/src/test/incremental/hashes/for_loops.rs +++ b/src/test/incremental/hashes/for_loops.rs @@ -94,7 +94,7 @@ pub fn change_iterable() { } #[cfg(not(cfail1))] -#[rustc_clean(cfg="cfail2", except="HirBody, mir_built")] +#[rustc_clean(cfg="cfail2", except="HirBody, mir_built, promoted_mir")] #[rustc_clean(cfg="cfail3")] pub fn change_iterable() { let mut _x = 0; diff --git a/src/test/incremental/hashes/inherent_impls.rs b/src/test/incremental/hashes/inherent_impls.rs index 882383e841957..e98f9b67ca421 100644 --- a/src/test/incremental/hashes/inherent_impls.rs +++ b/src/test/incremental/hashes/inherent_impls.rs @@ -42,7 +42,10 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")] + #[rustc_clean( + cfg="cfail2", + except="HirBody,optimized_mir,promoted_mir,mir_built,typeck_tables_of" + )] #[rustc_clean(cfg="cfail3")] pub fn method_body() { println!("Hello, world!"); @@ -63,7 +66,10 @@ impl Foo { #[rustc_clean(cfg="cfail2")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_clean(cfg="cfail2", except="HirBody,optimized_mir,mir_built,typeck_tables_of")] + #[rustc_clean( + cfg="cfail2", + except="HirBody,optimized_mir,promoted_mir,mir_built,typeck_tables_of" + )] #[rustc_clean(cfg="cfail3")] #[inline] pub fn method_body_inlined() { @@ -97,7 +103,7 @@ impl Foo { #[rustc_clean(cfg="cfail2", except="Hir,HirBody")] #[rustc_clean(cfg="cfail3")] impl Foo { - #[rustc_dirty(cfg="cfail2", except="type_of,predicates_of")] + #[rustc_dirty(cfg="cfail2", except="type_of,predicates_of,promoted_mir")] #[rustc_clean(cfg="cfail3")] pub fn method_selfness(&self) { } }