Use future lang item instead of hardcoded std::future::Future
This commit is contained in:
parent
30bc3b93be
commit
ab7774545c
@ -24,6 +24,7 @@
|
||||
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 @@ pub fn autoderef<'a>(
|
||||
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
|
||||
|
@ -37,7 +37,7 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
|
||||
}
|
||||
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);
|
||||
@ -441,9 +441,14 @@ struct A { the_field: u32 }
|
||||
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 {}
|
||||
@ -452,13 +457,13 @@ impl Future for 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",
|
||||
⋮ },
|
||||
|
Loading…
Reference in New Issue
Block a user