• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //! **Canonicalization** is the key to constructing a query in the
2 //! middle of type inference. Ordinarily, it is not possible to store
3 //! types from type inference in query keys, because they contain
4 //! references to inference variables whose lifetimes are too short
5 //! and so forth. Canonicalizing a value T1 using `canonicalize_query`
6 //! produces two things:
7 //!
8 //! - a value T2 where each unbound inference variable has been
9 //!   replaced with a **canonical variable**;
10 //! - a map M (of type `CanonicalVarValues`) from those canonical
11 //!   variables back to the original.
12 //!
13 //! We can then do queries using T2. These will give back constraints
14 //! on the canonical variables which can be translated, using the map
15 //! M, into constraints in our source context. This process of
16 //! translating the results back is done by the
17 //! `instantiate_query_result` method.
18 //!
19 //! For a more detailed look at what is happening here, check
20 //! out the [chapter in the rustc dev guide][c].
21 //!
22 //! [c]: https://rust-lang.github.io/chalk/book/canonical_queries/canonicalization.html
23 
24 use crate::infer::MemberConstraint;
25 use crate::mir::ConstraintCategory;
26 use crate::ty::subst::GenericArg;
27 use crate::ty::{self, BoundVar, List, Region, Ty, TyCtxt};
28 use rustc_macros::HashStable;
29 use smallvec::SmallVec;
30 use std::ops::Index;
31 
32 /// A "canonicalized" type `V` is one where all free inference
33 /// variables have been rewritten to "canonical vars". These are
34 /// numbered starting from 0 in order of first appearance.
35 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
36 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
37 pub struct Canonical<'tcx, V> {
38     pub value: V,
39     pub max_universe: ty::UniverseIndex,
40     pub variables: CanonicalVarInfos<'tcx>,
41 }
42 
43 pub type CanonicalVarInfos<'tcx> = &'tcx List<CanonicalVarInfo<'tcx>>;
44 
45 impl<'tcx> ty::TypeFoldable<TyCtxt<'tcx>> for CanonicalVarInfos<'tcx> {
try_fold_with<F: ty::FallibleTypeFolder<TyCtxt<'tcx>>>( self, folder: &mut F, ) -> Result<Self, F::Error>46     fn try_fold_with<F: ty::FallibleTypeFolder<TyCtxt<'tcx>>>(
47         self,
48         folder: &mut F,
49     ) -> Result<Self, F::Error> {
50         ty::util::fold_list(self, folder, |tcx, v| tcx.mk_canonical_var_infos(v))
51     }
52 }
53 
54 /// A set of values corresponding to the canonical variables from some
55 /// `Canonical`. You can give these values to
56 /// `canonical_value.substitute` to substitute them into the canonical
57 /// value at the right places.
58 ///
59 /// When you canonicalize a value `V`, you get back one of these
60 /// vectors with the original values that were replaced by canonical
61 /// variables. You will need to supply it later to instantiate the
62 /// canonicalized query response.
63 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable)]
64 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
65 pub struct CanonicalVarValues<'tcx> {
66     pub var_values: ty::SubstsRef<'tcx>,
67 }
68 
69 impl CanonicalVarValues<'_> {
is_identity(&self) -> bool70     pub fn is_identity(&self) -> bool {
71         self.var_values.iter().enumerate().all(|(bv, arg)| match arg.unpack() {
72             ty::GenericArgKind::Lifetime(r) => {
73                 matches!(*r, ty::ReLateBound(ty::INNERMOST, br) if br.var.as_usize() == bv)
74             }
75             ty::GenericArgKind::Type(ty) => {
76                 matches!(*ty.kind(), ty::Bound(ty::INNERMOST, bt) if bt.var.as_usize() == bv)
77             }
78             ty::GenericArgKind::Const(ct) => {
79                 matches!(ct.kind(), ty::ConstKind::Bound(ty::INNERMOST, bc) if bc.as_usize() == bv)
80             }
81         })
82     }
83 
is_identity_modulo_regions(&self) -> bool84     pub fn is_identity_modulo_regions(&self) -> bool {
85         let mut var = ty::BoundVar::from_u32(0);
86         for arg in self.var_values {
87             match arg.unpack() {
88                 ty::GenericArgKind::Lifetime(r) => {
89                     if let ty::ReLateBound(ty::INNERMOST, br) = *r
90                         && var == br.var
91                     {
92                         var = var + 1;
93                     } else {
94                         // It's ok if this region var isn't unique
95                     }
96                 },
97                 ty::GenericArgKind::Type(ty) => {
98                     if let ty::Bound(ty::INNERMOST, bt) = *ty.kind()
99                         && var == bt.var
100                     {
101                         var = var + 1;
102                     } else {
103                         return false;
104                     }
105                 }
106                 ty::GenericArgKind::Const(ct) => {
107                     if let ty::ConstKind::Bound(ty::INNERMOST, bc) = ct.kind()
108                         && var == bc
109                     {
110                         var = var + 1;
111                     } else {
112                         return false;
113                     }
114                 }
115             }
116         }
117 
118         true
119     }
120 }
121 
122 /// When we canonicalize a value to form a query, we wind up replacing
123 /// various parts of it with canonical variables. This struct stores
124 /// those replaced bits to remember for when we process the query
125 /// result.
126 #[derive(Clone, Debug)]
127 pub struct OriginalQueryValues<'tcx> {
128     /// Map from the universes that appear in the query to the universes in the
129     /// caller context. For all queries except `evaluate_goal` (used by Chalk),
130     /// we only ever put ROOT values into the query, so this map is very
131     /// simple.
132     pub universe_map: SmallVec<[ty::UniverseIndex; 4]>,
133 
134     /// This is equivalent to `CanonicalVarValues`, but using a
135     /// `SmallVec` yields a significant performance win.
136     pub var_values: SmallVec<[GenericArg<'tcx>; 8]>,
137 }
138 
139 impl<'tcx> Default for OriginalQueryValues<'tcx> {
default() -> Self140     fn default() -> Self {
141         let mut universe_map = SmallVec::default();
142         universe_map.push(ty::UniverseIndex::ROOT);
143 
144         Self { universe_map, var_values: SmallVec::default() }
145     }
146 }
147 
148 /// Information about a canonical variable that is included with the
149 /// canonical value. This is sufficient information for code to create
150 /// a copy of the canonical value in some other inference context,
151 /// with fresh inference variables replacing the canonical values.
152 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)]
153 #[derive(TypeFoldable, TypeVisitable)]
154 pub struct CanonicalVarInfo<'tcx> {
155     pub kind: CanonicalVarKind<'tcx>,
156 }
157 
158 impl<'tcx> CanonicalVarInfo<'tcx> {
universe(&self) -> ty::UniverseIndex159     pub fn universe(&self) -> ty::UniverseIndex {
160         self.kind.universe()
161     }
162 
163     #[must_use]
with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarInfo<'tcx>164     pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarInfo<'tcx> {
165         CanonicalVarInfo { kind: self.kind.with_updated_universe(ui) }
166     }
167 
is_existential(&self) -> bool168     pub fn is_existential(&self) -> bool {
169         match self.kind {
170             CanonicalVarKind::Ty(_) => true,
171             CanonicalVarKind::PlaceholderTy(_) => false,
172             CanonicalVarKind::Region(_) => true,
173             CanonicalVarKind::PlaceholderRegion(..) => false,
174             CanonicalVarKind::Const(..) => true,
175             CanonicalVarKind::PlaceholderConst(_, _) => false,
176         }
177     }
178 
is_region(&self) -> bool179     pub fn is_region(&self) -> bool {
180         match self.kind {
181             CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => true,
182             CanonicalVarKind::Ty(_)
183             | CanonicalVarKind::PlaceholderTy(_)
184             | CanonicalVarKind::Const(_, _)
185             | CanonicalVarKind::PlaceholderConst(_, _) => false,
186         }
187     }
188 
expect_placeholder_index(self) -> usize189     pub fn expect_placeholder_index(self) -> usize {
190         match self.kind {
191             CanonicalVarKind::Ty(_)
192             | CanonicalVarKind::Region(_)
193             | CanonicalVarKind::Const(_, _) => bug!("expected placeholder: {self:?}"),
194 
195             CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.bound.var.as_usize(),
196             CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.bound.var.as_usize(),
197             CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.bound.as_usize(),
198         }
199     }
200 }
201 
202 /// Describes the "kind" of the canonical variable. This is a "kind"
203 /// in the type-theory sense of the term -- i.e., a "meta" type system
204 /// that analyzes type-like values.
205 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)]
206 #[derive(TypeFoldable, TypeVisitable)]
207 pub enum CanonicalVarKind<'tcx> {
208     /// Some kind of type inference variable.
209     Ty(CanonicalTyVarKind),
210 
211     /// A "placeholder" that represents "any type".
212     PlaceholderTy(ty::PlaceholderType),
213 
214     /// Region variable `'?R`.
215     Region(ty::UniverseIndex),
216 
217     /// A "placeholder" that represents "any region". Created when you
218     /// are solving a goal like `for<'a> T: Foo<'a>` to represent the
219     /// bound region `'a`.
220     PlaceholderRegion(ty::PlaceholderRegion),
221 
222     /// Some kind of const inference variable.
223     Const(ty::UniverseIndex, Ty<'tcx>),
224 
225     /// A "placeholder" that represents "any const".
226     PlaceholderConst(ty::PlaceholderConst<'tcx>, Ty<'tcx>),
227 }
228 
229 impl<'tcx> CanonicalVarKind<'tcx> {
universe(self) -> ty::UniverseIndex230     pub fn universe(self) -> ty::UniverseIndex {
231         match self {
232             CanonicalVarKind::Ty(kind) => match kind {
233                 CanonicalTyVarKind::General(ui) => ui,
234                 CanonicalTyVarKind::Float | CanonicalTyVarKind::Int => ty::UniverseIndex::ROOT,
235             },
236 
237             CanonicalVarKind::PlaceholderTy(placeholder) => placeholder.universe,
238             CanonicalVarKind::Region(ui) => ui,
239             CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe,
240             CanonicalVarKind::Const(ui, _) => ui,
241             CanonicalVarKind::PlaceholderConst(placeholder, _) => placeholder.universe,
242         }
243     }
244 
245     /// Replaces the universe of this canonical variable with `ui`.
246     ///
247     /// In case this is a float or int variable, this causes an ICE if
248     /// the updated universe is not the root.
with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarKind<'tcx>249     pub fn with_updated_universe(self, ui: ty::UniverseIndex) -> CanonicalVarKind<'tcx> {
250         match self {
251             CanonicalVarKind::Ty(kind) => match kind {
252                 CanonicalTyVarKind::General(_) => {
253                     CanonicalVarKind::Ty(CanonicalTyVarKind::General(ui))
254                 }
255                 CanonicalTyVarKind::Int | CanonicalTyVarKind::Float => {
256                     assert_eq!(ui, ty::UniverseIndex::ROOT);
257                     CanonicalVarKind::Ty(kind)
258                 }
259             },
260             CanonicalVarKind::PlaceholderTy(placeholder) => {
261                 CanonicalVarKind::PlaceholderTy(ty::Placeholder { universe: ui, ..placeholder })
262             }
263             CanonicalVarKind::Region(_) => CanonicalVarKind::Region(ui),
264             CanonicalVarKind::PlaceholderRegion(placeholder) => {
265                 CanonicalVarKind::PlaceholderRegion(ty::Placeholder { universe: ui, ..placeholder })
266             }
267             CanonicalVarKind::Const(_, ty) => CanonicalVarKind::Const(ui, ty),
268             CanonicalVarKind::PlaceholderConst(placeholder, ty) => {
269                 CanonicalVarKind::PlaceholderConst(
270                     ty::Placeholder { universe: ui, ..placeholder },
271                     ty,
272                 )
273             }
274         }
275     }
276 }
277 
278 /// Rust actually has more than one category of type variables;
279 /// notably, the type variables we create for literals (e.g., 22 or
280 /// 22.) can only be instantiated with integral/float types (e.g.,
281 /// usize or f32). In order to faithfully reproduce a type, we need to
282 /// know what set of types a given type variable can be unified with.
283 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyDecodable, TyEncodable, HashStable)]
284 pub enum CanonicalTyVarKind {
285     /// General type variable `?T` that can be unified with arbitrary types.
286     General(ty::UniverseIndex),
287 
288     /// Integral type variable `?I` (that can only be unified with integral types).
289     Int,
290 
291     /// Floating-point type variable `?F` (that can only be unified with float types).
292     Float,
293 }
294 
295 /// After we execute a query with a canonicalized key, we get back a
296 /// `Canonical<QueryResponse<..>>`. You can use
297 /// `instantiate_query_result` to access the data in this result.
298 #[derive(Clone, Debug, HashStable, TypeFoldable, TypeVisitable, Lift)]
299 pub struct QueryResponse<'tcx, R> {
300     pub var_values: CanonicalVarValues<'tcx>,
301     pub region_constraints: QueryRegionConstraints<'tcx>,
302     pub certainty: Certainty,
303     /// List of opaque types which we tried to compare to another type.
304     /// Inside the query we don't know yet whether the opaque type actually
305     /// should get its hidden type inferred. So we bubble the opaque type
306     /// and the type it was compared against upwards and let the query caller
307     /// handle it.
308     pub opaque_types: Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)>,
309     pub value: R,
310 }
311 
312 #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
313 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)]
314 pub struct QueryRegionConstraints<'tcx> {
315     pub outlives: Vec<QueryOutlivesConstraint<'tcx>>,
316     pub member_constraints: Vec<MemberConstraint<'tcx>>,
317 }
318 
319 impl QueryRegionConstraints<'_> {
320     /// Represents an empty (trivially true) set of region
321     /// constraints.
is_empty(&self) -> bool322     pub fn is_empty(&self) -> bool {
323         self.outlives.is_empty() && self.member_constraints.is_empty()
324     }
325 }
326 
327 pub type CanonicalQueryResponse<'tcx, T> = &'tcx Canonical<'tcx, QueryResponse<'tcx, T>>;
328 
329 /// Indicates whether or not we were able to prove the query to be
330 /// true.
331 #[derive(Copy, Clone, Debug, HashStable)]
332 pub enum Certainty {
333     /// The query is known to be true, presuming that you apply the
334     /// given `var_values` and the region-constraints are satisfied.
335     Proven,
336 
337     /// The query is not known to be true, but also not known to be
338     /// false. The `var_values` represent *either* values that must
339     /// hold in order for the query to be true, or helpful tips that
340     /// *might* make it true. Currently rustc's trait solver cannot
341     /// distinguish the two (e.g., due to our preference for where
342     /// clauses over impls).
343     ///
344     /// After some unification and things have been done, it makes
345     /// sense to try and prove again -- of course, at that point, the
346     /// canonical form will be different, making this a distinct
347     /// query.
348     Ambiguous,
349 }
350 
351 impl Certainty {
is_proven(&self) -> bool352     pub fn is_proven(&self) -> bool {
353         match self {
354             Certainty::Proven => true,
355             Certainty::Ambiguous => false,
356         }
357     }
358 }
359 
360 impl<'tcx, R> QueryResponse<'tcx, R> {
is_proven(&self) -> bool361     pub fn is_proven(&self) -> bool {
362         self.certainty.is_proven()
363     }
364 }
365 
366 impl<'tcx, R> Canonical<'tcx, QueryResponse<'tcx, R>> {
is_proven(&self) -> bool367     pub fn is_proven(&self) -> bool {
368         self.value.is_proven()
369     }
370 
is_ambiguous(&self) -> bool371     pub fn is_ambiguous(&self) -> bool {
372         !self.is_proven()
373     }
374 }
375 
376 impl<'tcx, V> Canonical<'tcx, V> {
377     /// Allows you to map the `value` of a canonical while keeping the
378     /// same set of bound variables.
379     ///
380     /// **WARNING:** This function is very easy to mis-use, hence the
381     /// name!  In particular, the new value `W` must use all **the
382     /// same type/region variables** in **precisely the same order**
383     /// as the original! (The ordering is defined by the
384     /// `TypeFoldable` implementation of the type in question.)
385     ///
386     /// An example of a **correct** use of this:
387     ///
388     /// ```rust,ignore (not real code)
389     /// let a: Canonical<'_, T> = ...;
390     /// let b: Canonical<'_, (T,)> = a.unchecked_map(|v| (v, ));
391     /// ```
392     ///
393     /// An example of an **incorrect** use of this:
394     ///
395     /// ```rust,ignore (not real code)
396     /// let a: Canonical<'tcx, T> = ...;
397     /// let ty: Ty<'tcx> = ...;
398     /// let b: Canonical<'tcx, (T, Ty<'tcx>)> = a.unchecked_map(|v| (v, ty));
399     /// ```
unchecked_map<W>(self, map_op: impl FnOnce(V) -> W) -> Canonical<'tcx, W>400     pub fn unchecked_map<W>(self, map_op: impl FnOnce(V) -> W) -> Canonical<'tcx, W> {
401         let Canonical { max_universe, variables, value } = self;
402         Canonical { max_universe, variables, value: map_op(value) }
403     }
404 
405     /// Allows you to map the `value` of a canonical while keeping the same set of
406     /// bound variables.
407     ///
408     /// **WARNING:** This function is very easy to mis-use, hence the name! See
409     /// the comment of [Canonical::unchecked_map] for more details.
unchecked_rebind<W>(self, value: W) -> Canonical<'tcx, W>410     pub fn unchecked_rebind<W>(self, value: W) -> Canonical<'tcx, W> {
411         let Canonical { max_universe, variables, value: _ } = self;
412         Canonical { max_universe, variables, value }
413     }
414 }
415 
416 pub type QueryOutlivesConstraint<'tcx> =
417     (ty::OutlivesPredicate<GenericArg<'tcx>, Region<'tcx>>, ConstraintCategory<'tcx>);
418 
419 TrivialTypeTraversalAndLiftImpls! {
420     crate::infer::canonical::Certainty,
421     crate::infer::canonical::CanonicalTyVarKind,
422 }
423 
424 impl<'tcx> CanonicalVarValues<'tcx> {
425     // Given a list of canonical variables, construct a set of values which are
426     // the identity response.
make_identity( tcx: TyCtxt<'tcx>, infos: CanonicalVarInfos<'tcx>, ) -> CanonicalVarValues<'tcx>427     pub fn make_identity(
428         tcx: TyCtxt<'tcx>,
429         infos: CanonicalVarInfos<'tcx>,
430     ) -> CanonicalVarValues<'tcx> {
431         CanonicalVarValues {
432             var_values: tcx.mk_substs_from_iter(infos.iter().enumerate().map(
433                 |(i, info)| -> ty::GenericArg<'tcx> {
434                     match info.kind {
435                         CanonicalVarKind::Ty(_) | CanonicalVarKind::PlaceholderTy(_) => {
436                             Ty::new_bound(tcx, ty::INNERMOST, ty::BoundVar::from_usize(i).into())
437                                 .into()
438                         }
439                         CanonicalVarKind::Region(_) | CanonicalVarKind::PlaceholderRegion(_) => {
440                             let br = ty::BoundRegion {
441                                 var: ty::BoundVar::from_usize(i),
442                                 kind: ty::BrAnon(None),
443                             };
444                             ty::Region::new_late_bound(tcx, ty::INNERMOST, br).into()
445                         }
446                         CanonicalVarKind::Const(_, ty)
447                         | CanonicalVarKind::PlaceholderConst(_, ty) => ty::Const::new_bound(
448                             tcx,
449                             ty::INNERMOST,
450                             ty::BoundVar::from_usize(i),
451                             ty,
452                         )
453                         .into(),
454                     }
455                 },
456             )),
457         }
458     }
459 
460     /// Creates dummy var values which should not be used in a
461     /// canonical response.
dummy() -> CanonicalVarValues<'tcx>462     pub fn dummy() -> CanonicalVarValues<'tcx> {
463         CanonicalVarValues { var_values: ty::List::empty() }
464     }
465 
466     #[inline]
len(&self) -> usize467     pub fn len(&self) -> usize {
468         self.var_values.len()
469     }
470 }
471 
472 impl<'a, 'tcx> IntoIterator for &'a CanonicalVarValues<'tcx> {
473     type Item = GenericArg<'tcx>;
474     type IntoIter = ::std::iter::Copied<::std::slice::Iter<'a, GenericArg<'tcx>>>;
475 
into_iter(self) -> Self::IntoIter476     fn into_iter(self) -> Self::IntoIter {
477         self.var_values.iter()
478     }
479 }
480 
481 impl<'tcx> Index<BoundVar> for CanonicalVarValues<'tcx> {
482     type Output = GenericArg<'tcx>;
483 
index(&self, value: BoundVar) -> &GenericArg<'tcx>484     fn index(&self, value: BoundVar) -> &GenericArg<'tcx> {
485         &self.var_values[value.as_usize()]
486     }
487 }
488