|
21 | 21 | //! |
22 | 22 | //! [c]: https://rust-lang.github.io/rustc-guide/traits/canonicalization.html |
23 | 23 |
|
24 | | -use crate::infer::region_constraints::MemberConstraint; |
25 | 24 | use crate::infer::{ConstVariableOrigin, ConstVariableOriginKind}; |
26 | 25 | use crate::infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin, TypeVariableOriginKind}; |
27 | | -use crate::ty::fold::TypeFoldable; |
28 | | -use crate::ty::subst::GenericArg; |
29 | | -use crate::ty::{self, BoundVar, List, Region, TyCtxt}; |
| 26 | +use rustc::ty::fold::TypeFoldable; |
| 27 | +use rustc::ty::subst::GenericArg; |
| 28 | +use rustc::ty::{self, BoundVar, List}; |
30 | 29 | use rustc_index::vec::IndexVec; |
31 | | -use rustc_macros::HashStable; |
32 | | -use rustc_serialize::UseSpecializedDecodable; |
33 | 30 | use rustc_span::source_map::Span; |
34 | | -use smallvec::SmallVec; |
35 | | -use std::ops::Index; |
| 31 | + |
| 32 | +pub use rustc::infer::types::canonical::*; |
36 | 33 |
|
37 | 34 | mod canonicalizer; |
38 | 35 |
|
39 | 36 | pub mod query_response; |
40 | 37 |
|
41 | 38 | mod substitute; |
42 | 39 |
|
43 | | -/// A "canonicalized" type `V` is one where all free inference |
44 | | -/// variables have been rewritten to "canonical vars". These are |
45 | | -/// numbered starting from 0 in order of first appearance. |
46 | | -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)] |
47 | | -#[derive(HashStable, TypeFoldable, Lift)] |
48 | | -pub struct Canonical<'tcx, V> { |
49 | | - pub max_universe: ty::UniverseIndex, |
50 | | - pub variables: CanonicalVarInfos<'tcx>, |
51 | | - pub value: V, |
52 | | -} |
53 | | - |
54 | | -pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo>; |
55 | | - |
56 | | -impl<'tcx> UseSpecializedDecodable for CanonicalVarInfos<'tcx> {} |
57 | | - |
58 | | -/// A set of values corresponding to the canonical variables from some |
59 | | -/// `Canonical`. You can give these values to |
60 | | -/// `canonical_value.substitute` to substitute them into the canonical |
61 | | -/// value at the right places. |
62 | | -/// |
63 | | -/// When you canonicalize a value `V`, you get back one of these |
64 | | -/// vectors with the original values that were replaced by canonical |
65 | | -/// variables. You will need to supply it later to instantiate the |
66 | | -/// canonicalized query response. |
67 | | -#[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)] |
68 | | -#[derive(HashStable, TypeFoldable, Lift)] |
69 | | -pub struct CanonicalVarValues<'tcx> { |
70 | | - pub var_values: IndexVec<BoundVar, GenericArg<'tcx>>, |
71 | | -} |
72 | | - |
73 | | -/// When we canonicalize a value to form a query, we wind up replacing |
74 | | -/// various parts of it with canonical variables. This struct stores |
75 | | -/// those replaced bits to remember for when we process the query |
76 | | -/// result. |
77 | | -#[derive(Clone, Debug)] |
78 | | -pub struct OriginalQueryValues<'tcx> { |
79 | | - /// Map from the universes that appear in the query to the |
80 | | - /// universes in the caller context. For the time being, we only |
81 | | - /// ever put ROOT values into the query, so this map is very |
82 | | - /// simple. |
83 | | - pub universe_map: SmallVec<[ty::UniverseIndex; 4]>, |
84 | | - |
85 | | - /// This is equivalent to `CanonicalVarValues`, but using a |
86 | | - /// `SmallVec` yields a significant performance win. |
87 | | - pub var_values: SmallVec<[GenericArg<'tcx>; 8]>, |
88 | | -} |
89 | | - |
90 | | -impl Default for OriginalQueryValues<'tcx> { |
91 | | - fn default() -> Self { |
92 | | - let mut universe_map = SmallVec::default(); |
93 | | - universe_map.push(ty::UniverseIndex::ROOT); |
94 | | - |
95 | | - Self { universe_map, var_values: SmallVec::default() } |
96 | | - } |
97 | | -} |
98 | | - |
99 | | -/// Information about a canonical variable that is included with the |
100 | | -/// canonical value. This is sufficient information for code to create |
101 | | -/// a copy of the canonical value in some other inference context, |
102 | | -/// with fresh inference variables replacing the canonical values. |
103 | | -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable, HashStable)] |
104 | | -pub struct CanonicalVarInfo { |
105 | | - pub kind: CanonicalVarKind, |
106 | | -} |
107 | | - |
108 | | -impl CanonicalVarInfo { |
109 | | - pub fn universe(&self) -> ty::UniverseIndex { |
110 | | - self.kind.universe() |
111 | | - } |
112 | | - |
113 | | - pub fn is_existential(&self) -> bool { |
114 | | - match self.kind { |
115 | | - CanonicalVarKind::Ty(_) => true, |
116 | | - CanonicalVarKind::PlaceholderTy(_) => false, |
117 | | - CanonicalVarKind::Region(_) => true, |
118 | | - CanonicalVarKind::PlaceholderRegion(..) => false, |
119 | | - CanonicalVarKind::Const(_) => true, |
120 | | - CanonicalVarKind::PlaceholderConst(_) => false, |
121 | | - } |
122 | | - } |
123 | | -} |
124 | | - |
125 | | -/// Describes the "kind" of the canonical variable. This is a "kind" |
126 | | -/// in the type-theory sense of the term -- i.e., a "meta" type system |
127 | | -/// that analyzes type-like values. |
128 | | -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable, HashStable)] |
129 | | -pub enum CanonicalVarKind { |
130 | | - /// Some kind of type inference variable. |
131 | | - Ty(CanonicalTyVarKind), |
132 | | - |
133 | | - /// A "placeholder" that represents "any type". |
134 | | - PlaceholderTy(ty::PlaceholderType), |
135 | | - |
136 | | - /// Region variable `'?R`. |
137 | | - Region(ty::UniverseIndex), |
138 | | - |
139 | | - /// A "placeholder" that represents "any region". Created when you |
140 | | - /// are solving a goal like `for<'a> T: Foo<'a>` to represent the |
141 | | - /// bound region `'a`. |
142 | | - PlaceholderRegion(ty::PlaceholderRegion), |
143 | | - |
144 | | - /// Some kind of const inference variable. |
145 | | - Const(ty::UniverseIndex), |
146 | | - |
147 | | - /// A "placeholder" that represents "any const". |
148 | | - PlaceholderConst(ty::PlaceholderConst), |
149 | | -} |
150 | | - |
151 | | -impl CanonicalVarKind { |
152 | | - pub fn universe(self) -> ty::UniverseIndex { |
153 | | - match self { |
154 | | - CanonicalVarKind::Ty(kind) => match kind { |
155 | | - CanonicalTyVarKind::General(ui) => ui, |
156 | | - CanonicalTyVarKind::Float | CanonicalTyVarKind::Int => ty::UniverseIndex::ROOT, |
157 | | - }, |
158 | | - |
159 | | - CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe, |
160 | | - CanonicalVarKind::Region(ui) => ui, |
161 | | - CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe, |
162 | | - CanonicalVarKind::Const(ui) => ui, |
163 | | - CanonicalVarKind::PlaceholderConst(placeholder) => placeholder.universe, |
164 | | - } |
165 | | - } |
166 | | -} |
167 | | - |
168 | | -/// Rust actually has more than one category of type variables; |
169 | | -/// notably, the type variables we create for literals (e.g., 22 or |
170 | | -/// 22.) can only be instantiated with integral/float types (e.g., |
171 | | -/// usize or f32). In order to faithfully reproduce a type, we need to |
172 | | -/// know what set of types a given type variable can be unified with. |
173 | | -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable, HashStable)] |
174 | | -pub enum CanonicalTyVarKind { |
175 | | - /// General type variable `?T` that can be unified with arbitrary types. |
176 | | - General(ty::UniverseIndex), |
177 | | - |
178 | | - /// Integral type variable `?I` (that can only be unified with integral types). |
179 | | - Int, |
180 | | - |
181 | | - /// Floating-point type variable `?F` (that can only be unified with float types). |
182 | | - Float, |
183 | | -} |
184 | | - |
185 | | -/// After we execute a query with a canonicalized key, we get back a |
186 | | -/// `Canonical<QueryResponse<..>>`. You can use |
187 | | -/// `instantiate_query_result` to access the data in this result. |
188 | | -#[derive(Clone, Debug, HashStable, TypeFoldable, Lift)] |
189 | | -pub struct QueryResponse<'tcx, R> { |
190 | | - pub var_values: CanonicalVarValues<'tcx>, |
191 | | - pub region_constraints: QueryRegionConstraints<'tcx>, |
192 | | - pub certainty: Certainty, |
193 | | - pub value: R, |
194 | | -} |
195 | | - |
196 | | -#[derive(Clone, Debug, Default, HashStable, TypeFoldable, Lift)] |
197 | | -pub struct QueryRegionConstraints<'tcx> { |
198 | | - pub outlives: Vec<QueryOutlivesConstraint<'tcx>>, |
199 | | - pub member_constraints: Vec<MemberConstraint<'tcx>>, |
200 | | -} |
201 | | - |
202 | | -impl QueryRegionConstraints<'_> { |
203 | | - /// Represents an empty (trivially true) set of region |
204 | | - /// constraints. |
205 | | - pub fn is_empty(&self) -> bool { |
206 | | - self.outlives.is_empty() && self.member_constraints.is_empty() |
207 | | - } |
208 | | -} |
209 | | - |
210 | | -pub type Canonicalized<'tcx, V> = Canonical<'tcx, V>; |
211 | | - |
212 | | -pub type CanonicalizedQueryResponse<'tcx, T> = &'tcx Canonical<'tcx, QueryResponse<'tcx, T>>; |
213 | | - |
214 | | -/// Indicates whether or not we were able to prove the query to be |
215 | | -/// true. |
216 | | -#[derive(Copy, Clone, Debug, HashStable)] |
217 | | -pub enum Certainty { |
218 | | - /// The query is known to be true, presuming that you apply the |
219 | | - /// given `var_values` and the region-constraints are satisfied. |
220 | | - Proven, |
221 | | - |
222 | | - /// The query is not known to be true, but also not known to be |
223 | | - /// false. The `var_values` represent *either* values that must |
224 | | - /// hold in order for the query to be true, or helpful tips that |
225 | | - /// *might* make it true. Currently rustc's trait solver cannot |
226 | | - /// distinguish the two (e.g., due to our preference for where |
227 | | - /// clauses over impls). |
228 | | - /// |
229 | | - /// After some unifiations and things have been done, it makes |
230 | | - /// sense to try and prove again -- of course, at that point, the |
231 | | - /// canonical form will be different, making this a distinct |
232 | | - /// query. |
233 | | - Ambiguous, |
234 | | -} |
235 | | - |
236 | | -impl Certainty { |
237 | | - pub fn is_proven(&self) -> bool { |
238 | | - match self { |
239 | | - Certainty::Proven => true, |
240 | | - Certainty::Ambiguous => false, |
241 | | - } |
242 | | - } |
243 | | - |
244 | | - pub fn is_ambiguous(&self) -> bool { |
245 | | - !self.is_proven() |
246 | | - } |
247 | | -} |
248 | | - |
249 | | -impl<'tcx, R> QueryResponse<'tcx, R> { |
250 | | - pub fn is_proven(&self) -> bool { |
251 | | - self.certainty.is_proven() |
252 | | - } |
253 | | - |
254 | | - pub fn is_ambiguous(&self) -> bool { |
255 | | - !self.is_proven() |
256 | | - } |
257 | | -} |
258 | | - |
259 | | -impl<'tcx, R> Canonical<'tcx, QueryResponse<'tcx, R>> { |
260 | | - pub fn is_proven(&self) -> bool { |
261 | | - self.value.is_proven() |
262 | | - } |
263 | | - |
264 | | - pub fn is_ambiguous(&self) -> bool { |
265 | | - !self.is_proven() |
266 | | - } |
267 | | -} |
268 | | - |
269 | | -impl<'tcx, V> Canonical<'tcx, V> { |
270 | | - /// Allows you to map the `value` of a canonical while keeping the |
271 | | - /// same set of bound variables. |
272 | | - /// |
273 | | - /// **WARNING:** This function is very easy to mis-use, hence the |
274 | | - /// name! In particular, the new value `W` must use all **the |
275 | | - /// same type/region variables** in **precisely the same order** |
276 | | - /// as the original! (The ordering is defined by the |
277 | | - /// `TypeFoldable` implementation of the type in question.) |
278 | | - /// |
279 | | - /// An example of a **correct** use of this: |
280 | | - /// |
281 | | - /// ```rust,ignore (not real code) |
282 | | - /// let a: Canonical<'_, T> = ...; |
283 | | - /// let b: Canonical<'_, (T,)> = a.unchecked_map(|v| (v, )); |
284 | | - /// ``` |
285 | | - /// |
286 | | - /// An example of an **incorrect** use of this: |
287 | | - /// |
288 | | - /// ```rust,ignore (not real code) |
289 | | - /// let a: Canonical<'tcx, T> = ...; |
290 | | - /// let ty: Ty<'tcx> = ...; |
291 | | - /// let b: Canonical<'tcx, (T, Ty<'tcx>)> = a.unchecked_map(|v| (v, ty)); |
292 | | - /// ``` |
293 | | - pub fn unchecked_map<W>(self, map_op: impl FnOnce(V) -> W) -> Canonical<'tcx, W> { |
294 | | - let Canonical { max_universe, variables, value } = self; |
295 | | - Canonical { max_universe, variables, value: map_op(value) } |
296 | | - } |
297 | | -} |
298 | | - |
299 | | -pub type QueryOutlivesConstraint<'tcx> = |
300 | | - ty::Binder<ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>>; |
301 | | - |
302 | 40 | impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { |
303 | 41 | /// Creates a substitution S for the canonical value with fresh |
304 | 42 | /// inference variables and applies it to the canonical value. |
@@ -424,70 +162,3 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> { |
424 | 162 | } |
425 | 163 | } |
426 | 164 | } |
427 | | - |
428 | | -CloneTypeFoldableAndLiftImpls! { |
429 | | - crate::infer::canonical::Certainty, |
430 | | - crate::infer::canonical::CanonicalVarInfo, |
431 | | - crate::infer::canonical::CanonicalVarKind, |
432 | | -} |
433 | | - |
434 | | -CloneTypeFoldableImpls! { |
435 | | - for <'tcx> { |
436 | | - crate::infer::canonical::CanonicalVarInfos<'tcx>, |
437 | | - } |
438 | | -} |
439 | | - |
440 | | -impl<'tcx> CanonicalVarValues<'tcx> { |
441 | | - pub fn len(&self) -> usize { |
442 | | - self.var_values.len() |
443 | | - } |
444 | | - |
445 | | - /// Makes an identity substitution from this one: each bound var |
446 | | - /// is matched to the same bound var, preserving the original kinds. |
447 | | - /// For example, if we have: |
448 | | - /// `self.var_values == [Type(u32), Lifetime('a), Type(u64)]` |
449 | | - /// we'll return a substitution `subst` with: |
450 | | - /// `subst.var_values == [Type(^0), Lifetime(^1), Type(^2)]`. |
451 | | - pub fn make_identity(&self, tcx: TyCtxt<'tcx>) -> Self { |
452 | | - use crate::ty::subst::GenericArgKind; |
453 | | - |
454 | | - CanonicalVarValues { |
455 | | - var_values: self |
456 | | - .var_values |
457 | | - .iter() |
458 | | - .zip(0..) |
459 | | - .map(|(kind, i)| match kind.unpack() { |
460 | | - GenericArgKind::Type(..) => { |
461 | | - tcx.mk_ty(ty::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i).into())).into() |
462 | | - } |
463 | | - GenericArgKind::Lifetime(..) => tcx |
464 | | - .mk_region(ty::ReLateBound(ty::INNERMOST, ty::BoundRegion::BrAnon(i))) |
465 | | - .into(), |
466 | | - GenericArgKind::Const(ct) => tcx |
467 | | - .mk_const(ty::Const { |
468 | | - ty: ct.ty, |
469 | | - val: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from_u32(i)), |
470 | | - }) |
471 | | - .into(), |
472 | | - }) |
473 | | - .collect(), |
474 | | - } |
475 | | - } |
476 | | -} |
477 | | - |
478 | | -impl<'a, 'tcx> IntoIterator for &'a CanonicalVarValues<'tcx> { |
479 | | - type Item = GenericArg<'tcx>; |
480 | | - type IntoIter = ::std::iter::Cloned<::std::slice::Iter<'a, GenericArg<'tcx>>>; |
481 | | - |
482 | | - fn into_iter(self) -> Self::IntoIter { |
483 | | - self.var_values.iter().cloned() |
484 | | - } |
485 | | -} |
486 | | - |
487 | | -impl<'tcx> Index<BoundVar> for CanonicalVarValues<'tcx> { |
488 | | - type Output = GenericArg<'tcx>; |
489 | | - |
490 | | - fn index(&self, value: BoundVar) -> &GenericArg<'tcx> { |
491 | | - &self.var_values[value] |
492 | | - } |
493 | | -} |
0 commit comments