diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 593fe15981fc..f0936e9f33a2 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs @@ -183,6 +183,9 @@ pub enum Expr { arg_types: Vec>, body: ExprId, }, + Tuple { + exprs: Vec, + }, } pub use ra_syntax::ast::PrefixOp as UnaryOp; @@ -297,6 +300,11 @@ impl Expr { | Expr::UnaryOp { expr, .. } => { f(*expr); } + Expr::Tuple { exprs } => { + for expr in exprs { + f(*expr); + } + } } } } @@ -621,11 +629,14 @@ impl ExprCollector { let op = e.op(); self.alloc_expr(Expr::BinaryOp { lhs, rhs, op }, syntax_ptr) } + ast::ExprKind::TupleExpr(e) => { + let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect(); + self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr) + } // TODO implement HIR for these: ast::ExprKind::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), ast::ExprKind::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), - ast::ExprKind::TupleExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), ast::ExprKind::ArrayExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), ast::ExprKind::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), 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 5d5568d69a0a..0692d3b2a838 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> { } _ => Ty::Unknown, }, + Expr::Tuple { exprs } => { + let mut ty_vec = Vec::with_capacity(exprs.len()); + for arg in exprs.iter() { + ty_vec.push(self.infer_expr(*arg, &Expectation::none())?); + } + + Ty::Tuple(Arc::from(ty_vec)) + } }; // use a new type variable if we got Ty::Unknown here 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 1c31294410dc..920188fc912a 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) { ); } +#[test] +fn infer_tuple() { + check_inference( + r#" +fn test(x: &str, y: isize) { + let a: (u32, &str) = (1, "a"); + let b = (a, x); + let c = (y, x); + let d = (c, x); + + // we have not infered these case yet. + let e = (1, "e"); + let f = (e, "d"); +} +"#, + "tuple.txt", + ); +} + fn infer(content: &str) -> String { let (db, _, file_id) = MockDatabase::with_single_file(content); 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 000000000000..96169180d499 --- /dev/null +++ b/crates/ra_hir/src/ty/tests/data/tuple.txt @@ -0,0 +1,27 @@ +[9; 10) 'x': &str +[18; 19) 'y': isize +[28; 214) '{ ...d"); }': () +[38; 39) 'a': (u32, &str) +[55; 63) '(1, "a")': (u32, &str) +[56; 57) '1': u32 +[59; 62) '"a"': &str +[73; 74) 'b': ((u32, &str), &str) +[77; 83) '(a, x)': ((u32, &str), &str) +[78; 79) 'a': (u32, &str) +[81; 82) 'x': &str +[93; 94) 'c': (isize, &str) +[97; 103) '(y, x)': (isize, &str) +[98; 99) 'y': isize +[101; 102) 'x': &str +[113; 114) 'd': ((isize, &str), &str) +[117; 123) '(c, x)': ((isize, &str), &str) +[118; 119) 'c': (isize, &str) +[121; 122) 'x': &str +[177; 178) 'e': ([unknown], [unknown]) +[181; 189) '(1, "e")': ([unknown], [unknown]) +[182; 183) '1': [unknown] +[185; 188) '"e"': [unknown] +[199; 200) 'f': (([unknown], [unknown]), [unknown]) +[203; 211) '(e, "d")': (([unknown], [unknown]), [unknown]) +[204; 205) 'e': ([unknown], [unknown]) +[207; 210) '"d"': [unknown] diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index f745cb1cbfe6..94842a51434e 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs @@ -2969,7 +2969,11 @@ impl AstNode for TupleExpr { } -impl TupleExpr {} +impl TupleExpr { + pub fn exprs(&self) -> impl Iterator { + super::children(self) + } +} // TuplePat #[derive(Debug, PartialEq, Eq, Hash)] diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index bac62fa0478d..dfd88bd10957 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron @@ -357,7 +357,9 @@ Grammar( enum: ["FnDef", "TypeDef", "ConstDef"] ), - "TupleExpr": (), + "TupleExpr": ( + collections: [["exprs", "Expr"]] + ), "ArrayExpr": (), "ParenExpr": (options: ["Expr"]), "PathExpr": (options: ["Path"]),