diff options
Diffstat (limited to 'compiler/rustc_middle/src/ty/subst.rs')
-rw-r--r-- | compiler/rustc_middle/src/ty/subst.rs | 125 |
1 files changed, 113 insertions, 12 deletions
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 0660e9b79..a1b084a5e 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -6,11 +6,11 @@ use crate::ty::sty::{ClosureSubsts, GeneratorSubsts, InlineConstSubsts}; use crate::ty::visit::{TypeVisitable, TypeVisitor}; use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt}; -use rustc_data_structures::captures::Captures; -use rustc_data_structures::intern::{Interned, WithStableHash}; +use rustc_data_structures::intern::Interned; use rustc_hir::def_id::DefId; use rustc_macros::HashStable; use rustc_serialize::{self, Decodable, Encodable}; +use rustc_type_ir::WithCachedTypeInfo; use smallvec::SmallVec; use core::intrinsics; @@ -19,7 +19,7 @@ use std::fmt; use std::marker::PhantomData; use std::mem; use std::num::NonZeroUsize; -use std::ops::ControlFlow; +use std::ops::{ControlFlow, Deref}; use std::slice; /// An entity in the Rust type system, which can be one of @@ -85,7 +85,7 @@ impl<'tcx> GenericArgKind<'tcx> { GenericArgKind::Type(ty) => { // Ensure we can use the tag bits. assert_eq!(mem::align_of_val(&*ty.0.0) & TAG_MASK, 0); - (TYPE_TAG, ty.0.0 as *const WithStableHash<ty::TyS<'tcx>> as usize) + (TYPE_TAG, ty.0.0 as *const WithCachedTypeInfo<ty::TyKind<'tcx>> as usize) } GenericArgKind::Const(ct) => { // Ensure we can use the tag bits. @@ -141,6 +141,15 @@ impl<'tcx> From<ty::Const<'tcx>> for GenericArg<'tcx> { } } +impl<'tcx> From<ty::Term<'tcx>> for GenericArg<'tcx> { + fn from(value: ty::Term<'tcx>) -> Self { + match value.unpack() { + ty::TermKind::Ty(t) => t.into(), + ty::TermKind::Const(c) => c.into(), + } + } +} + impl<'tcx> GenericArg<'tcx> { #[inline] pub fn unpack(self) -> GenericArgKind<'tcx> { @@ -154,7 +163,7 @@ impl<'tcx> GenericArg<'tcx> { &*((ptr & !TAG_MASK) as *const ty::RegionKind<'tcx>), ))), TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked( - &*((ptr & !TAG_MASK) as *const WithStableHash<ty::TyS<'tcx>>), + &*((ptr & !TAG_MASK) as *const WithCachedTypeInfo<ty::TyKind<'tcx>>), ))), CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked( &*((ptr & !TAG_MASK) as *const ty::ConstS<'tcx>), @@ -344,6 +353,22 @@ impl<'tcx> InternalSubsts<'tcx> { } } + // Extend an `original_substs` list to the full number of substs expected by `def_id`, + // filling in the missing parameters with error ty/ct or 'static regions. + pub fn extend_with_error( + tcx: TyCtxt<'tcx>, + def_id: DefId, + original_substs: &[GenericArg<'tcx>], + ) -> SubstsRef<'tcx> { + ty::InternalSubsts::for_item(tcx, def_id, |def, substs| { + if let Some(subst) = original_substs.get(def.index as usize) { + *subst + } else { + def.to_error(tcx, substs) + } + }) + } + #[inline] pub fn types(&'tcx self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> + 'tcx { self.iter() @@ -506,6 +531,9 @@ impl<'tcx, T: TypeVisitable<'tcx>> TypeVisitable<'tcx> for &'tcx ty::List<T> { } } +/// Similar to [`super::Binder`] except that it tracks early bound generics, i.e. `struct Foo<T>(T)` +/// needs `T` substituted immediately. This type primarily exists to avoid forgetting to call +/// `subst`. #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] #[derive(Encodable, Decodable, HashStable)] pub struct EarlyBinder<T>(pub T); @@ -559,25 +587,94 @@ impl<T, U> EarlyBinder<(T, U)> { } } -impl<'tcx, 's, T: IntoIterator<Item = I>, I: TypeFoldable<'tcx>> EarlyBinder<T> { +impl<'tcx, 's, I: IntoIterator> EarlyBinder<I> +where + I::Item: TypeFoldable<'tcx>, +{ pub fn subst_iter( self, tcx: TyCtxt<'tcx>, substs: &'s [GenericArg<'tcx>], - ) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> { - self.0.into_iter().map(move |t| EarlyBinder(t).subst(tcx, substs)) + ) -> SubstIter<'s, 'tcx, I> { + SubstIter { it: self.0.into_iter(), tcx, substs } + } +} + +pub struct SubstIter<'s, 'tcx, I: IntoIterator> { + it: I::IntoIter, + tcx: TyCtxt<'tcx>, + substs: &'s [GenericArg<'tcx>], +} + +impl<'tcx, I: IntoIterator> Iterator for SubstIter<'_, 'tcx, I> +where + I::Item: TypeFoldable<'tcx>, +{ + type Item = I::Item; + + fn next(&mut self) -> Option<Self::Item> { + Some(EarlyBinder(self.it.next()?).subst(self.tcx, self.substs)) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.it.size_hint() } } -impl<'tcx, 's, 'a, T: IntoIterator<Item = &'a I>, I: Copy + TypeFoldable<'tcx> + 'a> - EarlyBinder<T> +impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIter<'_, 'tcx, I> +where + I::IntoIter: DoubleEndedIterator, + I::Item: TypeFoldable<'tcx>, +{ + fn next_back(&mut self) -> Option<Self::Item> { + Some(EarlyBinder(self.it.next_back()?).subst(self.tcx, self.substs)) + } +} + +impl<'tcx, 's, I: IntoIterator> EarlyBinder<I> +where + I::Item: Deref, + <I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>, { pub fn subst_iter_copied( self, tcx: TyCtxt<'tcx>, substs: &'s [GenericArg<'tcx>], - ) -> impl Iterator<Item = I> + Captures<'s> + Captures<'tcx> + Captures<'a> { - self.0.into_iter().map(move |t| EarlyBinder(*t).subst(tcx, substs)) + ) -> SubstIterCopied<'s, 'tcx, I> { + SubstIterCopied { it: self.0.into_iter(), tcx, substs } + } +} + +pub struct SubstIterCopied<'a, 'tcx, I: IntoIterator> { + it: I::IntoIter, + tcx: TyCtxt<'tcx>, + substs: &'a [GenericArg<'tcx>], +} + +impl<'tcx, I: IntoIterator> Iterator for SubstIterCopied<'_, 'tcx, I> +where + I::Item: Deref, + <I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>, +{ + type Item = <I::Item as Deref>::Target; + + fn next(&mut self) -> Option<Self::Item> { + Some(EarlyBinder(*self.it.next()?).subst(self.tcx, self.substs)) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.it.size_hint() + } +} + +impl<'tcx, I: IntoIterator> DoubleEndedIterator for SubstIterCopied<'_, 'tcx, I> +where + I::IntoIter: DoubleEndedIterator, + I::Item: Deref, + <I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>, +{ + fn next_back(&mut self) -> Option<Self::Item> { + Some(EarlyBinder(*self.it.next_back()?).subst(self.tcx, self.substs)) } } @@ -597,6 +694,10 @@ impl<T: Iterator> Iterator for EarlyBinderIter<T> { fn next(&mut self) -> Option<Self::Item> { self.t.next().map(|i| EarlyBinder(i)) } + + fn size_hint(&self) -> (usize, Option<usize>) { + self.t.size_hint() + } } impl<'tcx, T: TypeFoldable<'tcx>> ty::EarlyBinder<T> { |