Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-ty/src/chalk_ext.rs')
| -rw-r--r-- | crates/hir-ty/src/chalk_ext.rs | 55 |
1 files changed, 46 insertions, 9 deletions
diff --git a/crates/hir-ty/src/chalk_ext.rs b/crates/hir-ty/src/chalk_ext.rs index 2141894922..a8071591ad 100644 --- a/crates/hir-ty/src/chalk_ext.rs +++ b/crates/hir-ty/src/chalk_ext.rs @@ -1,24 +1,28 @@ //! Various extensions traits for Chalk types. -use chalk_ir::{FloatTy, IntTy, Mutability, Scalar, TyVariableKind, UintTy}; +use chalk_ir::{cast::Cast, FloatTy, IntTy, Mutability, Scalar, TyVariableKind, UintTy}; use hir_def::{ builtin_type::{BuiltinFloat, BuiltinInt, BuiltinType, BuiltinUint}, generics::TypeOrConstParamData, lang_item::LangItem, type_ref::Rawness, - FunctionId, GenericDefId, HasModule, ItemContainerId, Lookup, TraitId, + DefWithBodyId, FunctionId, GenericDefId, HasModule, ItemContainerId, Lookup, TraitId, }; use crate::{ - db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, - from_placeholder_idx, to_chalk_trait_id, utils::generics, AdtId, AliasEq, AliasTy, Binders, - CallableDefId, CallableSig, DynTy, FnPointer, ImplTraitId, Interner, Lifetime, ProjectionTy, + db::HirDatabase, + from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id, from_placeholder_idx, + to_chalk_trait_id, + utils::{generics, ClosureSubst}, + AdtId, AliasEq, AliasTy, Binders, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, + ClosureId, DynTy, FnPointer, ImplTraitId, InEnvironment, Interner, Lifetime, ProjectionTy, QuantifiedWhereClause, Substitution, TraitRef, Ty, TyBuilder, TyKind, TypeFlags, WhereClause, }; pub trait TyExt { fn is_unit(&self) -> bool; fn is_integral(&self) -> bool; + fn is_scalar(&self) -> bool; fn is_floating_point(&self) -> bool; fn is_never(&self) -> bool; fn is_unknown(&self) -> bool; @@ -28,8 +32,10 @@ pub trait TyExt { fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)>; fn as_builtin(&self) -> Option<BuiltinType>; fn as_tuple(&self) -> Option<&Substitution>; + fn as_closure(&self) -> Option<ClosureId>; fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId>; fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)>; + fn as_raw_ptr(&self) -> Option<(&Ty, Mutability)>; fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)>; fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId>; @@ -44,6 +50,7 @@ pub trait TyExt { fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>>; fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId>; + fn is_copy(self, db: &dyn HirDatabase, owner: DefWithBodyId) -> bool; /// FIXME: Get rid of this, it's not a good abstraction fn equals_ctor(&self, other: &Ty) -> bool; @@ -62,6 +69,10 @@ impl TyExt for Ty { ) } + fn is_scalar(&self) -> bool { + matches!(self.kind(Interner), TyKind::Scalar(_)) + } + fn is_floating_point(&self) -> bool { matches!( self.kind(Interner), @@ -128,12 +139,20 @@ impl TyExt for Ty { } } + fn as_closure(&self) -> Option<ClosureId> { + match self.kind(Interner) { + TyKind::Closure(id, _) => Some(*id), + _ => None, + } + } + fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId> { match self.callable_def(db) { Some(CallableDefId::FunctionId(func)) => Some(func), Some(CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_)) | None => None, } } + fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)> { match self.kind(Interner) { TyKind::Ref(mutability, lifetime, ty) => Some((ty, lifetime.clone(), *mutability)), @@ -141,6 +160,13 @@ impl TyExt for Ty { } } + fn as_raw_ptr(&self) -> Option<(&Ty, Mutability)> { + match self.kind(Interner) { + TyKind::Raw(mutability, ty) => Some((ty, *mutability)), + _ => None, + } + } + fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> { match self.kind(Interner) { TyKind::Ref(mutability, _, ty) => Some((ty, Rawness::Ref, *mutability)), @@ -176,10 +202,7 @@ impl TyExt for Ty { let sig = db.callable_item_signature(callable_def); Some(sig.substitute(Interner, parameters)) } - TyKind::Closure(.., substs) => { - let sig_param = substs.at(Interner, 0).assert_ty_ref(Interner); - sig_param.callable_sig(db) - } + TyKind::Closure(.., substs) => ClosureSubst(substs).sig_ty().callable_sig(db), _ => None, } } @@ -318,6 +341,20 @@ impl TyExt for Ty { } } + fn is_copy(self, db: &dyn HirDatabase, owner: DefWithBodyId) -> bool { + let crate_id = owner.module(db.upcast()).krate(); + let Some(copy_trait) = db.lang_item(crate_id, LangItem::Copy).and_then(|x| x.as_trait()) else { + return false; + }; + let trait_ref = TyBuilder::trait_ref(db, copy_trait).push(self).build(); + let env = db.trait_environment_for_body(owner); + let goal = Canonical { + value: InEnvironment::new(&env.env, trait_ref.cast(Interner)), + binders: CanonicalVarKinds::empty(Interner), + }; + db.trait_solve(crate_id, None, goal).is_some() + } + fn equals_ctor(&self, other: &Ty) -> bool { match (self.kind(Interner), other.kind(Interner)) { (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt == adt2, |