1 use rustc_infer::infer::canonical::QueryOutlivesConstraint;
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::ConstraintCategory;
8 use rustc_middle::ty::subst::GenericArgKind;
9 use rustc_middle::ty::{self, TyCtxt};
10 use rustc_span::DUMMY_SP;
12 use crate::borrow_check::{
13 constraints::OutlivesConstraint,
15 region_infer::TypeTest,
16 type_check::{Locations, MirTypeckRegionConstraints},
17 universal_regions::UniversalRegions,
20 crate struct ConstraintConversion<'a, 'tcx> {
21 infcx: &'a InferCtxt<'a, 'tcx>,
23 universal_regions: &'a UniversalRegions<'tcx>,
24 region_bound_pairs: &'a RegionBoundPairs<'tcx>,
25 implicit_region_bound: Option<ty::Region<'tcx>>,
26 param_env: ty::ParamEnv<'tcx>,
28 category: ConstraintCategory,
29 constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
32 impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
34 infcx: &'a InferCtxt<'a, 'tcx>,
35 universal_regions: &'a UniversalRegions<'tcx>,
36 region_bound_pairs: &'a RegionBoundPairs<'tcx>,
37 implicit_region_bound: Option<ty::Region<'tcx>>,
38 param_env: ty::ParamEnv<'tcx>,
40 category: ConstraintCategory,
41 constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
48 implicit_region_bound,
56 pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) {
57 debug!("convert_all(query_constraints={:#?})", query_constraints);
59 let QueryRegionConstraints { outlives, member_constraints } = query_constraints;
61 // Annoying: to invoke `self.to_region_vid`, we need access to
62 // `self.constraints`, but we also want to be mutating
63 // `self.member_constraints`. For now, just swap out the value
64 // we want and replace at the end.
65 let mut tmp = std::mem::take(&mut self.constraints.member_constraints);
66 for member_constraint in member_constraints {
67 tmp.push_constraint(member_constraint, |r| self.to_region_vid(r));
69 self.constraints.member_constraints = tmp;
71 for query_constraint in outlives {
72 self.convert(query_constraint);
76 pub(super) fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) {
77 debug!("generate: constraints at: {:#?}", self.locations);
79 // Extract out various useful fields we'll need below.
80 let ConstraintConversion {
81 tcx, region_bound_pairs, implicit_region_bound, param_env, ..
84 // At the moment, we never generate any "higher-ranked"
85 // region constraints like `for<'a> 'a: 'b`. At some point
86 // when we move to universes, we will, and this assertion
87 // will start to fail.
88 let ty::OutlivesPredicate(k1, r2) = query_constraint.no_bound_vars().unwrap_or_else(|| {
89 bug!("query_constraint {:?} contained bound vars", query_constraint,);
93 GenericArgKind::Lifetime(r1) => {
94 let r1_vid = self.to_region_vid(r1);
95 let r2_vid = self.to_region_vid(r2);
96 self.add_outlives(r1_vid, r2_vid);
99 GenericArgKind::Type(t1) => {
100 // we don't actually use this for anything, but
101 // the `TypeOutlives` code needs an origin.
102 let origin = infer::RelateParamBound(DUMMY_SP, t1);
108 implicit_region_bound,
111 .type_must_outlive(origin, t1, r2);
114 GenericArgKind::Const(_) => {
115 // Consts cannot outlive one another, so we
116 // don't need to handle any relations here.
121 fn verify_to_type_test(
123 generic_kind: GenericKind<'tcx>,
124 region: ty::Region<'tcx>,
125 verify_bound: VerifyBound<'tcx>,
126 ) -> TypeTest<'tcx> {
127 let lower_bound = self.to_region_vid(region);
129 TypeTest { generic_kind, lower_bound, locations: self.locations, verify_bound }
132 fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid {
133 if let ty::RePlaceholder(placeholder) = r {
134 self.constraints.placeholder_region(self.infcx, *placeholder).to_region_vid()
136 self.universal_regions.to_region_vid(r)
140 fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) {
141 self.constraints.outlives_constraints.push(OutlivesConstraint {
142 locations: self.locations,
143 category: self.category,
149 fn add_type_test(&mut self, type_test: TypeTest<'tcx>) {
150 debug!("add_type_test(type_test={:?})", type_test);
151 self.constraints.type_tests.push(type_test);
155 impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'b, 'tcx> {
156 fn push_sub_region_constraint(
158 _origin: SubregionOrigin<'tcx>,
162 let b = self.to_region_vid(b);
163 let a = self.to_region_vid(a);
164 self.add_outlives(b, a);
169 _origin: SubregionOrigin<'tcx>,
170 kind: GenericKind<'tcx>,
172 bound: VerifyBound<'tcx>,
174 let type_test = self.verify_to_type_test(kind, a, bound);
175 self.add_type_test(type_test);