aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorEdwin Cheng <[email protected]>2019-12-24 11:45:28 +0000
committerEdwin Cheng <[email protected]>2019-12-24 11:45:28 +0000
commit0edb5b4a501a66baa7db8ececf46135e6246f4de (patch)
treea65f9899f109d4df2c05069e037fe5dec0545d73 /crates
parent60aa4d12f95477565d5b01f122d2c9dd845015b4 (diff)
Implement infer await from async func
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir_def/src/data.rs27
-rw-r--r--crates/ra_hir_def/src/path.rs5
-rw-r--r--crates/ra_hir_ty/src/infer.rs17
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs57
-rw-r--r--crates/ra_syntax/src/ast/generated.rs1
-rw-r--r--crates/ra_syntax/src/ast/traits.rs7
-rw-r--r--crates/ra_syntax/src/grammar.ron3
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};
9use ra_syntax::ast::{self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner}; 9use ra_syntax::ast::{
10 self, AstNode, AsyncOwner, ImplItem, ModuleItemOwner, NameOwner, TypeAscriptionOwner,
11};
10 12
11use crate::{ 13use 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
81fn 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)]
71pub struct TypeAliasData { 94pub 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;
37use super::{ 37use 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};
43use crate::{db::HirDatabase, infer::diagnostics::InferenceDiagnostic}; 43use 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]
41fn infer_async() {
42 let (db, pos) = TestDB::with_position(
43 r#"
44//- /main.rs crate:main deps:std
45
46async fn foo() -> u64 {
47 128
48}
49
50fn test() {
51 let r = foo();
52 let v = r.await;
53 v<|>;
54}
55
56//- /std.rs crate:std
57#[prelude_import] use future::*;
58mod 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]
70fn infer_desugar_async() {
71 let (db, pos) = TestDB::with_position(
72 r#"
73//- /main.rs crate:main deps:std
74
75async fn foo() -> u64 {
76 128
77}
78
79fn test() {
80 let r = foo();
81 r<|>;
82}
83
84//- /std.rs crate:std
85#[prelude_import] use future::*;
86mod 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]
41fn infer_try() { 98fn 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 {}
1129impl ast::TypeParamsOwner for FnDef {} 1129impl ast::TypeParamsOwner for FnDef {}
1130impl ast::AttrsOwner for FnDef {} 1130impl ast::AttrsOwner for FnDef {}
1131impl ast::DocCommentsOwner for FnDef {} 1131impl ast::DocCommentsOwner for FnDef {}
1132impl ast::AsyncOwner for FnDef {}
1132impl FnDef { 1133impl 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
13pub trait TypeAscriptionOwner: AstNode { 14pub trait TypeAscriptionOwner: AstNode {
@@ -105,6 +106,12 @@ pub trait AttrsOwner: AstNode {
105 } 106 }
106} 107}
107 108
109pub 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
108pub trait DocCommentsOwner: AstNode { 115pub 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 ),