]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
Auto merge of #57770 - Zoxc:no-hash-query, r=michaelwoerister
[rust.git] / src / librustc_mir / borrow_check / nll / type_check / constraint_conversion.rs
1 use crate::borrow_check::nll::constraints::OutlivesConstraint;
2 use crate::borrow_check::nll::region_infer::TypeTest;
3 use crate::borrow_check::nll::type_check::{Locations, MirTypeckRegionConstraints};
4 use crate::borrow_check::nll::universal_regions::UniversalRegions;
5 use crate::borrow_check::nll::ToRegionVid;
6 use rustc::infer::canonical::QueryRegionConstraint;
7 use rustc::infer::outlives::env::RegionBoundPairs;
8 use rustc::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
9 use rustc::infer::region_constraints::{GenericKind, VerifyBound};
10 use rustc::infer::{self, InferCtxt, SubregionOrigin};
11 use rustc::mir::ConstraintCategory;
12 use rustc::ty::subst::UnpackedKind;
13 use rustc::ty::{self, TyCtxt};
14 use syntax_pos::DUMMY_SP;
15
16 crate struct ConstraintConversion<'a, 'gcx: 'tcx, 'tcx: 'a> {
17     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
18     tcx: TyCtxt<'a, 'gcx, 'tcx>,
19     universal_regions: &'a UniversalRegions<'tcx>,
20     region_bound_pairs: &'a RegionBoundPairs<'tcx>,
21     implicit_region_bound: Option<ty::Region<'tcx>>,
22     param_env: ty::ParamEnv<'tcx>,
23     locations: Locations,
24     category: ConstraintCategory,
25     constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
26 }
27
28 impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
29     crate fn new(
30         infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
31         universal_regions: &'a UniversalRegions<'tcx>,
32         region_bound_pairs: &'a RegionBoundPairs<'tcx>,
33         implicit_region_bound: Option<ty::Region<'tcx>>,
34         param_env: ty::ParamEnv<'tcx>,
35         locations: Locations,
36         category: ConstraintCategory,
37         constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
38     ) -> Self {
39         Self {
40             infcx,
41             tcx: infcx.tcx,
42             universal_regions,
43             region_bound_pairs,
44             implicit_region_bound,
45             param_env,
46             locations,
47             category,
48             constraints,
49         }
50     }
51
52     pub(super) fn convert_all(&mut self, query_constraints: &[QueryRegionConstraint<'tcx>]) {
53         for query_constraint in query_constraints {
54             self.convert(query_constraint);
55         }
56     }
57
58     pub(super) fn convert(&mut self, query_constraint: &QueryRegionConstraint<'tcx>) {
59         debug!("generate: constraints at: {:#?}", self.locations);
60
61         // Extract out various useful fields we'll need below.
62         let ConstraintConversion {
63             tcx,
64             region_bound_pairs,
65             implicit_region_bound,
66             param_env,
67             ..
68         } = *self;
69
70         // At the moment, we never generate any "higher-ranked"
71         // region constraints like `for<'a> 'a: 'b`. At some point
72         // when we move to universes, we will, and this assertion
73         // will start to fail.
74         let ty::OutlivesPredicate(k1, r2) =
75             query_constraint.no_bound_vars().unwrap_or_else(|| {
76                 bug!(
77                     "query_constraint {:?} contained bound vars",
78                     query_constraint,
79                 );
80             });
81
82         match k1.unpack() {
83             UnpackedKind::Lifetime(r1) => {
84                 let r1_vid = self.to_region_vid(r1);
85                 let r2_vid = self.to_region_vid(r2);
86                 self.add_outlives(r1_vid, r2_vid);
87             }
88
89             UnpackedKind::Type(t1) => {
90                 // we don't actually use this for anything, but
91                 // the `TypeOutlives` code needs an origin.
92                 let origin = infer::RelateParamBound(DUMMY_SP, t1);
93
94                 TypeOutlives::new(
95                     &mut *self,
96                     tcx,
97                     region_bound_pairs,
98                     implicit_region_bound,
99                     param_env,
100                 ).type_must_outlive(origin, t1, r2);
101             }
102         }
103     }
104
105     fn verify_to_type_test(
106         &mut self,
107         generic_kind: GenericKind<'tcx>,
108         region: ty::Region<'tcx>,
109         verify_bound: VerifyBound<'tcx>,
110     ) -> TypeTest<'tcx> {
111         let lower_bound = self.to_region_vid(region);
112
113         TypeTest {
114             generic_kind,
115             lower_bound,
116             locations: self.locations,
117             verify_bound,
118         }
119     }
120
121     fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid {
122         if let ty::RePlaceholder(placeholder) = r {
123             self.constraints
124                 .placeholder_region(self.infcx, *placeholder)
125                 .to_region_vid()
126         } else {
127             self.universal_regions.to_region_vid(r)
128         }
129     }
130
131     fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) {
132         self.constraints
133             .outlives_constraints
134             .push(OutlivesConstraint {
135                 locations: self.locations,
136                 category: self.category,
137                 sub,
138                 sup,
139             });
140     }
141
142     fn add_type_test(&mut self, type_test: TypeTest<'tcx>) {
143         debug!("add_type_test(type_test={:?})", type_test);
144         self.constraints.type_tests.push(type_test);
145     }
146 }
147
148 impl<'a, 'b, 'gcx, 'tcx> TypeOutlivesDelegate<'tcx>
149     for &'a mut ConstraintConversion<'b, 'gcx, 'tcx>
150 {
151     fn push_sub_region_constraint(
152         &mut self,
153         _origin: SubregionOrigin<'tcx>,
154         a: ty::Region<'tcx>,
155         b: ty::Region<'tcx>,
156     ) {
157         let b = self.to_region_vid(b);
158         let a = self.to_region_vid(a);
159         self.add_outlives(b, a);
160     }
161
162     fn push_verify(
163         &mut self,
164         _origin: SubregionOrigin<'tcx>,
165         kind: GenericKind<'tcx>,
166         a: ty::Region<'tcx>,
167         bound: VerifyBound<'tcx>,
168     ) {
169         let type_test = self.verify_to_type_test(kind, a, bound);
170         self.add_type_test(type_test);
171     }
172 }