Rollup merge of #70165 - matthewjasper:erase-more, r=nikomatsakis

Remove the erase regions MIR transform

We now ensure that MIR never contains unerased regions in the first place.
This commit is contained in:
Mazdak Farrokhzad 2020-03-21 05:33:24 +01:00 committed by GitHub
commit b24d168e10
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 63 additions and 110 deletions

View File

@ -39,7 +39,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
let loc_ty = self
.tcx
.type_of(self.tcx.require_lang_item(PanicLocationLangItem, None))
.subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_static.into()].iter()));
.subst(*self.tcx, self.tcx.mk_substs([self.tcx.lifetimes.re_erased.into()].iter()));
let loc_layout = self.layout_of(loc_ty).unwrap();
let location = self.allocate(loc_layout, MemoryKind::CallerLocation);

View File

@ -32,6 +32,7 @@ impl<'tcx> MirPass<'tcx> for CleanupNonCodegenStatements {
fn run_pass(&self, tcx: TyCtxt<'tcx>, _source: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
let mut delete = DeleteNonCodegenStatements { tcx };
delete.visit_body(body);
body.user_type_annotations.raw.clear();
}
}

View File

@ -1,63 +0,0 @@
//! This pass erases all early-bound regions from the types occurring in the MIR.
//! We want to do this once just before codegen, so codegen does not have to take
//! care erasing regions all over the place.
//! N.B., we do _not_ erase regions of statements that are relevant for
//! "types-as-contracts"-validation, namely, `AcquireValid` and `ReleaseValid`.
use crate::transform::{MirPass, MirSource};
use rustc::mir::visit::{MutVisitor, TyContext};
use rustc::mir::*;
use rustc::ty::subst::SubstsRef;
use rustc::ty::{self, Ty, TyCtxt};
struct EraseRegionsVisitor<'tcx> {
tcx: TyCtxt<'tcx>,
}
impl EraseRegionsVisitor<'tcx> {
pub fn new(tcx: TyCtxt<'tcx>) -> Self {
EraseRegionsVisitor { tcx }
}
}
impl MutVisitor<'tcx> for EraseRegionsVisitor<'tcx> {
fn tcx(&self) -> TyCtxt<'tcx> {
self.tcx
}
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, _: TyContext) {
*ty = self.tcx.erase_regions(ty);
}
fn visit_region(&mut self, region: &mut ty::Region<'tcx>, _: Location) {
*region = self.tcx.lifetimes.re_erased;
}
fn visit_const(&mut self, constant: &mut &'tcx ty::Const<'tcx>, _: Location) {
*constant = self.tcx.erase_regions(constant);
}
fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, _: Location) {
*substs = self.tcx.erase_regions(substs);
}
fn process_projection_elem(&mut self, elem: &PlaceElem<'tcx>) -> Option<PlaceElem<'tcx>> {
if let PlaceElem::Field(field, ty) = elem {
let new_ty = self.tcx.erase_regions(ty);
if new_ty != *ty {
return Some(PlaceElem::Field(*field, new_ty));
}
}
None
}
}
pub struct EraseRegions;
impl<'tcx> MirPass<'tcx> for EraseRegions {
fn run_pass(&self, tcx: TyCtxt<'tcx>, _: MirSource<'tcx>, body: &mut BodyAndCache<'tcx>) {
EraseRegionsVisitor::new(tcx).visit_body(body);
}
}

View File

@ -357,18 +357,11 @@ impl MutVisitor<'tcx> for TransformVisitor<'tcx> {
}
}
fn make_generator_state_argument_indirect<'tcx>(
tcx: TyCtxt<'tcx>,
def_id: DefId,
body: &mut BodyAndCache<'tcx>,
) {
fn make_generator_state_argument_indirect<'tcx>(tcx: TyCtxt<'tcx>, body: &mut BodyAndCache<'tcx>) {
let gen_ty = body.local_decls.raw[1].ty;
let region = ty::ReFree(ty::FreeRegion { scope: def_id, bound_region: ty::BoundRegion::BrEnv });
let region = tcx.mk_region(region);
let ref_gen_ty = tcx.mk_ref(region, ty::TypeAndMut { ty: gen_ty, mutbl: hir::Mutability::Mut });
let ref_gen_ty =
tcx.mk_ref(tcx.lifetimes.re_erased, ty::TypeAndMut { ty: gen_ty, mutbl: Mutability::Mut });
// Replace the by value generator argument
body.local_decls.raw[1].ty = ref_gen_ty;
@ -874,7 +867,6 @@ fn elaborate_generator_drops<'tcx>(
fn create_generator_drop_shim<'tcx>(
tcx: TyCtxt<'tcx>,
transform: &TransformVisitor<'tcx>,
def_id: DefId,
source: MirSource<'tcx>,
gen_ty: Ty<'tcx>,
body: &mut BodyAndCache<'tcx>,
@ -912,7 +904,7 @@ fn create_generator_drop_shim<'tcx>(
local_info: LocalInfo::Other,
};
make_generator_state_argument_indirect(tcx, def_id, &mut body);
make_generator_state_argument_indirect(tcx, &mut body);
// Change the generator argument from &mut to *mut
body.local_decls[SELF_ARG] = LocalDecl {
@ -1047,7 +1039,6 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
fn create_generator_resume_function<'tcx>(
tcx: TyCtxt<'tcx>,
transform: TransformVisitor<'tcx>,
def_id: DefId,
source: MirSource<'tcx>,
body: &mut BodyAndCache<'tcx>,
can_return: bool,
@ -1112,7 +1103,7 @@ fn create_generator_resume_function<'tcx>(
insert_switch(body, cases, &transform, TerminatorKind::Unreachable);
make_generator_state_argument_indirect(tcx, def_id, body);
make_generator_state_argument_indirect(tcx, body);
make_generator_state_argument_pinned(tcx, body);
no_landing_pads(tcx, body);
@ -1332,11 +1323,11 @@ impl<'tcx> MirPass<'tcx> for StateTransform {
// Create a copy of our MIR and use it to create the drop shim for the generator
let drop_shim =
create_generator_drop_shim(tcx, &transform, def_id, source, gen_ty, body, drop_clean);
create_generator_drop_shim(tcx, &transform, source, gen_ty, body, drop_clean);
body.generator_drop = Some(box drop_shim);
// Create the Generator::resume function
create_generator_resume_function(tcx, transform, def_id, source, body, can_return);
create_generator_resume_function(tcx, transform, source, body, can_return);
}
}

