rustc_borrowck/diagnostics/
var_name.rs

1use rustc_index::IndexSlice;
2use rustc_middle::mir::{Body, Local};
3use rustc_middle::ty::{self, RegionVid, TyCtxt};
4use rustc_span::{Span, Symbol};
5use tracing::debug;
6
7use crate::region_infer::RegionInferenceContext;
8
9impl<'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: &IndexSlice<Local, Option<Symbol>>,
15        upvars: &[&ty::CapturedPlace<'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().iter().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.as_var();
47                    debug!("get_upvar_index_for_region: r={r:?} fr={fr:?}");
48                    r == fr
49                })
50            })?;
51
52        let upvar_ty = self.universal_regions().defining_ty.upvar_tys().get(upvar_index);
53
54        debug!(
55            "get_upvar_index_for_region: found {fr:?} in upvar {upvar_index} which has type {upvar_ty:?}",
56        );
57
58        Some(upvar_index)
59    }
60
61    /// Given the index of an upvar, finds its name and the span from where it was
62    /// declared.
63    pub(crate) fn get_upvar_name_and_span_for_region(
64        &self,
65        tcx: TyCtxt<'tcx>,
66        upvars: &[&ty::CapturedPlace<'tcx>],
67        upvar_index: usize,
68    ) -> (Symbol, Span) {
69        let upvar_hir_id = upvars[upvar_index].get_root_variable();
70        debug!("get_upvar_name_and_span_for_region: upvar_hir_id={upvar_hir_id:?}");
71
72        let upvar_name = tcx.hir().name(upvar_hir_id);
73        let upvar_span = tcx.hir().span(upvar_hir_id);
74        debug!(
75            "get_upvar_name_and_span_for_region: upvar_name={upvar_name:?} upvar_span={upvar_span:?}",
76        );
77
78        (upvar_name, upvar_span)
79    }
80
81    /// Search the argument types for one that references fr (which should be a free region).
82    /// Returns Some(_) with the index of the input if one is found.
83    ///
84    /// N.B., in the case of a closure, the index is indexing into the signature as seen by the
85    /// user - in particular, index 0 is not the implicit self parameter.
86    pub(crate) fn get_argument_index_for_region(
87        &self,
88        tcx: TyCtxt<'tcx>,
89        fr: RegionVid,
90    ) -> Option<usize> {
91        let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs();
92        let argument_index =
93            self.universal_regions().unnormalized_input_tys.iter().skip(implicit_inputs).position(
94                |arg_ty| {
95                    debug!("get_argument_index_for_region: arg_ty = {arg_ty:?}");
96                    tcx.any_free_region_meets(arg_ty, |r| r.as_var() == fr)
97                },
98            )?;
99
100        debug!(
101            "get_argument_index_for_region: found {fr:?} in argument {argument_index} which has type {:?}",
102            self.universal_regions().unnormalized_input_tys[argument_index],
103        );
104
105        Some(argument_index)
106    }
107
108    /// Given the index of an argument, finds its name (if any) and the span from where it was
109    /// declared.
110    pub(crate) fn get_argument_name_and_span_for_region(
111        &self,
112        body: &Body<'tcx>,
113        local_names: &IndexSlice<Local, Option<Symbol>>,
114        argument_index: usize,
115    ) -> (Option<Symbol>, Span) {
116        let implicit_inputs = self.universal_regions().defining_ty.implicit_inputs();
117        let argument_local = Local::from_usize(implicit_inputs + argument_index + 1);
118        debug!("get_argument_name_and_span_for_region: argument_local={argument_local:?}");
119
120        let argument_name = local_names[argument_local];
121        let argument_span = body.local_decls[argument_local].source_info.span;
122        debug!(
123            "get_argument_name_and_span_for_region: argument_name={argument_name:?} argument_span={argument_span:?}",
124        );
125
126        (argument_name, argument_span)
127    }
128}