1 // Copyright 2014 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.
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.
11 //! **Canonicalization** is the key to constructing a query in the
12 //! middle of type inference. Ordinarily, it is not possible to store
13 //! types from type inference in query keys, because they contain
14 //! references to inference variables whose lifetimes are too short
15 //! and so forth. Canonicalizing a value T1 using `canonicalize_query`
16 //! produces two things:
18 //! - a value T2 where each unbound inference variable has been
19 //! replaced with a **canonical variable**;
20 //! - a map M (of type `CanonicalVarValues`) from those canonical
21 //! variables back to the original.
23 //! We can then do queries using T2. These will give back constraints
24 //! on the canonical variables which can be translated, using the map
25 //! M, into constraints in our source context. This process of
26 //! translating the results back is done by the
27 //! `instantiate_query_result` method.
29 //! For a more detailed look at what is happening here, check
30 //! out the [chapter in the rustc guide][c].
32 //! [c]: https://rust-lang-nursery.github.io/rustc-guide/traits/canonicalization.html
34 use infer::{InferCtxt, RegionVariableOrigin, TypeVariableOrigin};
35 use rustc_data_structures::indexed_vec::IndexVec;
36 use rustc_data_structures::sync::Lrc;
37 use serialize::UseSpecializedDecodable;
38 use smallvec::SmallVec;
40 use syntax::source_map::Span;
41 use ty::fold::TypeFoldable;
43 use ty::{self, BoundVar, Lift, List, Region, TyCtxt};
47 pub mod query_response;
51 /// A "canonicalized" type `V` is one where all free inference
52 /// variables have been rewritten to "canonical vars". These are
53 /// numbered starting from 0 in order of first appearance.
54 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
55 pub struct Canonical<'gcx, V> {
56 pub max_universe: ty::UniverseIndex,
57 pub variables: CanonicalVarInfos<'gcx>,
61 pub type CanonicalVarInfos<'gcx> = &'gcx List<CanonicalVarInfo>;
63 impl<'gcx> UseSpecializedDecodable for CanonicalVarInfos<'gcx> {}
65 /// A set of values corresponding to the canonical variables from some
66 /// `Canonical`. You can give these values to
67 /// `canonical_value.substitute` to substitute them into the canonical
68 /// value at the right places.
70 /// When you canonicalize a value `V`, you get back one of these
71 /// vectors with the original values that were replaced by canonical
72 /// variables. You will need to supply it later to instantiate the
73 /// canonicalized query response.
74 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
75 pub struct CanonicalVarValues<'tcx> {
76 pub var_values: IndexVec<BoundVar, Kind<'tcx>>,
79 /// When we canonicalize a value to form a query, we wind up replacing
80 /// various parts of it with canonical variables. This struct stores
81 /// those replaced bits to remember for when we process the query
83 #[derive(Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
84 pub struct OriginalQueryValues<'tcx> {
85 /// Map from the universes that appear in the query to the
86 /// universes in the caller context. For the time being, we only
87 /// ever put ROOT values into the query, so this map is very
89 pub universe_map: SmallVec<[ty::UniverseIndex; 4]>,
91 /// This is equivalent to `CanonicalVarValues`, but using a
92 /// `SmallVec` yields a significant performance win.
93 pub var_values: SmallVec<[Kind<'tcx>; 8]>,
96 impl Default for OriginalQueryValues<'tcx> {
97 fn default() -> Self {
98 let mut universe_map = SmallVec::default();
99 universe_map.push(ty::UniverseIndex::ROOT);
103 var_values: SmallVec::default(),
108 /// Information about a canonical variable that is included with the
109 /// canonical value. This is sufficient information for code to create
110 /// a copy of the canonical value in some other inference context,
111 /// with fresh inference variables replacing the canonical values.
112 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
113 pub struct CanonicalVarInfo {
114 pub kind: CanonicalVarKind,
117 impl CanonicalVarInfo {
118 pub fn universe(&self) -> ty::UniverseIndex {
122 pub fn is_existential(&self) -> bool {
124 CanonicalVarKind::Ty(_) => true,
125 CanonicalVarKind::Region(_) => true,
126 CanonicalVarKind::PlaceholderRegion(..) => false,
131 /// Describes the "kind" of the canonical variable. This is a "kind"
132 /// in the type-theory sense of the term -- i.e., a "meta" type system
133 /// that analyzes type-like values.
134 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
135 pub enum CanonicalVarKind {
136 /// Some kind of type inference variable.
137 Ty(CanonicalTyVarKind),
139 /// Region variable `'?R`.
140 Region(ty::UniverseIndex),
142 /// A "placeholder" that represents "any region". Created when you
143 /// are solving a goal like `for<'a> T: Foo<'a>` to represent the
144 /// bound region `'a`.
145 PlaceholderRegion(ty::PlaceholderRegion),
148 impl CanonicalVarKind {
149 pub fn universe(self) -> ty::UniverseIndex {
151 // At present, we don't support higher-ranked
152 // quantification over types, so all type variables are in
153 // the root universe.
154 CanonicalVarKind::Ty(_) => ty::UniverseIndex::ROOT,
156 // Region variables can be created in sub-universes.
157 CanonicalVarKind::Region(ui) => ui,
158 CanonicalVarKind::PlaceholderRegion(placeholder) => placeholder.universe,
163 /// Rust actually has more than one category of type variables;
164 /// notably, the type variables we create for literals (e.g., 22 or
165 /// 22.) can only be instantiated with integral/float types (e.g.,
166 /// usize or f32). In order to faithfully reproduce a type, we need to
167 /// know what set of types a given type variable can be unified with.
168 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, RustcDecodable, RustcEncodable)]
169 pub enum CanonicalTyVarKind {
170 /// General type variable `?T` that can be unified with arbitrary types.
173 /// Integral type variable `?I` (that can only be unified with integral types).
176 /// Floating-point type variable `?F` (that can only be unified with float types).
180 /// After we execute a query with a canonicalized key, we get back a
181 /// `Canonical<QueryResponse<..>>`. You can use
182 /// `instantiate_query_result` to access the data in this result.
183 #[derive(Clone, Debug)]
184 pub struct QueryResponse<'tcx, R> {
185 pub var_values: CanonicalVarValues<'tcx>,
186 pub region_constraints: Vec<QueryRegionConstraint<'tcx>>,
187 pub certainty: Certainty,
191 pub type Canonicalized<'gcx, V> = Canonical<'gcx, <V as Lift<'gcx>>::Lifted>;
193 pub type CanonicalizedQueryResponse<'gcx, T> =
194 Lrc<Canonical<'gcx, QueryResponse<'gcx, <T as Lift<'gcx>>::Lifted>>>;
196 /// Indicates whether or not we were able to prove the query to be
198 #[derive(Copy, Clone, Debug)]
200 /// The query is known to be true, presuming that you apply the
201 /// given `var_values` and the region-constraints are satisfied.
204 /// The query is not known to be true, but also not known to be
205 /// false. The `var_values` represent *either* values that must
206 /// hold in order for the query to be true, or helpful tips that
207 /// *might* make it true. Currently rustc's trait solver cannot
208 /// distinguish the two (e.g., due to our preference for where
209 /// clauses over impls).
211 /// After some unifiations and things have been done, it makes
212 /// sense to try and prove again -- of course, at that point, the
213 /// canonical form will be different, making this a distinct
219 pub fn is_proven(&self) -> bool {
221 Certainty::Proven => true,
222 Certainty::Ambiguous => false,
226 pub fn is_ambiguous(&self) -> bool {
231 impl<'tcx, R> QueryResponse<'tcx, R> {
232 pub fn is_proven(&self) -> bool {
233 self.certainty.is_proven()
236 pub fn is_ambiguous(&self) -> bool {
241 impl<'tcx, R> Canonical<'tcx, QueryResponse<'tcx, R>> {
242 pub fn is_proven(&self) -> bool {
243 self.value.is_proven()
246 pub fn is_ambiguous(&self) -> bool {
251 impl<'gcx, V> Canonical<'gcx, V> {
252 /// Allows you to map the `value` of a canonical while keeping the
253 /// same set of bound variables.
255 /// **WARNING:** This function is very easy to mis-use, hence the
256 /// name! In particular, the new value `W` must use all **the
257 /// same type/region variables** in **precisely the same order**
258 /// as the original! (The ordering is defined by the
259 /// `TypeFoldable` implementation of the type in question.)
261 /// An example of a **correct** use of this:
263 /// ```rust,ignore (not real code)
264 /// let a: Canonical<'_, T> = ...;
265 /// let b: Canonical<'_, (T,)> = a.unchecked_map(|v| (v, ));
268 /// An example of an **incorrect** use of this:
270 /// ```rust,ignore (not real code)
271 /// let a: Canonical<'tcx, T> = ...;
272 /// let ty: Ty<'tcx> = ...;
273 /// let b: Canonical<'tcx, (T, Ty<'tcx>)> = a.unchecked_map(|v| (v, ty));
275 pub fn unchecked_map<W>(self, map_op: impl FnOnce(V) -> W) -> Canonical<'gcx, W> {
284 value: map_op(value),
289 pub type QueryRegionConstraint<'tcx> = ty::Binder<ty::OutlivesPredicate<Kind<'tcx>, Region<'tcx>>>;
291 impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
292 /// Creates a substitution S for the canonical value with fresh
293 /// inference variables and applies it to the canonical value.
294 /// Returns both the instantiated result *and* the substitution S.
296 /// This is only meant to be invoked as part of constructing an
297 /// inference context at the start of a query (see
298 /// `InferCtxtBuilder::enter_with_canonical`). It basically
299 /// brings the canonical value "into scope" within your new infcx.
301 /// At the end of processing, the substitution S (once
302 /// canonicalized) then represents the values that you computed
303 /// for each of the canonical inputs to your query.
305 pub fn instantiate_canonical_with_fresh_inference_vars<T>(
308 canonical: &Canonical<'tcx, T>,
309 ) -> (T, CanonicalVarValues<'tcx>)
311 T: TypeFoldable<'tcx>,
313 // For each universe that is referred to in the incoming
314 // query, create a universe in our local inference context. In
315 // practice, as of this writing, all queries have no universes
316 // in them, so this code has no effect, but it is looking
317 // forward to the day when we *do* want to carry universes
318 // through into queries.
319 let universes: IndexVec<ty::UniverseIndex, _> = std::iter::once(ty::UniverseIndex::ROOT)
320 .chain((0..canonical.max_universe.as_u32()).map(|_| self.create_next_universe()))
323 let canonical_inference_vars =
324 self.instantiate_canonical_vars(span, canonical.variables, |ui| universes[ui]);
325 let result = canonical.substitute(self.tcx, &canonical_inference_vars);
326 (result, canonical_inference_vars)
329 /// Given the "infos" about the canonical variables from some
330 /// canonical, creates fresh variables with the same
331 /// characteristics (see `instantiate_canonical_var` for
332 /// details). You can then use `substitute` to instantiate the
333 /// canonical variable with these inference variables.
334 fn instantiate_canonical_vars(
337 variables: &List<CanonicalVarInfo>,
338 universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
339 ) -> CanonicalVarValues<'tcx> {
340 let var_values: IndexVec<BoundVar, Kind<'tcx>> = variables
342 .map(|info| self.instantiate_canonical_var(span, *info, &universe_map))
345 CanonicalVarValues { var_values }
348 /// Given the "info" about a canonical variable, creates a fresh
349 /// variable for it. If this is an existentially quantified
350 /// variable, then you'll get a new inference variable; if it is a
351 /// universally quantified variable, you get a placeholder.
352 fn instantiate_canonical_var(
355 cv_info: CanonicalVarInfo,
356 universe_map: impl Fn(ty::UniverseIndex) -> ty::UniverseIndex,
359 CanonicalVarKind::Ty(ty_kind) => {
360 let ty = match ty_kind {
361 CanonicalTyVarKind::General => {
362 self.next_ty_var(TypeVariableOrigin::MiscVariable(span))
365 CanonicalTyVarKind::Int => self.tcx.mk_int_var(self.next_int_var_id()),
367 CanonicalTyVarKind::Float => self.tcx.mk_float_var(self.next_float_var_id()),
372 CanonicalVarKind::Region(ui) => self.next_region_var_in_universe(
373 RegionVariableOrigin::MiscVariable(span),
377 CanonicalVarKind::PlaceholderRegion(ty::PlaceholderRegion { universe, name }) => {
378 let universe_mapped = universe_map(universe);
379 let placeholder_mapped = ty::PlaceholderRegion {
380 universe: universe_mapped,
384 .mk_region(ty::RePlaceholder(placeholder_mapped))
391 CloneTypeFoldableAndLiftImpls! {
392 ::infer::canonical::Certainty,
393 ::infer::canonical::CanonicalVarInfo,
394 ::infer::canonical::CanonicalVarKind,
397 CloneTypeFoldableImpls! {
399 ::infer::canonical::CanonicalVarInfos<'tcx>,
403 BraceStructTypeFoldableImpl! {
404 impl<'tcx, C> TypeFoldable<'tcx> for Canonical<'tcx, C> {
408 } where C: TypeFoldable<'tcx>
411 BraceStructLiftImpl! {
412 impl<'a, 'tcx, T> Lift<'tcx> for Canonical<'a, T> {
413 type Lifted = Canonical<'tcx, T::Lifted>;
414 max_universe, variables, value
415 } where T: Lift<'tcx>
418 impl<'tcx> CanonicalVarValues<'tcx> {
419 fn len(&self) -> usize {
420 self.var_values.len()
424 impl<'a, 'tcx> IntoIterator for &'a CanonicalVarValues<'tcx> {
425 type Item = Kind<'tcx>;
426 type IntoIter = ::std::iter::Cloned<::std::slice::Iter<'a, Kind<'tcx>>>;
428 fn into_iter(self) -> Self::IntoIter {
429 self.var_values.iter().cloned()
433 BraceStructLiftImpl! {
434 impl<'a, 'tcx> Lift<'tcx> for CanonicalVarValues<'a> {
435 type Lifted = CanonicalVarValues<'tcx>;
440 BraceStructTypeFoldableImpl! {
441 impl<'tcx> TypeFoldable<'tcx> for CanonicalVarValues<'tcx> {
446 BraceStructTypeFoldableImpl! {
447 impl<'tcx, R> TypeFoldable<'tcx> for QueryResponse<'tcx, R> {
448 var_values, region_constraints, certainty, value
449 } where R: TypeFoldable<'tcx>,
452 BraceStructLiftImpl! {
453 impl<'a, 'tcx, R> Lift<'tcx> for QueryResponse<'a, R> {
454 type Lifted = QueryResponse<'tcx, R::Lifted>;
455 var_values, region_constraints, certainty, value
456 } where R: Lift<'tcx>
459 impl<'tcx> Index<BoundVar> for CanonicalVarValues<'tcx> {
460 type Output = Kind<'tcx>;
462 fn index(&self, value: BoundVar) -> &Kind<'tcx> {
463 &self.var_values[value]