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