]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_borrowck/src/diagnostics/var_name.rs
Auto merge of #101784 - reitermarkus:const-memchr, r=thomcc
[rust.git] / compiler / rustc_borrowck / src / diagnostics / var_name.rs
1 use crate::Upvar;
2 use crate::{nll::ToRegionVid, region_infer::RegionInferenceContext};
3 use rustc_index::vec::{Idx, IndexVec};
4 use rustc_middle::mir::{Body, Local};
5 use rustc_middle::ty::{RegionVid, TyCtxt};
6 use rustc_span::source_map::Span;
7 use rustc_span::symbol::Symbol;
8
9 impl<'tcx> RegionInferenceContext<'tcx> {
10     pub(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<'tcx>],
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                 // FIXME(project-rfc-2229#8): Use place span for diagnostics
25                 let (name, span) = 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     pub(crate) fn get_upvar_index_for_region(
38         &self,
39         tcx: TyCtxt<'tcx>,
40         fr: RegionVid,
41     ) -> Option<usize> {
42         let upvar_index =
43             self.universal_regions().defining_ty.upvar_tys().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.universal_regions().defining_ty.upvar_tys().nth(upvar_index);
53
54         debug!(
55             "get_upvar_index_for_region: found {:?} in upvar {} which has type {:?}",
56             fr, upvar_index, upvar_ty,
57         );
58
59         Some(upvar_index)
60     }
61
62     /// Given the index of an upvar, finds its name and the span from where it was
63     /// declared.
64     pub(crate) fn get_upvar_name_and_span_for_region(
65         &self,
66         tcx: TyCtxt<'tcx>,
67         upvars: &[Upvar<'tcx>],
68         upvar_index: usize,
69     ) -> (Symbol, Span) {
70         let upvar_hir_id = upvars[upvar_index].place.get_root_variable();
71         debug!("get_upvar_name_and_span_for_region: upvar_hir_id={:?}", upvar_hir_id);
72
73         let upvar_name = tcx.hir().name(upvar_hir_id);
74         let upvar_span = tcx.hir().span(upvar_hir_id);
75         debug!(
76             "get_upvar_name_and_span_for_region: upvar_name={:?} upvar_span={:?}",
77             upvar_name, upvar_span
78         );
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     pub(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 =
95             self.universal_regions().unnormalized_input_tys.iter().skip(implicit_inputs).position(
96                 |arg_ty| {
97                     debug!("get_argument_index_for_region: arg_ty = {:?}", arg_ty);
98                     tcx.any_free_region_meets(arg_ty, |r| r.to_region_vid() == fr)
99                 },
100             )?;
101
102         debug!(
103             "get_argument_index_for_region: found {:?} in argument {} which has type {:?}",
104             fr,
105             argument_index,
106             self.universal_regions().unnormalized_input_tys[argument_index],
107         );
108
109         Some(argument_index)
110     }
111
112     /// Given the index of an argument, finds its name (if any) and the span from where it was
113     /// declared.
114     pub(crate) fn get_argument_name_and_span_for_region(
115         &self,
116         body: &Body<'tcx>,
117         local_names: &IndexVec<Local, Option<Symbol>>,
118         argument_index: usize,
119     ) -> (Option<Symbol>, Span) {
120         let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs();
121         let argument_local = Local::new(implicit_inputs + argument_index + 1);
122         debug!("get_argument_name_and_span_for_region: argument_local={:?}", argument_local);
123
124         let argument_name = local_names[argument_local];
125         let argument_span = body.local_decls[argument_local].source_info.span;
126         debug!(
127             "get_argument_name_and_span_for_region: argument_name={:?} argument_span={:?}",
128             argument_name, argument_span
129         );
130
131         (argument_name, argument_span)
132     }
133 }