diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-16 15:11:19 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-16 15:11:19 +0000 |
commit | 454cc313589fb17de92d6f3dbf576a5ea5f4adf2 (patch) | |
tree | e67129e4e514e140463d8f0f7bd7556793cac484 | |
parent | d75a0368f5048243d6561e42e77835f6f574b321 (diff) | |
parent | 0aedd4fb2f28ec24902d26c7d8a24d6146263d2f (diff) |
Merge #524
524: Implement array inference r=flodiebold a=h-michael
related #394
Co-authored-by: Hirokazu Hata <[email protected]>
-rw-r--r-- | crates/ra_hir/src/expr.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 26 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 26 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests/data/array.txt | 52 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/generated.rs | 6 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar.ron | 4 |
6 files changed, 115 insertions, 9 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 663338844..6e98ebc69 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -197,6 +197,9 @@ pub enum Expr { | |||
197 | Tuple { | 197 | Tuple { |
198 | exprs: Vec<ExprId>, | 198 | exprs: Vec<ExprId>, |
199 | }, | 199 | }, |
200 | Array { | ||
201 | exprs: Vec<ExprId>, | ||
202 | }, | ||
200 | Literal(Literal), | 203 | Literal(Literal), |
201 | } | 204 | } |
202 | 205 | ||
@@ -312,7 +315,7 @@ impl Expr { | |||
312 | | Expr::UnaryOp { expr, .. } => { | 315 | | Expr::UnaryOp { expr, .. } => { |
313 | f(*expr); | 316 | f(*expr); |
314 | } | 317 | } |
315 | Expr::Tuple { exprs } => { | 318 | Expr::Tuple { exprs } | Expr::Array { exprs } => { |
316 | for expr in exprs { | 319 | for expr in exprs { |
317 | f(*expr); | 320 | f(*expr); |
318 | } | 321 | } |
@@ -649,6 +652,10 @@ impl ExprCollector { | |||
649 | let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect(); | 652 | let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect(); |
650 | self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr) | 653 | self.alloc_expr(Expr::Tuple { exprs }, syntax_ptr) |
651 | } | 654 | } |
655 | ast::ExprKind::ArrayExpr(e) => { | ||
656 | let exprs = e.exprs().map(|expr| self.collect_expr(expr)).collect(); | ||
657 | self.alloc_expr(Expr::Array { exprs }, syntax_ptr) | ||
658 | } | ||
652 | ast::ExprKind::Literal(e) => { | 659 | ast::ExprKind::Literal(e) => { |
653 | let child = if let Some(child) = e.literal_expr() { | 660 | let child = if let Some(child) = e.literal_expr() { |
654 | child | 661 | child |
@@ -691,7 +698,6 @@ impl ExprCollector { | |||
691 | // TODO implement HIR for these: | 698 | // TODO implement HIR for these: |
692 | ast::ExprKind::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | 699 | ast::ExprKind::Label(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), |
693 | ast::ExprKind::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | 700 | ast::ExprKind::IndexExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), |
694 | ast::ExprKind::ArrayExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | ||
695 | ast::ExprKind::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), | 701 | ast::ExprKind::RangeExpr(_e) => self.alloc_expr(Expr::Missing, syntax_ptr), |
696 | } | 702 | } |
697 | } | 703 | } |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 85d4dc05c..c7c063601 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -181,11 +181,12 @@ pub enum Ty { | |||
181 | /// The pointee of a string slice. Written as `str`. | 181 | /// The pointee of a string slice. Written as `str`. |
182 | Str, | 182 | Str, |
183 | 183 | ||
184 | // An array with the given length. Written as `[T; n]`. | ||
185 | // Array(Ty, ty::Const), | ||
186 | /// The pointee of an array slice. Written as `[T]`. | 184 | /// The pointee of an array slice. Written as `[T]`. |
187 | Slice(Arc<Ty>), | 185 | Slice(Arc<Ty>), |
188 | 186 | ||
187 | // An array with the given length. Written as `[T; n]`. | ||
188 | Array(Arc<Ty>), | ||
189 | |||
189 | /// A raw pointer. Written as `*mut T` or `*const T` | 190 | /// A raw pointer. Written as `*mut T` or `*const T` |
190 | RawPtr(Arc<Ty>, Mutability), | 191 | RawPtr(Arc<Ty>, Mutability), |
191 | 192 | ||
@@ -276,7 +277,10 @@ impl Ty { | |||
276 | let inner_ty = Ty::from_hir(db, module, impl_block, inner); | 277 | let inner_ty = Ty::from_hir(db, module, impl_block, inner); |
277 | Ty::RawPtr(Arc::new(inner_ty), *mutability) | 278 | Ty::RawPtr(Arc::new(inner_ty), *mutability) |
278 | } | 279 | } |
279 | TypeRef::Array(_inner) => Ty::Unknown, // TODO | 280 | TypeRef::Array(inner) => { |
281 | let inner_ty = Ty::from_hir(db, module, impl_block, inner); | ||
282 | Ty::Array(Arc::new(inner_ty)) | ||
283 | } | ||
280 | TypeRef::Slice(inner) => { | 284 | TypeRef::Slice(inner) => { |
281 | let inner_ty = Ty::from_hir(db, module, impl_block, inner); | 285 | let inner_ty = Ty::from_hir(db, module, impl_block, inner); |
282 | Ty::Slice(Arc::new(inner_ty)) | 286 | Ty::Slice(Arc::new(inner_ty)) |
@@ -352,7 +356,7 @@ impl Ty { | |||
352 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 356 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
353 | f(self); | 357 | f(self); |
354 | match self { | 358 | match self { |
355 | Ty::Slice(t) => Arc::make_mut(t).walk_mut(f), | 359 | Ty::Slice(t) | Ty::Array(t) => Arc::make_mut(t).walk_mut(f), |
356 | Ty::RawPtr(t, _) => Arc::make_mut(t).walk_mut(f), | 360 | Ty::RawPtr(t, _) => Arc::make_mut(t).walk_mut(f), |
357 | Ty::Ref(t, _) => Arc::make_mut(t).walk_mut(f), | 361 | Ty::Ref(t, _) => Arc::make_mut(t).walk_mut(f), |
358 | Ty::Tuple(ts) => { | 362 | Ty::Tuple(ts) => { |
@@ -400,7 +404,7 @@ impl fmt::Display for Ty { | |||
400 | Ty::Int(t) => write!(f, "{}", t.ty_to_string()), | 404 | Ty::Int(t) => write!(f, "{}", t.ty_to_string()), |
401 | Ty::Float(t) => write!(f, "{}", t.ty_to_string()), | 405 | Ty::Float(t) => write!(f, "{}", t.ty_to_string()), |
402 | Ty::Str => write!(f, "str"), | 406 | Ty::Str => write!(f, "str"), |
403 | Ty::Slice(t) => write!(f, "[{}]", t), | 407 | Ty::Slice(t) | Ty::Array(t) => write!(f, "[{}]", t), |
404 | Ty::RawPtr(t, m) => write!(f, "*{}{}", m.as_keyword_for_ptr(), t), | 408 | Ty::RawPtr(t, m) => write!(f, "*{}{}", m.as_keyword_for_ptr(), t), |
405 | Ty::Ref(t, m) => write!(f, "&{}{}", m.as_keyword_for_ref(), t), | 409 | Ty::Ref(t, m) => write!(f, "&{}{}", m.as_keyword_for_ref(), t), |
406 | Ty::Never => write!(f, "!"), | 410 | Ty::Never => write!(f, "!"), |
@@ -1102,6 +1106,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1102 | 1106 | ||
1103 | Ty::Tuple(Arc::from(ty_vec)) | 1107 | Ty::Tuple(Arc::from(ty_vec)) |
1104 | } | 1108 | } |
1109 | Expr::Array { exprs } => { | ||
1110 | let elem_ty = match &expected.ty { | ||
1111 | Ty::Slice(inner) | Ty::Array(inner) => Ty::clone(&inner), | ||
1112 | _ => self.new_type_var(), | ||
1113 | }; | ||
1114 | |||
1115 | for expr in exprs.iter() { | ||
1116 | self.infer_expr(*expr, &Expectation::has_type(elem_ty.clone())); | ||
1117 | } | ||
1118 | |||
1119 | Ty::Array(Arc::new(elem_ty)) | ||
1120 | } | ||
1105 | Expr::Literal(lit) => match lit { | 1121 | Expr::Literal(lit) => match lit { |
1106 | Literal::Bool(..) => Ty::Bool, | 1122 | Literal::Bool(..) => Ty::Bool, |
1107 | Literal::String(..) => Ty::Ref(Arc::new(Ty::Str), Mutability::Shared), | 1123 | Literal::String(..) => Ty::Ref(Arc::new(Ty::Str), Mutability::Shared), |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 5d7bc25cc..affd63a85 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -334,6 +334,32 @@ fn test(x: &str, y: isize) { | |||
334 | ); | 334 | ); |
335 | } | 335 | } |
336 | 336 | ||
337 | #[test] | ||
338 | fn infer_array() { | ||
339 | check_inference( | ||
340 | r#" | ||
341 | fn test(x: &str, y: isize) { | ||
342 | let a = [x]; | ||
343 | let b = [a, a]; | ||
344 | let c = [b, b]; | ||
345 | |||
346 | let d = [y, 1, 2, 3]; | ||
347 | let d = [1, y, 2, 3]; | ||
348 | let e = [y]; | ||
349 | let f = [d, d]; | ||
350 | let g = [e, e]; | ||
351 | |||
352 | let h = [1, 2]; | ||
353 | let i = ["a", "b"]; | ||
354 | |||
355 | let b = [a, ["b"]]; | ||
356 | let x: [u8; 0] = []; | ||
357 | } | ||
358 | "#, | ||
359 | "array.txt", | ||
360 | ); | ||
361 | } | ||
362 | |||
337 | fn infer(content: &str) -> String { | 363 | fn infer(content: &str) -> String { |
338 | let (db, _, file_id) = MockDatabase::with_single_file(content); | 364 | let (db, _, file_id) = MockDatabase::with_single_file(content); |
339 | let source_file = db.source_file(file_id); | 365 | let source_file = db.source_file(file_id); |
diff --git a/crates/ra_hir/src/ty/tests/data/array.txt b/crates/ra_hir/src/ty/tests/data/array.txt new file mode 100644 index 000000000..acdf74ba4 --- /dev/null +++ b/crates/ra_hir/src/ty/tests/data/array.txt | |||
@@ -0,0 +1,52 @@ | |||
1 | [9; 10) 'x': &str | ||
2 | [18; 19) 'y': isize | ||
3 | [28; 293) '{ ... []; }': () | ||
4 | [38; 39) 'a': [&str] | ||
5 | [42; 45) '[x]': [&str] | ||
6 | [43; 44) 'x': &str | ||
7 | [55; 56) 'b': [[&str]] | ||
8 | [59; 65) '[a, a]': [[&str]] | ||
9 | [60; 61) 'a': [&str] | ||
10 | [63; 64) 'a': [&str] | ||
11 | [75; 76) 'c': [[[&str]]] | ||
12 | [79; 85) '[b, b]': [[[&str]]] | ||
13 | [80; 81) 'b': [[&str]] | ||
14 | [83; 84) 'b': [[&str]] | ||
15 | [96; 97) 'd': [isize] | ||
16 | [100; 112) '[y, 1, 2, 3]': [isize] | ||
17 | [101; 102) 'y': isize | ||
18 | [104; 105) '1': isize | ||
19 | [107; 108) '2': isize | ||
20 | [110; 111) '3': isize | ||
21 | [122; 123) 'd': [isize] | ||
22 | [126; 138) '[1, y, 2, 3]': [isize] | ||
23 | [127; 128) '1': isize | ||
24 | [130; 131) 'y': isize | ||
25 | [133; 134) '2': isize | ||
26 | [136; 137) '3': isize | ||
27 | [148; 149) 'e': [isize] | ||
28 | [152; 155) '[y]': [isize] | ||
29 | [153; 154) 'y': isize | ||
30 | [165; 166) 'f': [[isize]] | ||
31 | [169; 175) '[d, d]': [[isize]] | ||
32 | [170; 171) 'd': [isize] | ||
33 | [173; 174) 'd': [isize] | ||
34 | [185; 186) 'g': [[isize]] | ||
35 | [189; 195) '[e, e]': [[isize]] | ||
36 | [190; 191) 'e': [isize] | ||
37 | [193; 194) 'e': [isize] | ||
38 | [206; 207) 'h': [i32] | ||
39 | [210; 216) '[1, 2]': [i32] | ||
40 | [211; 212) '1': i32 | ||
41 | [214; 215) '2': i32 | ||
42 | [226; 227) 'i': [&str] | ||
43 | [230; 240) '["a", "b"]': [&str] | ||
44 | [231; 234) '"a"': &str | ||
45 | [236; 239) '"b"': &str | ||
46 | [251; 252) 'b': [[&str]] | ||
47 | [255; 265) '[a, ["b"]]': [[&str]] | ||
48 | [256; 257) 'a': [&str] | ||
49 | [259; 264) '["b"]': [&str] | ||
50 | [260; 263) '"b"': &str | ||
51 | [275; 276) 'x': [u8] | ||
52 | [288; 290) '[]': [u8] | ||
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 3471d5226..2d9603d90 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs | |||
@@ -67,7 +67,11 @@ impl AstNode for ArrayExpr { | |||
67 | } | 67 | } |
68 | 68 | ||
69 | 69 | ||
70 | impl ArrayExpr {} | 70 | impl ArrayExpr { |
71 | pub fn exprs(&self) -> impl Iterator<Item = &Expr> { | ||
72 | super::children(self) | ||
73 | } | ||
74 | } | ||
71 | 75 | ||
72 | // ArrayType | 76 | // ArrayType |
73 | #[derive(Debug, PartialEq, Eq, Hash)] | 77 | #[derive(Debug, PartialEq, Eq, Hash)] |
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index bd8c5b411..2aaad46b1 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron | |||
@@ -360,7 +360,9 @@ Grammar( | |||
360 | "TupleExpr": ( | 360 | "TupleExpr": ( |
361 | collections: [["exprs", "Expr"]] | 361 | collections: [["exprs", "Expr"]] |
362 | ), | 362 | ), |
363 | "ArrayExpr": (), | 363 | "ArrayExpr": ( |
364 | collections: [["exprs", "Expr"]] | ||
365 | ), | ||
364 | "ParenExpr": (options: ["Expr"]), | 366 | "ParenExpr": (options: ["Expr"]), |
365 | "PathExpr": (options: ["Path"]), | 367 | "PathExpr": (options: ["Path"]), |
366 | "LambdaExpr": ( | 368 | "LambdaExpr": ( |