1 use rustc_hir::def_id::DefId;
2 use rustc_infer::infer::canonical::QueryRegionConstraints;
3 use rustc_infer::infer::outlives::env::RegionBoundPairs;
4 use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
5 use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
6 use rustc_infer::infer::{self, InferCtxt, SubregionOrigin};
7 use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory};
8 use rustc_middle::ty::subst::GenericArgKind;
9 use rustc_middle::ty::TypeFoldable;
10 use rustc_middle::ty::{self, TyCtxt};
11 use rustc_span::{Span, DUMMY_SP};
14 constraints::OutlivesConstraint,
16 region_infer::TypeTest,
17 type_check::{Locations, MirTypeckRegionConstraints},
18 universal_regions::UniversalRegions,
21 pub(crate) struct ConstraintConversion<'a, 'tcx> {
22 infcx: &'a InferCtxt<'tcx>,
24 universal_regions: &'a UniversalRegions<'tcx>,
25 /// Each RBP `GK: 'a` is assumed to be true. These encode
26 /// relationships like `T: 'a` that are added via implicit bounds
27 /// or the `param_env`.
29 /// Each region here is guaranteed to be a key in the `indices`
30 /// map. We use the "original" regions (i.e., the keys from the
31 /// map, and not the values) because the code in
32 /// `process_registered_region_obligations` has some special-cased
33 /// logic expecting to see (e.g.) `ReStatic`, and if we supplied
34 /// our special inference variable there, we would mess that up.
35 region_bound_pairs: &'a RegionBoundPairs<'tcx>,
36 implicit_region_bound: ty::Region<'tcx>,
37 param_env: ty::ParamEnv<'tcx>,
40 category: ConstraintCategory<'tcx>,
42 constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
45 impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
47 infcx: &'a InferCtxt<'tcx>,
48 universal_regions: &'a UniversalRegions<'tcx>,
49 region_bound_pairs: &'a RegionBoundPairs<'tcx>,
50 implicit_region_bound: ty::Region<'tcx>,
51 param_env: ty::ParamEnv<'tcx>,
54 category: ConstraintCategory<'tcx>,
55 constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
62 implicit_region_bound,
72 #[instrument(skip(self), level = "debug")]
73 pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) {
74 let QueryRegionConstraints { outlives, member_constraints } = query_constraints;
76 // Annoying: to invoke `self.to_region_vid`, we need access to
77 // `self.constraints`, but we also want to be mutating
78 // `self.member_constraints`. For now, just swap out the value
79 // we want and replace at the end.
80 let mut tmp = std::mem::take(&mut self.constraints.member_constraints);
81 for member_constraint in member_constraints {
82 tmp.push_constraint(member_constraint, |r| self.to_region_vid(r));
84 self.constraints.member_constraints = tmp;
86 for (predicate, constraint_category) in outlives {
87 // At the moment, we never generate any "higher-ranked"
88 // region constraints like `for<'a> 'a: 'b`. At some point
89 // when we move to universes, we will, and this assertion
90 // will start to fail.
91 let predicate = predicate.no_bound_vars().unwrap_or_else(|| {
92 bug!("query_constraint {:?} contained bound vars", predicate,);
95 self.convert(predicate, *constraint_category);
99 /// Given an instance of the closure type, this method instantiates the "extra" requirements
100 /// that we computed for the closure. This has the effect of adding new outlives obligations
101 /// to existing region variables in `closure_substs`.
102 #[instrument(skip(self), level = "debug")]
103 pub fn apply_closure_requirements(
105 closure_requirements: &ClosureRegionRequirements<'tcx>,
106 closure_def_id: DefId,
107 closure_substs: ty::SubstsRef<'tcx>,
109 // Extract the values of the free regions in `closure_substs`
110 // into a vector. These are the regions that we will be
111 // relating to one another.
112 let closure_mapping = &UniversalRegions::closure_mapping(
115 closure_requirements.num_external_vids,
116 closure_def_id.expect_local(),
118 debug!(?closure_mapping);
120 // Create the predicates.
121 let backup = (self.category, self.span, self.from_closure);
122 self.from_closure = true;
123 for outlives_requirement in &closure_requirements.outlives_requirements {
124 let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
125 let subject = match outlives_requirement.subject {
126 ClosureOutlivesSubject::Region(re) => closure_mapping[re].into(),
127 ClosureOutlivesSubject::Ty(ty) => ty.into(),
130 self.category = outlives_requirement.category;
131 self.span = outlives_requirement.blame_span;
132 self.convert(ty::OutlivesPredicate(subject, outlived_region), self.category);
134 (self.category, self.span, self.from_closure) = backup;
139 predicate: ty::OutlivesPredicate<ty::GenericArg<'tcx>, ty::Region<'tcx>>,
140 constraint_category: ConstraintCategory<'tcx>,
142 debug!("generate: constraints at: {:#?}", self.locations);
144 // Extract out various useful fields we'll need below.
145 let ConstraintConversion {
146 tcx, region_bound_pairs, implicit_region_bound, param_env, ..
149 let ty::OutlivesPredicate(k1, r2) = predicate;
151 GenericArgKind::Lifetime(r1) => {
152 let r1_vid = self.to_region_vid(r1);
153 let r2_vid = self.to_region_vid(r2);
154 self.add_outlives(r1_vid, r2_vid, constraint_category);
157 GenericArgKind::Type(t1) => {
158 // we don't actually use this for anything, but
159 // the `TypeOutlives` code needs an origin.
160 let origin = infer::RelateParamBound(DUMMY_SP, t1, None);
166 Some(implicit_region_bound),
169 .type_must_outlive(origin, t1, r2, constraint_category);
172 GenericArgKind::Const(_) => unreachable!(),
176 /// Placeholder regions need to be converted eagerly because it may
177 /// create new region variables, which we must not do when verifying
178 /// our region bounds.
180 /// FIXME: This should get removed once higher ranked region obligations
181 /// are dealt with during trait solving.
182 fn replace_placeholders_with_nll<T: TypeFoldable<'tcx>>(&mut self, value: T) -> T {
183 if value.has_placeholders() {
184 self.tcx.fold_regions(value, |r, _| match *r {
185 ty::RePlaceholder(placeholder) => {
186 self.constraints.placeholder_region(self.infcx, placeholder)
195 fn verify_to_type_test(
197 generic_kind: GenericKind<'tcx>,
198 region: ty::Region<'tcx>,
199 verify_bound: VerifyBound<'tcx>,
200 ) -> TypeTest<'tcx> {
201 let lower_bound = self.to_region_vid(region);
202 TypeTest { generic_kind, lower_bound, span: self.span, verify_bound }
205 fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid {
206 if let ty::RePlaceholder(placeholder) = *r {
207 self.constraints.placeholder_region(self.infcx, placeholder).to_region_vid()
209 self.universal_regions.to_region_vid(r)
217 category: ConstraintCategory<'tcx>,
219 let category = match self.category {
220 ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation => category,
223 self.constraints.outlives_constraints.push(OutlivesConstraint {
224 locations: self.locations,
229 variance_info: ty::VarianceDiagInfo::default(),
230 from_closure: self.from_closure,
234 fn add_type_test(&mut self, type_test: TypeTest<'tcx>) {
235 debug!("add_type_test(type_test={:?})", type_test);
236 self.constraints.type_tests.push(type_test);
240 impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'b, 'tcx> {
241 fn push_sub_region_constraint(
243 _origin: SubregionOrigin<'tcx>,
246 constraint_category: ConstraintCategory<'tcx>,
248 let b = self.to_region_vid(b);
249 let a = self.to_region_vid(a);
250 self.add_outlives(b, a, constraint_category);
255 _origin: SubregionOrigin<'tcx>,
256 kind: GenericKind<'tcx>,
258 bound: VerifyBound<'tcx>,
260 let kind = self.replace_placeholders_with_nll(kind);
261 let bound = self.replace_placeholders_with_nll(bound);
262 let type_test = self.verify_to_type_test(kind, a, bound);
263 self.add_type_test(type_test);