]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/borrow_check/nll/type_check/constraint_conversion.rs
Handle new ConstValue variants in mir
[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             UnpackedKind::Const(_) => {
104                 // Consts cannot outlive one another, so we
105                 // don't need to handle any relations here.
106             }
107         }
108     }
109
110     fn verify_to_type_test(
111         &mut self,
112         generic_kind: GenericKind<'tcx>,
113         region: ty::Region<'tcx>,
114         verify_bound: VerifyBound<'tcx>,
115     ) -> TypeTest<'tcx> {
116         let lower_bound = self.to_region_vid(region);
117
118         TypeTest {
119             generic_kind,
120             lower_bound,
121             locations: self.locations,
122             verify_bound,
123         }
124     }
125
126     fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid {
127         if let ty::RePlaceholder(placeholder) = r {
128             self.constraints
129                 .placeholder_region(self.infcx, *placeholder)
130                 .to_region_vid()
131         } else {
132             self.universal_regions.to_region_vid(r)
133         }
134     }
135
136     fn add_outlives(&mut self, sup: ty::RegionVid, sub: ty::RegionVid) {
137         self.constraints
138             .outlives_constraints
139             .push(OutlivesConstraint {
140                 locations: self.locations,
141                 category: self.category,
142                 sub,
143                 sup,
144             });
145     }
146
147     fn add_type_test(&mut self, type_test: TypeTest<'tcx>) {
148         debug!("add_type_test(type_test={:?})", type_test);
149         self.constraints.type_tests.push(type_test);
150     }
151 }
152
153 impl<'a, 'b, 'gcx, 'tcx> TypeOutlivesDelegate<'tcx>
154     for &'a mut ConstraintConversion<'b, 'gcx, 'tcx>
155 {
156     fn push_sub_region_constraint(
157         &mut self,
158         _origin: SubregionOrigin<'tcx>,
159         a: ty::Region<'tcx>,
160         b: ty::Region<'tcx>,
161     ) {
162         let b = self.to_region_vid(b);
163         let a = self.to_region_vid(a);
164         self.add_outlives(b, a);
165     }
166
167     fn push_verify(
168         &mut self,
169         _origin: SubregionOrigin<'tcx>,
170         kind: GenericKind<'tcx>,
171         a: ty::Region<'tcx>,
172         bound: VerifyBound<'tcx>,
173     ) {
174         let type_test = self.verify_to_type_test(kind, a, bound);
175         self.add_type_test(type_test);
176     }
177 }