View File

@ -22,7 +22,6 @@ pub mod copy_prop;
pub mod deaggregator;
pub mod dump_mir;
pub mod elaborate_drops;
pub mod erase_regions;
pub mod generator;
pub mod inline;
pub mod instcombine;
@ -296,8 +295,6 @@ fn run_optimization_passes<'tcx>(
&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.
&unreachable_prop::UnreachablePropagation,
&uninhabited_enum_branching::UninhabitedEnumBranching,
@ -341,6 +338,9 @@ fn optimized_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &BodyAndCache<'_> {
let mut body = body.steal();
run_optimization_passes(tcx, &mut body, def_id, None);
body.ensure_predecessors();
debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR");
tcx.arena.alloc(body)
}
@ -358,5 +358,7 @@ fn promoted_mir(tcx: TyCtxt<'_>, def_id: DefId) -> &IndexVec<Promoted, BodyAndCa
body.ensure_predecessors();
}
debug_assert!(!promoted.has_free_regions(), "Free regions in promoted MIR");
tcx.intern_promoted(promoted)
}

View File

@ -913,7 +913,13 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
ty,
val: ty::ConstKind::Unevaluated(
def_id,
InternalSubsts::identity_for_item(tcx, def_id),
InternalSubsts::for_item(tcx, def_id, |param, _| {
if let ty::GenericParamDefKind::Lifetime = param.kind {
tcx.lifetimes.re_erased.into()
} else {
tcx.mk_param_from_def(param)
}
}),
Some(promoted_id),
),
}),

View File

@ -6,7 +6,7 @@ use rustc::middle::lang_items;
use rustc::middle::region;
use rustc::mir::*;
use rustc::ty::subst::Subst;
use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
use rustc_attr::{self as attr, UnwindAttr};
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
@ -43,8 +43,7 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
..
})
| Node::TraitItem(hir::TraitItem {
kind:
hir::TraitItemKind::Fn(hir::FnSig { decl, .. }, hir::TraitFn::Provided(body_id)),
kind: hir::TraitItemKind::Fn(hir::FnSig { decl, .. }, hir::TraitFn::Provided(body_id)),
..
}) => (*body_id, decl.output.span()),
Node::Item(hir::Item { kind: hir::ItemKind::Static(ty, _, body_id), .. })
@ -128,12 +127,8 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
let ty = if fn_sig.c_variadic && index == fn_sig.inputs().len() {
let va_list_did =
tcx.require_lang_item(lang_items::VaListTypeLangItem, Some(arg.span));
let region = tcx.mk_region(ty::ReScope(region::Scope {
id: body.value.hir_id.local_id,
data: region::ScopeData::CallSite,
}));
tcx.type_of(va_list_did).subst(tcx, &[region.into()])
tcx.type_of(va_list_did).subst(tcx, &[tcx.lifetimes.re_erased.into()])
} else {
fn_sig.inputs()[index]
};
@ -189,6 +184,20 @@ fn mir_build(tcx: TyCtxt<'_>, def_id: DefId) -> BodyAndCache<'_> {
let mut body = BodyAndCache::new(body);
body.ensure_predecessors();
// The borrow checker will replace all the regions here with its own
// inference variables. There's no point having non-erased regions here.
// The exception is `body.user_type_annotations`, which is used unmodified
// by borrow checking.
debug_assert!(
!(body.local_decls.has_free_regions()
|| body.basic_blocks().has_free_regions()
|| body.var_debug_info.has_free_regions()
|| body.yield_ty.has_free_regions()),
"Unexpected free regions in MIR: {:?}",
body,
);
body
})
}
@ -209,7 +218,7 @@ fn liberated_closure_env_ty(
};
let closure_env_ty = tcx.closure_env_ty(closure_def_id, closure_substs).unwrap();
tcx.liberate_late_bound_regions(closure_def_id, &closure_env_ty)
tcx.erase_late_bound_regions(&closure_env_ty)
}
#[derive(Debug, PartialEq, Eq)]

