• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![deny(rustc::untranslatable_diagnostic)]
2 #![deny(rustc::diagnostic_outside_of_impl)]
3 use crate::BorrowckInferCtxt;
4 use rustc_index::IndexSlice;
5 use rustc_infer::infer::NllRegionVariableOrigin;
6 use rustc_middle::mir::visit::{MutVisitor, TyContext};
7 use rustc_middle::mir::Constant;
8 use rustc_middle::mir::{Body, Location, Promoted};
9 use rustc_middle::ty::subst::SubstsRef;
10 use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable};
11 use rustc_span::{Span, Symbol};
12 
13 /// Replaces all free regions appearing in the MIR with fresh
14 /// inference variables, returning the number of variables created.
15 #[instrument(skip(infcx, body, promoted), level = "debug")]
renumber_mir<'tcx>( infcx: &BorrowckInferCtxt<'_, 'tcx>, body: &mut Body<'tcx>, promoted: &mut IndexSlice<Promoted, Body<'tcx>>, )16 pub fn renumber_mir<'tcx>(
17     infcx: &BorrowckInferCtxt<'_, 'tcx>,
18     body: &mut Body<'tcx>,
19     promoted: &mut IndexSlice<Promoted, Body<'tcx>>,
20 ) {
21     debug!(?body.arg_count);
22 
23     let mut renumberer = RegionRenumberer { infcx };
24 
25     for body in promoted.iter_mut() {
26         renumberer.visit_body(body);
27     }
28 
29     renumberer.visit_body(body);
30 }
31 
32 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
33 pub(crate) enum BoundRegionInfo {
34     Name(Symbol),
35     Span(Span),
36 }
37 
38 #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
39 pub(crate) enum RegionCtxt {
40     Location(Location),
41     TyContext(TyContext),
42     Free(Symbol),
43     Bound(BoundRegionInfo),
44     LateBound(BoundRegionInfo),
45     Existential(Option<Symbol>),
46     Placeholder(BoundRegionInfo),
47     Unknown,
48 }
49 
50 impl RegionCtxt {
51     /// Used to determine the representative of a component in the strongly connected
52     /// constraint graph
preference_value(self) -> usize53     pub(crate) fn preference_value(self) -> usize {
54         match self {
55             RegionCtxt::Unknown => 1,
56             RegionCtxt::Existential(None) => 2,
57             RegionCtxt::Existential(Some(_)) | RegionCtxt::Free(_) => 2,
58             RegionCtxt::Location(_) => 3,
59             RegionCtxt::TyContext(_) => 4,
60             _ => 5,
61         }
62     }
63 }
64 
65 struct RegionRenumberer<'a, 'tcx> {
66     infcx: &'a BorrowckInferCtxt<'a, 'tcx>,
67 }
68 
69 impl<'a, 'tcx> RegionRenumberer<'a, 'tcx> {
70     /// Replaces all regions appearing in `value` with fresh inference
71     /// variables.
renumber_regions<T, F>(&mut self, value: T, region_ctxt_fn: F) -> T where T: TypeFoldable<TyCtxt<'tcx>>, F: Fn() -> RegionCtxt,72     fn renumber_regions<T, F>(&mut self, value: T, region_ctxt_fn: F) -> T
73     where
74         T: TypeFoldable<TyCtxt<'tcx>>,
75         F: Fn() -> RegionCtxt,
76     {
77         let origin = NllRegionVariableOrigin::Existential { from_forall: false };
78         self.infcx.tcx.fold_regions(value, |_region, _depth| {
79             self.infcx.next_nll_region_var(origin, || region_ctxt_fn())
80         })
81     }
82 }
83 
84 impl<'a, 'tcx> MutVisitor<'tcx> for RegionRenumberer<'a, 'tcx> {
tcx(&self) -> TyCtxt<'tcx>85     fn tcx(&self) -> TyCtxt<'tcx> {
86         self.infcx.tcx
87     }
88 
89     #[instrument(skip(self), level = "debug")]
visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext)90     fn visit_ty(&mut self, ty: &mut Ty<'tcx>, ty_context: TyContext) {
91         *ty = self.renumber_regions(*ty, || RegionCtxt::TyContext(ty_context));
92 
93         debug!(?ty);
94     }
95 
96     #[instrument(skip(self), level = "debug")]
visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location)97     fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) {
98         *substs = self.renumber_regions(*substs, || RegionCtxt::Location(location));
99 
100         debug!(?substs);
101     }
102 
103     #[instrument(skip(self), level = "debug")]
visit_region(&mut self, region: &mut ty::Region<'tcx>, location: Location)104     fn visit_region(&mut self, region: &mut ty::Region<'tcx>, location: Location) {
105         let old_region = *region;
106         *region = self.renumber_regions(old_region, || RegionCtxt::Location(location));
107 
108         debug!(?region);
109     }
110 
111     #[instrument(skip(self), level = "debug")]
visit_ty_const(&mut self, ct: &mut ty::Const<'tcx>, location: Location)112     fn visit_ty_const(&mut self, ct: &mut ty::Const<'tcx>, location: Location) {
113         let old_ct = *ct;
114         *ct = self.renumber_regions(old_ct, || RegionCtxt::Location(location));
115 
116         debug!(?ct);
117     }
118 
119     #[instrument(skip(self), level = "debug")]
visit_constant(&mut self, constant: &mut Constant<'tcx>, location: Location)120     fn visit_constant(&mut self, constant: &mut Constant<'tcx>, location: Location) {
121         let literal = constant.literal;
122         constant.literal = self.renumber_regions(literal, || RegionCtxt::Location(location));
123         debug!("constant: {:#?}", constant);
124     }
125 }
126