diff options
-rw-r--r-- | crates/ra_hir_def/src/data.rs | 27 | ||||
-rw-r--r-- | crates/ra_hir_def/src/path.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/infer.rs | 17 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 57 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/generated.rs | 1 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/traits.rs | 7 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar.ron | 3 |
7 files changed, 112 insertions, 5 deletions
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index 1aa9a9b7d..0a282f31b 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs | |||
@@ -6,12 +6,15 @@ use hir_expand::{ | |||
6 | name::{name, AsName, Name}, | 6 | name::{name, AsName, Name}, |
7 | AstId, InFile, | 7 | AstId, InFile, |
8 | }; | 8 | }; |
9 | use ra_syntax::ast::{self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner}; | 9 | use ra_syntax::ast::{ |
10 | self, AstNode, AsyncOwner, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner, | ||
11 | }; | ||
10 | 12 | ||
11 | use crate::{ | 13 | use crate::{ |
12 | db::DefDatabase, | 14 | db::DefDatabase, |
15 | path::{path, GenericArgs, Path}, | ||
13 | src::HasSource, | 16 | src::HasSource, |
14 | type_ref::{Mutability, TypeRef}, | 17 | type_ref::{Mutability, TypeBound, TypeRef}, |
15 | AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule, | 18 | AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule, |
16 | ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, | 19 | ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, |
17 | }; | 20 | }; |
@@ -62,11 +65,31 @@ impl FunctionData { | |||
62 | TypeRef::unit() | 65 | TypeRef::unit() |
63 | }; | 66 | }; |
64 | 67 | ||
68 | let ret_type = if src.value.is_async() { | ||
69 | let future_impl = desugar_future_path(ret_type); | ||
70 | let ty_bound = TypeBound::Path(future_impl); | ||
71 | TypeRef::ImplTrait(vec![ty_bound]) | ||
72 | } else { | ||
73 | ret_type | ||
74 | }; | ||
75 | |||
65 | let sig = FunctionData { name, params, ret_type, has_self_param }; | 76 | let sig = FunctionData { name, params, ret_type, has_self_param }; |
66 | Arc::new(sig) | 77 | Arc::new(sig) |
67 | } | 78 | } |
68 | } | 79 | } |
69 | 80 | ||
81 | fn desugar_future_path(orig: TypeRef) -> Path { | ||
82 | let path = path![std::future::Future]; | ||
83 | |||
84 | let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect(); | ||
85 | |||
86 | let mut last = GenericArgs::empty(); | ||
87 | last.bindings.push((name![Output], orig)); | ||
88 | generic_args.push(Some(Arc::new(last))); | ||
89 | |||
90 | Path::from_known_path(path, generic_args) | ||
91 | } | ||
92 | |||
70 | #[derive(Debug, Clone, PartialEq, Eq)] | 93 | #[derive(Debug, Clone, PartialEq, Eq)] |
71 | pub struct TypeAliasData { | 94 | pub struct TypeAliasData { |
72 | pub name: Name, | 95 | pub name: Name, |
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs index 8e1294201..bf401df35 100644 --- a/crates/ra_hir_def/src/path.rs +++ b/crates/ra_hir_def/src/path.rs | |||
@@ -130,6 +130,11 @@ impl Path { | |||
130 | Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] } | 130 | Path { type_anchor: None, mod_path: name_ref.as_name().into(), generic_args: vec![None] } |
131 | } | 131 | } |
132 | 132 | ||
133 | /// Converts a known mod path to `Path`. | ||
134 | pub(crate) fn from_known_path(path: ModPath, generic_args: Vec<Option<Arc<GenericArgs>>>) -> Path { | ||
135 | Path { type_anchor: None, mod_path: path, generic_args } | ||
136 | } | ||
137 | |||
133 | pub fn kind(&self) -> &PathKind { | 138 | pub fn kind(&self) -> &PathKind { |
134 | &self.mod_path.kind | 139 | &self.mod_path.kind |
135 | } | 140 | } |
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs index e97b81473..08c220cfe 100644 --- a/crates/ra_hir_ty/src/infer.rs +++ b/crates/ra_hir_ty/src/infer.rs | |||
@@ -37,8 +37,8 @@ use test_utils::tested_by; | |||
37 | use super::{ | 37 | use super::{ |
38 | primitive::{FloatTy, IntTy}, | 38 | primitive::{FloatTy, IntTy}, |
39 | traits::{Guidance, Obligation, ProjectionPredicate, Solution}, | 39 | traits::{Guidance, Obligation, ProjectionPredicate, Solution}, |
40 | ApplicationTy, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, Ty, TypeCtor, | 40 | ApplicationTy, GenericPredicate, InEnvironment, ProjectionTy, Substs, TraitEnvironment, |
41 | TypeWalk, Uncertain, | 41 | TraitRef, Ty, TypeCtor, TypeWalk, Uncertain, |
42 | }; | 42 | }; |
43 | use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; | 43 | use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; |
44 | 44 | ||
@@ -379,6 +379,19 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
379 | ) -> Ty { | 379 | ) -> Ty { |
380 | match assoc_ty { | 380 | match assoc_ty { |
381 | Some(res_assoc_ty) => { | 381 | Some(res_assoc_ty) => { |
382 | // Fast path: Check if inner_ty is is `impl Trait` and contained input TypeAlias id | ||
383 | if let Ty::Opaque(ref predicates) = inner_ty { | ||
384 | for p in predicates.iter() { | ||
385 | if let GenericPredicate::Projection(projection) = p { | ||
386 | if projection.projection_ty.associated_ty == res_assoc_ty | ||
387 | && projection.ty != Ty::Unknown | ||
388 | { | ||
389 | return projection.ty.clone(); | ||
390 | } | ||
391 | } | ||
392 | } | ||
393 | } | ||
394 | |||
382 | let ty = self.table.new_type_var(); | 395 | let ty = self.table.new_type_var(); |
383 | let builder = Substs::build_for_def(self.db, res_assoc_ty) | 396 | let builder = Substs::build_for_def(self.db, res_assoc_ty) |
384 | .push(inner_ty) | 397 | .push(inner_ty) |
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 76e2198b6..08d1bf044 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs | |||
@@ -38,6 +38,63 @@ mod future { | |||
38 | } | 38 | } |
39 | 39 | ||
40 | #[test] | 40 | #[test] |
41 | fn infer_async() { | ||
42 | let (db, pos) = TestDB::with_position( | ||
43 | r#" | ||
44 | //- /main.rs crate:main deps:std | ||
45 | |||
46 | async fn foo() -> u64 { | ||
47 | 128 | ||
48 | } | ||
49 | |||
50 | fn test() { | ||
51 | let r = foo(); | ||
52 | let v = r.await; | ||
53 | v<|>; | ||
54 | } | ||
55 | |||
56 | //- /std.rs crate:std | ||
57 | #[prelude_import] use future::*; | ||
58 | mod future { | ||
59 | trait Future { | ||
60 | type Output; | ||
61 | } | ||
62 | } | ||
63 | |||
64 | "#, | ||
65 | ); | ||
66 | assert_eq!("u64", type_at_pos(&db, pos)); | ||
67 | } | ||
68 | |||
69 | #[test] | ||
70 | fn infer_desugar_async() { | ||
71 | let (db, pos) = TestDB::with_position( | ||
72 | r#" | ||
73 | //- /main.rs crate:main deps:std | ||
74 | |||
75 | async fn foo() -> u64 { | ||
76 | 128 | ||
77 | } | ||
78 | |||
79 | fn test() { | ||
80 | let r = foo(); | ||
81 | r<|>; | ||
82 | } | ||
83 | |||
84 | //- /std.rs crate:std | ||
85 | #[prelude_import] use future::*; | ||
86 | mod future { | ||
87 | trait Future { | ||
88 | type Output; | ||
89 | } | ||
90 | } | ||
91 | |||
92 | "#, | ||
93 | ); | ||
94 | assert_eq!("impl Future<Output = u64>", type_at_pos(&db, pos)); | ||
95 | } | ||
96 | |||
97 | #[test] | ||
41 | fn infer_try() { | 98 | fn infer_try() { |
42 | let (db, pos) = TestDB::with_position( | 99 | let (db, pos) = TestDB::with_position( |
43 | r#" | 100 | r#" |
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 9f9d6e63c..73e1c407c 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs | |||
@@ -1129,6 +1129,7 @@ impl ast::NameOwner for FnDef {} | |||
1129 | impl ast::TypeParamsOwner for FnDef {} | 1129 | impl ast::TypeParamsOwner for FnDef {} |
1130 | impl ast::AttrsOwner for FnDef {} | 1130 | impl ast::AttrsOwner for FnDef {} |
1131 | impl ast::DocCommentsOwner for FnDef {} | 1131 | impl ast::DocCommentsOwner for FnDef {} |
1132 | impl ast::AsyncOwner for FnDef {} | ||
1132 | impl FnDef { | 1133 | impl FnDef { |
1133 | pub fn param_list(&self) -> Option<ParamList> { | 1134 | pub fn param_list(&self) -> Option<ParamList> { |
1134 | AstChildren::new(&self.syntax).next() | 1135 | AstChildren::new(&self.syntax).next() |
diff --git a/crates/ra_syntax/src/ast/traits.rs b/crates/ra_syntax/src/ast/traits.rs index f99984fe0..8bf6aa2f0 100644 --- a/crates/ra_syntax/src/ast/traits.rs +++ b/crates/ra_syntax/src/ast/traits.rs | |||
@@ -8,6 +8,7 @@ use crate::{ | |||
8 | ast::{self, child_opt, children, AstChildren, AstNode, AstToken}, | 8 | ast::{self, child_opt, children, AstChildren, AstNode, AstToken}, |
9 | match_ast, | 9 | match_ast, |
10 | syntax_node::{SyntaxElementChildren, SyntaxNodeChildren}, | 10 | syntax_node::{SyntaxElementChildren, SyntaxNodeChildren}, |
11 | SyntaxKind, | ||
11 | }; | 12 | }; |
12 | 13 | ||
13 | pub trait TypeAscriptionOwner: AstNode { | 14 | pub trait TypeAscriptionOwner: AstNode { |
@@ -105,6 +106,12 @@ pub trait AttrsOwner: AstNode { | |||
105 | } | 106 | } |
106 | } | 107 | } |
107 | 108 | ||
109 | pub trait AsyncOwner: AstNode { | ||
110 | fn is_async(&self) -> bool { | ||
111 | self.syntax().children_with_tokens().any(|t| t.kind() == SyntaxKind::ASYNC_KW) | ||
112 | } | ||
113 | } | ||
114 | |||
108 | pub trait DocCommentsOwner: AstNode { | 115 | pub trait DocCommentsOwner: AstNode { |
109 | fn doc_comments(&self) -> CommentIter { | 116 | fn doc_comments(&self) -> CommentIter { |
110 | CommentIter { iter: self.syntax().children_with_tokens() } | 117 | CommentIter { iter: self.syntax().children_with_tokens() } |
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index 08aafb610..7d11f0176 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron | |||
@@ -275,7 +275,8 @@ Grammar( | |||
275 | "NameOwner", | 275 | "NameOwner", |
276 | "TypeParamsOwner", | 276 | "TypeParamsOwner", |
277 | "AttrsOwner", | 277 | "AttrsOwner", |
278 | "DocCommentsOwner" | 278 | "DocCommentsOwner", |
279 | "AsyncOwner" | ||
279 | ], | 280 | ], |
280 | options: [ "ParamList", ["body", "BlockExpr"], "RetType" ], | 281 | options: [ "ParamList", ["body", "BlockExpr"], "RetType" ], |
281 | ), | 282 | ), |