#![deny(rust_2018_idioms)]
use chalk_derive::{Fold, HasInterner, Visit};
use chalk_ir::cast::Cast;
use chalk_ir::fold::shift::Shift;
use chalk_ir::interner::{Interner, TargetInterner};
use chalk_ir::{
AliasEq, AliasTy, AssocTypeId, Binders, BoundVar, DebruijnIndex, ImplId, LifetimeData,
OpaqueTyId, Parameter, ParameterKind, ProjectionTy, QuantifiedWhereClause, StructId,
Substitution, TraitId, TraitRef, Ty, TyData, TypeName, WhereClause,
};
use std::iter;
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct AssociatedTyValueId<I: Interner>(pub I::DefId);
chalk_ir::id_fold!(AssociatedTyValueId);
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct ImplDatum<I: Interner> {
pub polarity: Polarity,
pub binders: Binders<ImplDatumBound<I>>,
pub impl_type: ImplType,
pub associated_ty_value_ids: Vec<AssociatedTyValueId<I>>,
}
impl<I: Interner> ImplDatum<I> {
pub fn is_positive(&self) -> bool {
self.polarity.is_positive()
}
pub fn trait_id(&self) -> TraitId<I> {
self.binders.skip_binders().trait_ref.trait_id
}
pub fn self_type_struct_id(&self, interner: &I) -> Option<StructId<I>> {
match self
.binders
.skip_binders()
.trait_ref
.self_type_parameter(interner)
.data(interner)
{
TyData::Apply(apply) => match apply.name {
TypeName::Struct(id) => Some(id),
_ => None,
},
_ => None,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, HasInterner, Fold)]
pub struct ImplDatumBound<I: Interner> {
pub trait_ref: TraitRef<I>,
pub where_clauses: Vec<QuantifiedWhereClause<I>>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum ImplType {
Local,
External,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct DefaultImplDatum<I: Interner> {
pub binders: Binders<DefaultImplDatumBound<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, HasInterner)]
pub struct DefaultImplDatumBound<I: Interner> {
pub trait_ref: TraitRef<I>,
pub accessible_tys: Vec<Ty<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct StructDatum<I: Interner> {
pub binders: Binders<StructDatumBound<I>>,
pub id: StructId<I>,
pub flags: StructFlags,
}
impl<I: Interner> StructDatum<I> {
pub fn name(&self, interner: &I) -> TypeName<I> {
self.id.cast(interner)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, HasInterner)]
pub struct StructDatumBound<I: Interner> {
pub fields: Vec<Ty<I>>,
pub where_clauses: Vec<QuantifiedWhereClause<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct StructFlags {
pub upstream: bool,
pub fundamental: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct TraitDatum<I: Interner> {
pub id: TraitId<I>,
pub binders: Binders<TraitDatumBound<I>>,
pub flags: TraitFlags,
pub associated_ty_ids: Vec<AssocTypeId<I>>,
pub well_known: Option<WellKnownTrait>,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub enum WellKnownTrait {
SizedTrait,
CopyTrait,
CloneTrait,
DropTrait,
}
impl<I: Interner> TraitDatum<I> {
pub fn is_auto_trait(&self) -> bool {
self.flags.auto
}
pub fn is_non_enumerable_trait(&self) -> bool {
self.flags.non_enumerable
}
pub fn is_coinductive_trait(&self) -> bool {
self.flags.coinductive
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, HasInterner)]
pub struct TraitDatumBound<I: Interner> {
pub where_clauses: Vec<QuantifiedWhereClause<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct TraitFlags {
pub auto: bool,
pub marker: bool,
pub upstream: bool,
pub fundamental: bool,
pub non_enumerable: bool,
pub coinductive: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, Visit, HasInterner)]
pub enum InlineBound<I: Interner> {
TraitBound(TraitBound<I>),
AliasEqBound(AliasEqBound<I>),
}
#[allow(type_alias_bounds)]
pub type QuantifiedInlineBound<I: Interner> = Binders<InlineBound<I>>;
pub trait IntoWhereClauses<I: Interner> {
type Output;
fn into_where_clauses(&self, interner: &I, self_ty: Ty<I>) -> Vec<Self::Output>;
}
impl<I: Interner> IntoWhereClauses<I> for InlineBound<I> {
type Output = WhereClause<I>;
fn into_where_clauses(&self, interner: &I, self_ty: Ty<I>) -> Vec<WhereClause<I>> {
match self {
InlineBound::TraitBound(b) => b.into_where_clauses(interner, self_ty),
InlineBound::AliasEqBound(b) => b.into_where_clauses(interner, self_ty),
}
}
}
impl<I: Interner> IntoWhereClauses<I> for QuantifiedInlineBound<I> {
type Output = QuantifiedWhereClause<I>;
fn into_where_clauses(&self, interner: &I, self_ty: Ty<I>) -> Vec<QuantifiedWhereClause<I>> {
let self_ty = self_ty.shifted_in(interner);
self.map_ref(|b| b.into_where_clauses(interner, self_ty))
.into_iter()
.collect()
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, Visit)]
pub struct TraitBound<I: Interner> {
pub trait_id: TraitId<I>,
pub args_no_self: Vec<Parameter<I>>,
}
impl<I: Interner> TraitBound<I> {
fn into_where_clauses(&self, interner: &I, self_ty: Ty<I>) -> Vec<WhereClause<I>> {
let trait_ref = self.as_trait_ref(interner, self_ty);
vec![WhereClause::Implemented(trait_ref)]
}
pub fn as_trait_ref(&self, interner: &I, self_ty: Ty<I>) -> TraitRef<I> {
TraitRef {
trait_id: self.trait_id,
substitution: Substitution::from(
interner,
iter::once(self_ty.cast(interner)).chain(self.args_no_self.iter().cloned()),
),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, Visit)]
pub struct AliasEqBound<I: Interner> {
pub trait_bound: TraitBound<I>,
pub associated_ty_id: AssocTypeId<I>,
pub parameters: Vec<Parameter<I>>,
pub value: Ty<I>,
}
impl<I: Interner> AliasEqBound<I> {
fn into_where_clauses(&self, interner: &I, self_ty: Ty<I>) -> Vec<WhereClause<I>> {
let trait_ref = self.trait_bound.as_trait_ref(interner, self_ty);
let substitution = Substitution::from(
interner,
self.parameters
.iter()
.cloned()
.chain(trait_ref.substitution.iter(interner).cloned()),
);
vec![
WhereClause::Implemented(trait_ref),
WhereClause::AliasEq(AliasEq {
alias: AliasTy::Projection(ProjectionTy {
associated_ty_id: self.associated_ty_id,
substitution,
}),
ty: self.value.clone(),
}),
]
}
}
pub trait Anonymize {
fn anonymize(&self) -> Vec<ParameterKind<()>>;
}
impl<T> Anonymize for [ParameterKind<T>] {
fn anonymize(&self) -> Vec<ParameterKind<()>> {
self.iter().map(|pk| pk.map_ref(|_| ())).collect()
}
}
pub trait ToParameter {
fn to_parameter<I: Interner>(&self, interner: &I) -> Parameter<I> {
self.to_parameter_at_depth(interner, DebruijnIndex::INNERMOST)
}
fn to_parameter_at_depth<I: Interner>(
&self,
interner: &I,
debruijn: DebruijnIndex,
) -> Parameter<I>;
}
impl<'a> ToParameter for (&'a ParameterKind<()>, usize) {
fn to_parameter_at_depth<I: Interner>(
&self,
interner: &I,
debruijn: DebruijnIndex,
) -> Parameter<I> {
let &(binder, index) = self;
let bound_var = BoundVar::new(debruijn, index);
match *binder {
ParameterKind::Lifetime(_) => LifetimeData::BoundVar(bound_var)
.intern(interner)
.cast(interner),
ParameterKind::Ty(_) => TyData::BoundVar(bound_var).intern(interner).cast(interner),
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct AssociatedTyDatum<I: Interner> {
pub trait_id: TraitId<I>,
pub id: AssocTypeId<I>,
pub name: I::Identifier,
pub binders: Binders<AssociatedTyDatumBound<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, Visit, HasInterner)]
pub struct AssociatedTyDatumBound<I: Interner> {
pub bounds: Vec<QuantifiedInlineBound<I>>,
pub where_clauses: Vec<QuantifiedWhereClause<I>>,
}
impl<I: Interner> AssociatedTyDatum<I> {
pub fn bounds_on_self(&self, interner: &I) -> Vec<QuantifiedWhereClause<I>> {
let (binders, assoc_ty_datum) = self.binders.as_ref().into();
let substitution = Substitution::from(
interner,
binders
.iter(interner)
.zip(0..)
.map(|p| p.to_parameter(interner)),
);
let self_ty = TyData::Alias(AliasTy::Projection(ProjectionTy {
associated_ty_id: self.id,
substitution,
}))
.intern(interner);
assoc_ty_datum
.bounds
.iter()
.flat_map(|b| b.into_where_clauses(interner, self_ty.clone()))
.collect()
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, Visit)]
pub struct AssociatedTyValue<I: Interner> {
pub impl_id: ImplId<I>,
pub associated_ty_id: AssocTypeId<I>,
pub value: Binders<AssociatedTyValueBound<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, Visit, HasInterner)]
pub struct AssociatedTyValueBound<I: Interner> {
pub ty: Ty<I>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold)]
pub struct OpaqueTyDatum<I: Interner> {
pub opaque_ty_id: OpaqueTyId<I>,
pub bound: Binders<OpaqueTyDatumBound<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, HasInterner)]
pub struct OpaqueTyDatumBound<I: Interner> {
pub hidden_ty: Ty<I>,
pub bounds: Binders<Vec<QuantifiedWhereClause<I>>>,
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub enum Polarity {
Positive,
Negative,
}
impl Polarity {
pub fn is_positive(&self) -> bool {
match *self {
Polarity::Positive => true,
Polarity::Negative => false,
}
}
}