use std::hash::Hash;
use std::{fmt, iter};
use derive_where::derive_where;
#[cfg(feature = "nightly")]
use rustc_macros::{Decodable_NoContext, Encodable_NoContext, StableHash, StableHash_NoContext};
use rustc_type_ir_macros::{
GenericTypeVisitable, Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic,
};
use crate::inherent::*;
use crate::lift::Lift;
use crate::upcast::{Upcast, UpcastFrom};
use crate::visit::TypeVisitableExt as _;
use crate::{self as ty, AliasTyKind, Interner};
#[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, A)]
#[derive_where(Copy; I: Interner, A: Copy)]
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic)]
#[cfg_attr(
feature = "nightly",
derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext)
)]
pub struct OutlivesPredicate<I: Interner, A>(pub A, pub I::Region);
impl<I: Interner, A: Eq> Eq for OutlivesPredicate<I, A> {}
impl<I: Interner, U: Interner, A> Lift<U> for OutlivesPredicate<I, A>
where
A: Lift<U>,
I::Region: Lift<U, Lifted = U::Region>,
{
type Lifted = OutlivesPredicate<U, A::Lifted>;
fn lift_to_interner(self, cx: U) -> Self::Lifted {
OutlivesPredicate(self.0.lift_to_interner(cx), self.1.lift_to_interner(cx))
}
}
#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(
feature = "nightly",
derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext)
)]
pub struct RegionEqPredicate<I: Interner>(pub I::Region, pub I::Region);
impl<I: Interner> RegionEqPredicate<I> {
pub fn into_bidirectional_outlives(self) -> [OutlivesPredicate<I, I::GenericArg>; 2] {
[OutlivesPredicate(self.0.into(), self.1), OutlivesPredicate(self.1.into(), self.0)]
}
}
#[derive_where(Clone, Copy, Hash, PartialEq, Eq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(
feature = "nightly",
derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext)
)]
pub enum RegionConstraint<I: Interner> {
Outlives(OutlivesPredicate<I, I::GenericArg>),
Eq(RegionEqPredicate<I>),
}
impl<I: Interner> From<OutlivesPredicate<I, I::GenericArg>> for RegionConstraint<I> {
fn from(value: OutlivesPredicate<I, I::GenericArg>) -> Self {
RegionConstraint::Outlives(value)
}
}
impl<I: Interner> From<RegionEqPredicate<I>> for RegionConstraint<I> {
fn from(value: RegionEqPredicate<I>) -> Self {
RegionConstraint::Eq(value)
}
}
impl<I: Interner> RegionConstraint<I> {
pub fn is_trivial(self) -> bool {
match self {
RegionConstraint::Outlives(outlives) => {
outlives.0.as_region().is_some_and(|re| re == outlives.1)
}
RegionConstraint::Eq(eq) => eq.0 == eq.1,
}
}
pub fn iter_outlives(self) -> impl Iterator<Item = OutlivesPredicate<I, I::GenericArg>> {
match self {
RegionConstraint::Outlives(outlives) => iter::once(outlives).chain(None),
RegionConstraint::Eq(eq) => {
let [outlives1, outlives2] = eq.into_bidirectional_outlives();
iter::once(outlives1).chain(Some(outlives2))
}
}
}
}
#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(
feature = "nightly",
derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext)
)]
pub struct TraitRef<I: Interner> {
pub def_id: I::TraitId,
pub args: I::GenericArgs,
_use_trait_ref_new_instead: (),
}
impl<I: Interner> Eq for TraitRef<I> {}
impl<I: Interner> TraitRef<I> {
pub fn new_from_args(interner: I, trait_def_id: I::TraitId, args: I::GenericArgs) -> Self {
interner.debug_assert_args_compatible(trait_def_id.into(), args);
Self { def_id: trait_def_id, args, _use_trait_ref_new_instead: () }
}
pub fn new(
interner: I,
trait_def_id: I::TraitId,
args: impl IntoIterator<Item: Into<I::GenericArg>>,
) -> Self {
let args = interner.mk_args_from_iter(args.into_iter().map(Into::into));
Self::new_from_args(interner, trait_def_id, args)
}
pub fn from_assoc(interner: I, trait_id: I::TraitId, args: I::GenericArgs) -> TraitRef<I> {
let generics = interner.generics_of(trait_id.into());
TraitRef::new(interner, trait_id, args.iter().take(generics.count()))
}
pub fn identity(interner: I, def_id: I::TraitId) -> TraitRef<I> {
TraitRef::new_from_args(
interner,
def_id,
I::GenericArgs::identity_for_item(interner, def_id.into()),
)
}
pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
TraitRef::new(
interner,
self.def_id,
[self_ty.into()].into_iter().chain(self.args.iter().skip(1)),
)
}
#[inline]
pub fn self_ty(&self) -> I::Ty {
self.args.type_at(0)
}
}
impl<I: Interner> ty::Binder<I, TraitRef<I>> {
pub fn self_ty(&self) -> ty::Binder<I, I::Ty> {
self.map_bound_ref(|tr| tr.self_ty())
}
pub fn def_id(&self) -> I::TraitId {
self.skip_binder().def_id
}
pub fn to_host_effect_clause(self, cx: I, constness: BoundConstness) -> I::Clause {
self.map_bound(|trait_ref| {
ty::ClauseKind::HostEffect(HostEffectPredicate { trait_ref, constness })
})
.upcast(cx)
}
}
#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(
feature = "nightly",
derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext)
)]
pub struct TraitPredicate<I: Interner> {
pub trait_ref: TraitRef<I>,
pub polarity: PredicatePolarity,
}
impl<I: Interner> Eq for TraitPredicate<I> {}
impl<I: Interner> TraitPredicate<I> {
pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
Self {
trait_ref: self.trait_ref.with_replaced_self_ty(interner, self_ty),
polarity: self.polarity,
}
}
pub fn def_id(self) -> I::TraitId {
self.trait_ref.def_id
}
pub fn self_ty(self) -> I::Ty {
self.trait_ref.self_ty()
}
}
impl<I: Interner> ty::Binder<I, TraitPredicate<I>> {
pub fn def_id(self) -> I::TraitId {
self.skip_binder().def_id()
}
pub fn self_ty(self) -> ty::Binder<I, I::Ty> {
self.map_bound(|trait_ref| trait_ref.self_ty())
}
#[inline]
pub fn polarity(self) -> PredicatePolarity {
self.skip_binder().polarity
}
}
impl<I: Interner> UpcastFrom<I, TraitRef<I>> for TraitPredicate<I> {
fn upcast_from(from: TraitRef<I>, _tcx: I) -> Self {
TraitPredicate { trait_ref: from, polarity: PredicatePolarity::Positive }
}
}
impl<I: Interner> UpcastFrom<I, ty::Binder<I, TraitRef<I>>> for ty::Binder<I, TraitPredicate<I>> {
fn upcast_from(from: ty::Binder<I, TraitRef<I>>, _tcx: I) -> Self {
from.map_bound(|trait_ref| TraitPredicate {
trait_ref,
polarity: PredicatePolarity::Positive,
})
}
}
impl<I: Interner> fmt::Debug for TraitPredicate<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "TraitPredicate({:?}, polarity:{:?})", self.trait_ref, self.polarity)
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[cfg_attr(feature = "nightly", derive(Decodable_NoContext, Encodable_NoContext, StableHash))]
pub enum ImplPolarity {
Positive,
Negative,
Reservation,
}
impl fmt::Display for ImplPolarity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Positive => f.write_str("positive"),
Self::Negative => f.write_str("negative"),
Self::Reservation => f.write_str("reservation"),
}
}
}
impl ImplPolarity {
pub fn as_str(self) -> &'static str {
match self {
Self::Positive => "",
Self::Negative => "!",
Self::Reservation => "",
}
}
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
#[cfg_attr(feature = "nightly", derive(Decodable_NoContext, Encodable_NoContext, StableHash))]
pub enum PredicatePolarity {
Positive,
Negative,
}
impl PredicatePolarity {
pub fn flip(&self) -> PredicatePolarity {
match self {
PredicatePolarity::Positive => PredicatePolarity::Negative,
PredicatePolarity::Negative => PredicatePolarity::Positive,
}
}
}
impl fmt::Display for PredicatePolarity {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Positive => f.write_str("positive"),
Self::Negative => f.write_str("negative"),
}
}
}
#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(
feature = "nightly",
derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext)
)]
pub enum ExistentialPredicate<I: Interner> {
Trait(ExistentialTraitRef<I>),
Projection(ExistentialProjection<I>),
AutoTrait(I::TraitId),
}
impl<I: Interner> Eq for ExistentialPredicate<I> {}
impl<I: Interner> ty::Binder<I, ExistentialPredicate<I>> {
pub fn def_id(&self) -> I::DefId {
match self.skip_binder() {
ExistentialPredicate::Trait(tr) => tr.def_id.into(),
ExistentialPredicate::Projection(p) => p.def_id.into(),
ExistentialPredicate::AutoTrait(did) => did.into(),
}
}
pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> I::Clause {
match self.skip_binder() {
ExistentialPredicate::Trait(tr) => self.rebind(tr).with_self_ty(cx, self_ty).upcast(cx),
ExistentialPredicate::Projection(p) => {
self.rebind(p.with_self_ty(cx, self_ty)).upcast(cx)
}
ExistentialPredicate::AutoTrait(did) => {
let generics = cx.generics_of(did.into());
let trait_ref = if generics.count() == 1 {
ty::TraitRef::new(cx, did, [self_ty])
} else {
let err_args =
GenericArgs::extend_with_error(cx, did.into(), &[self_ty.into()]);
ty::TraitRef::new_from_args(cx, did, err_args)
};
self.rebind(trait_ref).upcast(cx)
}
}
}
}
#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(
feature = "nightly",
derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext)
)]
pub struct ExistentialTraitRef<I: Interner> {
pub def_id: I::TraitId,
pub args: I::GenericArgs,
_use_existential_trait_ref_new_instead: (),
}
impl<I: Interner> Eq for ExistentialTraitRef<I> {}
impl<I: Interner> ExistentialTraitRef<I> {
pub fn new_from_args(interner: I, trait_def_id: I::TraitId, args: I::GenericArgs) -> Self {
interner.debug_assert_existential_args_compatible(trait_def_id.into(), args);
Self { def_id: trait_def_id, args, _use_existential_trait_ref_new_instead: () }
}
pub fn new(
interner: I,
trait_def_id: I::TraitId,
args: impl IntoIterator<Item: Into<I::GenericArg>>,
) -> Self {
let args = interner.mk_args_from_iter(args.into_iter().map(Into::into));
Self::new_from_args(interner, trait_def_id, args)
}
pub fn erase_self_ty(interner: I, trait_ref: TraitRef<I>) -> ExistentialTraitRef<I> {
trait_ref.args.type_at(0);
ExistentialTraitRef {
def_id: trait_ref.def_id,
args: interner.mk_args(&trait_ref.args.as_slice()[1..]),
_use_existential_trait_ref_new_instead: (),
}
}
pub fn with_self_ty(self, interner: I, self_ty: I::Ty) -> TraitRef<I> {
TraitRef::new(interner, self.def_id, [self_ty.into()].into_iter().chain(self.args.iter()))
}
}
impl<I: Interner> ty::Binder<I, ExistentialTraitRef<I>> {
pub fn def_id(&self) -> I::TraitId {
self.skip_binder().def_id
}
pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> ty::Binder<I, TraitRef<I>> {
self.map_bound(|trait_ref| trait_ref.with_self_ty(cx, self_ty))
}
}
#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(
feature = "nightly",
derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext)
)]
pub struct ExistentialProjection<I: Interner> {
pub def_id: I::TraitAssocTermId,
pub args: I::GenericArgs,
pub term: I::Term,
#[derive_where(skip(Debug))]
use_existential_projection_new_instead: (),
}
impl<I: Interner> Eq for ExistentialProjection<I> {}
impl<I: Interner> ExistentialProjection<I> {
pub fn new_from_args(
interner: I,
def_id: I::TraitAssocTermId,
args: I::GenericArgs,
term: I::Term,
) -> ExistentialProjection<I> {
interner.debug_assert_existential_args_compatible(def_id.into(), args);
Self { def_id, args, term, use_existential_projection_new_instead: () }
}
pub fn new(
interner: I,
def_id: I::TraitAssocTermId,
args: impl IntoIterator<Item: Into<I::GenericArg>>,
term: I::Term,
) -> ExistentialProjection<I> {
let args = interner.mk_args_from_iter(args.into_iter().map(Into::into));
Self::new_from_args(interner, def_id, args, term)
}
pub fn trait_ref(&self, interner: I) -> ExistentialTraitRef<I> {
let def_id = interner.projection_parent(self.def_id);
let args_count = interner.generics_of(def_id.into()).count() - 1;
let args = interner.mk_args(&self.args.as_slice()[..args_count]);
ExistentialTraitRef::new_from_args(interner, def_id, args)
}
pub fn with_self_ty(&self, interner: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
debug_assert!(!self_ty.has_escaping_bound_vars());
ProjectionPredicate {
projection_term: AliasTerm::new(
interner,
interner.alias_term_kind_from_def_id(self.def_id.into()),
[self_ty.into()].iter().chain(self.args.iter()),
),
term: self.term,
}
}
pub fn erase_self_ty(interner: I, projection_predicate: ProjectionPredicate<I>) -> Self {
projection_predicate.projection_term.args.type_at(0);
Self {
def_id: projection_predicate.def_id(),
args: interner.mk_args(&projection_predicate.projection_term.args.as_slice()[1..]),
term: projection_predicate.term,
use_existential_projection_new_instead: (),
}
}
}
impl<I: Interner> ty::Binder<I, ExistentialProjection<I>> {
pub fn with_self_ty(&self, cx: I, self_ty: I::Ty) -> ty::Binder<I, ProjectionPredicate<I>> {
self.map_bound(|p| p.with_self_ty(cx, self_ty))
}
pub fn item_def_id(&self) -> I::TraitAssocTermId {
self.skip_binder().def_id
}
}
#[derive_where(Clone, Copy, PartialEq, Eq, Hash, Debug; I: Interner)]
#[derive(Lift_Generic, GenericTypeVisitable)]
#[cfg_attr(
feature = "nightly",
derive(Encodable_NoContext, Decodable_NoContext, StableHash_NoContext)
)]
pub enum AliasTermKind<I: Interner> {
ProjectionTy { def_id: I::TraitAssocTyId },
InherentTy { def_id: I::InherentAssocTyId },
OpaqueTy { def_id: I::OpaqueTyId },
FreeTy { def_id: I::FreeTyAliasId },
UnevaluatedConst { def_id: I::UnevaluatedConstId },
ProjectionConst { def_id: I::TraitAssocConstId },
FreeConst { def_id: I::FreeConstAliasId },
InherentConst { def_id: I::InherentAssocConstId },
}
impl<I: Interner> AliasTermKind<I> {
pub fn descr(self) -> &'static str {
match self {
AliasTermKind::ProjectionTy { .. } => "associated type",
AliasTermKind::ProjectionConst { .. } => "associated const",
AliasTermKind::InherentTy { .. } => "inherent associated type",
AliasTermKind::InherentConst { .. } => "inherent associated const",
AliasTermKind::OpaqueTy { .. } => "opaque type",
AliasTermKind::FreeTy { .. } => "type alias",
AliasTermKind::FreeConst { .. } => "unevaluated constant",
AliasTermKind::UnevaluatedConst { .. } => "unevaluated constant",
}
}
pub fn is_type(self) -> bool {
match self {
AliasTermKind::ProjectionTy { .. }
| AliasTermKind::InherentTy { .. }
| AliasTermKind::OpaqueTy { .. }
| AliasTermKind::FreeTy { .. } => true,
AliasTermKind::UnevaluatedConst { .. }
| AliasTermKind::ProjectionConst { .. }
| AliasTermKind::InherentConst { .. }
| AliasTermKind::FreeConst { .. } => false,
}
}
pub fn def_id(self) -> I::DefId {
match self {
AliasTermKind::ProjectionTy { def_id } => def_id.into(),
AliasTermKind::InherentTy { def_id } => def_id.into(),
AliasTermKind::OpaqueTy { def_id } => def_id.into(),
AliasTermKind::FreeTy { def_id } => def_id.into(),
AliasTermKind::UnevaluatedConst { def_id } => def_id.into(),
AliasTermKind::ProjectionConst { def_id } => def_id.into(),
AliasTermKind::FreeConst { def_id } => def_id.into(),
AliasTermKind::InherentConst { def_id } => def_id.into(),
}
}
}
impl<I: Interner> From<ty::AliasTyKind<I>> for AliasTermKind<I> {
fn from(value: ty::AliasTyKind<I>) -> Self {
match value {
ty::Projection { def_id } => AliasTermKind::ProjectionTy { def_id },
ty::Opaque { def_id } => AliasTermKind::OpaqueTy { def_id },
ty::Free { def_id } => AliasTermKind::FreeTy { def_id },
ty::Inherent { def_id } => AliasTermKind::InherentTy { def_id },
}
}
}
#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(
feature = "nightly",
derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext)
)]
pub struct AliasTerm<I: Interner> {
pub args: I::GenericArgs,
#[type_foldable(identity)]
#[type_visitable(ignore)]
pub kind: AliasTermKind<I>,
#[derive_where(skip(Debug))]
_use_alias_term_new_instead: (),
}
impl<I: Interner> Eq for AliasTerm<I> {}
impl<I: Interner> AliasTerm<I> {
pub fn new_from_args(
interner: I,
kind: AliasTermKind<I>,
args: I::GenericArgs,
) -> AliasTerm<I> {
interner.debug_assert_args_compatible(kind.def_id(), args);
AliasTerm { kind, args, _use_alias_term_new_instead: () }
}
pub fn new(
interner: I,
kind: AliasTermKind<I>,
args: impl IntoIterator<Item: Into<I::GenericArg>>,
) -> AliasTerm<I> {
let args = interner.mk_args_from_iter(args.into_iter().map(Into::into));
Self::new_from_args(interner, kind, args)
}
pub fn new_from_def_id(interner: I, def_id: I::DefId, args: I::GenericArgs) -> AliasTerm<I> {
let kind = interner.alias_term_kind_from_def_id(def_id);
Self::new_from_args(interner, kind, args)
}
pub fn from_unevaluated_const(interner: I, ct: ty::UnevaluatedConst<I>) -> Self {
let kind = interner.alias_term_kind_from_def_id(ct.def.into());
AliasTerm::new_from_args(interner, kind, ct.args)
}
pub fn expect_ty(self, interner: I) -> ty::AliasTy<I> {
let kind = match self.kind(interner) {
AliasTermKind::ProjectionTy { def_id } => AliasTyKind::Projection { def_id },
AliasTermKind::InherentTy { def_id } => AliasTyKind::Inherent { def_id },
AliasTermKind::OpaqueTy { def_id } => AliasTyKind::Opaque { def_id },
AliasTermKind::FreeTy { def_id } => AliasTyKind::Free { def_id },
kind @ (AliasTermKind::InherentConst { .. }
| AliasTermKind::FreeConst { .. }
| AliasTermKind::UnevaluatedConst { .. }
| AliasTermKind::ProjectionConst { .. }) => {
panic!("Cannot turn `{}` into `AliasTy`", kind.descr())
}
};
ty::AliasTy { kind, args: self.args, _use_alias_ty_new_instead: () }
}
pub fn expect_ct(self, interner: I) -> ty::UnevaluatedConst<I> {
let def = match self.kind(interner) {
AliasTermKind::InherentConst { def_id } => def_id.into(),
AliasTermKind::FreeConst { def_id } => def_id.into(),
AliasTermKind::UnevaluatedConst { def_id } => def_id,
AliasTermKind::ProjectionConst { def_id } => def_id.into(),
kind @ (AliasTermKind::ProjectionTy { .. }
| AliasTermKind::InherentTy { .. }
| AliasTermKind::OpaqueTy { .. }
| AliasTermKind::FreeTy { .. }) => {
panic!("Cannot turn `{}` into `UnevaluatedConst`", kind.descr())
}
};
ty::UnevaluatedConst { def, args: self.args }
}
pub fn kind(self, _interner: I) -> AliasTermKind<I> {
self.kind
}
pub fn def_id(self) -> I::DefId {
self.kind.def_id()
}
pub fn to_term(self, interner: I) -> I::Term {
let unevaluated_const = |def_id| {
I::Const::new_unevaluated(interner, ty::UnevaluatedConst::new(def_id, self.args)).into()
};
let alias_ty_kind = match self.kind(interner) {
AliasTermKind::FreeConst { def_id } => return unevaluated_const(def_id.into()),
AliasTermKind::InherentConst { def_id } => return unevaluated_const(def_id.into()),
AliasTermKind::UnevaluatedConst { def_id } => return unevaluated_const(def_id),
AliasTermKind::ProjectionConst { def_id } => return unevaluated_const(def_id.into()),
AliasTermKind::ProjectionTy { def_id } => ty::Projection { def_id },
AliasTermKind::InherentTy { def_id } => ty::Inherent { def_id },
AliasTermKind::OpaqueTy { def_id } => ty::Opaque { def_id },
AliasTermKind::FreeTy { def_id } => ty::Free { def_id },
};
Ty::new_alias(interner, ty::AliasTy::new_from_args(interner, alias_ty_kind, self.args))
.into()
}
pub fn with_args(self, interner: I, args: I::GenericArgs) -> Self {
Self::new_from_args(interner, self.kind, args)
}
}
impl<I: Interner> AliasTerm<I> {
pub fn self_ty(self) -> I::Ty {
self.args.type_at(0)
}
pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
AliasTerm::new(
interner,
self.kind,
[self_ty.into()].into_iter().chain(self.args.iter().skip(1)),
)
}
fn projection_def_id(self) -> Option<I::TraitAssocTermId> {
match self.kind {
AliasTermKind::ProjectionTy { def_id } => Some(def_id.into()),
AliasTermKind::ProjectionConst { def_id } => Some(def_id.into()),
AliasTermKind::InherentTy { .. }
| AliasTermKind::OpaqueTy { .. }
| AliasTermKind::FreeTy { .. }
| AliasTermKind::UnevaluatedConst { .. }
| AliasTermKind::FreeConst { .. }
| AliasTermKind::InherentConst { .. } => None,
}
}
fn expect_projection_def_id(self) -> I::TraitAssocTermId {
self.projection_def_id().expect("expected a projection")
}
pub fn trait_def_id(self, interner: I) -> I::TraitId {
interner.projection_parent(self.expect_projection_def_id())
}
pub fn trait_ref_and_own_args(self, interner: I) -> (TraitRef<I>, I::GenericArgsSlice) {
interner.trait_ref_and_own_args_for_alias(self.expect_projection_def_id(), self.args)
}
pub fn trait_ref(self, interner: I) -> TraitRef<I> {
self.trait_ref_and_own_args(interner).0
}
pub fn own_args(self, interner: I) -> I::GenericArgsSlice {
self.trait_ref_and_own_args(interner).1
}
}
impl<I: Interner> AliasTerm<I> {
pub fn rebase_inherent_args_onto_impl(
self,
impl_args: I::GenericArgs,
interner: I,
) -> I::GenericArgs {
debug_assert!(matches!(
self.kind(interner),
AliasTermKind::InherentTy { .. } | AliasTermKind::InherentConst { .. }
));
interner.mk_args_from_iter(impl_args.iter().chain(self.args.iter().skip(1)))
}
}
impl<I: Interner> From<ty::AliasTy<I>> for AliasTerm<I> {
fn from(ty: ty::AliasTy<I>) -> Self {
AliasTerm {
args: ty.args,
kind: AliasTermKind::from(ty.kind),
_use_alias_term_new_instead: (),
}
}
}
#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(
feature = "nightly",
derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext)
)]
pub struct ProjectionPredicate<I: Interner> {
pub projection_term: AliasTerm<I>,
pub term: I::Term,
}
impl<I: Interner> Eq for ProjectionPredicate<I> {}
impl<I: Interner> ProjectionPredicate<I> {
pub fn self_ty(self) -> I::Ty {
self.projection_term.self_ty()
}
pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> ProjectionPredicate<I> {
Self {
projection_term: self.projection_term.with_replaced_self_ty(interner, self_ty),
..self
}
}
pub fn trait_def_id(self, interner: I) -> I::TraitId {
self.projection_term.trait_def_id(interner)
}
pub fn def_id(self) -> I::TraitAssocTermId {
self.projection_term.expect_projection_def_id()
}
}
impl<I: Interner> ty::Binder<I, ProjectionPredicate<I>> {
#[inline]
pub fn trait_def_id(&self, cx: I) -> I::TraitId {
self.skip_binder().projection_term.trait_def_id(cx)
}
pub fn term(&self) -> ty::Binder<I, I::Term> {
self.map_bound(|predicate| predicate.term)
}
pub fn item_def_id(&self) -> I::DefId {
self.skip_binder().projection_term.def_id()
}
}
impl<I: Interner> fmt::Debug for ProjectionPredicate<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "ProjectionPredicate({:?}, {:?})", self.projection_term, self.term)
}
}
#[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)]
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(
feature = "nightly",
derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext)
)]
pub struct NormalizesTo<I: Interner> {
pub alias: AliasTerm<I>,
pub term: I::Term,
}
impl<I: Interner> Eq for NormalizesTo<I> {}
impl<I: Interner> NormalizesTo<I> {
pub fn self_ty(self) -> I::Ty {
self.alias.self_ty()
}
pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> NormalizesTo<I> {
Self { alias: self.alias.with_replaced_self_ty(interner, self_ty), ..self }
}
pub fn trait_def_id(self, interner: I) -> I::TraitId {
self.alias.trait_def_id(interner)
}
pub fn def_id(self) -> I::DefId {
self.alias.def_id()
}
}
impl<I: Interner> fmt::Debug for NormalizesTo<I> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "NormalizesTo({:?}, {:?})", self.alias, self.term)
}
}
#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(
feature = "nightly",
derive(Encodable_NoContext, Decodable_NoContext, StableHash_NoContext)
)]
pub struct HostEffectPredicate<I: Interner> {
pub trait_ref: ty::TraitRef<I>,
pub constness: BoundConstness,
}
impl<I: Interner> Eq for HostEffectPredicate<I> {}
impl<I: Interner> HostEffectPredicate<I> {
pub fn self_ty(self) -> I::Ty {
self.trait_ref.self_ty()
}
pub fn with_replaced_self_ty(self, interner: I, self_ty: I::Ty) -> Self {
Self { trait_ref: self.trait_ref.with_replaced_self_ty(interner, self_ty), ..self }
}
pub fn def_id(self) -> I::TraitId {
self.trait_ref.def_id
}
}
impl<I: Interner> ty::Binder<I, HostEffectPredicate<I>> {
pub fn def_id(self) -> I::TraitId {
self.skip_binder().def_id()
}
pub fn self_ty(self) -> ty::Binder<I, I::Ty> {
self.map_bound(|trait_ref| trait_ref.self_ty())
}
#[inline]
pub fn constness(self) -> BoundConstness {
self.skip_binder().constness
}
}
#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(
feature = "nightly",
derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext)
)]
pub struct SubtypePredicate<I: Interner> {
pub a_is_expected: bool,
pub a: I::Ty,
pub b: I::Ty,
}
impl<I: Interner> Eq for SubtypePredicate<I> {}
#[derive_where(Clone, Copy, Hash, PartialEq, Debug; I: Interner)]
#[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)]
#[cfg_attr(
feature = "nightly",
derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext)
)]
pub struct CoercePredicate<I: Interner> {
pub a: I::Ty,
pub b: I::Ty,
}
impl<I: Interner> Eq for CoercePredicate<I> {}
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "nightly", derive(Encodable_NoContext, Decodable_NoContext, StableHash))]
pub enum BoundConstness {
Const,
Maybe,
}
impl BoundConstness {
pub fn satisfies(self, goal: BoundConstness) -> bool {
match (self, goal) {
(BoundConstness::Const, BoundConstness::Const | BoundConstness::Maybe) => true,
(BoundConstness::Maybe, BoundConstness::Maybe) => true,
(BoundConstness::Maybe, BoundConstness::Const) => false,
}
}
pub fn as_str(self) -> &'static str {
match self {
Self::Const => "const",
Self::Maybe => "[const]",
}
}
}
impl fmt::Display for BoundConstness {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Const => f.write_str("const"),
Self::Maybe => f.write_str("[const]"),
}
}
}