aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/code_model.rs20
-rw-r--r--crates/ra_hir/src/lib.rs4
-rw-r--r--crates/ra_hir/src/source_analyzer.rs (renamed from crates/ra_hir/src/source_binder.rs)141
-rw-r--r--crates/ra_hir_ty/src/method_resolution.rs3
-rw-r--r--crates/ra_ide/src/completion/complete_dot.rs3
5 files changed, 82 insertions, 89 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index a177cebca..346118350 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -21,8 +21,8 @@ use hir_expand::{
21 MacroDefId, 21 MacroDefId,
22}; 22};
23use hir_ty::{ 23use hir_ty::{
24 autoderef, display::HirFormatter, expr::ExprValidator, ApplicationTy, Canonical, InEnvironment, 24 autoderef, display::HirFormatter, expr::ExprValidator, method_resolution::implements_trait,
25 TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk, 25 ApplicationTy, Canonical, InEnvironment, TraitEnvironment, Ty, TyDefId, TypeCtor, TypeWalk,
26}; 26};
27use ra_db::{CrateId, Edition, FileId}; 27use ra_db::{CrateId, Edition, FileId};
28use ra_prof::profile; 28use ra_prof::profile;
@@ -878,6 +878,22 @@ impl Type {
878 } 878 }
879 } 879 }
880 880
881 /// Checks that particular type `ty` implements `std::future::Future`.
882 /// This function is used in `.await` syntax completion.
883 pub fn impls_future(&self, db: &impl HirDatabase) -> bool {
884 let krate = self.krate;
885
886 let std_future_trait =
887 db.lang_item(krate, "future_trait".into()).and_then(|it| it.as_trait());
888 let std_future_trait = match std_future_trait {
889 Some(it) => it,
890 None => return false,
891 };
892
893 let canonical_ty = Canonical { value: self.ty.value.clone(), num_vars: 0 };
894 implements_trait(&canonical_ty, db, self.ty.environment.clone(), krate, std_future_trait)
895 }
896
881 // FIXME: this method is broken, as it doesn't take closures into account. 897 // FIXME: this method is broken, as it doesn't take closures into account.
882 pub fn as_callable(&self) -> Option<CallableDef> { 898 pub fn as_callable(&self) -> Option<CallableDef> {
883 Some(self.ty.value.as_callable()?.0) 899 Some(self.ty.value.as_callable()?.0)
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 3d13978d4..a1cf89010 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -27,7 +27,7 @@ macro_rules! impl_froms {
27} 27}
28 28
29pub mod db; 29pub mod db;
30pub mod source_binder; 30pub mod source_analyzer;
31 31
32pub mod diagnostics; 32pub mod diagnostics;
33 33
@@ -46,7 +46,7 @@ pub use crate::{
46 }, 46 },
47 from_source::FromSource, 47 from_source::FromSource,
48 has_source::HasSource, 48 has_source::HasSource,
49 source_binder::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer}, 49 source_analyzer::{PathResolution, ScopeEntryWithSyntax, SourceAnalyzer},
50}; 50};
51 51
52pub use hir_def::{ 52pub use hir_def::{
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_analyzer.rs
index a2a9d968c..3df48842d 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_analyzer.rs
@@ -15,17 +15,13 @@ use hir_def::{
15 }, 15 },
16 expr::{ExprId, PatId}, 16 expr::{ExprId, PatId},
17 nameres::ModuleSource, 17 nameres::ModuleSource,
18 path::path,
19 resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs}, 18 resolver::{self, resolver_for_scope, HasResolver, Resolver, TypeNs, ValueNs},
20 AssocItemId, DefWithBodyId, 19 AssocItemId, DefWithBodyId,
21}; 20};
22use hir_expand::{ 21use hir_expand::{
23 hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind, 22 hygiene::Hygiene, name::AsName, AstId, HirFileId, InFile, MacroCallId, MacroCallKind,
24}; 23};
25use hir_ty::{ 24use hir_ty::{method_resolution, Canonical, InEnvironment, InferenceResult, TraitEnvironment, Ty};
26 method_resolution::{self, implements_trait},
27 Canonical, InEnvironment, InferenceResult, TraitEnvironment, Ty,
28};
29use ra_prof::profile; 25use ra_prof::profile;
30use ra_syntax::{ 26use ra_syntax::{
31 ast::{self, AstNode}, 27 ast::{self, AstNode},
@@ -40,64 +36,6 @@ use crate::{
40 TypeParam, 36 TypeParam,
41}; 37};
42 38
43fn try_get_resolver_for_node(db: &impl HirDatabase, node: InFile<&SyntaxNode>) -> Option<Resolver> {
44 match_ast! {
45 match (node.value) {
46 ast::Module(it) => {
47 let src = node.with_value(it);
48 Some(crate::Module::from_declaration(db, src)?.id.resolver(db))
49 },
50 ast::SourceFile(it) => {
51 let src = node.with_value(ModuleSource::SourceFile(it));
52 Some(crate::Module::from_definition(db, src)?.id.resolver(db))
53 },
54 ast::StructDef(it) => {
55 let src = node.with_value(it);
56 Some(Struct::from_source(db, src)?.id.resolver(db))
57 },
58 ast::EnumDef(it) => {
59 let src = node.with_value(it);
60 Some(Enum::from_source(db, src)?.id.resolver(db))
61 },
62 ast::ImplBlock(it) => {
63 let src = node.with_value(it);
64 Some(ImplBlock::from_source(db, src)?.id.resolver(db))
65 },
66 ast::TraitDef(it) => {
67 let src = node.with_value(it);
68 Some(Trait::from_source(db, src)?.id.resolver(db))
69 },
70 _ => match node.value.kind() {
71 FN_DEF | CONST_DEF | STATIC_DEF => {
72 let def = def_with_body_from_child_node(db, node)?;
73 let def = DefWithBodyId::from(def);
74 Some(def.resolver(db))
75 }
76 // FIXME add missing cases
77 _ => None
78 }
79 }
80 }
81}
82
83fn def_with_body_from_child_node(
84 db: &impl HirDatabase,
85 child: InFile<&SyntaxNode>,
86) -> Option<DefWithBody> {
87 let _p = profile("def_with_body_from_child_node");
88 child.cloned().ancestors_with_macros(db).find_map(|node| {
89 let n = &node.value;
90 match_ast! {
91 match n {
92 ast::FnDef(def) => { return Function::from_source(db, node.with_value(def)).map(DefWithBody::from); },
93 ast::ConstDef(def) => { return Const::from_source(db, node.with_value(def)).map(DefWithBody::from); },
94 ast::StaticDef(def) => { return Static::from_source(db, node.with_value(def)).map(DefWithBody::from); },
95 _ => { None },
96 }
97 }
98 })
99}
100
101/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of 39/// `SourceAnalyzer` is a convenience wrapper which exposes HIR API in terms of
102/// original source files. It should not be used inside the HIR itself. 40/// original source files. It should not be used inside the HIR itself.
103#[derive(Debug)] 41#[derive(Debug)]
@@ -454,25 +392,6 @@ impl SourceAnalyzer {
454 ) 392 )
455 } 393 }
456 394
457 /// Checks that particular type `ty` implements `std::future::Future`.
458 /// This function is used in `.await` syntax completion.
459 pub fn impls_future(&self, db: &impl HirDatabase, ty: Type) -> bool {
460 let std_future_path = path![std::future::Future];
461
462 let std_future_trait = match self.resolver.resolve_known_trait(db, &std_future_path) {
463 Some(it) => it.into(),
464 _ => return false,
465 };
466
467 let krate = match self.resolver.krate() {
468 Some(krate) => krate,
469 _ => return false,
470 };
471
472 let canonical_ty = Canonical { value: ty.ty.value, num_vars: 0 };
473 implements_trait(&canonical_ty, db, &self.resolver, krate.into(), std_future_trait)
474 }
475
476 pub fn expand( 395 pub fn expand(
477 &self, 396 &self,
478 db: &impl HirDatabase, 397 db: &impl HirDatabase,
@@ -487,6 +406,64 @@ impl SourceAnalyzer {
487 } 406 }
488} 407}
489 408
409fn try_get_resolver_for_node(db: &impl HirDatabase, node: InFile<&SyntaxNode>) -> Option<Resolver> {
410 match_ast! {
411 match (node.value) {
412 ast::Module(it) => {
413 let src = node.with_value(it);
414 Some(crate::Module::from_declaration(db, src)?.id.resolver(db))
415 },
416 ast::SourceFile(it) => {
417 let src = node.with_value(ModuleSource::SourceFile(it));
418 Some(crate::Module::from_definition(db, src)?.id.resolver(db))
419 },
420 ast::StructDef(it) => {
421 let src = node.with_value(it);
422 Some(Struct::from_source(db, src)?.id.resolver(db))
423 },
424 ast::EnumDef(it) => {
425 let src = node.with_value(it);
426 Some(Enum::from_source(db, src)?.id.resolver(db))
427 },
428 ast::ImplBlock(it) => {
429 let src = node.with_value(it);
430 Some(ImplBlock::from_source(db, src)?.id.resolver(db))
431 },
432 ast::TraitDef(it) => {
433 let src = node.with_value(it);
434 Some(Trait::from_source(db, src)?.id.resolver(db))
435 },
436 _ => match node.value.kind() {
437 FN_DEF | CONST_DEF | STATIC_DEF => {
438 let def = def_with_body_from_child_node(db, node)?;
439 let def = DefWithBodyId::from(def);
440 Some(def.resolver(db))
441 }
442 // FIXME add missing cases
443 _ => None
444 }
445 }
446 }
447}
448
449fn def_with_body_from_child_node(
450 db: &impl HirDatabase,
451 child: InFile<&SyntaxNode>,
452) -> Option<DefWithBody> {
453 let _p = profile("def_with_body_from_child_node");
454 child.cloned().ancestors_with_macros(db).find_map(|node| {
455 let n = &node.value;
456 match_ast! {
457 match n {
458 ast::FnDef(def) => { return Function::from_source(db, node.with_value(def)).map(DefWithBody::from); },
459 ast::ConstDef(def) => { return Const::from_source(db, node.with_value(def)).map(DefWithBody::from); },
460 ast::StaticDef(def) => { return Static::from_source(db, node.with_value(def)).map(DefWithBody::from); },
461 _ => { None },
462 }
463 }
464 })
465}
466
490fn scope_for( 467fn scope_for(
491 scopes: &ExprScopes, 468 scopes: &ExprScopes,
492 source_map: &BodySourceMap, 469 source_map: &BodySourceMap,
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs
index 888dc3116..55435e6ea 100644
--- a/crates/ra_hir_ty/src/method_resolution.rs
+++ b/crates/ra_hir_ty/src/method_resolution.rs
@@ -465,7 +465,7 @@ fn transform_receiver_ty(
465pub fn implements_trait( 465pub fn implements_trait(
466 ty: &Canonical<Ty>, 466 ty: &Canonical<Ty>,
467 db: &impl HirDatabase, 467 db: &impl HirDatabase,
468 resolver: &Resolver, 468 env: Arc<TraitEnvironment>,
469 krate: CrateId, 469 krate: CrateId,
470 trait_: TraitId, 470 trait_: TraitId,
471) -> bool { 471) -> bool {
@@ -474,7 +474,6 @@ pub fn implements_trait(
474 // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet 474 // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet
475 return true; 475 return true;
476 } 476 }
477 let env = TraitEnvironment::lower(db, resolver);
478 let goal = generic_implements_goal(db, env, trait_, ty.clone()); 477 let goal = generic_implements_goal(db, env, trait_, ty.clone());
479 let solution = db.trait_solve(krate.into(), goal); 478 let solution = db.trait_solve(krate.into(), goal);
480 479
diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs
index 210a685e4..9ab43644e 100644
--- a/crates/ra_ide/src/completion/complete_dot.rs
+++ b/crates/ra_ide/src/completion/complete_dot.rs
@@ -27,7 +27,7 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
27 complete_methods(acc, ctx, &receiver_ty); 27 complete_methods(acc, ctx, &receiver_ty);
28 28
29 // Suggest .await syntax for types that implement Future trait 29 // Suggest .await syntax for types that implement Future trait
30 if ctx.analyzer.impls_future(ctx.db, receiver_ty) { 30 if receiver_ty.impls_future(ctx.db) {
31 CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await") 31 CompletionItem::new(CompletionKind::Keyword, ctx.source_range(), "await")
32 .detail("expr.await") 32 .detail("expr.await")
33 .insert_text("await") 33 .insert_text("await")
@@ -525,6 +525,7 @@ mod tests {
525 525
526 //- /std/lib.rs 526 //- /std/lib.rs
527 pub mod future { 527 pub mod future {
528 #[lang = "future_trait"]
528 pub trait Future {} 529 pub trait Future {}
529 } 530 }
530 "###, CompletionKind::Keyword), 531 "###, CompletionKind::Keyword),