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,
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 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);
+ 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,
+ };
- 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
}
complete_methods(acc, ctx, receiver_ty.clone());
- // Suggest .await syntax for types that implement std::future::Future
+ // Suggest .await syntax for types that implement Future trait
if ctx.analyzer.impls_future(ctx.db, receiver_ty) {
postfix_reference(ctx, ".await", "expr.await", &format!("{}.await", receiver_text))
.add_to(acc);
fn test_completion_await_impls_future() {
assert_debug_snapshot_matches!(
do_ref_completion(
- r"
+ r###"
// Mock Future trait from stdlib
- pub mod std { pub mod future { pub trait Future {} } }
+ pub mod std {
+ pub mod future {
+ #[lang = "future_trait"]
+ pub trait Future {}
+ }
+ }
use std::future::*;
struct A {}
fn foo(a: A) {
a.<|>
}
- "),
+ "###),
@r###"
⋮[
⋮ CompletionItem {
⋮ label: ".await",
- ⋮ source_range: [249; 249),
- ⋮ delete: [247; 249),
+ ⋮ source_range: [358; 358),
+ ⋮ delete: [356; 358),
⋮ insert: "a.await",
⋮ detail: "expr.await",
⋮ },