1 // Type substitutions. 2 3 use crate::ty::codec::{TyDecoder, TyEncoder}; 4 use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldable}; 5 use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts}; 6 use crate::ty::visit::{TypeVisitable, TypeVisitableExt, TypeVisitor}; 7 use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; 8 9 use rustc_data_structures::intern::Interned; 10 use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg}; 11 use rustc_hir::def_id::DefId; 12 use rustc_macros::HashStable; 13 use rustc_serialize::{self, Decodable, Encodable}; 14 use rustc_span::sym; 15 use rustc_type_ir::WithCachedTypeInfo; 16 use smallvec::SmallVec; 17 18 use core::intrinsics; 19 use std::cmp::Ordering; 20 use std::fmt; 21 use std::marker::PhantomData; 22 use std::mem; 23 use std::num::NonZeroUsize; 24 use std::ops::{ControlFlow, Deref}; 25 26 /// An entity in the Rust type system, which can be one of 27 /// several kinds (types, lifetimes, and consts). 28 /// To reduce memory usage, a `GenericArg` is an interned pointer, 29 /// with the lowest 2 bits being reserved for a tag to 30 /// indicate the type (`Ty`, `Region`, or `Const`) it points to. 31 /// 32 /// Note: the `PartialEq`, `Eq` and `Hash` derives are only valid because `Ty`, 33 /// `Region` and `Const` are all interned. 34 #[derive(Copy, Clone, PartialEq, Eq, Hash)] 35 pub struct GenericArg<'tcx> { 36 ptr: NonZeroUsize, 37 marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>)>, 38 } 39 40 impl<'tcx> IntoDiagnosticArg for GenericArg<'tcx> { into_diagnostic_arg(self) -> DiagnosticArgValue<'static>41 fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> { 42 self.to_string().into_diagnostic_arg() 43 } 44 } 45 46 const TAG_MASK: usize = 0b11; 47 const TYPE_TAG: usize = 0b00; 48 const REGION_TAG: usize = 0b01; 49 const CONST_TAG: usize = 0b10; 50 51 #[derive(Debug, TyEncodable, TyDecodable, PartialEq, Eq, PartialOrd, Ord, HashStable)] 52 pub enum GenericArgKind<'tcx> { 53 Lifetime(ty::Region<'tcx>), 54 Type(Ty<'tcx>), 55 Const(ty::Const<'tcx>), 56 } 57 58 impl<'tcx> GenericArgKind<'tcx> { 59 #[inline] pack(self) -> GenericArg<'tcx>60 fn pack(self) -> GenericArg<'tcx> { 61 let (tag, ptr) = match self { 62 GenericArgKind::Lifetime(lt) => { 63 // Ensure we can use the tag bits. 64 assert_eq!(mem::align_of_val(&*lt.0.0) & TAG_MASK, 0); 65 (REGION_TAG, lt.0.0 as *const ty::RegionKind<'tcx> as usize) 66 } 67 GenericArgKind::Type(ty) => { 68 // Ensure we can use the tag bits. 69 assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); 70 (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize) 71 } 72 GenericArgKind::Const(ct) => { 73 // Ensure we can use the tag bits. 74 assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0); 75 (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize) 76 } 77 }; 78 79 GenericArg { ptr: unsafe { NonZeroUsize::new_unchecked(ptr | tag) }, marker: PhantomData } 80 } 81 } 82 83 impl<'tcx> fmt::Debug for GenericArg<'tcx> { fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result84 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 85 match self.unpack() { 86 GenericArgKind::Lifetime(lt) => lt.fmt(f), 87 GenericArgKind::Type(ty) => ty.fmt(f), 88 GenericArgKind::Const(ct) => ct.fmt(f), 89 } 90 } 91 } 92 93 impl<'tcx> Ord for GenericArg<'tcx> { cmp(&self, other: &GenericArg<'tcx>) -> Ordering94 fn cmp(&self, other: &GenericArg<'tcx>) -> Ordering { 95 self.unpack().cmp(&other.unpack()) 96 } 97 } 98 99 impl<'tcx> PartialOrd for GenericArg<'tcx> { partial_cmp(&self, other: &GenericArg<'tcx>) -> Option<Ordering>100 fn partial_cmp(&self, other: &GenericArg<'tcx>) -> Option<Ordering> { 101 Some(self.cmp(&other)) 102 } 103 } 104 105 impl<'tcx> From<ty::Region<'tcx>> for GenericArg<'tcx> { 106 #[inline] from(r: ty::Region<'tcx>) -> GenericArg<'tcx>107 fn from(r: ty::Region<'tcx>) -> GenericArg<'tcx> { 108 GenericArgKind::Lifetime(r).pack() 109 } 110 } 111 112 impl<'tcx> From<Ty<'tcx>> for GenericArg<'tcx> { 113 #[inline] from(ty: Ty<'tcx>) -> GenericArg<'tcx>114 fn from(ty: Ty<'tcx>) -> GenericArg<'tcx> { 115 GenericArgKind::Type(ty).pack() 116 } 117 } 118 119 impl<'tcx> From<ty::Const<'tcx>> for GenericArg<'tcx> { 120 #[inline] from(c: ty::Const<'tcx>) -> GenericArg<'tcx>121 fn from(c: ty::Const<'tcx>) -> GenericArg<'tcx> { 122 GenericArgKind::Const(c).pack() 123 } 124 } 125 126 impl<'tcx> From<ty::Term<'tcx>> for GenericArg<'tcx> { from(value: ty::Term<'tcx>) -> Self127 fn from(value: ty::Term<'tcx>) -> Self { 128 match value.unpack() { 129 ty::TermKind::Ty(t) => t.into(), 130 ty::TermKind::Const(c) => c.into(), 131 } 132 } 133 } 134 135 impl<'tcx> GenericArg<'tcx> { 136 #[inline] unpack(self) -> GenericArgKind<'tcx>137 pub fn unpack(self) -> GenericArgKind<'tcx> { 138 let ptr = self.ptr.get(); 139 // SAFETY: use of `Interned::new_unchecked` here is ok because these 140 // pointers were originally created from `Interned` types in `pack()`, 141 // and this is just going in the other direction. 142 unsafe { 143 match ptr & TAG_MASK { 144 REGION_TAG => GenericArgKind::Lifetime(ty::Region(Interned::new_unchecked( 145 &*((ptr & !TAG_MASK) as *const ty::RegionKind<'tcx>), 146 ))), 147 TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked( 148 &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>), 149 ))), 150 CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( 151 &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>), 152 ))), 153 _ => intrinsics::unreachable(), 154 } 155 } 156 } 157 158 #[inline] as_type(self) -> Option<Ty<'tcx>>159 pub fn as_type(self) -> Option<Ty<'tcx>> { 160 match self.unpack() { 161 GenericArgKind::Type(ty) => Some(ty), 162 _ => None, 163 } 164 } 165 166 #[inline] as_region(self) -> Option<ty::Region<'tcx>>167 pub fn as_region(self) -> Option<ty::Region<'tcx>> { 168 match self.unpack() { 169 GenericArgKind::Lifetime(re) => Some(re), 170 _ => None, 171 } 172 } 173 174 #[inline] as_const(self) -> Option<ty::Const<'tcx>>175 pub fn as_const(self) -> Option<ty::Const<'tcx>> { 176 match self.unpack() { 177 GenericArgKind::Const(ct) => Some(ct), 178 _ => None, 179 } 180 } 181 182 /// Unpack the `GenericArg` as a region when it is known certainly to be a region. expect_region(self) -> ty::Region<'tcx>183 pub fn expect_region(self) -> ty::Region<'tcx> { 184 self.as_region().unwrap_or_else(|| bug!("expected a region, but found another kind")) 185 } 186 187 /// Unpack the `GenericArg` as a type when it is known certainly to be a type. 188 /// This is true in cases where `Substs` is used in places where the kinds are known 189 /// to be limited (e.g. in tuples, where the only parameters are type parameters). expect_ty(self) -> Ty<'tcx>190 pub fn expect_ty(self) -> Ty<'tcx> { 191 self.as_type().unwrap_or_else(|| bug!("expected a type, but found another kind")) 192 } 193 194 /// Unpack the `GenericArg` as a const when it is known certainly to be a const. expect_const(self) -> ty::Const<'tcx>195 pub fn expect_const(self) -> ty::Const<'tcx> { 196 self.as_const().unwrap_or_else(|| bug!("expected a const, but found another kind")) 197 } 198 is_non_region_infer(self) -> bool199 pub fn is_non_region_infer(self) -> bool { 200 match self.unpack() { 201 GenericArgKind::Lifetime(_) => false, 202 GenericArgKind::Type(ty) => ty.is_ty_or_numeric_infer(), 203 GenericArgKind::Const(ct) => ct.is_ct_infer(), 204 } 205 } 206 } 207 208 impl<'a, 'tcx> Lift<'tcx> for GenericArg<'a> { 209 type Lifted = GenericArg<'tcx>; 210 lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted>211 fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> { 212 match self.unpack() { 213 GenericArgKind::Lifetime(lt) => tcx.lift(lt).map(|lt| lt.into()), 214 GenericArgKind::Type(ty) => tcx.lift(ty).map(|ty| ty.into()), 215 GenericArgKind::Const(ct) => tcx.lift(ct).map(|ct| ct.into()), 216 } 217 } 218 } 219 220 impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for GenericArg<'tcx> { try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( self, folder: &mut F, ) -> Result<Self, F::Error>221 fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( 222 self, 223 folder: &mut F, 224 ) -> Result<Self, F::Error> { 225 match self.unpack() { 226 GenericArgKind::Lifetime(lt) => lt.try_fold_with(folder).map(Into::into), 227 GenericArgKind::Type(ty) => ty.try_fold_with(folder).map(Into::into), 228 GenericArgKind::Const(ct) => ct.try_fold_with(folder).map(Into::into), 229 } 230 } 231 } 232 233 impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for GenericArg<'tcx> { visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>234 fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { 235 match self.unpack() { 236 GenericArgKind::Lifetime(lt) => lt.visit_with(visitor), 237 GenericArgKind::Type(ty) => ty.visit_with(visitor), 238 GenericArgKind::Const(ct) => ct.visit_with(visitor), 239 } 240 } 241 } 242 243 impl<'tcx, E: TyEncoder<I = TyCtxt<'tcx>>> Encodable<E> for GenericArg<'tcx> { encode(&self, e: &mut E)244 fn encode(&self, e: &mut E) { 245 self.unpack().encode(e) 246 } 247 } 248 249 impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for GenericArg<'tcx> { decode(d: &mut D) -> GenericArg<'tcx>250 fn decode(d: &mut D) -> GenericArg<'tcx> { 251 GenericArgKind::decode(d).pack() 252 } 253 } 254 255 /// List of generic arguments that are gonna be used to substitute generic parameters. 256 pub type InternalSubsts<'tcx> = List<GenericArg<'tcx>>; 257 258 pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>; 259 260 impl<'tcx> InternalSubsts<'tcx> { 261 /// Converts substs to a type list. 262 /// 263 /// # Panics 264 /// 265 /// If any of the generic arguments are not types. into_type_list(&self, tcx: TyCtxt<'tcx>) -> &'tcx List<Ty<'tcx>>266 pub fn into_type_list(&self, tcx: TyCtxt<'tcx>) -> &'tcx List<Ty<'tcx>> { 267 tcx.mk_type_list_from_iter(self.iter().map(|arg| match arg.unpack() { 268 GenericArgKind::Type(ty) => ty, 269 _ => bug!("`into_type_list` called on substs with non-types"), 270 })) 271 } 272 273 /// Interpret these substitutions as the substitutions of a closure type. 274 /// Closure substitutions have a particular structure controlled by the 275 /// compiler that encodes information like the signature and closure kind; 276 /// see `ty::ClosureSubsts` struct for more comments. as_closure(&'tcx self) -> ClosureSubsts<'tcx>277 pub fn as_closure(&'tcx self) -> ClosureSubsts<'tcx> { 278 ClosureSubsts { substs: self } 279 } 280 281 /// Interpret these substitutions as the substitutions of a generator type. 282 /// Generator substitutions have a particular structure controlled by the 283 /// compiler that encodes information like the signature and generator kind; 284 /// see `ty::GeneratorSubsts` struct for more comments. as_generator(&'tcx self) -> GeneratorSubsts<'tcx>285 pub fn as_generator(&'tcx self) -> GeneratorSubsts<'tcx> { 286 GeneratorSubsts { substs: self } 287 } 288 289 /// Interpret these substitutions as the substitutions of an inline const. 290 /// Inline const substitutions have a particular structure controlled by the 291 /// compiler that encodes information like the inferred type; 292 /// see `ty::InlineConstSubsts` struct for more comments. as_inline_const(&'tcx self) -> InlineConstSubsts<'tcx>293 pub fn as_inline_const(&'tcx self) -> InlineConstSubsts<'tcx> { 294 InlineConstSubsts { substs: self } 295 } 296 297 /// Creates an `InternalSubsts` that maps each generic parameter to itself. identity_for_item(tcx: TyCtxt<'tcx>, def_id: impl Into<DefId>) -> SubstsRef<'tcx>298 pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: impl Into<DefId>) -> SubstsRef<'tcx> { 299 Self::for_item(tcx, def_id.into(), |param, _| tcx.mk_param_from_def(param)) 300 } 301 302 /// Creates an `InternalSubsts` for generic parameter definitions, 303 /// by calling closures to obtain each kind. 304 /// The closures get to observe the `InternalSubsts` as they're 305 /// being built, which can be used to correctly 306 /// substitute defaults of generic parameters. for_item<F>(tcx: TyCtxt<'tcx>, def_id: DefId, mut mk_kind: F) -> SubstsRef<'tcx> where F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>,307 pub fn for_item<F>(tcx: TyCtxt<'tcx>, def_id: DefId, mut mk_kind: F) -> SubstsRef<'tcx> 308 where 309 F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>, 310 { 311 let defs = tcx.generics_of(def_id); 312 let count = defs.count(); 313 let mut substs = SmallVec::with_capacity(count); 314 Self::fill_item(&mut substs, tcx, defs, &mut mk_kind); 315 tcx.mk_substs(&substs) 316 } 317 extend_to<F>(&self, tcx: TyCtxt<'tcx>, def_id: DefId, mut mk_kind: F) -> SubstsRef<'tcx> where F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>,318 pub fn extend_to<F>(&self, tcx: TyCtxt<'tcx>, def_id: DefId, mut mk_kind: F) -> SubstsRef<'tcx> 319 where 320 F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>, 321 { 322 Self::for_item(tcx, def_id, |param, substs| { 323 self.get(param.index as usize).cloned().unwrap_or_else(|| mk_kind(param, substs)) 324 }) 325 } 326 fill_item<F>( substs: &mut SmallVec<[GenericArg<'tcx>; 8]>, tcx: TyCtxt<'tcx>, defs: &ty::Generics, mk_kind: &mut F, ) where F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>,327 pub fn fill_item<F>( 328 substs: &mut SmallVec<[GenericArg<'tcx>; 8]>, 329 tcx: TyCtxt<'tcx>, 330 defs: &ty::Generics, 331 mk_kind: &mut F, 332 ) where 333 F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>, 334 { 335 if let Some(def_id) = defs.parent { 336 let parent_defs = tcx.generics_of(def_id); 337 Self::fill_item(substs, tcx, parent_defs, mk_kind); 338 } 339 Self::fill_single(substs, defs, mk_kind) 340 } 341 fill_single<F>( substs: &mut SmallVec<[GenericArg<'tcx>; 8]>, defs: &ty::Generics, mk_kind: &mut F, ) where F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>,342 pub fn fill_single<F>( 343 substs: &mut SmallVec<[GenericArg<'tcx>; 8]>, 344 defs: &ty::Generics, 345 mk_kind: &mut F, 346 ) where 347 F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>, 348 { 349 substs.reserve(defs.params.len()); 350 for param in &defs.params { 351 let kind = mk_kind(param, substs); 352 assert_eq!(param.index as usize, substs.len(), "{substs:#?}, {defs:#?}"); 353 substs.push(kind); 354 } 355 } 356 357 // Extend an `original_substs` list to the full number of substs expected by `def_id`, 358 // filling in the missing parameters with error ty/ct or 'static regions. extend_with_error( tcx: TyCtxt<'tcx>, def_id: DefId, original_substs: &[GenericArg<'tcx>], ) -> SubstsRef<'tcx>359 pub fn extend_with_error( 360 tcx: TyCtxt<'tcx>, 361 def_id: DefId, 362 original_substs: &[GenericArg<'tcx>], 363 ) -> SubstsRef<'tcx> { 364 ty::InternalSubsts::for_item(tcx, def_id, |def, substs| { 365 if let Some(subst) = original_substs.get(def.index as usize) { 366 *subst 367 } else { 368 def.to_error(tcx, substs) 369 } 370 }) 371 } 372 373 #[inline] types(&'tcx self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'tcx374 pub fn types(&'tcx self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'tcx { 375 self.iter().filter_map(|k| k.as_type()) 376 } 377 378 #[inline] regions(&'tcx self) -> impl DoubleEndedIterator<Item = ty::Region<'tcx>> + 'tcx379 pub fn regions(&'tcx self) -> impl DoubleEndedIterator<Item = ty::Region<'tcx>> + 'tcx { 380 self.iter().filter_map(|k| k.as_region()) 381 } 382 383 #[inline] consts(&'tcx self) -> impl DoubleEndedIterator<Item = ty::Const<'tcx>> + 'tcx384 pub fn consts(&'tcx self) -> impl DoubleEndedIterator<Item = ty::Const<'tcx>> + 'tcx { 385 self.iter().filter_map(|k| k.as_const()) 386 } 387 388 #[inline] non_erasable_generics( &'tcx self, ) -> impl DoubleEndedIterator<Item = GenericArgKind<'tcx>> + 'tcx389 pub fn non_erasable_generics( 390 &'tcx self, 391 ) -> impl DoubleEndedIterator<Item = GenericArgKind<'tcx>> + 'tcx { 392 self.iter().filter_map(|k| match k.unpack() { 393 GenericArgKind::Lifetime(_) => None, 394 generic => Some(generic), 395 }) 396 } 397 398 #[inline] 399 #[track_caller] type_at(&self, i: usize) -> Ty<'tcx>400 pub fn type_at(&self, i: usize) -> Ty<'tcx> { 401 self[i].as_type().unwrap_or_else(|| bug!("expected type for param #{} in {:?}", i, self)) 402 } 403 404 #[inline] 405 #[track_caller] region_at(&self, i: usize) -> ty::Region<'tcx>406 pub fn region_at(&self, i: usize) -> ty::Region<'tcx> { 407 self[i] 408 .as_region() 409 .unwrap_or_else(|| bug!("expected region for param #{} in {:?}", i, self)) 410 } 411 412 #[inline] 413 #[track_caller] const_at(&self, i: usize) -> ty::Const<'tcx>414 pub fn const_at(&self, i: usize) -> ty::Const<'tcx> { 415 self[i].as_const().unwrap_or_else(|| bug!("expected const for param #{} in {:?}", i, self)) 416 } 417 418 #[inline] 419 #[track_caller] type_for_def(&self, def: &ty::GenericParamDef) -> GenericArg<'tcx>420 pub fn type_for_def(&self, def: &ty::GenericParamDef) -> GenericArg<'tcx> { 421 self.type_at(def.index as usize).into() 422 } 423 424 /// Transform from substitutions for a child of `source_ancestor` 425 /// (e.g., a trait or impl) to substitutions for the same child 426 /// in a different item, with `target_substs` as the base for 427 /// the target impl/trait, with the source child-specific 428 /// parameters (e.g., method parameters) on top of that base. 429 /// 430 /// For example given: 431 /// 432 /// ```no_run 433 /// trait X<S> { fn f<T>(); } 434 /// impl<U> X<U> for U { fn f<V>() {} } 435 /// ``` 436 /// 437 /// * If `self` is `[Self, S, T]`: the identity substs of `f` in the trait. 438 /// * If `source_ancestor` is the def_id of the trait. 439 /// * If `target_substs` is `[U]`, the substs for the impl. 440 /// * Then we will return `[U, T]`, the subst for `f` in the impl that 441 /// are needed for it to match the trait. rebase_onto( &self, tcx: TyCtxt<'tcx>, source_ancestor: DefId, target_substs: SubstsRef<'tcx>, ) -> SubstsRef<'tcx>442 pub fn rebase_onto( 443 &self, 444 tcx: TyCtxt<'tcx>, 445 source_ancestor: DefId, 446 target_substs: SubstsRef<'tcx>, 447 ) -> SubstsRef<'tcx> { 448 let defs = tcx.generics_of(source_ancestor); 449 tcx.mk_substs_from_iter(target_substs.iter().chain(self.iter().skip(defs.params.len()))) 450 } 451 truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> SubstsRef<'tcx>452 pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> SubstsRef<'tcx> { 453 tcx.mk_substs_from_iter(self.iter().take(generics.count())) 454 } 455 host_effect_param(&'tcx self) -> Option<ty::Const<'tcx>>456 pub fn host_effect_param(&'tcx self) -> Option<ty::Const<'tcx>> { 457 self.consts().rfind(|x| matches!(x.kind(), ty::ConstKind::Param(p) if p.name == sym::host)) 458 } 459 } 460 461 impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for SubstsRef<'tcx> { try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( self, folder: &mut F, ) -> Result<Self, F::Error>462 fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( 463 self, 464 folder: &mut F, 465 ) -> Result<Self, F::Error> { 466 // This code is hot enough that it's worth specializing for the most 467 // common length lists, to avoid the overhead of `SmallVec` creation. 468 // The match arms are in order of frequency. The 1, 2, and 0 cases are 469 // typically hit in 90--99.99% of cases. When folding doesn't change 470 // the substs, it's faster to reuse the existing substs rather than 471 // calling `mk_substs`. 472 match self.len() { 473 1 => { 474 let param0 = self[0].try_fold_with(folder)?; 475 if param0 == self[0] { 476 Ok(self) 477 } else { 478 Ok(folder.interner().mk_substs(&[param0])) 479 } 480 } 481 2 => { 482 let param0 = self[0].try_fold_with(folder)?; 483 let param1 = self[1].try_fold_with(folder)?; 484 if param0 == self[0] && param1 == self[1] { 485 Ok(self) 486 } else { 487 Ok(folder.interner().mk_substs(&[param0, param1])) 488 } 489 } 490 0 => Ok(self), 491 _ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_substs(v)), 492 } 493 } 494 } 495 496 impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx>> { try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( self, folder: &mut F, ) -> Result<Self, F::Error>497 fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( 498 self, 499 folder: &mut F, 500 ) -> Result<Self, F::Error> { 501 // This code is fairly hot, though not as hot as `SubstsRef`. 502 // 503 // When compiling stage 2, I get the following results: 504 // 505 // len | total | % 506 // --- | --------- | ----- 507 // 2 | 15083590 | 48.1 508 // 3 | 7540067 | 24.0 509 // 1 | 5300377 | 16.9 510 // 4 | 1351897 | 4.3 511 // 0 | 1256849 | 4.0 512 // 513 // I've tried it with some private repositories and got 514 // close to the same result, with 4 and 0 swapping places 515 // sometimes. 516 match self.len() { 517 2 => { 518 let param0 = self[0].try_fold_with(folder)?; 519 let param1 = self[1].try_fold_with(folder)?; 520 if param0 == self[0] && param1 == self[1] { 521 Ok(self) 522 } else { 523 Ok(folder.interner().mk_type_list(&[param0, param1])) 524 } 525 } 526 _ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_type_list(v)), 527 } 528 } 529 } 530 531 impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for &'tcx ty::List<T> { 532 #[inline] visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy>533 fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { 534 self.iter().try_for_each(|t| t.visit_with(visitor)) 535 } 536 } 537 538 /// Similar to [`super::Binder`] except that it tracks early bound generics, i.e. `struct Foo<T>(T)` 539 /// needs `T` substituted immediately. This type primarily exists to avoid forgetting to call 540 /// `subst`. 541 /// 542 /// If you don't have anything to `subst`, you may be looking for 543 /// [`subst_identity`](EarlyBinder::subst_identity) or [`skip_binder`](EarlyBinder::skip_binder). 544 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] 545 #[derive(Encodable, Decodable, HashStable)] 546 pub struct EarlyBinder<T> { 547 value: T, 548 } 549 550 /// For early binders, you should first call `subst` before using any visitors. 551 impl<'tcx, T> !TypeFoldable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {} 552 impl<'tcx, T> !TypeVisitable<TyCtxt<'tcx>> for ty::EarlyBinder<T> {} 553 554 impl<T> EarlyBinder<T> { bind(value: T) -> EarlyBinder<T>555 pub fn bind(value: T) -> EarlyBinder<T> { 556 EarlyBinder { value } 557 } 558 as_ref(&self) -> EarlyBinder<&T>559 pub fn as_ref(&self) -> EarlyBinder<&T> { 560 EarlyBinder { value: &self.value } 561 } 562 map_bound_ref<F, U>(&self, f: F) -> EarlyBinder<U> where F: FnOnce(&T) -> U,563 pub fn map_bound_ref<F, U>(&self, f: F) -> EarlyBinder<U> 564 where 565 F: FnOnce(&T) -> U, 566 { 567 self.as_ref().map_bound(f) 568 } 569 map_bound<F, U>(self, f: F) -> EarlyBinder<U> where F: FnOnce(T) -> U,570 pub fn map_bound<F, U>(self, f: F) -> EarlyBinder<U> 571 where 572 F: FnOnce(T) -> U, 573 { 574 let value = f(self.value); 575 EarlyBinder { value } 576 } 577 try_map_bound<F, U, E>(self, f: F) -> Result<EarlyBinder<U>, E> where F: FnOnce(T) -> Result<U, E>,578 pub fn try_map_bound<F, U, E>(self, f: F) -> Result<EarlyBinder<U>, E> 579 where 580 F: FnOnce(T) -> Result<U, E>, 581 { 582 let value = f(self.value)?; 583 Ok(EarlyBinder { value }) 584 } 585 rebind<U>(&self, value: U) -> EarlyBinder<U>586 pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> { 587 EarlyBinder { value } 588 } 589 590 /// Skips the binder and returns the "bound" value. 591 /// This can be used to extract data that does not depend on generic parameters 592 /// (e.g., getting the `DefId` of the inner value or getting the number of 593 /// arguments of an `FnSig`). Otherwise, consider using 594 /// [`subst_identity`](EarlyBinder::subst_identity). 595 /// 596 /// To skip the binder on `x: &EarlyBinder<T>` to obtain `&T`, leverage 597 /// [`EarlyBinder::as_ref`](EarlyBinder::as_ref): `x.as_ref().skip_binder()`. 598 /// 599 /// See also [`Binder::skip_binder`](super::Binder::skip_binder), which is 600 /// the analogous operation on [`super::Binder`]. skip_binder(self) -> T601 pub fn skip_binder(self) -> T { 602 self.value 603 } 604 } 605 606 impl<T> EarlyBinder<Option<T>> { transpose(self) -> Option<EarlyBinder<T>>607 pub fn transpose(self) -> Option<EarlyBinder<T>> { 608 self.value.map(|value| EarlyBinder { value }) 609 } 610 } 611 612 impl<T, U> EarlyBinder<(T, U)> { transpose_tuple2(self) -> (EarlyBinder<T>, EarlyBinder<U>)613 pub fn transpose_tuple2(self) -> (EarlyBinder<T>, EarlyBinder<U>) { 614 let EarlyBinder { value: (lhs, rhs) } = self; 615 (EarlyBinder { value: lhs }, EarlyBinder { value: rhs }) 616 } 617 } 618 619 impl<'tcx, 's, I: IntoIterator> EarlyBinder<I> 620 where 621 I::Item: TypeFoldable<TyCtxt<'tcx>>, 622 { subst_iter( self, tcx: TyCtxt<'tcx>, substs: &'s [GenericArg<'tcx>], ) -> SubstIter<'s, 'tcx, I>623 pub fn subst_iter( 624 self, 625 tcx: TyCtxt<'tcx>, 626 substs: &'s [GenericArg<'tcx>], 627 ) -> SubstIter<'s, 'tcx, I> { 628 SubstIter { it: self.value.into_iter(), tcx, substs } 629 } 630 631 /// Similar to [`subst_identity`](EarlyBinder::subst_identity), 632 /// but on an iterator of `TypeFoldable` values. subst_identity_iter(self) -> I::IntoIter633 pub fn subst_identity_iter(self) -> I::IntoIter { 634 self.value.into_iter() 635 } 636 } 637 638 pub struct SubstIter<'s, 'tcx, I: IntoIterator> { 639 it: I::IntoIter, 640 tcx: TyCtxt<'tcx>, 641 substs: &'s [GenericArg<'tcx>], 642 } 643 644 impl<'tcx, I: IntoIterator> Iterator for SubstIter<'_, 'tcx, I> 645 where 646 I::Item: TypeFoldable<TyCtxt<'tcx>>, 647 { 648 type Item = I::Item; 649 next(&mut self) -> Option<Self::Item>650 fn next(&mut self) -> Option<Self::Item> { 651 Some(EarlyBinder { value: self.it.next()? }.subst(self.tcx, self.substs)) 652 } 653 size_hint(&self) -> (usize, Option<usize>)654 fn size_hint(&self) -> (usize, Option<usize>) { 655 self.it.size_hint() 656 } 657 } 658 659 impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIter<'_, 'tcx, I> 660 where 661 I::IntoIter: DoubleEndedIterator, 662 I::Item: TypeFoldable<TyCtxt<'tcx>>, 663 { next_back(&mut self) -> Option<Self::Item>664 fn next_back(&mut self) -> Option<Self::Item> { 665 Some(EarlyBinder { value: self.it.next_back()? }.subst(self.tcx, self.substs)) 666 } 667 } 668 669 impl<'tcx, I: IntoIterator> ExactSizeIterator for SubstIter<'_, 'tcx, I> 670 where 671 I::IntoIter: ExactSizeIterator, 672 I::Item: TypeFoldable<TyCtxt<'tcx>>, 673 { 674 } 675 676 impl<'tcx, 's, I: IntoIterator> EarlyBinder<I> 677 where 678 I::Item: Deref, 679 <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>, 680 { subst_iter_copied( self, tcx: TyCtxt<'tcx>, substs: &'s [GenericArg<'tcx>], ) -> SubstIterCopied<'s, 'tcx, I>681 pub fn subst_iter_copied( 682 self, 683 tcx: TyCtxt<'tcx>, 684 substs: &'s [GenericArg<'tcx>], 685 ) -> SubstIterCopied<'s, 'tcx, I> { 686 SubstIterCopied { it: self.value.into_iter(), tcx, substs } 687 } 688 689 /// Similar to [`subst_identity`](EarlyBinder::subst_identity), 690 /// but on an iterator of values that deref to a `TypeFoldable`. subst_identity_iter_copied(self) -> impl Iterator<Item = <I::Item as Deref>::Target>691 pub fn subst_identity_iter_copied(self) -> impl Iterator<Item = <I::Item as Deref>::Target> { 692 self.value.into_iter().map(|v| *v) 693 } 694 } 695 696 pub struct SubstIterCopied<'a, 'tcx, I: IntoIterator> { 697 it: I::IntoIter, 698 tcx: TyCtxt<'tcx>, 699 substs: &'a [GenericArg<'tcx>], 700 } 701 702 impl<'tcx, I: IntoIterator> Iterator for SubstIterCopied<'_, 'tcx, I> 703 where 704 I::Item: Deref, 705 <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>, 706 { 707 type Item = <I::Item as Deref>::Target; 708 next(&mut self) -> Option<Self::Item>709 fn next(&mut self) -> Option<Self::Item> { 710 self.it.next().map(|value| EarlyBinder { value: *value }.subst(self.tcx, self.substs)) 711 } 712 size_hint(&self) -> (usize, Option<usize>)713 fn size_hint(&self) -> (usize, Option<usize>) { 714 self.it.size_hint() 715 } 716 } 717 718 impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIterCopied<'_, 'tcx, I> 719 where 720 I::IntoIter: DoubleEndedIterator, 721 I::Item: Deref, 722 <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>, 723 { next_back(&mut self) -> Option<Self::Item>724 fn next_back(&mut self) -> Option<Self::Item> { 725 self.it.next_back().map(|value| EarlyBinder { value: *value }.subst(self.tcx, self.substs)) 726 } 727 } 728 729 impl<'tcx, I: IntoIterator> ExactSizeIterator for SubstIterCopied<'_, 'tcx, I> 730 where 731 I::IntoIter: ExactSizeIterator, 732 I::Item: Deref, 733 <I::Item as Deref>::Target: Copy + TypeFoldable<TyCtxt<'tcx>>, 734 { 735 } 736 737 pub struct EarlyBinderIter<T> { 738 t: T, 739 } 740 741 impl<T: IntoIterator> EarlyBinder<T> { transpose_iter(self) -> EarlyBinderIter<T::IntoIter>742 pub fn transpose_iter(self) -> EarlyBinderIter<T::IntoIter> { 743 EarlyBinderIter { t: self.value.into_iter() } 744 } 745 } 746 747 impl<T: Iterator> Iterator for EarlyBinderIter<T> { 748 type Item = EarlyBinder<T::Item>; 749 next(&mut self) -> Option<Self::Item>750 fn next(&mut self) -> Option<Self::Item> { 751 self.t.next().map(|value| EarlyBinder { value }) 752 } 753 size_hint(&self) -> (usize, Option<usize>)754 fn size_hint(&self) -> (usize, Option<usize>) { 755 self.t.size_hint() 756 } 757 } 758 759 impl<'tcx, T: TypeFoldable<TyCtxt<'tcx>>> ty::EarlyBinder<T> { subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> T760 pub fn subst(self, tcx: TyCtxt<'tcx>, substs: &[GenericArg<'tcx>]) -> T { 761 let mut folder = SubstFolder { tcx, substs, binders_passed: 0 }; 762 self.value.fold_with(&mut folder) 763 } 764 765 /// Makes the identity substitution `T0 => T0, ..., TN => TN`. 766 /// Conceptually, this converts universally bound variables into placeholders 767 /// when inside of a given item. 768 /// 769 /// For example, consider `for<T> fn foo<T>(){ .. }`: 770 /// - Outside of `foo`, `T` is bound (represented by the presence of `EarlyBinder`). 771 /// - Inside of the body of `foo`, we treat `T` as a placeholder by calling 772 /// `subst_identity` to discharge the `EarlyBinder`. subst_identity(self) -> T773 pub fn subst_identity(self) -> T { 774 self.value 775 } 776 777 /// Returns the inner value, but only if it contains no bound vars. no_bound_vars(self) -> Option<T>778 pub fn no_bound_vars(self) -> Option<T> { 779 if !self.value.has_param() { Some(self.value) } else { None } 780 } 781 } 782 783 /////////////////////////////////////////////////////////////////////////// 784 // The actual substitution engine itself is a type folder. 785 786 struct SubstFolder<'a, 'tcx> { 787 tcx: TyCtxt<'tcx>, 788 substs: &'a [GenericArg<'tcx>], 789 790 /// Number of region binders we have passed through while doing the substitution 791 binders_passed: u32, 792 } 793 794 impl<'a, 'tcx> TypeFolder<TyCtxt<'tcx>> for SubstFolder<'a, 'tcx> { 795 #[inline] interner(&self) -> TyCtxt<'tcx>796 fn interner(&self) -> TyCtxt<'tcx> { 797 self.tcx 798 } 799 fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>( &mut self, t: ty::Binder<'tcx, T>, ) -> ty::Binder<'tcx, T>800 fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>( 801 &mut self, 802 t: ty::Binder<'tcx, T>, 803 ) -> ty::Binder<'tcx, T> { 804 self.binders_passed += 1; 805 let t = t.super_fold_with(self); 806 self.binders_passed -= 1; 807 t 808 } 809 fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx>810 fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { 811 #[cold] 812 #[inline(never)] 813 fn region_param_out_of_range(data: ty::EarlyBoundRegion, substs: &[GenericArg<'_>]) -> ! { 814 bug!( 815 "Region parameter out of range when substituting in region {} (index={}, substs = {:?})", 816 data.name, 817 data.index, 818 substs, 819 ) 820 } 821 822 #[cold] 823 #[inline(never)] 824 fn region_param_invalid(data: ty::EarlyBoundRegion, other: GenericArgKind<'_>) -> ! { 825 bug!( 826 "Unexpected parameter {:?} when substituting in region {} (index={})", 827 other, 828 data.name, 829 data.index 830 ) 831 } 832 833 // Note: This routine only handles regions that are bound on 834 // type declarations and other outer declarations, not those 835 // bound in *fn types*. Region substitution of the bound 836 // regions that appear in a function signature is done using 837 // the specialized routine `ty::replace_late_regions()`. 838 match *r { 839 ty::ReEarlyBound(data) => { 840 let rk = self.substs.get(data.index as usize).map(|k| k.unpack()); 841 match rk { 842 Some(GenericArgKind::Lifetime(lt)) => self.shift_region_through_binders(lt), 843 Some(other) => region_param_invalid(data, other), 844 None => region_param_out_of_range(data, self.substs), 845 } 846 } 847 ty::ReLateBound(..) 848 | ty::ReFree(_) 849 | ty::ReStatic 850 | ty::RePlaceholder(_) 851 | ty::ReErased 852 | ty::ReError(_) => r, 853 ty::ReVar(_) => bug!("unexpected region: {r:?}"), 854 } 855 } 856 fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx>857 fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { 858 if !t.has_param() { 859 return t; 860 } 861 862 match *t.kind() { 863 ty::Param(p) => self.ty_for_param(p, t), 864 _ => t.super_fold_with(self), 865 } 866 } 867 fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx>868 fn fold_const(&mut self, c: ty::Const<'tcx>) -> ty::Const<'tcx> { 869 if let ty::ConstKind::Param(p) = c.kind() { 870 self.const_for_param(p, c) 871 } else { 872 c.super_fold_with(self) 873 } 874 } 875 } 876 877 impl<'a, 'tcx> SubstFolder<'a, 'tcx> { ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx>878 fn ty_for_param(&self, p: ty::ParamTy, source_ty: Ty<'tcx>) -> Ty<'tcx> { 879 // Look up the type in the substitutions. It really should be in there. 880 let opt_ty = self.substs.get(p.index as usize).map(|k| k.unpack()); 881 let ty = match opt_ty { 882 Some(GenericArgKind::Type(ty)) => ty, 883 Some(kind) => self.type_param_expected(p, source_ty, kind), 884 None => self.type_param_out_of_range(p, source_ty), 885 }; 886 887 self.shift_vars_through_binders(ty) 888 } 889 890 #[cold] 891 #[inline(never)] type_param_expected(&self, p: ty::ParamTy, ty: Ty<'tcx>, kind: GenericArgKind<'tcx>) -> !892 fn type_param_expected(&self, p: ty::ParamTy, ty: Ty<'tcx>, kind: GenericArgKind<'tcx>) -> ! { 893 bug!( 894 "expected type for `{:?}` ({:?}/{}) but found {:?} when substituting, substs={:?}", 895 p, 896 ty, 897 p.index, 898 kind, 899 self.substs, 900 ) 901 } 902 903 #[cold] 904 #[inline(never)] type_param_out_of_range(&self, p: ty::ParamTy, ty: Ty<'tcx>) -> !905 fn type_param_out_of_range(&self, p: ty::ParamTy, ty: Ty<'tcx>) -> ! { 906 bug!( 907 "type parameter `{:?}` ({:?}/{}) out of range when substituting, substs={:?}", 908 p, 909 ty, 910 p.index, 911 self.substs, 912 ) 913 } 914 const_for_param(&self, p: ParamConst, source_ct: ty::Const<'tcx>) -> ty::Const<'tcx>915 fn const_for_param(&self, p: ParamConst, source_ct: ty::Const<'tcx>) -> ty::Const<'tcx> { 916 // Look up the const in the substitutions. It really should be in there. 917 let opt_ct = self.substs.get(p.index as usize).map(|k| k.unpack()); 918 let ct = match opt_ct { 919 Some(GenericArgKind::Const(ct)) => ct, 920 Some(kind) => self.const_param_expected(p, source_ct, kind), 921 None => self.const_param_out_of_range(p, source_ct), 922 }; 923 924 self.shift_vars_through_binders(ct) 925 } 926 927 #[cold] 928 #[inline(never)] const_param_expected( &self, p: ty::ParamConst, ct: ty::Const<'tcx>, kind: GenericArgKind<'tcx>, ) -> !929 fn const_param_expected( 930 &self, 931 p: ty::ParamConst, 932 ct: ty::Const<'tcx>, 933 kind: GenericArgKind<'tcx>, 934 ) -> ! { 935 bug!( 936 "expected const for `{:?}` ({:?}/{}) but found {:?} when substituting substs={:?}", 937 p, 938 ct, 939 p.index, 940 kind, 941 self.substs, 942 ) 943 } 944 945 #[cold] 946 #[inline(never)] const_param_out_of_range(&self, p: ty::ParamConst, ct: ty::Const<'tcx>) -> !947 fn const_param_out_of_range(&self, p: ty::ParamConst, ct: ty::Const<'tcx>) -> ! { 948 bug!( 949 "const parameter `{:?}` ({:?}/{}) out of range when substituting substs={:?}", 950 p, 951 ct, 952 p.index, 953 self.substs, 954 ) 955 } 956 957 /// It is sometimes necessary to adjust the De Bruijn indices during substitution. This occurs 958 /// when we are substituting a type with escaping bound vars into a context where we have 959 /// passed through binders. That's quite a mouthful. Let's see an example: 960 /// 961 /// ``` 962 /// type Func<A> = fn(A); 963 /// type MetaFunc = for<'a> fn(Func<&'a i32>); 964 /// ``` 965 /// 966 /// The type `MetaFunc`, when fully expanded, will be 967 /// ```ignore (illustrative) 968 /// for<'a> fn(fn(&'a i32)) 969 /// // ^~ ^~ ^~~ 970 /// // | | | 971 /// // | | DebruijnIndex of 2 972 /// // Binders 973 /// ``` 974 /// Here the `'a` lifetime is bound in the outer function, but appears as an argument of the 975 /// inner one. Therefore, that appearance will have a DebruijnIndex of 2, because we must skip 976 /// over the inner binder (remember that we count De Bruijn indices from 1). However, in the 977 /// definition of `MetaFunc`, the binder is not visible, so the type `&'a i32` will have a 978 /// De Bruijn index of 1. It's only during the substitution that we can see we must increase the 979 /// depth by 1 to account for the binder that we passed through. 980 /// 981 /// As a second example, consider this twist: 982 /// 983 /// ``` 984 /// type FuncTuple<A> = (A,fn(A)); 985 /// type MetaFuncTuple = for<'a> fn(FuncTuple<&'a i32>); 986 /// ``` 987 /// 988 /// Here the final type will be: 989 /// ```ignore (illustrative) 990 /// for<'a> fn((&'a i32, fn(&'a i32))) 991 /// // ^~~ ^~~ 992 /// // | | 993 /// // DebruijnIndex of 1 | 994 /// // DebruijnIndex of 2 995 /// ``` 996 /// As indicated in the diagram, here the same type `&'a i32` is substituted once, but in the 997 /// first case we do not increase the De Bruijn index and in the second case we do. The reason 998 /// is that only in the second case have we passed through a fn binder. shift_vars_through_binders<T: TypeFoldable<TyCtxt<'tcx>>>(&self, val: T) -> T999 fn shift_vars_through_binders<T: TypeFoldable<TyCtxt<'tcx>>>(&self, val: T) -> T { 1000 debug!( 1001 "shift_vars(val={:?}, binders_passed={:?}, has_escaping_bound_vars={:?})", 1002 val, 1003 self.binders_passed, 1004 val.has_escaping_bound_vars() 1005 ); 1006 1007 if self.binders_passed == 0 || !val.has_escaping_bound_vars() { 1008 return val; 1009 } 1010 1011 let result = ty::fold::shift_vars(TypeFolder::interner(self), val, self.binders_passed); 1012 debug!("shift_vars: shifted result = {:?}", result); 1013 1014 result 1015 } 1016 shift_region_through_binders(&self, region: ty::Region<'tcx>) -> ty::Region<'tcx>1017 fn shift_region_through_binders(&self, region: ty::Region<'tcx>) -> ty::Region<'tcx> { 1018 if self.binders_passed == 0 || !region.has_escaping_bound_vars() { 1019 return region; 1020 } 1021 ty::fold::shift_region(self.tcx, region, self.binders_passed) 1022 } 1023 } 1024 1025 /// Stores the user-given substs to reach some fully qualified path 1026 /// (e.g., `<T>::Item` or `<T as Trait>::Item`). 1027 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] 1028 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] 1029 pub struct UserSubsts<'tcx> { 1030 /// The substitutions for the item as given by the user. 1031 pub substs: SubstsRef<'tcx>, 1032 1033 /// The self type, in the case of a `<T>::Item` path (when applied 1034 /// to an inherent impl). See `UserSelfTy` below. 1035 pub user_self_ty: Option<UserSelfTy<'tcx>>, 1036 } 1037 1038 /// Specifies the user-given self type. In the case of a path that 1039 /// refers to a member in an inherent impl, this self type is 1040 /// sometimes needed to constrain the type parameters on the impl. For 1041 /// example, in this code: 1042 /// 1043 /// ```ignore (illustrative) 1044 /// struct Foo<T> { } 1045 /// impl<A> Foo<A> { fn method() { } } 1046 /// ``` 1047 /// 1048 /// when you then have a path like `<Foo<&'static u32>>::method`, 1049 /// this struct would carry the `DefId` of the impl along with the 1050 /// self type `Foo<u32>`. Then we can instantiate the parameters of 1051 /// the impl (with the substs from `UserSubsts`) and apply those to 1052 /// the self type, giving `Foo<?A>`. Finally, we unify that with 1053 /// the self type here, which contains `?A` to be `&'static u32` 1054 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)] 1055 #[derive(HashStable, TypeFoldable, TypeVisitable, Lift)] 1056 pub struct UserSelfTy<'tcx> { 1057 pub impl_def_id: DefId, 1058 pub self_ty: Ty<'tcx>, 1059 } 1060