]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
switch to use `VerifyBound` instead of `RegionTest`
[rust.git] / src / librustc_mir / borrow_check / nll / type_check / constraint_conversion.rs
1 // Copyright 2017 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use borrow_check::location::LocationTable;
12 use borrow_check::nll::constraints::{ConstraintCategory, ConstraintSet, OutlivesConstraint};
13 use borrow_check::nll::facts::AllFacts;
14 use borrow_check::nll::region_infer::TypeTest;
15 use borrow_check::nll::type_check::Locations;
16 use borrow_check::nll::universal_regions::UniversalRegions;
17 use rustc::infer::canonical::QueryRegionConstraint;
18 use rustc::infer::outlives::env::RegionBoundPairs;
19 use rustc::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
20 use rustc::infer::region_constraints::{GenericKind, VerifyBound};
21 use rustc::infer::{self, SubregionOrigin};
22 use rustc::ty::subst::UnpackedKind;
23 use rustc::ty::{self, TyCtxt};
24 use syntax_pos::DUMMY_SP;
25
26 crate struct ConstraintConversion<'a, 'gcx: 'tcx, 'tcx: 'a> {
27     tcx: TyCtxt<'a, 'gcx, 'tcx>,
28     universal_regions: &'a UniversalRegions<'tcx>,
29     location_table: &'a LocationTable,
30     region_bound_pairs: &'a RegionBoundPairs<'tcx>,
31     implicit_region_bound: Option<ty::Region<'tcx>>,
32     param_env: ty::ParamEnv<'tcx>,
33     locations: Locations,
34     category: ConstraintCategory,
35     outlives_constraints: &'a mut ConstraintSet,
36     type_tests: &'a mut Vec<TypeTest<'tcx>>,
37     all_facts: &'a mut Option<AllFacts>,
38 }
39
40 impl<'a, 'gcx, 'tcx> ConstraintConversion<'a, 'gcx, 'tcx> {
41     crate fn new(
42         tcx: TyCtxt<'a, 'gcx, 'tcx>,
43         universal_regions: &'a UniversalRegions<'tcx>,
44         location_table: &'a LocationTable,
45         region_bound_pairs: &'a RegionBoundPairs<'tcx>,
46         implicit_region_bound: Option<ty::Region<'tcx>>,
47         param_env: ty::ParamEnv<'tcx>,
48         locations: Locations,
49         category: ConstraintCategory,
50         outlives_constraints: &'a mut ConstraintSet,
51         type_tests: &'a mut Vec<TypeTest<'tcx>>,
52         all_facts: &'a mut Option<AllFacts>,
53     ) -> Self {
54         Self {
55             tcx,
56             universal_regions,
57             location_table,
58             region_bound_pairs,
59             implicit_region_bound,
60             param_env,
61             locations,
62             category,
63             outlives_constraints,
64             type_tests,
65             all_facts,
66         }
67     }
68
69     pub(super) fn convert_all(&mut self, query_constraints: &[QueryRegionConstraint<'tcx>]) {
70         for query_constraint in query_constraints {
71             self.convert(query_constraint);
72         }
73     }
74
75     pub(super) fn convert(&mut self, query_constraint: &QueryRegionConstraint<'tcx>) {
76         debug!("generate: constraints at: {:#?}", self.locations);
77
78         // Extract out various useful fields we'll need below.
79         let ConstraintConversion {
80             tcx,
81             region_bound_pairs,
82             implicit_region_bound,
83             param_env,
84             ..
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) =
92             query_constraint.no_late_bound_regions().unwrap_or_else(|| {
93                 bug!(
94                     "query_constraint {:?} contained bound regions",
95                     query_constraint,
96                 );
97             });
98
99         match k1.unpack() {
100             UnpackedKind::Lifetime(r1) => {
101                 let r1_vid = self.to_region_vid(r1);
102                 let r2_vid = self.to_region_vid(r2);
103                 self.add_outlives(r1_vid, r2_vid);
104
105                 // In the new analysis, all outlives relations etc
106                 // "take effect" at the mid point of the statement
107                 // that requires them, so ignore the `at_location`.
108                 if let Some(all_facts) = &mut self.all_facts {
109                     if let Some(from_location) = self.locations.from_location() {
110                         all_facts.outlives.push((
111                             r1_vid,
112                             r2_vid,
113                             self.location_table.mid_index(from_location),
114                         ));
115                     } else {
116                         for location in self.location_table.all_points() {
117                             all_facts.outlives.push((r1_vid, r2_vid, location));
118                         }
119                     }
120                 }
121             }
122
123             UnpackedKind::Type(t1) => {
124                 // we don't actually use this for anything, but
125                 // the `TypeOutlives` code needs an origin.
126                 let origin = infer::RelateParamBound(DUMMY_SP, t1);
127
128                 TypeOutlives::new(
129                     &mut *self,
130                     tcx,
131                     region_bound_pairs,
132                     implicit_region_bound,
133                     param_env,
134                 ).type_must_outlive(origin, t1, r2);
135             }
136         }
137     }
138
139     fn verify_to_type_test(
140         &self,
141         generic_kind: GenericKind<'tcx>,
142         region: ty::Region<'tcx>,
143         verify_bound: VerifyBound<'tcx>,
144     ) -> TypeTest<'tcx> {
145         let lower_bound = self.to_region_vid(region);
146
147         TypeTest {
148             generic_kind,
149             lower_bound,
150             locations: self.locations,
151             verify_bound,
152         }
153     }
154
155     fn to_region_vid(&self, r: ty::Region<'tcx>) -> ty::RegionVid {
156         self.universal_regions.to_region_vid(r)
157     }
158
159     fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) {
160         self.outlives_constraints.push(OutlivesConstraint {
161             locations: self.locations,
162             category: self.category,
163             sub,
164             sup,
165         });
166     }
167
168     fn add_type_test(&mut self, type_test: TypeTest<'tcx>) {
169         self.type_tests.push(type_test);
170     }
171 }
172
173 impl<'a, 'b, 'gcx, 'tcx> TypeOutlivesDelegate<'tcx>
174     for &'a mut ConstraintConversion<'b, 'gcx, 'tcx>
175 {
176     fn push_sub_region_constraint(
177         &mut self,
178         _origin: SubregionOrigin<'tcx>,
179         a: ty::Region<'tcx>,
180         b: ty::Region<'tcx>,
181     ) {
182         let b = self.universal_regions.to_region_vid(b);
183         let a = self.universal_regions.to_region_vid(a);
184         self.add_outlives(b, a);
185     }
186
187     fn push_verify(
188         &mut self,
189         _origin: SubregionOrigin<'tcx>,
190         kind: GenericKind<'tcx>,
191         a: ty::Region<'tcx>,
192         bound: VerifyBound<'tcx>,
193     ) {
194         let type_test = self.verify_to_type_test(kind, a, bound);
195         self.add_type_test(type_test);
196     }
197 }