View File

@ -15,7 +15,7 @@ fn main() {
}
// END RUST SOURCE
// START rustc.main.EraseRegions.after.mir
// START rustc.main.SimplifyCfg-elaborate-drops.after.mir
// bb0: {
// ...
// _4 = &mut _2;
@ -38,4 +38,4 @@ fn main() {
// ...
// return;
// }
// END rustc.main.EraseRegions.after.mir
// END rustc.main.SimplifyCfg-elaborate-drops.after.mir

View File

@ -6,10 +6,10 @@ fn main() {
}
// END RUST SOURCE
// START rustc.main.EraseRegions.after.mir
// START rustc.main.SimplifyCfg-elaborate-drops.after.mir
// ...
// _1 = const b"foo";
// ...
// _2 = [const 5u8, const 120u8];
// ...
// END rustc.main.EraseRegions.after.mir
// END rustc.main.SimplifyCfg-elaborate-drops.after.mir

View File

@ -15,7 +15,7 @@ impl Drop for Droppy {
}
// END RUST SOURCE
// START rustc.main.EraseRegions.before.mir
// START rustc.main.SimplifyCfg-elaborate-drops.after.mir
// fn main() -> () {
// let mut _0: ();
// let mut _1: Packed;
@ -56,4 +56,4 @@ impl Drop for Droppy {
// drop(_1) -> [return: bb2, unwind: bb1];
// }
// }
// END rustc.main.EraseRegions.before.mir
// END rustc.main.SimplifyCfg-elaborate-drops.after.mir

View File

@ -8,8 +8,12 @@ struct Test(i32);
impl Test {
// Make sure we run the pass on a method, not just on bare functions.
fn foo<'x>(&self, x: &'x mut i32) -> &'x mut i32 { x }
fn foo_shr<'x>(&self, x: &'x i32) -> &'x i32 { x }
fn foo<'x>(&self, x: &'x mut i32) -> &'x mut i32 {
x
}
fn foo_shr<'x>(&self, x: &'x i32) -> &'x i32 {
x
}
}
impl Drop for Test {
@ -27,7 +31,10 @@ fn main() {
}
// Also test closures
let c: fn(&i32) -> &i32 = |x: &i32| -> &i32 { let _y = x; x };
let c: fn(&i32) -> &i32 = |x: &i32| -> &i32 {
let _y = x;
x
};
let _w = c(&x);
// need to call `foo_shr` or it doesn't even get generated
@ -38,7 +45,7 @@ fn main() {
}
// END RUST SOURCE
// START rustc.{{impl}}-foo.EraseRegions.after.mir
// START rustc.{{impl}}-foo.SimplifyCfg-elaborate-drops.after.mir
// bb0: {
// Retag([fn entry] _1);
// Retag([fn entry] _2);
@ -48,8 +55,8 @@ fn main() {
// ...
// return;
// }
// END rustc.{{impl}}-foo.EraseRegions.after.mir
// START rustc.{{impl}}-foo_shr.EraseRegions.after.mir
// END rustc.{{impl}}-foo.SimplifyCfg-elaborate-drops.after.mir
// START rustc.{{impl}}-foo_shr.SimplifyCfg-elaborate-drops.after.mir
// bb0: {
// Retag([fn entry] _1);
// Retag([fn entry] _2);
@ -59,8 +66,8 @@ fn main() {
// ...
// return;
// }
// END rustc.{{impl}}-foo_shr.EraseRegions.after.mir
// START rustc.main.EraseRegions.after.mir
// END rustc.{{impl}}-foo_shr.SimplifyCfg-elaborate-drops.after.mir
// START rustc.main.SimplifyCfg-elaborate-drops.after.mir
// fn main() -> () {
// ...
// bb0: {
@ -96,8 +103,8 @@ fn main() {
//
// ...
// }
// END rustc.main.EraseRegions.after.mir
// START rustc.main-{{closure}}.EraseRegions.after.mir
// END rustc.main.SimplifyCfg-elaborate-drops.after.mir
// START rustc.main-{{closure}}.SimplifyCfg-elaborate-drops.after.mir
// fn main::{{closure}}#0(_1: &[closure@main::{{closure}}#0], _2: &i32) -> &i32 {
// ...
// bb0: {
@ -112,7 +119,7 @@ fn main() {
// return;
// }
// }
// END rustc.main-{{closure}}.EraseRegions.after.mir
// END rustc.main-{{closure}}.SimplifyCfg-elaborate-drops.after.mir
// START rustc.ptr-drop_in_place.Test.SimplifyCfg-make_shim.after.mir
// fn std::intrinsics::drop_in_place(_1: *mut Test) -> () {
// ...