diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-07-20 12:27:50 +0100 |
---|---|---|
committer | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2019-07-20 12:27:50 +0100 |
commit | dac6adbef90286f053f034eace9df65d6a19c0ff (patch) | |
tree | fe3376a1bdd3649240465fb6711f4b21cffd47f1 /crates/ra_hir/src | |
parent | 6b352ffeb346eb7c7e46e00e790c2f395907eaa6 (diff) | |
parent | bacf926a77a3e4040ccaf64cce1b1517e41a8d47 (diff) |
Merge #1562
1562: Continue support for .await r=matklad a=unrealhoang
- add await expr to ast and HIR Expr
- infer type for `.await`
Co-authored-by: Unreal Hoang <[email protected]>
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/expr.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/name.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 41 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 35 |
4 files changed, 87 insertions, 0 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 6eed67f50..4dcea19a9 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -220,6 +220,9 @@ pub enum Expr { | |||
220 | expr: ExprId, | 220 | expr: ExprId, |
221 | name: Name, | 221 | name: Name, |
222 | }, | 222 | }, |
223 | Await { | ||
224 | expr: ExprId, | ||
225 | }, | ||
223 | Try { | 226 | Try { |
224 | expr: ExprId, | 227 | expr: ExprId, |
225 | }, | 228 | }, |
@@ -359,6 +362,7 @@ impl Expr { | |||
359 | f(*rhs); | 362 | f(*rhs); |
360 | } | 363 | } |
361 | Expr::Field { expr, .. } | 364 | Expr::Field { expr, .. } |
365 | | Expr::Await { expr } | ||
362 | | Expr::Try { expr } | 366 | | Expr::Try { expr } |
363 | | Expr::Cast { expr, .. } | 367 | | Expr::Cast { expr, .. } |
364 | | Expr::Ref { expr, .. } | 368 | | Expr::Ref { expr, .. } |
@@ -729,6 +733,10 @@ where | |||
729 | }; | 733 | }; |
730 | self.alloc_expr(Expr::Field { expr, name }, syntax_ptr) | 734 | self.alloc_expr(Expr::Field { expr, name }, syntax_ptr) |
731 | } | 735 | } |
736 | ast::ExprKind::AwaitExpr(e) => { | ||
737 | let expr = self.collect_expr_opt(e.expr()); | ||
738 | self.alloc_expr(Expr::Await { expr }, syntax_ptr) | ||
739 | } | ||
732 | ast::ExprKind::TryExpr(e) => { | 740 | ast::ExprKind::TryExpr(e) => { |
733 | let expr = self.collect_expr_opt(e.expr()); | 741 | let expr = self.collect_expr_opt(e.expr()); |
734 | self.alloc_expr(Expr::Try { expr }, syntax_ptr) | 742 | self.alloc_expr(Expr::Try { expr }, syntax_ptr) |
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs index c589f8aba..6d14eea8e 100644 --- a/crates/ra_hir/src/name.rs +++ b/crates/ra_hir/src/name.rs | |||
@@ -118,6 +118,9 @@ pub(crate) const ITEM: Name = Name::new(SmolStr::new_inline_from_ascii(4, b"Item | |||
118 | pub(crate) const OPS: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"ops")); | 118 | pub(crate) const OPS: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"ops")); |
119 | pub(crate) const TRY: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Try")); | 119 | pub(crate) const TRY: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Try")); |
120 | pub(crate) const OK: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok")); | 120 | pub(crate) const OK: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok")); |
121 | pub(crate) const FUTURE_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"future")); | ||
122 | pub(crate) const FUTURE_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Future")); | ||
123 | pub(crate) const OUTPUT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output")); | ||
121 | 124 | ||
122 | fn resolve_name(text: &SmolStr) -> SmolStr { | 125 | fn resolve_name(text: &SmolStr) -> SmolStr { |
123 | let raw_start = "r#"; | 126 | let raw_start = "r#"; |
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 0e030576d..a82dff711 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -1114,6 +1114,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1114 | .unwrap_or(Ty::Unknown); | 1114 | .unwrap_or(Ty::Unknown); |
1115 | self.insert_type_vars(ty) | 1115 | self.insert_type_vars(ty) |
1116 | } | 1116 | } |
1117 | Expr::Await { expr } => { | ||
1118 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); | ||
1119 | let ty = match self.resolve_future_future_output() { | ||
1120 | Some(future_future_output_alias) => { | ||
1121 | let ty = self.new_type_var(); | ||
1122 | let projection = ProjectionPredicate { | ||
1123 | ty: ty.clone(), | ||
1124 | projection_ty: ProjectionTy { | ||
1125 | associated_ty: future_future_output_alias, | ||
1126 | parameters: vec![inner_ty].into(), | ||
1127 | }, | ||
1128 | }; | ||
1129 | self.obligations.push(Obligation::Projection(projection)); | ||
1130 | self.resolve_ty_as_possible(&mut vec![], ty) | ||
1131 | } | ||
1132 | None => Ty::Unknown, | ||
1133 | }; | ||
1134 | ty | ||
1135 | } | ||
1117 | Expr::Try { expr } => { | 1136 | Expr::Try { expr } => { |
1118 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); | 1137 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); |
1119 | let ty = match self.resolve_ops_try_ok() { | 1138 | let ty = match self.resolve_ops_try_ok() { |
@@ -1368,6 +1387,28 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1368 | _ => None, | 1387 | _ => None, |
1369 | } | 1388 | } |
1370 | } | 1389 | } |
1390 | |||
1391 | fn resolve_future_future_output(&self) -> Option<TypeAlias> { | ||
1392 | let future_future_path = Path { | ||
1393 | kind: PathKind::Abs, | ||
1394 | segments: vec![ | ||
1395 | PathSegment { name: name::STD, args_and_bindings: None }, | ||
1396 | PathSegment { name: name::FUTURE_MOD, args_and_bindings: None }, | ||
1397 | PathSegment { name: name::FUTURE_TYPE, args_and_bindings: None }, | ||
1398 | ], | ||
1399 | }; | ||
1400 | |||
1401 | match self | ||
1402 | .resolver | ||
1403 | .resolve_path_segments(self.db, &future_future_path) | ||
1404 | .into_fully_resolved() | ||
1405 | { | ||
1406 | PerNs { types: Some(Def(Trait(trait_))), .. } => { | ||
1407 | Some(trait_.associated_type_by_name(self.db, name::OUTPUT)?) | ||
1408 | } | ||
1409 | _ => None, | ||
1410 | } | ||
1411 | } | ||
1371 | } | 1412 | } |
1372 | 1413 | ||
1373 | /// The ID of a type variable. | 1414 | /// 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 7b2bdeb3f..706500484 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -21,6 +21,41 @@ use crate::{ | |||
21 | // update the snapshots. | 21 | // update the snapshots. |
22 | 22 | ||
23 | #[test] | 23 | #[test] |
24 | fn infer_await() { | ||
25 | let (mut db, pos) = MockDatabase::with_position( | ||
26 | r#" | ||
27 | //- /main.rs | ||
28 | |||
29 | struct IntFuture; | ||
30 | |||
31 | impl Future for IntFuture { | ||
32 | type Output = u64; | ||
33 | } | ||
34 | |||
35 | fn test() { | ||
36 | let r = IntFuture; | ||
37 | let v = r.await; | ||
38 | v<|>; | ||
39 | } | ||
40 | |||
41 | //- /std.rs | ||
42 | #[prelude_import] use future::*; | ||
43 | mod future { | ||
44 | trait Future { | ||
45 | type Output; | ||
46 | } | ||
47 | } | ||
48 | |||
49 | "#, | ||
50 | ); | ||
51 | db.set_crate_graph_from_fixture(crate_graph! { | ||
52 | "main": ("/main.rs", ["std"]), | ||
53 | "std": ("/std.rs", []), | ||
54 | }); | ||
55 | assert_eq!("u64", type_at_pos(&db, pos)); | ||
56 | } | ||
57 | |||
58 | #[test] | ||
24 | fn infer_try() { | 59 | fn infer_try() { |
25 | let (mut db, pos) = MockDatabase::with_position( | 60 | let (mut db, pos) = MockDatabase::with_position( |
26 | r#" | 61 | r#" |