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