• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! Various code related to computing outlives relations.
2 use self::env::OutlivesEnvironment;
3 use super::region_constraints::RegionConstraintData;
4 use super::{InferCtxt, RegionResolutionError};
5 use crate::infer::free_regions::RegionRelations;
6 use crate::infer::lexical_region_resolve::{self, LexicalRegionResolutions};
7 use rustc_middle::traits::query::OutlivesBound;
8 use rustc_middle::ty;
9 
10 pub mod components;
11 pub mod env;
12 pub mod obligations;
13 pub mod test_type_match;
14 pub mod verify;
15 
16 #[instrument(level = "debug", skip(param_env), ret)]
explicit_outlives_bounds<'tcx>( param_env: ty::ParamEnv<'tcx>, ) -> impl Iterator<Item = OutlivesBound<'tcx>> + 'tcx17 pub fn explicit_outlives_bounds<'tcx>(
18     param_env: ty::ParamEnv<'tcx>,
19 ) -> impl Iterator<Item = OutlivesBound<'tcx>> + 'tcx {
20     param_env
21         .caller_bounds()
22         .into_iter()
23         .map(ty::Clause::kind)
24         .filter_map(ty::Binder::no_bound_vars)
25         .filter_map(move |kind| match kind {
26             ty::ClauseKind::RegionOutlives(ty::OutlivesPredicate(r_a, r_b)) => {
27                 Some(OutlivesBound::RegionSubRegion(r_b, r_a))
28             }
29             ty::ClauseKind::Trait(_)
30             | ty::ClauseKind::TypeOutlives(_)
31             | ty::ClauseKind::Projection(_)
32             | ty::ClauseKind::ConstArgHasType(_, _)
33             | ty::ClauseKind::WellFormed(_)
34             | ty::ClauseKind::ConstEvaluatable(_) => None,
35         })
36 }
37 
38 impl<'tcx> InferCtxt<'tcx> {
skip_region_resolution(&self)39     pub fn skip_region_resolution(&self) {
40         let (var_infos, _) = {
41             let mut inner = self.inner.borrow_mut();
42             let inner = &mut *inner;
43             // Note: `inner.region_obligations` may not be empty, because we
44             // didn't necessarily call `process_registered_region_obligations`.
45             // This is okay, because that doesn't introduce new vars.
46             inner
47                 .region_constraint_storage
48                 .take()
49                 .expect("regions already resolved")
50                 .with_log(&mut inner.undo_log)
51                 .into_infos_and_data()
52         };
53 
54         let lexical_region_resolutions = LexicalRegionResolutions {
55             values: rustc_index::IndexVec::from_elem_n(
56                 crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased),
57                 var_infos.len(),
58             ),
59         };
60 
61         let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
62         assert!(old_value.is_none());
63     }
64 
65     /// Process the region constraints and return any errors that
66     /// result. After this, no more unification operations should be
67     /// done -- or the compiler will panic -- but it is legal to use
68     /// `resolve_vars_if_possible` as well as `fully_resolve`.
69     #[must_use]
resolve_regions( &self, outlives_env: &OutlivesEnvironment<'tcx>, ) -> Vec<RegionResolutionError<'tcx>>70     pub fn resolve_regions(
71         &self,
72         outlives_env: &OutlivesEnvironment<'tcx>,
73     ) -> Vec<RegionResolutionError<'tcx>> {
74         self.process_registered_region_obligations(outlives_env);
75 
76         let (var_infos, data) = {
77             let mut inner = self.inner.borrow_mut();
78             let inner = &mut *inner;
79             assert!(
80                 self.tainted_by_errors().is_some() || inner.region_obligations.is_empty(),
81                 "region_obligations not empty: {:#?}",
82                 inner.region_obligations
83             );
84             inner
85                 .region_constraint_storage
86                 .take()
87                 .expect("regions already resolved")
88                 .with_log(&mut inner.undo_log)
89                 .into_infos_and_data()
90         };
91 
92         let region_rels = &RegionRelations::new(self.tcx, outlives_env.free_region_map());
93 
94         let (lexical_region_resolutions, errors) =
95             lexical_region_resolve::resolve(outlives_env.param_env, region_rels, var_infos, data);
96 
97         let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
98         assert!(old_value.is_none());
99 
100         errors
101     }
102 
103     /// Obtains (and clears) the current set of region
104     /// constraints. The inference context is still usable: further
105     /// unifications will simply add new constraints.
106     ///
107     /// This method is not meant to be used with normal lexical region
108     /// resolution. Rather, it is used in the NLL mode as a kind of
109     /// interim hack: basically we run normal type-check and generate
110     /// region constraints as normal, but then we take them and
111     /// translate them into the form that the NLL solver
112     /// understands. See the NLL module for mode details.
take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx>113     pub fn take_and_reset_region_constraints(&self) -> RegionConstraintData<'tcx> {
114         assert!(
115             self.inner.borrow().region_obligations.is_empty(),
116             "region_obligations not empty: {:#?}",
117             self.inner.borrow().region_obligations
118         );
119 
120         self.inner.borrow_mut().unwrap_region_constraints().take_and_reset_data()
121     }
122 
123     /// Gives temporary access to the region constraint data.
with_region_constraints<R>( &self, op: impl FnOnce(&RegionConstraintData<'tcx>) -> R, ) -> R124     pub fn with_region_constraints<R>(
125         &self,
126         op: impl FnOnce(&RegionConstraintData<'tcx>) -> R,
127     ) -> R {
128         let mut inner = self.inner.borrow_mut();
129         op(inner.unwrap_region_constraints().data())
130     }
131 }
132