]>
Commit | Line | Data |
---|---|---|
c295e0f8 XL |
1 | use crate::Upvar; |
2 | use crate::{nll::ToRegionVid, region_infer::RegionInferenceContext}; | |
60c5eb7d | 3 | use rustc_index::vec::{Idx, IndexVec}; |
ba9703b0 XL |
4 | use rustc_middle::mir::{Body, Local}; |
5 | use rustc_middle::ty::{RegionVid, TyCtxt}; | |
dfeec247 XL |
6 | use rustc_span::source_map::Span; |
7 | use rustc_span::symbol::Symbol; | |
8faf50e0 XL |
8 | |
9 | impl<'tcx> RegionInferenceContext<'tcx> { | |
10 | crate fn get_var_name_and_span_for_region( | |
11 | &self, | |
dc9dc135 XL |
12 | tcx: TyCtxt<'tcx>, |
13 | body: &Body<'tcx>, | |
60c5eb7d | 14 | local_names: &IndexVec<Local, Option<Symbol>>, |
5869c6ff | 15 | upvars: &[Upvar<'tcx>], |
8faf50e0 XL |
16 | fr: RegionVid, |
17 | ) -> Option<(Option<Symbol>, Span)> { | |
18 | debug!("get_var_name_and_span_for_region(fr={:?})", fr); | |
dfeec247 | 19 | assert!(self.universal_regions().is_universal_region(fr)); |
8faf50e0 XL |
20 | |
21 | debug!("get_var_name_and_span_for_region: attempting upvar"); | |
22 | self.get_upvar_index_for_region(tcx, fr) | |
23 | .map(|index| { | |
5869c6ff | 24 | // FIXME(project-rfc-2229#8): Use place span for diagnostics |
dfeec247 | 25 | let (name, span) = self.get_upvar_name_and_span_for_region(tcx, upvars, index); |
8faf50e0 XL |
26 | (Some(name), span) |
27 | }) | |
28 | .or_else(|| { | |
29 | debug!("get_var_name_and_span_for_region: attempting argument"); | |
60c5eb7d XL |
30 | self.get_argument_index_for_region(tcx, fr).map(|index| { |
31 | self.get_argument_name_and_span_for_region(body, local_names, index) | |
32 | }) | |
8faf50e0 XL |
33 | }) |
34 | } | |
35 | ||
36 | /// Search the upvars (if any) to find one that references fr. Return its index. | |
dc9dc135 | 37 | crate fn get_upvar_index_for_region(&self, tcx: TyCtxt<'tcx>, fr: RegionVid) -> Option<usize> { |
dfeec247 | 38 | let upvar_index = |
ba9703b0 | 39 | self.universal_regions().defining_ty.upvar_tys().position(|upvar_ty| { |
0bf4aa26 XL |
40 | debug!("get_upvar_index_for_region: upvar_ty={:?}", upvar_ty); |
41 | tcx.any_free_region_meets(&upvar_ty, |r| { | |
42 | let r = r.to_region_vid(); | |
43 | debug!("get_upvar_index_for_region: r={:?} fr={:?}", r, fr); | |
44 | r == fr | |
45 | }) | |
8faf50e0 XL |
46 | })?; |
47 | ||
ba9703b0 | 48 | let upvar_ty = self.universal_regions().defining_ty.upvar_tys().nth(upvar_index); |
8faf50e0 XL |
49 | |
50 | debug!( | |
51 | "get_upvar_index_for_region: found {:?} in upvar {} which has type {:?}", | |
52 | fr, upvar_index, upvar_ty, | |
53 | ); | |
54 | ||
55 | Some(upvar_index) | |
56 | } | |
57 | ||
58 | /// Given the index of an upvar, finds its name and the span from where it was | |
59 | /// declared. | |
60 | crate fn get_upvar_name_and_span_for_region( | |
61 | &self, | |
dc9dc135 | 62 | tcx: TyCtxt<'tcx>, |
5869c6ff | 63 | upvars: &[Upvar<'tcx>], |
8faf50e0 XL |
64 | upvar_index: usize, |
65 | ) -> (Symbol, Span) { | |
5869c6ff | 66 | let upvar_hir_id = upvars[upvar_index].place.get_root_variable(); |
9fa01778 | 67 | debug!("get_upvar_name_and_span_for_region: upvar_hir_id={:?}", upvar_hir_id); |
8faf50e0 | 68 | |
dc9dc135 XL |
69 | let upvar_name = tcx.hir().name(upvar_hir_id); |
70 | let upvar_span = tcx.hir().span(upvar_hir_id); | |
dfeec247 XL |
71 | debug!( |
72 | "get_upvar_name_and_span_for_region: upvar_name={:?} upvar_span={:?}", | |
73 | upvar_name, upvar_span | |
74 | ); | |
8faf50e0 XL |
75 | |
76 | (upvar_name, upvar_span) | |
77 | } | |
78 | ||
79 | /// Search the argument types for one that references fr (which should be a free region). | |
80 | /// Returns Some(_) with the index of the input if one is found. | |
81 | /// | |
0731742a | 82 | /// N.B., in the case of a closure, the index is indexing into the signature as seen by the |
8faf50e0 XL |
83 | /// user - in particular, index 0 is not the implicit self parameter. |
84 | crate fn get_argument_index_for_region( | |
85 | &self, | |
dc9dc135 | 86 | tcx: TyCtxt<'tcx>, |
8faf50e0 XL |
87 | fr: RegionVid, |
88 | ) -> Option<usize> { | |
dfeec247 XL |
89 | let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs(); |
90 | let argument_index = | |
91 | self.universal_regions().unnormalized_input_tys.iter().skip(implicit_inputs).position( | |
92 | |arg_ty| { | |
93 | debug!("get_argument_index_for_region: arg_ty = {:?}", arg_ty); | |
94 | tcx.any_free_region_meets(arg_ty, |r| r.to_region_vid() == fr) | |
95 | }, | |
96 | )?; | |
8faf50e0 XL |
97 | |
98 | debug!( | |
99 | "get_argument_index_for_region: found {:?} in argument {} which has type {:?}", | |
dfeec247 XL |
100 | fr, |
101 | argument_index, | |
102 | self.universal_regions().unnormalized_input_tys[argument_index], | |
8faf50e0 XL |
103 | ); |
104 | ||
105 | Some(argument_index) | |
106 | } | |
107 | ||
108 | /// Given the index of an argument, finds its name (if any) and the span from where it was | |
109 | /// declared. | |
110 | crate fn get_argument_name_and_span_for_region( | |
111 | &self, | |
dc9dc135 | 112 | body: &Body<'tcx>, |
60c5eb7d | 113 | local_names: &IndexVec<Local, Option<Symbol>>, |
8faf50e0 XL |
114 | argument_index: usize, |
115 | ) -> (Option<Symbol>, Span) { | |
dfeec247 | 116 | let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs(); |
8faf50e0 XL |
117 | let argument_local = Local::new(implicit_inputs + argument_index + 1); |
118 | debug!("get_argument_name_and_span_for_region: argument_local={:?}", argument_local); | |
119 | ||
60c5eb7d | 120 | let argument_name = local_names[argument_local]; |
dc9dc135 | 121 | let argument_span = body.local_decls[argument_local].source_info.span; |
dfeec247 XL |
122 | debug!( |
123 | "get_argument_name_and_span_for_region: argument_name={:?} argument_span={:?}", | |
124 | argument_name, argument_span | |
125 | ); | |
8faf50e0 XL |
126 | |
127 | (argument_name, argument_span) | |
128 | } | |
8faf50e0 | 129 | } |