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( db: &dyn RustIrDatabase, builder: &mut ClauseBuilder<'_, I>, self_ty: Ty, ) -> 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::Generator(..) | TyKind::Closure(..) | TyKind::GeneratorWitness(..) | 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, }; if !can_determine_discriminant { return Err(Floundered); } let disc_ty = db.discriminant_type(self_ty.clone()); 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); let trait_ref = TraitRef { trait_id, substitution: substitution.clone(), }; let normalize = Normalize { alias: AliasTy::Projection(ProjectionTy { associated_ty_id, substitution, }), ty: disc_ty, }; builder.push_fact(trait_ref); builder.push_fact(normalize); Ok(()) }