]>
Commit | Line | Data |
---|---|---|
8faf50e0 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 | ||
11 | use borrow_check::nll::region_infer::RegionInferenceContext; | |
12 | use borrow_check::nll::ToRegionVid; | |
13 | use rustc::mir::{Local, Mir}; | |
14 | use rustc::ty::{RegionVid, TyCtxt}; | |
15 | use rustc_data_structures::indexed_vec::Idx; | |
16 | use syntax::codemap::Span; | |
17 | use syntax_pos::symbol::Symbol; | |
18 | ||
19 | impl<'tcx> RegionInferenceContext<'tcx> { | |
20 | crate fn get_var_name_and_span_for_region( | |
21 | &self, | |
22 | tcx: TyCtxt<'_, '_, 'tcx>, | |
23 | mir: &Mir<'tcx>, | |
24 | fr: RegionVid, | |
25 | ) -> Option<(Option<Symbol>, Span)> { | |
26 | debug!("get_var_name_and_span_for_region(fr={:?})", fr); | |
27 | assert!(self.universal_regions.is_universal_region(fr)); | |
28 | ||
29 | debug!("get_var_name_and_span_for_region: attempting upvar"); | |
30 | self.get_upvar_index_for_region(tcx, fr) | |
31 | .map(|index| { | |
32 | let (name, span) = self.get_upvar_name_and_span_for_region(tcx, mir, index); | |
33 | (Some(name), span) | |
34 | }) | |
35 | .or_else(|| { | |
36 | debug!("get_var_name_and_span_for_region: attempting argument"); | |
37 | self.get_argument_index_for_region(tcx, fr) | |
38 | .map(|index| self.get_argument_name_and_span_for_region(mir, index)) | |
39 | }) | |
40 | } | |
41 | ||
42 | /// Search the upvars (if any) to find one that references fr. Return its index. | |
43 | crate fn get_upvar_index_for_region( | |
44 | &self, | |
45 | tcx: TyCtxt<'_, '_, 'tcx>, | |
46 | fr: RegionVid, | |
47 | ) -> Option<usize> { | |
48 | let upvar_index = self | |
49 | .universal_regions | |
50 | .defining_ty | |
51 | .upvar_tys(tcx) | |
52 | .position(|upvar_ty| { | |
53 | debug!( | |
54 | "get_upvar_index_for_region: upvar_ty = {:?}", | |
55 | upvar_ty, | |
56 | ); | |
57 | tcx.any_free_region_meets(&upvar_ty, |r| r.to_region_vid() == fr) | |
58 | })?; | |
59 | ||
60 | let upvar_ty = self | |
61 | .universal_regions | |
62 | .defining_ty | |
63 | .upvar_tys(tcx) | |
64 | .nth(upvar_index); | |
65 | ||
66 | debug!( | |
67 | "get_upvar_index_for_region: found {:?} in upvar {} which has type {:?}", | |
68 | fr, upvar_index, upvar_ty, | |
69 | ); | |
70 | ||
71 | Some(upvar_index) | |
72 | } | |
73 | ||
74 | /// Given the index of an upvar, finds its name and the span from where it was | |
75 | /// declared. | |
76 | crate fn get_upvar_name_and_span_for_region( | |
77 | &self, | |
78 | tcx: TyCtxt<'_, '_, 'tcx>, | |
79 | mir: &Mir<'tcx>, | |
80 | upvar_index: usize, | |
81 | ) -> (Symbol, Span) { | |
82 | let upvar_hir_id = mir.upvar_decls[upvar_index].var_hir_id.assert_crate_local(); | |
83 | let upvar_node_id = tcx.hir.hir_to_node_id(upvar_hir_id); | |
84 | debug!("get_upvar_name_and_span_for_region: upvar_node_id={:?}", upvar_node_id); | |
85 | ||
86 | let upvar_name = tcx.hir.name(upvar_node_id); | |
87 | let upvar_span = tcx.hir.span(upvar_node_id); | |
88 | debug!("get_upvar_name_and_span_for_region: upvar_name={:?} upvar_span={:?}", | |
89 | upvar_name, upvar_span); | |
90 | ||
91 | (upvar_name, upvar_span) | |
92 | } | |
93 | ||
94 | /// Search the argument types for one that references fr (which should be a free region). | |
95 | /// Returns Some(_) with the index of the input if one is found. | |
96 | /// | |
97 | /// NB: In the case of a closure, the index is indexing into the signature as seen by the | |
98 | /// user - in particular, index 0 is not the implicit self parameter. | |
99 | crate fn get_argument_index_for_region( | |
100 | &self, | |
101 | tcx: TyCtxt<'_, '_, 'tcx>, | |
102 | fr: RegionVid, | |
103 | ) -> Option<usize> { | |
104 | let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs(); | |
105 | let argument_index = self | |
106 | .universal_regions | |
107 | .unnormalized_input_tys | |
108 | .iter() | |
109 | .skip(implicit_inputs) | |
110 | .position(|arg_ty| { | |
111 | debug!( | |
112 | "get_argument_index_for_region: arg_ty = {:?}", | |
113 | arg_ty | |
114 | ); | |
115 | tcx.any_free_region_meets(arg_ty, |r| r.to_region_vid() == fr) | |
116 | })?; | |
117 | ||
118 | debug!( | |
119 | "get_argument_index_for_region: found {:?} in argument {} which has type {:?}", | |
120 | fr, argument_index, self.universal_regions.unnormalized_input_tys[argument_index], | |
121 | ); | |
122 | ||
123 | Some(argument_index) | |
124 | } | |
125 | ||
126 | /// Given the index of an argument, finds its name (if any) and the span from where it was | |
127 | /// declared. | |
128 | crate fn get_argument_name_and_span_for_region( | |
129 | &self, | |
130 | mir: &Mir<'tcx>, | |
131 | argument_index: usize, | |
132 | ) -> (Option<Symbol>, Span) { | |
133 | let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs(); | |
134 | let argument_local = Local::new(implicit_inputs + argument_index + 1); | |
135 | debug!("get_argument_name_and_span_for_region: argument_local={:?}", argument_local); | |
136 | ||
137 | let argument_name = mir.local_decls[argument_local].name; | |
138 | let argument_span = mir.local_decls[argument_local].source_info.span; | |
139 | debug!("get_argument_name_and_span_for_region: argument_name={:?} argument_span={:?}", | |
140 | argument_name, argument_span); | |
141 | ||
142 | (argument_name, argument_span) | |
143 | } | |
144 | ||
145 | } |