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