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