]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_borrowck/src/type_check/constraint_conversion.rs
Rollup merge of #93613 - crlf0710:rename_to_async_iter, r=yaahc
[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::TypeFoldable;
10 use rustc_middle::ty::{self, TyCtxt};
11 use rustc_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 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: Option<ty::Region<'tcx>>,
27     param_env: ty::ParamEnv<'tcx>,
28     locations: Locations,
29     category: ConstraintCategory,
30     constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
31 }
32
33 impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
34     crate fn new(
35         infcx: &'a InferCtxt<'a, 'tcx>,
36         universal_regions: &'a UniversalRegions<'tcx>,
37         region_bound_pairs: &'a RegionBoundPairs<'tcx>,
38         implicit_region_bound: Option<ty::Region<'tcx>>,
39         param_env: ty::ParamEnv<'tcx>,
40         locations: Locations,
41         category: ConstraintCategory,
42         constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
43     ) -> Self {
44         Self {
45             infcx,
46             tcx: infcx.tcx,
47             universal_regions,
48             region_bound_pairs,
49             implicit_region_bound,
50             param_env,
51             locations,
52             category,
53             constraints,
54         }
55     }
56
57     #[instrument(skip(self), level = "debug")]
58     pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) {
59         let QueryRegionConstraints { outlives, member_constraints } = query_constraints;
60
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));
68         }
69         self.constraints.member_constraints = tmp;
70
71         for query_constraint in outlives {
72             self.convert(query_constraint);
73         }
74     }
75
76     pub(super) fn convert(&mut self, query_constraint: &QueryOutlivesConstraint<'tcx>) {
77         debug!("generate: constraints at: {:#?}", self.locations);
78
79         // Extract out various useful fields we'll need below.
80         let ConstraintConversion {
81             tcx, region_bound_pairs, implicit_region_bound, param_env, ..
82         } = *self;
83
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,);
90         });
91
92         match k1.unpack() {
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);
97             }
98
99             GenericArgKind::Type(mut 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, None);
103
104                 // Placeholder regions need to be converted now because it may
105                 // create new region variables, which can't be done later when
106                 // verifying these bounds.
107                 if t1.has_placeholders() {
108                     t1 = tcx.fold_regions(t1, &mut false, |r, _| match *r {
109                         ty::RePlaceholder(placeholder) => {
110                             self.constraints.placeholder_region(self.infcx, placeholder)
111                         }
112                         _ => r,
113                     });
114                 }
115
116                 TypeOutlives::new(
117                     &mut *self,
118                     tcx,
119                     region_bound_pairs,
120                     implicit_region_bound,
121                     param_env,
122                 )
123                 .type_must_outlive(origin, t1, r2);
124             }
125
126             GenericArgKind::Const(_) => {
127                 // Consts cannot outlive one another, so we
128                 // don't need to handle any relations here.
129             }
130         }
131     }
132
133     fn verify_to_type_test(
134         &mut self,
135         generic_kind: GenericKind<'tcx>,
136         region: ty::Region<'tcx>,
137         verify_bound: VerifyBound<'tcx>,
138     ) -> TypeTest<'tcx> {
139         let lower_bound = self.to_region_vid(region);
140
141         TypeTest { generic_kind, lower_bound, locations: self.locations, verify_bound }
142     }
143
144     fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid {
145         if let ty::RePlaceholder(placeholder) = *r {
146             self.constraints.placeholder_region(self.infcx, placeholder).to_region_vid()
147         } else {
148             self.universal_regions.to_region_vid(r)
149         }
150     }
151
152     fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) {
153         self.constraints.outlives_constraints.push(OutlivesConstraint {
154             locations: self.locations,
155             category: self.category,
156             sub,
157             sup,
158             variance_info: ty::VarianceDiagInfo::default(),
159         });
160     }
161
162     fn add_type_test(&mut self, type_test: TypeTest<'tcx>) {
163         debug!("add_type_test(type_test={:?})", type_test);
164         self.constraints.type_tests.push(type_test);
165     }
166 }
167
168 impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'b, 'tcx> {
169     fn push_sub_region_constraint(
170         &mut self,
171         _origin: SubregionOrigin<'tcx>,
172         a: ty::Region<'tcx>,
173         b: ty::Region<'tcx>,
174     ) {
175         let b = self.to_region_vid(b);
176         let a = self.to_region_vid(a);
177         self.add_outlives(b, a);
178     }
179
180     fn push_verify(
181         &mut self,
182         _origin: SubregionOrigin<'tcx>,
183         kind: GenericKind<'tcx>,
184         a: ty::Region<'tcx>,
185         bound: VerifyBound<'tcx>,
186     ) {
187         let type_test = self.verify_to_type_test(kind, a, bound);
188         self.add_type_test(type_test);
189     }
190 }