aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-07-20 12:27:50 +0100
committerbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-07-20 12:27:50 +0100
commitdac6adbef90286f053f034eace9df65d6a19c0ff (patch)
treefe3376a1bdd3649240465fb6711f4b21cffd47f1 /crates/ra_hir
parent6b352ffeb346eb7c7e46e00e790c2f395907eaa6 (diff)
parentbacf926a77a3e4040ccaf64cce1b1517e41a8d47 (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')
-rw-r--r--crates/ra_hir/src/expr.rs8
-rw-r--r--crates/ra_hir/src/name.rs3
-rw-r--r--crates/ra_hir/src/ty/infer.rs41
-rw-r--r--crates/ra_hir/src/ty/tests.rs35
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
118pub(crate) const OPS: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"ops")); 118pub(crate) const OPS: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"ops"));
119pub(crate) const TRY: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Try")); 119pub(crate) const TRY: Name = Name::new(SmolStr::new_inline_from_ascii(3, b"Try"));
120pub(crate) const OK: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok")); 120pub(crate) const OK: Name = Name::new(SmolStr::new_inline_from_ascii(2, b"Ok"));
121pub(crate) const FUTURE_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"future"));
122pub(crate) const FUTURE_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Future"));
123pub(crate) const OUTPUT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output"));
121 124
122fn resolve_name(text: &SmolStr) -> SmolStr { 125fn 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]
24fn infer_await() {
25 let (mut db, pos) = MockDatabase::with_position(
26 r#"
27//- /main.rs
28
29struct IntFuture;
30
31impl Future for IntFuture {
32 type Output = u64;
33}
34
35fn test() {
36 let r = IntFuture;
37 let v = r.await;
38 v<|>;
39}
40
41//- /std.rs
42#[prelude_import] use future::*;
43mod 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]
24fn infer_try() { 59fn infer_try() {
25 let (mut db, pos) = MockDatabase::with_position( 60 let (mut db, pos) = MockDatabase::with_position(
26 r#" 61 r#"