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