summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_middle/src/ty/subst.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_middle/src/ty/subst.rs')
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs63
1 files changed, 58 insertions, 5 deletions
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index a1b084a5e..a07582fc8 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -7,6 +7,7 @@ use crate::ty::visit::{TypeVisitable, TypeVisitor};
use crate::ty::{self, Lift, List, ParamConst, Ty, TyCtxt};
use rustc_data_structures::intern::Interned;
+use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
use rustc_hir::def_id::DefId;
use rustc_macros::HashStable;
use rustc_serialize::{self, Decodable, Encodable};
@@ -36,6 +37,12 @@ pub struct GenericArg<'tcx> {
marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>)>,
}
+impl<'tcx> IntoDiagnosticArg for GenericArg<'tcx> {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ self.to_string().into_diagnostic_arg()
+ }
+}
+
const TAG_MASK: usize = 0b11;
const TYPE_TAG: usize = 0b00;
const REGION_TAG: usize = 0b01;
@@ -90,7 +97,7 @@ impl<'tcx> GenericArgKind<'tcx> {
GenericArgKind::Const(ct) => {
// Ensure we can use the tag bits.
assert_eq!(mem::align_of_val(&*ct.0.0) & TAG_MASK, 0);
- (CONST_TAG, ct.0.0 as *const ty::ConstS<'tcx> as usize)
+ (CONST_TAG, ct.0.0 as *const ty::ConstData<'tcx> as usize)
}
};
@@ -166,7 +173,7 @@ impl<'tcx> GenericArg<'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>),
+ &*((ptr & !TAG_MASK) as *const ty::ConstData<'tcx>),
))),
_ => intrinsics::unreachable(),
}
@@ -202,7 +209,7 @@ impl<'tcx> GenericArg<'tcx> {
pub fn is_non_region_infer(self) -> bool {
match self.unpack() {
GenericArgKind::Lifetime(_) => false,
- GenericArgKind::Type(ty) => ty.is_ty_infer(),
+ GenericArgKind::Type(ty) => ty.is_ty_or_numeric_infer(),
GenericArgKind::Const(ct) => ct.is_ct_infer(),
}
}
@@ -252,7 +259,7 @@ impl<'tcx, D: TyDecoder<I = TyCtxt<'tcx>>> Decodable<D> for GenericArg<'tcx> {
}
}
-/// A substitution mapping generic parameters to new values.
+/// List of generic arguments that are gonna be used to substitute generic parameters.
pub type InternalSubsts<'tcx> = List<GenericArg<'tcx>>;
pub type SubstsRef<'tcx> = &'tcx InternalSubsts<'tcx>;
@@ -348,7 +355,7 @@ impl<'tcx> InternalSubsts<'tcx> {
substs.reserve(defs.params.len());
for param in &defs.params {
let kind = mk_kind(param, substs);
- assert_eq!(param.index as usize, substs.len());
+ assert_eq!(param.index as usize, substs.len(), "{substs:#?}, {defs:#?}");
substs.push(kind);
}
}
@@ -400,6 +407,7 @@ impl<'tcx> InternalSubsts<'tcx> {
}
#[inline]
+ #[track_caller]
pub fn type_at(&self, i: usize) -> Ty<'tcx> {
if let GenericArgKind::Type(ty) = self[i].unpack() {
ty
@@ -409,6 +417,7 @@ impl<'tcx> InternalSubsts<'tcx> {
}
#[inline]
+ #[track_caller]
pub fn region_at(&self, i: usize) -> ty::Region<'tcx> {
if let GenericArgKind::Lifetime(lt) = self[i].unpack() {
lt
@@ -418,6 +427,7 @@ impl<'tcx> InternalSubsts<'tcx> {
}
#[inline]
+ #[track_caller]
pub fn const_at(&self, i: usize) -> ty::Const<'tcx> {
if let GenericArgKind::Const(ct) = self[i].unpack() {
ct
@@ -427,6 +437,7 @@ impl<'tcx> InternalSubsts<'tcx> {
}
#[inline]
+ #[track_caller]
pub fn type_for_def(&self, def: &ty::GenericParamDef) -> GenericArg<'tcx> {
self.type_at(def.index as usize).into()
}
@@ -534,6 +545,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`.
+///
+/// If you don't have anything to `subst`, you may be looking for
+/// [`subst_identity`](EarlyBinder::subst_identity) or [`skip_binder`](EarlyBinder::skip_binder).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[derive(Encodable, Decodable, HashStable)]
pub struct EarlyBinder<T>(pub T);
@@ -573,6 +587,18 @@ impl<T> EarlyBinder<T> {
pub fn rebind<U>(&self, value: U) -> EarlyBinder<U> {
EarlyBinder(value)
}
+
+ /// Skips the binder and returns the "bound" value.
+ /// This can be used to extract data that does not depend on generic parameters
+ /// (e.g., getting the `DefId` of the inner value or getting the number of
+ /// arguments of an `FnSig`). Otherwise, consider using
+ /// [`subst_identity`](EarlyBinder::subst_identity).
+ ///
+ /// See also [`Binder::skip_binder`](super::Binder::skip_binder), which is
+ /// the analogous operation on [`super::Binder`].
+ pub fn skip_binder(self) -> T {
+ self.0
+ }
}
impl<T> EarlyBinder<Option<T>> {
@@ -631,6 +657,13 @@ where
}
}
+impl<'tcx, I: IntoIterator> ExactSizeIterator for SubstIter<'_, 'tcx, I>
+where
+ I::IntoIter: ExactSizeIterator,
+ I::Item: TypeFoldable<'tcx>,
+{
+}
+
impl<'tcx, 's, I: IntoIterator> EarlyBinder<I>
where
I::Item: Deref,
@@ -678,6 +711,14 @@ where
}
}
+impl<'tcx, I: IntoIterator> ExactSizeIterator for SubstIterCopied<'_, 'tcx, I>
+where
+ I::IntoIter: ExactSizeIterator,
+ I::Item: Deref,
+ <I::Item as Deref>::Target: Copy + TypeFoldable<'tcx>,
+{
+}
+
pub struct EarlyBinderIter<T> {
t: T,
}
@@ -705,6 +746,18 @@ impl<'tcx, T: TypeFoldable<'tcx>> ty::EarlyBinder<T> {
let mut folder = SubstFolder { tcx, substs, binders_passed: 0 };
self.0.fold_with(&mut folder)
}
+
+ /// Makes the identity substitution `T0 => T0, ..., TN => TN`.
+ /// Conceptually, this converts universally bound variables into placeholders
+ /// when inside of a given item.
+ ///
+ /// For example, consider `for<T> fn foo<T>(){ .. }`:
+ /// - Outside of `foo`, `T` is bound (represented by the presence of `EarlyBinder`).
+ /// - Inside of the body of `foo`, we treat `T` as a placeholder by calling
+ /// `subst_identity` to discharge the `EarlyBinder`.
+ pub fn subst_identity(self) -> T {
+ self.0
+ }
}
///////////////////////////////////////////////////////////////////////////