]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
Rollup merge of #98707 - joboet:fuchsia_locks, r=m-ou-se
[rust.git] / compiler / rustc_borrowck / src / type_check / constraint_conversion.rs
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::TypeVisitable;
10 use rustc_middle::ty::{self, TyCtxt};
11 use rustc_span::{Span, DUMMY_SP};
12
13 use crate::{
14     constraints::OutlivesConstraint,
15     nll::ToRegionVid,
16     region_infer::TypeTest,
17     type_check::{Locations, MirTypeckRegionConstraints},
18     universal_regions::UniversalRegions,
19 };
20
21 pub(crate) struct ConstraintConversion<'a, 'tcx> {
22     infcx: &'a InferCtxt<'a, 'tcx>,
23     tcx: TyCtxt<'tcx>,
24     universal_regions: &'a UniversalRegions<'tcx>,
25     region_bound_pairs: &'a RegionBoundPairs<'tcx>,
26     implicit_region_bound: ty::Region<'tcx>,
27     param_env: ty::ParamEnv<'tcx>,
28     locations: Locations,
29     span: Span,
30     category: ConstraintCategory<'tcx>,
31     constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
32 }
33
34 impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
35     pub(crate) fn new(
36         infcx: &'a InferCtxt<'a, 'tcx>,
37         universal_regions: &'a UniversalRegions<'tcx>,
38         region_bound_pairs: &'a RegionBoundPairs<'tcx>,
39         implicit_region_bound: ty::Region<'tcx>,
40         param_env: ty::ParamEnv<'tcx>,
41         locations: Locations,
42         span: Span,
43         category: ConstraintCategory<'tcx>,
44         constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
45     ) -> Self {
46         Self {
47             infcx,
48             tcx: infcx.tcx,
49             universal_regions,
50             region_bound_pairs,
51             implicit_region_bound,
52             param_env,
53             locations,
54             span,
55             category,
56             constraints,
57         }
58     }
59
60     #[instrument(skip(self), level = "debug")]
61     pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) {
62         let QueryRegionConstraints { outlives, member_constraints } = query_constraints;
63
64         // Annoying: to invoke `self.to_region_vid`, we need access to
65         // `self.constraints`, but we also want to be mutating
66         // `self.member_constraints`. For now, just swap out the value
67         // we want and replace at the end.
68         let mut tmp = std::mem::take(&mut self.constraints.member_constraints);
69         for member_constraint in member_constraints {
70             tmp.push_constraint(member_constraint, |r| self.to_region_vid(r));
71         }
72         self.constraints.member_constraints = tmp;
73
74         for query_constraint in outlives {
75             self.convert(query_constraint);
76         }
77     }
78
79     pub(super) fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) {
80         debug!("generate: constraints at: {:#?}", self.locations);
81
82         // Extract out various useful fields we'll need below.
83         let ConstraintConversion {
84             tcx, region_bound_pairs, implicit_region_bound, param_env, ..
85         } = *self;
86
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 ty::OutlivesPredicate(k1, r2) = query_constraint.no_bound_vars().unwrap_or_else(|| {
92             bug!("query_constraint {:?} contained bound vars", query_constraint,);
93         });
94
95         match k1.unpack() {
96             GenericArgKind::Lifetime(r1) => {
97                 let r1_vid = self.to_region_vid(r1);
98                 let r2_vid = self.to_region_vid(r2);
99                 self.add_outlives(r1_vid, r2_vid);
100             }
101
102             GenericArgKind::Type(mut t1) => {
103                 // we don't actually use this for anything, but
104                 // the `TypeOutlives` code needs an origin.
105                 let origin = infer::RelateParamBound(DUMMY_SP, t1, None);
106
107                 // Placeholder regions need to be converted now because it may
108                 // create new region variables, which can't be done later when
109                 // verifying these bounds.
110                 if t1.has_placeholders() {
111                     t1 = tcx.fold_regions(t1, |r, _| match *r {
112                         ty::RePlaceholder(placeholder) => {
113                             self.constraints.placeholder_region(self.infcx, placeholder)
114                         }
115                         _ => r,
116                     });
117                 }
118
119                 TypeOutlives::new(
120                     &mut *self,
121                     tcx,
122                     region_bound_pairs,
123                     Some(implicit_region_bound),
124                     param_env,
125                 )
126                 .type_must_outlive(origin, t1, r2);
127             }
128
129             GenericArgKind::Const(_) => {
130                 // Consts cannot outlive one another, so we
131                 // don't need to handle any relations here.
132             }
133         }
134     }
135
136     fn verify_to_type_test(
137         &mut self,
138         generic_kind: GenericKind<'tcx>,
139         region: ty::Region<'tcx>,
140         verify_bound: VerifyBound<'tcx>,
141     ) -> TypeTest<'tcx> {
142         let lower_bound = self.to_region_vid(region);
143
144         TypeTest { generic_kind, lower_bound, locations: self.locations, verify_bound }
145     }
146
147     fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid {
148         if let ty::RePlaceholder(placeholder) = *r {
149             self.constraints.placeholder_region(self.infcx, placeholder).to_region_vid()
150         } else {
151             self.universal_regions.to_region_vid(r)
152         }
153     }
154
155     fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) {
156         self.constraints.outlives_constraints.push(OutlivesConstraint {
157             locations: self.locations,
158             category: self.category,
159             span: self.span,
160             sub,
161             sup,
162             variance_info: ty::VarianceDiagInfo::default(),
163         });
164     }
165
166     fn add_type_test(&mut self, type_test: TypeTest<'tcx>) {
167         debug!("add_type_test(type_test={:?})", type_test);
168         self.constraints.type_tests.push(type_test);
169     }
170 }
171
172 impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'b, 'tcx> {
173     fn push_sub_region_constraint(
174         &mut self,
175         _origin: SubregionOrigin<'tcx>,
176         a: ty::Region<'tcx>,
177         b: ty::Region<'tcx>,
178     ) {
179         let b = self.to_region_vid(b);
180         let a = self.to_region_vid(a);
181         self.add_outlives(b, a);
182     }
183
184     fn push_verify(
185         &mut self,
186         _origin: SubregionOrigin<'tcx>,
187         kind: GenericKind<'tcx>,
188         a: ty::Region<'tcx>,
189         bound: VerifyBound<'tcx>,
190     ) {
191         let type_test = self.verify_to_type_test(kind, a, bound);
192         self.add_type_test(type_test);
193     }
194 }