aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir_def/src/data.rs21
-rw-r--r--crates/ra_hir_def/src/path.rs8
-rw-r--r--crates/ra_hir_ty/src/infer.rs23
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs57
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs4
-rw-r--r--xtask/src/main.rs2
6 files changed, 111 insertions, 4 deletions
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs
index 1aa9a9b7d..c900a6a18 100644
--- a/crates/ra_hir_def/src/data.rs
+++ b/crates/ra_hir_def/src/data.rs
@@ -10,8 +10,9 @@ use ra_syntax::ast::{self, AstNode, ImplItem, ModuleItemOwner, NameOwner, TypeAs
10 10
11use crate::{ 11use crate::{
12 db::DefDatabase, 12 db::DefDatabase,
13 path::{path, GenericArgs, Path},
13 src::HasSource, 14 src::HasSource,
14 type_ref::{Mutability, TypeRef}, 15 type_ref::{Mutability, TypeBound, TypeRef},
15 AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule, 16 AssocContainerId, AssocItemId, ConstId, ConstLoc, Expander, FunctionId, FunctionLoc, HasModule,
16 ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, 17 ImplId, Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
17}; 18};
@@ -62,11 +63,29 @@ impl FunctionData {
62 TypeRef::unit() 63 TypeRef::unit()
63 }; 64 };
64 65
66 let ret_type = if src.value.is_async() {
67 let future_impl = desugar_future_path(ret_type);
68 let ty_bound = TypeBound::Path(future_impl);
69 TypeRef::ImplTrait(vec![ty_bound])
70 } else {
71 ret_type
72 };
73
65 let sig = FunctionData { name, params, ret_type, has_self_param }; 74 let sig = FunctionData { name, params, ret_type, has_self_param };
66 Arc::new(sig) 75 Arc::new(sig)
67 } 76 }
68} 77}
69 78
79fn desugar_future_path(orig: TypeRef) -> Path {
80 let path = path![std::future::Future];
81 let mut generic_args: Vec<_> = std::iter::repeat(None).take(path.segments.len() - 1).collect();
82 let mut last = GenericArgs::empty();
83 last.bindings.push((name![Output], orig));
84 generic_args.push(Some(Arc::new(last)));
85
86 Path::from_known_path(path, generic_args)
87}
88
70#[derive(Debug, Clone, PartialEq, Eq)] 89#[derive(Debug, Clone, PartialEq, Eq)]
71pub struct TypeAliasData { 90pub struct TypeAliasData {
72 pub name: Name, 91 pub name: Name,
diff --git a/crates/ra_hir_def/src/path.rs b/crates/ra_hir_def/src/path.rs
index 8e1294201..107d2d799 100644
--- a/crates/ra_hir_def/src/path.rs
+++ b/crates/ra_hir_def/src/path.rs
@@ -130,6 +130,14 @@ 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(
135 path: ModPath,
136 generic_args: Vec<Option<Arc<GenericArgs>>>,
137 ) -> Path {
138 Path { type_anchor: None, mod_path: path, generic_args }
139 }
140
133 pub fn kind(&self) -> &PathKind { 141 pub fn kind(&self) -> &PathKind {
134 &self.mod_path.kind 142 &self.mod_path.kind
135 } 143 }
diff --git a/crates/ra_hir_ty/src/infer.rs b/crates/ra_hir_ty/src/infer.rs
index e97b81473..32c0d07a5 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,25 @@ 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 // FIXME:
383 // Check if inner_ty is is `impl Trait` and contained input TypeAlias id
384 // this is a workaround while Chalk assoc type projection doesn't always work yet,
385 // but once that is fixed I don't think we should keep this
386 // (we'll probably change how associated types are resolved anyway)
387 if let Ty::Opaque(ref predicates) = inner_ty {
388 for p in predicates.iter() {
389 if let GenericPredicate::Projection(projection) = p {
390 if projection.projection_ty.associated_ty == res_assoc_ty {
391 if let ty_app!(_, params) = &projection.ty {
392 if params.len() == 0 {
393 return projection.ty.clone();
394 }
395 }
396 }
397 }
398 }
399 }
400
382 let ty = self.table.new_type_var(); 401 let ty = self.table.new_type_var();
383 let builder = Substs::build_for_def(self.db, res_assoc_ty) 402 let builder = Substs::build_for_def(self.db, res_assoc_ty)
384 .push(inner_ty) 403 .push(inner_ty)
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs
index ae316922b..0bc72644a 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/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index a8f625176..baaef3023 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -221,6 +221,10 @@ impl ast::FnDef {
221 .and_then(|it| it.into_token()) 221 .and_then(|it| it.into_token())
222 .filter(|it| it.kind() == T![;]) 222 .filter(|it| it.kind() == T![;])
223 } 223 }
224
225 pub fn is_async(&self) -> bool {
226 self.syntax().children_with_tokens().any(|it| it.kind() == T![async])
227 }
224} 228}
225 229
226impl ast::LetStmt { 230impl ast::LetStmt {
diff --git a/xtask/src/main.rs b/xtask/src/main.rs
index 4201c6a6a..9cefad925 100644
--- a/xtask/src/main.rs
+++ b/xtask/src/main.rs
@@ -226,7 +226,7 @@ fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> {
226 if !str::from_utf8(&output.stdout)?.contains("ra-lsp") { 226 if !str::from_utf8(&output.stdout)?.contains("ra-lsp") {
227 anyhow::bail!( 227 anyhow::bail!(
228 "Could not install the Visual Studio Code extension. \ 228 "Could not install the Visual Studio Code extension. \
229 Please make sure you have at least NodeJS 10.x installed and try again." 229 Please make sure you have at least NodeJS 10.x together with the latest version of VS Code installed and try again."
230 ); 230 );
231 } 231 }
232 232