use crate::clauses::ClauseBuilder;
use crate::{Interner, RustIrDatabase, TraitRef, WellKnownTrait};
use chalk_ir::{
AliasTy, Floundered, Normalize, ProjectionTy, Substitution, Ty, TyKind, TyVariableKind,
};
pub fn add_discriminant_clauses<I: Interner>(
db: &dyn RustIrDatabase<I>,
builder: &mut ClauseBuilder<'_, I>,
self_ty: Ty<I>,
) -> Result<(), Floundered> {
let interner = db.interner();
let can_determine_discriminant = match self_ty.data(interner).kind {
TyKind::Adt(..)
| TyKind::Array(..)
| TyKind::Tuple(..)
| TyKind::Slice(..)
| TyKind::Raw(..)
| TyKind::Ref(..)
| TyKind::Scalar(_)
| TyKind::Str
| TyKind::Never
| TyKind::FnDef(..)
| TyKind::Coroutine(..)
| TyKind::Closure(..)
| TyKind::CoroutineWitness(..)
| TyKind::Foreign(_)
| TyKind::Dyn(_)
| TyKind::Function(..)
| TyKind::InferenceVar(_, TyVariableKind::Integer)
| TyKind::InferenceVar(_, TyVariableKind::Float) => true,
TyKind::OpaqueType(..)
| TyKind::Alias(_)
| TyKind::BoundVar(_)
| TyKind::Placeholder(_)
| TyKind::AssociatedType(..)
| TyKind::Error
| TyKind::InferenceVar(..) => false,
};
let trait_id = db
.well_known_trait_id(WellKnownTrait::DiscriminantKind)
.unwrap();
let trait_datum = db.trait_datum(trait_id);
let associated_ty_id = trait_datum.associated_ty_ids[0];
let substitution = Substitution::from1(interner, self_ty.clone());
let trait_ref = TraitRef {
trait_id,
substitution: substitution.clone(),
};
builder.push_fact(trait_ref);
if !can_determine_discriminant {
return Ok(());
}
let disc_ty = db.discriminant_type(self_ty);
let normalize = Normalize {
alias: AliasTy::Projection(ProjectionTy {
associated_ty_id,
substitution,
}),
ty: disc_ty,
};
builder.push_fact(normalize);
Ok(())
}