From ab7774545cb5e45064c907429417bdee8d89f4d4 Mon Sep 17 00:00:00 2001 From: Evgenii P Date: Sat, 3 Aug 2019 01:53:51 +0700 Subject: Use future lang item instead of hardcoded std::future::Future --- crates/ra_hir/src/source_binder.rs | 41 ++++++------------------ crates/ra_ide_api/src/completion/complete_dot.rs | 17 ++++++---- 2 files changed, 21 insertions(+), 37 deletions(-) (limited to 'crates') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 67cb19615..7720329e3 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -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 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 diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs index 1dbbdb1bc..93e5d816d 100644 --- a/crates/ra_ide_api/src/completion/complete_dot.rs +++ b/crates/ra_ide_api/src/completion/complete_dot.rs @@ -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 @@ mod tests { 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 @@ mod tests { 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", ⋮ }, -- cgit v1.2.3