From c417b98f02004a10819111903882482b39e50d17 Mon Sep 17 00:00:00 2001 From: Evgenii P Date: Sat, 3 Aug 2019 01:15:43 +0700 Subject: Implement completion for the .await syntax --- crates/ra_hir/src/source_binder.rs | 37 +++++++++++++++++++++++++++++++ crates/ra_hir/src/ty/method_resolution.rs | 16 ++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index c2c6921cb..8496b143a 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -23,6 +23,7 @@ use crate::{ scope::{ExprScopes, ScopeId}, BodySourceMap, }, + ty::method_resolution::implements_trait, ids::LocationCtx, AsName, AstId, Const, Crate, DefWithBody, Either, Enum, Function, HirDatabase, HirFileId, MacroDef, Module, Name, Path, PerNs, Resolver, Static, Struct, Trait, Ty, @@ -409,6 +410,42 @@ impl SourceAnalyzer { crate::ty::autoderef(db, &self.resolver, canonical).map(|canonical| canonical.value) } + /// Checks that particular type `ty` implements `std::future::Future` trait. + /// 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); + + 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_); + } + } + + false + } + #[cfg(test)] pub(crate) fn body_source_map(&self) -> Arc { self.body_source_map.clone().unwrap() diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index d421bf9ef..2e2f88138 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -15,7 +15,7 @@ use crate::{ resolve::Resolver, traits::TraitItem, ty::primitive::{FloatBitness, UncertainFloatTy, UncertainIntTy}, - ty::{Ty, TypeCtor}, + ty::{Ty, TypeCtor, traits::Solution}, Crate, Function, HirDatabase, Module, Name, Trait, }; @@ -255,6 +255,20 @@ fn iterate_inherent_methods( None } +pub(crate) fn implements_trait(ty: &Canonical, db: &impl HirDatabase, resolver: &Resolver, krate: Crate, trait_: Trait) -> bool { + let env = lower::trait_env(db, resolver); + let goal = generic_implements_goal(db, env.clone(), trait_, ty.clone()); + let solution = db.trait_solve(krate, goal); + + if let Some(solution) = solution { + if let Solution::Unique(_) = solution { + return true + } + } + + false +} + impl Ty { // This would be nicer if it just returned an iterator, but that runs into // lifetime problems, because we need to borrow temp `CrateImplBlocks`. -- cgit v1.2.3 From 30bc3b93bec06256350b66869f2885ee71c3bedd Mon Sep 17 00:00:00 2001 From: Evgenii P Date: Sat, 3 Aug 2019 01:16:20 +0700 Subject: rustfmt --- crates/ra_hir/src/source_binder.rs | 23 +++++++++++++---------- crates/ra_hir/src/ty/method_resolution.rs | 12 +++++++++--- 2 files changed, 22 insertions(+), 13 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 8496b143a..67cb19615 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -23,8 +23,8 @@ use crate::{ scope::{ExprScopes, ScopeId}, BodySourceMap, }, - ty::method_resolution::implements_trait, ids::LocationCtx, + 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, }; @@ -414,22 +414,25 @@ impl SourceAnalyzer { /// 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) + 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"))) + 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) + 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); + let future_trait = + t.name(db).and_then(|n| Some(n.to_string() == "Future")).unwrap_or(false); std && future && future_trait }) diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 2e2f88138..8731d6ba4 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -15,7 +15,7 @@ use crate::{ resolve::Resolver, traits::TraitItem, ty::primitive::{FloatBitness, UncertainFloatTy, UncertainIntTy}, - ty::{Ty, TypeCtor, traits::Solution}, + ty::{traits::Solution, Ty, TypeCtor}, Crate, Function, HirDatabase, Module, Name, Trait, }; @@ -255,14 +255,20 @@ fn iterate_inherent_methods( None } -pub(crate) fn implements_trait(ty: &Canonical, db: &impl HirDatabase, resolver: &Resolver, krate: Crate, trait_: Trait) -> bool { +pub(crate) fn implements_trait( + ty: &Canonical, + db: &impl HirDatabase, + resolver: &Resolver, + krate: Crate, + trait_: Trait, +) -> bool { let env = lower::trait_env(db, resolver); let goal = generic_implements_goal(db, env.clone(), trait_, ty.clone()); let solution = db.trait_solve(krate, goal); if let Some(solution) = solution { if let Solution::Unique(_) = solution { - return true + return true; } } -- cgit v1.2.3 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 ++++++++++---------------------------- 1 file changed, 10 insertions(+), 31 deletions(-) (limited to 'crates/ra_hir/src') 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 -- cgit v1.2.3 From 291bd81e74742472572c88ccf3d2cf9cf70af6b2 Mon Sep 17 00:00:00 2001 From: Evgenii P Date: Sat, 3 Aug 2019 01:56:27 +0700 Subject: Relax trait solving more for completion --- crates/ra_hir/src/ty/method_resolution.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 8731d6ba4..aa625a013 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -266,13 +266,7 @@ pub(crate) fn implements_trait( let goal = generic_implements_goal(db, env.clone(), trait_, ty.clone()); let solution = db.trait_solve(krate, goal); - if let Some(solution) = solution { - if let Solution::Unique(_) = solution { - return true; - } - } - - false + solution.is_some() } impl Ty { -- cgit v1.2.3 From 858736c47758250c9a4b897300fce24e35e9a579 Mon Sep 17 00:00:00 2001 From: Evgenii P Date: Sat, 3 Aug 2019 02:46:00 +0700 Subject: do fixup: remove unused import --- crates/ra_hir/src/ty/method_resolution.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index aa625a013..88d012a74 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs @@ -15,7 +15,7 @@ use crate::{ resolve::Resolver, traits::TraitItem, ty::primitive::{FloatBitness, UncertainFloatTy, UncertainIntTy}, - ty::{traits::Solution, Ty, TypeCtor}, + ty::{Ty, TypeCtor}, Crate, Function, HirDatabase, Module, Name, Trait, }; -- cgit v1.2.3 From 6a94f203fc5e2dc6f48a592c26b48f3a98638d77 Mon Sep 17 00:00:00 2001 From: Evgenii P Date: Sat, 3 Aug 2019 17:07:20 +0700 Subject: Use std::future::Future trait from stdlib --- crates/ra_hir/src/source_binder.rs | 57 ++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 21 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 7720329e3..6a9f228b8 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -7,28 +7,29 @@ /// purely for "IDE needs". use std::sync::Arc; -use ra_db::{FileId, FilePosition}; -use ra_syntax::{ - algo::find_node_at_offset, - ast::{self, AstNode, NameOwner}, - AstPtr, - SyntaxKind::*, - SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, -}; -use rustc_hash::{FxHashMap, FxHashSet}; - use crate::{ - expr, expr::{ + self, scope::{ExprScopes, ScopeId}, BodySourceMap, }, ids::LocationCtx, - lang_item::LangItemTarget, + name, + path::{PathKind, PathSegment}, 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, + MacroDef, Module, ModuleDef, Name, Path, PerNs, Resolution, Resolver, Static, Struct, Trait, + Ty, +}; +use ra_db::{FileId, FilePosition}; +use ra_syntax::{ + algo::find_node_at_offset, + ast::{self, AstNode, NameOwner}, + AstPtr, + SyntaxKind::*, + SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, }; +use rustc_hash::{FxHashMap, FxHashSet}; /// Locates the module by `FileId`. Picks topmost module in the file. pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Option { @@ -411,18 +412,32 @@ impl SourceAnalyzer { crate::ty::autoderef(db, &self.resolver, canonical).map(|canonical| canonical.value) } - /// Checks that particular type `ty` implements `Future` trait (`future_trait` lang item). + /// Checks that particular type `ty` implements `std::future::Future`. /// This function is used in `.await` syntax completion. pub fn impls_future(&self, db: &impl HirDatabase, ty: Ty) -> bool { - 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 std_future_path = Path { + kind: PathKind::Abs, + segments: vec![ + PathSegment { name: name::STD, args_and_bindings: None }, + PathSegment { name: name::FUTURE_MOD, args_and_bindings: None }, + PathSegment { name: name::FUTURE_TYPE, args_and_bindings: None }, + ], + }; + + let std_future_trait = + match self.resolver.resolve_path_segments(db, &std_future_path).into_fully_resolved() { + PerNs { types: Some(Resolution::Def(ModuleDef::Trait(trait_))), .. } => { + Some(trait_) + } + _ => None, }; - let canonical_ty = crate::ty::Canonical { value: ty, num_vars: 0 }; - return implements_trait(&canonical_ty, db, &self.resolver, krate, future_trait); + let krate = self.resolver.krate(); + if let Some(krate) = krate { + if let Some(trait_) = std_future_trait { + let canonical_ty = crate::ty::Canonical { value: ty, num_vars: 0 }; + return implements_trait(&canonical_ty, db, &self.resolver, krate, trait_); + } } false -- cgit v1.2.3 From 4034ea9e4ebe2959327ddbf6c1d1e3103dd01f80 Mon Sep 17 00:00:00 2001 From: Evgenii P Date: Sun, 4 Aug 2019 07:56:29 +0700 Subject: source_binder.rs: fix order of imports --- crates/ra_hir/src/source_binder.rs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 6a9f228b8..cf9a9e108 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -7,6 +7,16 @@ /// purely for "IDE needs". use std::sync::Arc; +use ra_db::{FileId, FilePosition}; +use ra_syntax::{ + algo::find_node_at_offset, + ast::{self, AstNode, NameOwner}, + AstPtr, + SyntaxKind::*, + SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, +}; +use rustc_hash::{FxHashMap, FxHashSet}; + use crate::{ expr::{ self, @@ -21,15 +31,6 @@ use crate::{ MacroDef, Module, ModuleDef, Name, Path, PerNs, Resolution, Resolver, Static, Struct, Trait, Ty, }; -use ra_db::{FileId, FilePosition}; -use ra_syntax::{ - algo::find_node_at_offset, - ast::{self, AstNode, NameOwner}, - AstPtr, - SyntaxKind::*, - SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, -}; -use rustc_hash::{FxHashMap, FxHashSet}; /// Locates the module by `FileId`. Picks topmost module in the file. pub fn module_from_file_id(db: &impl HirDatabase, file_id: FileId) -> Option { -- cgit v1.2.3 From d610adfc2bfe3d4e9fec61b7a5bc02cfea503384 Mon Sep 17 00:00:00 2001 From: Evgenii P Date: Sun, 4 Aug 2019 08:03:17 +0700 Subject: Employ early return pattern more --- crates/ra_hir/src/source_binder.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index cf9a9e108..2c4cedd8b 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -428,20 +428,18 @@ impl SourceAnalyzer { let std_future_trait = match self.resolver.resolve_path_segments(db, &std_future_path).into_fully_resolved() { PerNs { types: Some(Resolution::Def(ModuleDef::Trait(trait_))), .. } => { - Some(trait_) + trait_ } - _ => None, + _ => return false, }; - let krate = self.resolver.krate(); - if let Some(krate) = krate { - if let Some(trait_) = std_future_trait { - let canonical_ty = crate::ty::Canonical { value: ty, num_vars: 0 }; - return implements_trait(&canonical_ty, db, &self.resolver, krate, trait_); - } - } + let krate = match self.resolver.krate() { + Some(krate) => krate, + _ => return false, + }; - false + let canonical_ty = crate::ty::Canonical { value: ty, num_vars: 0 }; + return implements_trait(&canonical_ty, db, &self.resolver, krate, std_future_trait); } #[cfg(test)] -- cgit v1.2.3 From 8597af8ed4ebed2e86e379a5a440b37373ace76d Mon Sep 17 00:00:00 2001 From: Evgenii P Date: Sun, 4 Aug 2019 08:08:46 +0700 Subject: Idiomatic return --- crates/ra_hir/src/source_binder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 2c4cedd8b..656061086 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -439,7 +439,7 @@ impl SourceAnalyzer { }; let canonical_ty = crate::ty::Canonical { value: ty, num_vars: 0 }; - return implements_trait(&canonical_ty, db, &self.resolver, krate, std_future_trait); + implements_trait(&canonical_ty, db, &self.resolver, krate, std_future_trait) } #[cfg(test)] -- cgit v1.2.3 From 9f9c5aa65914763f5a9ff80230544fea48cbcdf1 Mon Sep 17 00:00:00 2001 From: Evgenii P Date: Sun, 4 Aug 2019 08:45:14 +0700 Subject: rustfmt --- crates/ra_hir/src/source_binder.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'crates/ra_hir/src') diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs index 656061086..e86716d74 100644 --- a/crates/ra_hir/src/source_binder.rs +++ b/crates/ra_hir/src/source_binder.rs @@ -427,9 +427,7 @@ impl SourceAnalyzer { let std_future_trait = match self.resolver.resolve_path_segments(db, &std_future_path).into_fully_resolved() { - PerNs { types: Some(Resolution::Def(ModuleDef::Trait(trait_))), .. } => { - trait_ - } + PerNs { types: Some(Resolution::Def(ModuleDef::Trait(trait_))), .. } => trait_, _ => return false, }; -- cgit v1.2.3