]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_borrowck/src/diagnostics/var_name.rs
Auto merge of #105657 - oli-obk:mk_projection_ty, r=lcnr
[rust.git] / compiler / rustc_borrowck / src / diagnostics / var_name.rs
1 #![deny(rustc::untranslatable_diagnostic)]
2 #![deny(rustc::diagnostic_outside_of_impl)]
3
4 use crate::Upvar;
5 use crate::{nll::ToRegionVid, region_infer::RegionInferenceContext};
6 use rustc_index::vec::{Idx, IndexVec};
7 use rustc_middle::mir::{Body, Local};
8 use rustc_middle::ty::{RegionVid, TyCtxt};
9 use rustc_span::source_map::Span;
10 use rustc_span::symbol::Symbol;
11
12 impl<'tcx> RegionInferenceContext<'tcx> {
13     pub(crate) fn get_var_name_and_span_for_region(
14         &self,
15         tcx: TyCtxt<'tcx>,
16         body: &Body<'tcx>,
17         local_names: &IndexVec<Local, Option<Symbol>>,
18         upvars: &[Upvar<'tcx>],
19         fr: RegionVid,
20     ) -> Option<(Option<Symbol>, Span)> {
21         debug!("get_var_name_and_span_for_region(fr={:?})", fr);
22         assert!(self.universal_regions().is_universal_region(fr));
23
24         debug!("get_var_name_and_span_for_region: attempting upvar");
25         self.get_upvar_index_for_region(tcx, fr)
26             .map(|index| {
27                 // FIXME(project-rfc-2229#8): Use place span for diagnostics
28                 let (name, span) = self.get_upvar_name_and_span_for_region(tcx, upvars, index);
29                 (Some(name), span)
30             })
31             .or_else(|| {
32                 debug!("get_var_name_and_span_for_region: attempting argument");
33                 self.get_argument_index_for_region(tcx, fr).map(|index| {
34                     self.get_argument_name_and_span_for_region(body, local_names, index)
35                 })
36             })
37     }
38
39     /// Search the upvars (if any) to find one that references fr. Return its index.
40     pub(crate) fn get_upvar_index_for_region(
41         &self,
42         tcx: TyCtxt<'tcx>,
43         fr: RegionVid,
44     ) -> Option<usize> {
45         let upvar_index =
46             self.universal_regions().defining_ty.upvar_tys().position(|upvar_ty| {
47                 debug!("get_upvar_index_for_region: upvar_ty={:?}", upvar_ty);
48                 tcx.any_free_region_meets(&upvar_ty, |r| {
49                     let r = r.to_region_vid();
50                     debug!("get_upvar_index_for_region: r={:?} fr={:?}", r, fr);
51                     r == fr
52                 })
53             })?;
54
55         let upvar_ty = self.universal_regions().defining_ty.upvar_tys().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     pub(crate) fn get_upvar_name_and_span_for_region(
68         &self,
69         tcx: TyCtxt<'tcx>,
70         upvars: &[Upvar<'tcx>],
71         upvar_index: usize,
72     ) -> (Symbol, Span) {
73         let upvar_hir_id = upvars[upvar_index].place.get_root_variable();
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!(
79             "get_upvar_name_and_span_for_region: upvar_name={:?} upvar_span={:?}",
80             upvar_name, upvar_span
81         );
82
83         (upvar_name, upvar_span)
84     }
85
86     /// Search the argument types for one that references fr (which should be a free region).
87     /// Returns Some(_) with the index of the input if one is found.
88     ///
89     /// N.B., in the case of a closure, the index is indexing into the signature as seen by the
90     /// user - in particular, index 0 is not the implicit self parameter.
91     pub(crate) fn get_argument_index_for_region(
92         &self,
93         tcx: TyCtxt<'tcx>,
94         fr: RegionVid,
95     ) -> Option<usize> {
96         let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs();
97         let argument_index =
98             self.universal_regions().unnormalized_input_tys.iter().skip(implicit_inputs).position(
99                 |arg_ty| {
100                     debug!("get_argument_index_for_region: arg_ty = {:?}", arg_ty);
101                     tcx.any_free_region_meets(arg_ty, |r| r.to_region_vid() == fr)
102                 },
103             )?;
104
105         debug!(
106             "get_argument_index_for_region: found {:?} in argument {} which has type {:?}",
107             fr,
108             argument_index,
109             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     pub(crate) fn get_argument_name_and_span_for_region(
118         &self,
119         body: &Body<'tcx>,
120         local_names: &IndexVec<Local, Option<Symbol>>,
121         argument_index: usize,
122     ) -> (Option<Symbol>, Span) {
123         let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs();
124         let argument_local = Local::new(implicit_inputs + argument_index + 1);
125         debug!("get_argument_name_and_span_for_region: argument_local={:?}", argument_local);
126
127         let argument_name = local_names[argument_local];
128         let argument_span = body.local_decls[argument_local].source_info.span;
129         debug!(
130             "get_argument_name_and_span_for_region: argument_name={:?} argument_span={:?}",
131             argument_name, argument_span
132         );
133
134         (argument_name, argument_span)
135     }
136 }