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