Use future lang item instead of hardcoded std::future::Future

This commit is contained in:
Evgenii P 2019-08-03 01:53:51 +07:00
parent 30bc3b93be
commit ab7774545c
2 changed files with 21 additions and 37 deletions

View file

@ -24,6 +24,7 @@ use crate::{
BodySourceMap,
},
ids::LocationCtx,
lang_item::LangItemTarget,
ty::method_resolution::implements_trait,
AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HirDatabase, HirFileId,
MacroDef, Module, Name, Path, PerNs, Resolver, Static, Struct, Trait, Ty,
@ -410,40 +411,18 @@ impl SourceAnalyzer {
crate::ty::autoderef(db, &self.resolver, canonical).map(|canonical| canonical.value)
}
/// Checks that particular type `ty` implements `std::future::Future` trait.
/// Checks that particular type `ty` implements `Future` trait (`future_trait` lang item).
/// This function is used in `.await` syntax completion.
pub fn impls_future(&self, db: &impl HirDatabase, ty: Ty) -> bool {
// Search for std::future::Future trait in scope
let future_trait = self
.resolver
.traits_in_scope(db)
.into_iter()
.filter(|t| {
let std = t
.module(db)
.parent(db)
.and_then(|m| m.name(db).and_then(|n| Some(n.to_string() == "std")))
.unwrap_or(false);
let krate = self.resolver.krate();
if let Some(krate) = krate {
let future_trait = match db.lang_item(krate, "future_trait".into()) {
Some(LangItemTarget::Trait(t)) => t,
_ => return false,
};
let future = t
.module(db)
.name(db)
.and_then(|n| Some(n.to_string() == "future"))
.unwrap_or(false);
let future_trait =
t.name(db).and_then(|n| Some(n.to_string() == "Future")).unwrap_or(false);
std && future && future_trait
})
.nth(0);
if let Some(trait_) = future_trait {
let krate = self.resolver.krate();
if let Some(krate) = krate {
let canonical_ty = crate::ty::Canonical { value: ty, num_vars: 0 };
return implements_trait(&canonical_ty, db, &self.resolver, krate, trait_);
}
let canonical_ty = crate::ty::Canonical { value: ty, num_vars: 0 };
return implements_trait(&canonical_ty, db, &self.resolver, krate, future_trait);
}
false