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.rs55
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,