diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/expr.rs | 13 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 19 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests/data/tuple.txt | 27 |
4 files changed, 66 insertions, 1 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 593fe1598..f0936e9f3 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -183,6 +183,9 @@ pub enum Expr { | |||
183 | arg_types: Vec<Option<TypeRef>>, | 183 | arg_types: Vec<Option<TypeRef>>, |
184 | body: ExprId, | 184 | body: ExprId, |
185 | }, | 185 | }, |
186 | Tuple { | ||
187 | exprs: Vec<ExprId>, | ||
188 | }, | ||
186 | } | 189 | } |
187 | 190 | ||
188 | pub use ra_syntax::ast::PrefixOp as UnaryOp; | 191 | pub use ra_syntax::ast::PrefixOp as UnaryOp; |
@@ -297,6 +300,11 @@ impl Expr { | |||
297 | | Expr::UnaryOp { expr, .. } => { | 300 | | Expr::UnaryOp { expr, .. } => { |
298 | f(*expr); | 301 | f(*expr); |
299 | } | 302 | } |
303 | Expr::Tuple { exprs } => { | ||
304 | for expr in exprs { | ||
305 | f(*expr); | ||
306 | } | ||
307 | } | ||
300 | } | 308 | } |
301 | } | 309 | } |
302 | } | 310 | } |
@@ -621,11 +629,14 @@ impl ExprCollector { | |||
621 | let op = e.op(); | 629 | let op = e.op(); |
622 | self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr) | 630 | self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr) |
623 | } | 631 | } |
632 | ast::ExprKind::TupleExpr(e) => { | ||
633 | let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect(); | ||
634 | self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr) | ||
635 | } | ||
624 | 636 | ||
625 | // TODO implement HIR for these: | 637 | // TODO implement HIR for these: |
626 | ast::ExprKind::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | 638 | ast::ExprKind::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), |
627 | ast::ExprKind::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | 639 | ast::ExprKind::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), |
628 | ast::ExprKind::TupleExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | ||
629 | ast::ExprKind::ArrayExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | 640 | ast::ExprKind::ArrayExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), |
630 | ast::ExprKind::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | 641 | ast::ExprKind::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), |
631 | ast::ExprKind::Literal(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | 642 | ast::ExprKind::Literal(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 5d5568d69..0692d3b2a 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -1040,6 +1040,14 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1040 | } | 1040 | } |
1041 | _ => Ty::Unknown, | 1041 | _ => Ty::Unknown, |
1042 | }, | 1042 | }, |
1043 | Expr::Tuple { exprs } => { | ||
1044 | let mut ty_vec = Vec::with_capacity(exprs.len()); | ||
1045 | for arg in exprs.iter() { | ||
1046 | ty_vec.push(self.infer_expr(*arg, &Expectation::none())?); | ||
1047 | } | ||
1048 | |||
1049 | Ty::Tuple(Arc::from(ty_vec)) | ||
1050 | } | ||
1043 | }; | 1051 | }; |
1044 | // use a new type variable if we got Ty::Unknown here | 1052 | // use a new type variable if we got Ty::Unknown here |
1045 | let ty = self.insert_type_vars_shallow(ty); | 1053 | let ty = self.insert_type_vars_shallow(ty); |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 1c3129441..920188fc9 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -268,6 +268,25 @@ fn test(a: A) { | |||
268 | ); | 268 | ); |
269 | } | 269 | } |
270 | 270 | ||
271 | #[test] | ||
272 | fn infer_tuple() { | ||
273 | check_inference( | ||
274 | r#" | ||
275 | fn test(x: &str, y: isize) { | ||
276 | let a: (u32, &str) = (1, "a"); | ||
277 | let b = (a, x); | ||
278 | let c = (y, x); | ||
279 | let d = (c, x); | ||
280 | |||
281 | // we have not infered these case yet. | ||
282 | let e = (1, "e"); | ||
283 | let f = (e, "d"); | ||
284 | } | ||
285 | "#, | ||
286 | "tuple.txt", | ||
287 | ); | ||
288 | } | ||
289 | |||
271 | fn infer(content: &str) -> String { | 290 | fn infer(content: &str) -> String { |
272 | let (db, _, file_id) = MockDatabase::with_single_file(content); | 291 | let (db, _, file_id) = MockDatabase::with_single_file(content); |
273 | let source_file = db.source_file(file_id); | 292 | let source_file = db.source_file(file_id); |
diff --git a/crates/ra_hir/src/ty/tests/data/tuple.txt b/crates/ra_hir/src/ty/tests/data/tuple.txt new file mode 100644 index 000000000..96169180d --- /dev/null +++ b/crates/ra_hir/src/ty/tests/data/tuple.txt | |||
@@ -0,0 +1,27 @@ | |||
1 | [9; 10) 'x': &str | ||
2 | [18; 19) 'y': isize | ||
3 | [28; 214) '{ ...d"); }': () | ||
4 | [38; 39) 'a': (u32, &str) | ||
5 | [55; 63) '(1, "a")': (u32, &str) | ||
6 | [56; 57) '1': u32 | ||
7 | [59; 62) '"a"': &str | ||
8 | [73; 74) 'b': ((u32, &str), &str) | ||
9 | [77; 83) '(a, x)': ((u32, &str), &str) | ||
10 | [78; 79) 'a': (u32, &str) | ||
11 | [81; 82) 'x': &str | ||
12 | [93; 94) 'c': (isize, &str) | ||
13 | [97; 103) '(y, x)': (isize, &str) | ||
14 | [98; 99) 'y': isize | ||
15 | [101; 102) 'x': &str | ||
16 | [113; 114) 'd': ((isize, &str), &str) | ||
17 | [117; 123) '(c, x)': ((isize, &str), &str) | ||
18 | [118; 119) 'c': (isize, &str) | ||
19 | [121; 122) 'x': &str | ||
20 | [177; 178) 'e': ([unknown], [unknown]) | ||
21 | [181; 189) '(1, "e")': ([unknown], [unknown]) | ||
22 | [182; 183) '1': [unknown] | ||
23 | [185; 188) '"e"': [unknown] | ||
24 | [199; 200) 'f': (([unknown], [unknown]), [unknown]) | ||
25 | [203; 211) '(e, "d")': (([unknown], [unknown]), [unknown]) | ||
26 | [204; 205) 'e': ([unknown], [unknown]) | ||
27 | [207; 210) '"d"': [unknown] | ||