From 5ac9f5cdc7a88dcb9545d2e150780c8edee83b06 Mon Sep 17 00:00:00 2001 From: Unreal Hoang Date: Sat, 20 Jul 2019 19:35:49 +0900 Subject: add await expr to ast --- crates/ra_hir/src/ty/infer.rs | 3 +++ 1 file changed, 3 insertions(+) (limited to 'crates/ra_hir/src/ty') diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 0e030576d..6eae595a9 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -1114,6 +1114,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { .unwrap_or(Ty::Unknown); self.insert_type_vars(ty) } + Expr::Await { .. } => { + Ty::Unknown + } Expr::Try { expr } => { let inner_ty = self.infer_expr(*expr, &Expectation::none()); let ty = match self.resolve_ops_try_ok() { -- cgit v1.2.3 From bacf926a77a3e4040ccaf64cce1b1517e41a8d47 Mon Sep 17 00:00:00 2001 From: Unreal Hoang Date: Sat, 20 Jul 2019 20:11:18 +0900 Subject: infer type for await by projecting inner_ty to Future::Output alias --- crates/ra_hir/src/ty/infer.rs | 42 ++++++++++++++++++++++++++++++++++++++++-- crates/ra_hir/src/ty/tests.rs | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) (limited to 'crates/ra_hir/src/ty') diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 6eae595a9..a82dff711 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs @@ -1114,8 +1114,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { .unwrap_or(Ty::Unknown); self.insert_type_vars(ty) } - Expr::Await { .. } => { - Ty::Unknown + Expr::Await { expr } => { + let inner_ty = self.infer_expr(*expr, &Expectation::none()); + let ty = match self.resolve_future_future_output() { + Some(future_future_output_alias) => { + let ty = self.new_type_var(); + let projection = ProjectionPredicate { + ty: ty.clone(), + projection_ty: ProjectionTy { + associated_ty: future_future_output_alias, + parameters: vec![inner_ty].into(), + }, + }; + self.obligations.push(Obligation::Projection(projection)); + self.resolve_ty_as_possible(&mut vec![], ty) + } + None => Ty::Unknown, + }; + ty } Expr::Try { expr } => { let inner_ty = self.infer_expr(*expr, &Expectation::none()); @@ -1371,6 +1387,28 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { _ => None, } } + + fn resolve_future_future_output(&self) -> Option { + let future_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 }, + ], + }; + + match self + .resolver + .resolve_path_segments(self.db, &future_future_path) + .into_fully_resolved() + { + PerNs { types: Some(Def(Trait(trait_))), .. } => { + Some(trait_.associated_type_by_name(self.db, name::OUTPUT)?) + } + _ => None, + } + } } /// The ID of a type variable. diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 265740e54..d4bfcb888 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs @@ -20,6 +20,41 @@ use crate::{ // against snapshots of the expected results using insta. Use cargo-insta to // update the snapshots. +#[test] +fn infer_await() { + let (mut db, pos) = MockDatabase::with_position( + r#" +//- /main.rs + +struct IntFuture; + +impl Future for IntFuture { + type Output = u64; +} + +fn test() { + let r = IntFuture; + let v = r.await; + v<|>; +} + +//- /std.rs +#[prelude_import] use future::*; +mod future { + trait Future { + type Output; + } +} + +"#, + ); + db.set_crate_graph_from_fixture(crate_graph! { + "main": ("/main.rs", ["std"]), + "std": ("/std.rs", []), + }); + assert_eq!("u64", type_at_pos(&db, pos)); +} + #[test] fn infer_try() { let (mut db, pos) = MockDatabase::with_position( -- cgit v1.2.3