Add Callable modifier for variables that implements Fnonce

This commit is contained in:
GrayJack 2020-10-16 07:52:18 -03:00
parent 83d6bc7113
commit a483b5545d
No known key found for this signature in database
GPG Key ID: 12C54E04AAB9931E
2 changed files with 24 additions and 3 deletions

View File

@ -31,8 +31,7 @@ use hir_ty::{
autoderef, autoderef,
display::{HirDisplayError, HirFormatter}, display::{HirDisplayError, HirFormatter},
method_resolution, method_resolution,
traits::Solution, traits::{FnTrait, Solution, SolutionVariables},
traits::SolutionVariables,
ApplicationTy, BoundVar, CallableDefId, Canonical, DebruijnIndex, FnSig, GenericPredicate, ApplicationTy, BoundVar, CallableDefId, Canonical, DebruijnIndex, FnSig, GenericPredicate,
InEnvironment, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, Ty, InEnvironment, Obligation, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, Ty,
TyDefId, TyKind, TypeCtor, TyDefId, TyKind, TypeCtor,
@ -1385,6 +1384,28 @@ impl Type {
) )
} }
/// Checks that particular type `ty` implements `std::ops::FnOnce`.
///
/// This function can be used to check if a particular type is callable, since FnOnce is a
/// supertrait of Fn and FnMut, so all callable types implements at least FnOnce.
pub fn impls_fnonce(&self, db: &dyn HirDatabase) -> bool {
let krate = self.krate;
let fnonce_trait = match FnTrait::FnOnce.get_id(db, krate) {
Some(it) => it,
None => return false,
};
let canonical_ty = Canonical { value: self.ty.value.clone(), kinds: Arc::new([]) };
method_resolution::implements_trait(
&canonical_ty,
db,
self.ty.environment.clone(),
krate,
fnonce_trait,
)
}
pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool { pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
let trait_ref = hir_ty::TraitRef { let trait_ref = hir_ty::TraitRef {
trait_: trait_.id, trait_: trait_.id,

View File

@ -763,7 +763,7 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight {
if local.is_mut(db) || local.ty(db).is_mutable_reference() { if local.is_mut(db) || local.ty(db).is_mutable_reference() {
h |= HighlightModifier::Mutable; h |= HighlightModifier::Mutable;
} }
if local.ty(db).as_callable(db).is_some() { if local.ty(db).as_callable(db).is_some() || local.ty(db).impls_fnonce(db) {
h |= HighlightModifier::Callable; h |= HighlightModifier::Callable;
} }
return h; return h;