Skip to content

Commit 13d94d5

Browse files
committed
Auto merge of #43559 - Nashenas88:nll-region-renumberer, r=arielb1
Non-lexical lifetimes region renumberer Regenerates region variables for all regions in a cloned MIR in the nll mir pass. This is part of the work for #43234.
2 parents b617960 + 0d29cd4 commit 13d94d5

File tree

2 files changed

+114
-14
lines changed

2 files changed

+114
-14
lines changed

src/librustc/mir/visit.rs

+1
Original file line numberDiff line numberDiff line change
@@ -753,6 +753,7 @@ macro_rules! make_mir_visitor {
753753
make_mir_visitor!(Visitor,);
754754
make_mir_visitor!(MutVisitor,mut);
755755

756+
#[derive(Copy, Clone, Debug)]
756757
pub enum Lookup {
757758
Loc(Location),
758759
Src(SourceInfo),

src/librustc_mir/transform/nll.rs

+113-14
Original file line numberDiff line numberDiff line change
@@ -8,26 +8,119 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
use rustc::ty::TyCtxt;
12-
use rustc::mir::Mir;
13-
use rustc::mir::visit::MutVisitor;
11+
use rustc::ty::TypeFoldable;
12+
use rustc::ty::subst::{Kind, Substs};
13+
use rustc::ty::{Ty, TyCtxt, ClosureSubsts, RegionVid, RegionKind};
14+
use rustc::mir::{Mir, Location, Rvalue, BasicBlock, Statement, StatementKind};
15+
use rustc::mir::visit::{MutVisitor, Lookup};
1416
use rustc::mir::transform::{MirPass, MirSource};
17+
use rustc::infer::{self, InferCtxt};
18+
use syntax_pos::DUMMY_SP;
19+
use std::collections::HashMap;
1520

1621
#[allow(dead_code)]
17-
struct NLLVisitor<'a, 'tcx: 'a> {
18-
tcx: TyCtxt<'a, 'tcx, 'tcx>,
22+
struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
23+
lookup_map: HashMap<RegionVid, Lookup>,
24+
infcx: InferCtxt<'a, 'gcx, 'tcx>,
1925
}
2026

21-
impl<'a, 'tcx> NLLVisitor<'a, 'tcx> {
22-
pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
27+
impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> {
28+
pub fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>) -> Self {
2329
NLLVisitor {
24-
tcx: tcx
30+
infcx: infcx,
31+
lookup_map: HashMap::new(),
32+
}
33+
}
34+
35+
pub fn into_results(self) -> HashMap<RegionVid, Lookup> {
36+
self.lookup_map
37+
}
38+
39+
fn renumber_regions<T>(&self, value: &T) -> T where T: TypeFoldable<'tcx> {
40+
self.infcx.tcx.fold_regions(value, &mut false, |_region, _depth| {
41+
self.infcx.next_region_var(infer::MiscVariable(DUMMY_SP))
42+
})
43+
}
44+
45+
fn store_region(&mut self, region: &RegionKind, lookup: Lookup) {
46+
if let RegionKind::ReVar(rid) = *region {
47+
self.lookup_map.entry(rid).or_insert(lookup);
48+
}
49+
}
50+
51+
fn store_ty_regions(&mut self, ty: &Ty<'tcx>, lookup: Lookup) {
52+
for region in ty.regions() {
53+
self.store_region(region, lookup);
54+
}
55+
}
56+
57+
fn store_kind_regions(&mut self, kind: &'tcx Kind, lookup: Lookup) {
58+
if let Some(ty) = kind.as_type() {
59+
self.store_ty_regions(&ty, lookup);
60+
} else if let Some(region) = kind.as_region() {
61+
self.store_region(region, lookup);
2562
}
2663
}
2764
}
2865

29-
impl<'a, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'tcx> {
30-
// FIXME: Nashenas88: implement me!
66+
impl<'a, 'gcx, 'tcx> MutVisitor<'tcx> for NLLVisitor<'a, 'gcx, 'tcx> {
67+
fn visit_ty(&mut self, ty: &mut Ty<'tcx>, lookup: Lookup) {
68+
let old_ty = *ty;
69+
*ty = self.renumber_regions(&old_ty);
70+
self.store_ty_regions(ty, lookup);
71+
}
72+
73+
fn visit_substs(&mut self, substs: &mut &'tcx Substs<'tcx>, location: Location) {
74+
*substs = self.renumber_regions(&{*substs});
75+
let lookup = Lookup::Loc(location);
76+
for kind in *substs {
77+
self.store_kind_regions(kind, lookup);
78+
}
79+
}
80+
81+
fn visit_rvalue(&mut self, rvalue: &mut Rvalue<'tcx>, location: Location) {
82+
match *rvalue {
83+
Rvalue::Ref(ref mut r, _, _) => {
84+
let old_r = *r;
85+
*r = self.renumber_regions(&old_r);
86+
let lookup = Lookup::Loc(location);
87+
self.store_region(r, lookup);
88+
}
89+
Rvalue::Use(..) |
90+
Rvalue::Repeat(..) |
91+
Rvalue::Len(..) |
92+
Rvalue::Cast(..) |
93+
Rvalue::BinaryOp(..) |
94+
Rvalue::CheckedBinaryOp(..) |
95+
Rvalue::UnaryOp(..) |
96+
Rvalue::Discriminant(..) |
97+
Rvalue::NullaryOp(..) |
98+
Rvalue::Aggregate(..) => {
99+
// These variants don't contain regions.
100+
}
101+
}
102+
self.super_rvalue(rvalue, location);
103+
}
104+
105+
fn visit_closure_substs(&mut self,
106+
substs: &mut ClosureSubsts<'tcx>,
107+
location: Location) {
108+
*substs = self.renumber_regions(substs);
109+
let lookup = Lookup::Loc(location);
110+
for kind in substs.substs {
111+
self.store_kind_regions(kind, lookup);
112+
}
113+
}
114+
115+
fn visit_statement(&mut self,
116+
block: BasicBlock,
117+
statement: &mut Statement<'tcx>,
118+
location: Location) {
119+
if let StatementKind::EndRegion(_) = statement.kind {
120+
statement.kind = StatementKind::Nop;
121+
}
122+
self.super_statement(block, statement, location);
123+
}
31124
}
32125

33126
// MIR Pass for non-lexical lifetimes
@@ -38,10 +131,16 @@ impl MirPass for NLL {
38131
tcx: TyCtxt<'a, 'tcx, 'tcx>,
39132
_: MirSource,
40133
mir: &mut Mir<'tcx>) {
41-
if tcx.sess.opts.debugging_opts.nll {
42-
// Clone mir so we can mutate it without disturbing the rest
43-
// of the compiler
44-
NLLVisitor::new(tcx).visit_mir(&mut mir.clone());
134+
if !tcx.sess.opts.debugging_opts.nll {
135+
return;
45136
}
137+
138+
tcx.infer_ctxt().enter(|infcx| {
139+
// Clone mir so we can mutate it without disturbing the rest of the compiler
140+
let mut renumbered_mir = mir.clone();
141+
let mut visitor = NLLVisitor::new(infcx);
142+
visitor.visit_mir(&mut renumbered_mir);
143+
let _results = visitor.into_results();
144+
})
46145
}
47146
}

0 commit comments

Comments
 (0)