]> git.proxmox.com Git - rustc.git/blame - src/librustc_mir/transform/nll.rs
New upstream version 1.21.0+dfsg1
[rustc.git] / src / librustc_mir / transform / nll.rs
CommitLineData
3b2f2976
XL
1// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11use rustc::ty::TypeFoldable;
12use rustc::ty::subst::{Kind, Substs};
13use rustc::ty::{Ty, TyCtxt, ClosureSubsts, RegionVid, RegionKind};
14use rustc::mir::{Mir, Location, Rvalue, BasicBlock, Statement, StatementKind};
15use rustc::mir::visit::{MutVisitor, Lookup};
16use rustc::mir::transform::{MirPass, MirSource};
17use rustc::infer::{self, InferCtxt};
18use syntax_pos::DUMMY_SP;
19use std::collections::HashMap;
20
21#[allow(dead_code)]
22struct NLLVisitor<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> {
23 lookup_map: HashMap<RegionVid, Lookup>,
24 infcx: InferCtxt<'a, 'gcx, 'tcx>,
25}
26
27impl<'a, 'gcx, 'tcx> NLLVisitor<'a, 'gcx, 'tcx> {
28 pub fn new(infcx: InferCtxt<'a, 'gcx, 'tcx>) -> Self {
29 NLLVisitor {
30 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);
62 }
63 }
64}
65
66impl<'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 }
124}
125
126// MIR Pass for non-lexical lifetimes
127pub struct NLL;
128
129impl MirPass for NLL {
130 fn run_pass<'a, 'tcx>(&self,
131 tcx: TyCtxt<'a, 'tcx, 'tcx>,
132 _: MirSource,
133 mir: &mut Mir<'tcx>) {
134 if !tcx.sess.opts.debugging_opts.nll {
135 return;
136 }
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 })
145 }
146}