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::{
visit::{Visit, VisitResult},
AdtId, AliasEq, AliasTy, AssocTypeId, Binders, DebruijnIndex, FnDefId, GenericArg, ImplId,
OpaqueTyId, ProjectionTy, QuantifiedWhereClause, Substitution, ToGenericArg, TraitId, TraitRef,
Ty, TyKind, VariableKind, WhereClause, WithKind,
};
use std::iter;
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct AssociatedTyValueId<I: Interner>(pub I::DefId);
chalk_ir::id_visit!(AssociatedTyValueId);
chalk_ir::id_fold!(AssociatedTyValueId);
#[derive(Clone, Debug, PartialEq, Eq, Hash, Visit)]
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_adt_id(&self, interner: &I) -> Option<AdtId<I>> {
match self
.binders
.skip_binders()
.trait_ref
.self_type_parameter(interner)
.kind(interner)
{
TyKind::Adt(id, _) => Some(*id),
_ => None,
}
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, HasInterner, Fold, Visit)]
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,
}
chalk_ir::const_visit!(ImplType);
#[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, Visit)]
pub struct AdtDatum<I: Interner> {
pub binders: Binders<AdtDatumBound<I>>,
pub id: AdtId<I>,
pub flags: AdtFlags,
pub kind: AdtKind,
}
#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
pub enum AdtKind {
Struct,
Enum,
Union,
}
chalk_ir::const_visit!(AdtKind);
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, HasInterner, Visit)]
pub struct AdtDatumBound<I: Interner> {
pub variants: Vec<AdtVariantDatum<I>>,
pub where_clauses: Vec<QuantifiedWhereClause<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, HasInterner, Visit)]
pub struct AdtVariantDatum<I: Interner> {
pub fields: Vec<Ty<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct AdtFlags {
pub upstream: bool,
pub fundamental: bool,
pub phantom_data: bool,
}
chalk_ir::const_visit!(AdtFlags);
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct AdtRepr {
pub repr_c: bool,
pub repr_packed: bool,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct FnDefDatum<I: Interner> {
pub id: FnDefId<I>,
pub sig: chalk_ir::FnSig<I>,
pub binders: Binders<FnDefDatumBound<I>>,
}
impl<I: Interner> Visit<I> for FnDefDatum<I> {
fn visit_with<'i, R: VisitResult>(
&self,
visitor: &mut dyn chalk_ir::visit::Visitor<'i, I, Result = R>,
outer_binder: DebruijnIndex,
) -> R
where
I: 'i,
{
let result = R::new().combine(self.id.visit_with(visitor, outer_binder));
if result.return_early() {
return result;
}
result.combine(self.binders.visit_with(visitor, outer_binder))
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, HasInterner, Visit)]
pub struct FnDefInputsAndOutputDatum<I: Interner> {
pub argument_types: Vec<Ty<I>>,
pub return_type: Ty<I>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, HasInterner, Visit)]
pub struct FnDefDatumBound<I: Interner> {
pub inputs_and_output: Binders<FnDefInputsAndOutputDatum<I>>,
pub where_clauses: Vec<QuantifiedWhereClause<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
#[derive(Visit)]
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 {
Sized,
Copy,
Clone,
Drop,
FnOnce,
FnMut,
Fn,
Unsize,
Unpin,
CoerceUnsized,
}
chalk_ir::const_visit!(WellKnownTrait);
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
}
pub fn where_clauses(&self) -> Binders<&Vec<QuantifiedWhereClause<I>>> {
self.binders.as_ref().map(|td| &td.where_clauses)
}
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, HasInterner, Visit)]
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,
}
chalk_ir::const_visit!(TraitFlags);
#[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<GenericArg<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_iter(
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<GenericArg<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_iter(
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<I: Interner> {
fn anonymize(&self) -> Vec<VariableKind<I>>;
}
impl<I: Interner, T> Anonymize<I> for [WithKind<I, T>] {
fn anonymize(&self) -> Vec<VariableKind<I>> {
self.iter().map(|pk| pk.kind.clone()).collect()
}
}
#[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>>,
}
impl<I: Interner> Visit<I> for AssociatedTyDatum<I> {
fn visit_with<'i, R: VisitResult>(
&self,
visitor: &mut dyn chalk_ir::visit::Visitor<'i, I, Result = R>,
outer_binder: DebruijnIndex,
) -> R
where
I: 'i,
{
let result = R::new().combine(self.trait_id.visit_with(visitor, outer_binder));
if result.return_early() {
return result;
}
let result = result.combine(self.id.visit_with(visitor, outer_binder));
if result.return_early() {
return result;
}
result.combine(self.binders.visit_with(visitor, outer_binder))
}
}
#[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_iter(
interner,
binders
.iter(interner)
.enumerate()
.map(|p| p.to_generic_arg(interner)),
);
let self_ty = TyKind::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, Visit)]
pub struct OpaqueTyDatum<I: Interner> {
pub opaque_ty_id: OpaqueTyId<I>,
pub bound: Binders<OpaqueTyDatumBound<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, HasInterner, Visit)]
pub struct OpaqueTyDatumBound<I: Interner> {
pub bounds: Binders<Vec<QuantifiedWhereClause<I>>>,
pub where_clauses: Binders<Vec<QuantifiedWhereClause<I>>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, HasInterner)]
pub struct GeneratorDatum<I: Interner> {
pub input_output: Binders<GeneratorInputOutputDatum<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, HasInterner)]
pub struct GeneratorInputOutputDatum<I: Interner> {
pub resume_type: Ty<I>,
pub yield_type: Ty<I>,
pub return_type: Ty<I>,
pub upvars: Vec<Ty<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, HasInterner)]
pub struct GeneratorWitnessDatum<I: Interner> {
pub inner_types: Binders<GeneratorWitnessExistential<I>>,
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Fold, HasInterner)]
pub struct GeneratorWitnessExistential<I: Interner> {
pub types: Binders<Vec<Ty<I>>>,
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub enum Polarity {
Positive,
Negative,
}
chalk_ir::const_visit!(Polarity);
impl Polarity {
pub fn is_positive(&self) -> bool {
match *self {
Polarity::Positive => true,
Polarity::Negative => false,
}
}
}
#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub enum ClosureKind {
Fn,
FnMut,
FnOnce,
}