-
Notifications
You must be signed in to change notification settings - Fork 13.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Non-lexical lifetimes region renumberer #43559
Changes from 3 commits
d2fc06e
5b2f6c7
7193c68
0d29cd4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,26 +8,115 @@ | |
// option. This file may not be copied, modified, or distributed | ||
// except according to those terms. | ||
|
||
use rustc::ty::TyCtxt; | ||
use rustc::mir::Mir; | ||
use rustc::mir::visit::MutVisitor; | ||
use rustc::ty::TypeFoldable; | ||
use rustc::ty::subst::{Kind, Substs}; | ||
use rustc::ty::{Ty, TyCtxt, ClosureSubsts, RegionVid, RegionKind}; | ||
use rustc::mir::{Mir, Location, Rvalue, BasicBlock, Statement, StatementKind}; | ||
use rustc::mir::visit::{MutVisitor, Lookup}; | ||
use rustc::mir::transform::{MirPass, MirSource}; | ||
use rustc::infer::{self, InferCtxt}; | ||
use syntax_pos::DUMMY_SP; | ||
use std::collections::HashMap; | ||
|
||
#[allow(dead_code)] | ||
struct NLLVisitor<'a, 'tcx: 'a> { | ||
tcx: TyCtxt<'a, 'tcx, 'tcx>, | ||
struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { | ||
pub lookup_map: HashMap<RegionVid, Lookup>, | ||
infcx: InferCtxt<'a, 'gcx, 'tcx>, | ||
} | ||
|
||
impl<'a, 'tcx> NLLVisitor<'a, 'tcx> { | ||
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self { | ||
impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> { | ||
pub fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>) -> Self { | ||
NLLVisitor { | ||
tcx: tcx | ||
infcx: infcx, | ||
lookup_map: HashMap::new(), | ||
} | ||
} | ||
|
||
fn renumber_regions<T>(&self, value: &T) -> T where T: TypeFoldable<'tcx> { | ||
self.infcx.tcx.fold_regions(value, &mut false, |_region, _depth| { | ||
self.infcx.next_region_var(infer::MiscVariable(DUMMY_SP)) | ||
}) | ||
} | ||
|
||
fn store_region(&mut self, region: &RegionKind, lookup: Lookup) { | ||
if let RegionKind::ReVar(rid) = *region { | ||
self.lookup_map.entry(rid).or_insert(lookup); | ||
} | ||
} | ||
|
||
fn store_ty_regions(&mut self, ty: &Ty<'tcx>, lookup: Lookup) { | ||
for region in ty.regions() { | ||
self.store_region(region, lookup); | ||
} | ||
} | ||
|
||
fn store_kind_regions(&mut self, kind: &'tcx Kind, lookup: Lookup) { | ||
if let Some(ty) = kind.as_type() { | ||
self.store_ty_regions(&ty, lookup); | ||
} else if let Some(region) = kind.as_region() { | ||
self.store_region(region, lookup); | ||
} | ||
} | ||
} | ||
|
||
impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> { | ||
// FIXME: Nashenas88: implement me! | ||
impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> { | ||
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, lookup: Lookup) { | ||
let old_ty = *ty; | ||
*ty = self.renumber_regions(&old_ty); | ||
self.store_ty_regions(ty, lookup); | ||
} | ||
|
||
fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) { | ||
*substs = self.renumber_regions(&{*substs}); | ||
let lookup = Lookup::Loc(location); | ||
for kind in *substs { | ||
self.store_kind_regions(kind, lookup); | ||
} | ||
} | ||
|
||
fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) { | ||
match *rvalue { | ||
Rvalue::Ref(ref mut r, _, _) => { | ||
let old_r = *r; | ||
*r = self.renumber_regions(&old_r); | ||
let lookup = Lookup::Loc(location); | ||
self.store_region(r, lookup); | ||
} | ||
Rvalue::Use(..) | | ||
Rvalue::Repeat(..) | | ||
Rvalue::Len(..) | | ||
Rvalue::Cast(..) | | ||
Rvalue::BinaryOp(..) | | ||
Rvalue::CheckedBinaryOp(..) | | ||
Rvalue::UnaryOp(..) | | ||
Rvalue::Discriminant(..) | | ||
Rvalue::NullaryOp(..) | | ||
Rvalue::Aggregate(..) => { | ||
// These variants don't contain regions. | ||
} | ||
} | ||
self.super_rvalue(rvalue, location); | ||
} | ||
|
||
fn visit_closure_substs(&mut self, | ||
substs: &mut ClosureSubsts<'tcx>, | ||
location: Location) { | ||
*substs = self.renumber_regions(substs); | ||
let lookup = Lookup::Loc(location); | ||
for kind in substs.substs { | ||
self.store_kind_regions(kind, lookup); | ||
} | ||
} | ||
|
||
fn visit_statement(&mut self, | ||
block: BasicBlock, | ||
statement: &mut Statement<'tcx>, | ||
location: Location) { | ||
if let StatementKind::EndRegion(_) = statement.kind { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I wasn't sure if this should also be used from the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
statement.kind = StatementKind::Nop; | ||
} | ||
self.super_statement(block, statement, location); | ||
} | ||
} | ||
|
||
// MIR Pass for non-lexical lifetimes | ||
|
@@ -38,10 +127,15 @@ impl MirPass for NLL { | |
tcx: TyCtxt<'a, 'tcx, 'tcx>, | ||
_: MirSource, | ||
mir: &mut Mir<'tcx>) { | ||
if tcx.sess.opts.debugging_opts.nll { | ||
// Clone mir so we can mutate it without disturbing the rest | ||
// of the compiler | ||
NLLVisitor::new(tcx).visit_mir(&mut mir.clone()); | ||
if !tcx.sess.opts.debugging_opts.nll { | ||
return; | ||
} | ||
|
||
tcx.infer_ctxt().enter(|infcx| { | ||
// Clone mir so we can mutate it without disturbing the rest of the compiler | ||
let mut renumbered_mir = mir.clone(); | ||
let mut visitor = NLLVisitor::new(infcx); | ||
visitor.visit_mir(&mut renumbered_mir); | ||
}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to add a method on
NLLVisitor
that takes ownership ofself
and returns theHashMap
? This is rather than making the field public.fn to_lookup(self) -> HashMap<RegionVid, Lookup> { self.lookup_map }
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would usually do something like that, yeah, but I'd call it
into_lookup()
orinto_results()
.