diff options
author | Marcus Klaas de Vries <[email protected]> | 2019-01-28 22:06:11 +0000 |
---|---|---|
committer | Marcus Klaas de Vries <[email protected]> | 2019-01-28 22:09:14 +0000 |
commit | 3daca3eb4d843199540edfb1092f57f49938d0f6 (patch) | |
tree | 4cdc5c921b024d8b348b73e1a7c3e6a56fc11305 /crates | |
parent | 3f4f50baaa21cb2d0f6c102f1ca521946071a8dc (diff) |
Infer type of match guard
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/expr.rs | 8 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 16 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/snapshots/tests__infer_adt_pattern.snap | 23 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 3 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/generated.rs | 6 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar.ron | 2 | ||||
-rw-r--r-- | crates/ra_syntax/src/grammar/expressions/atom.rs | 18 | ||||
-rw-r--r-- | crates/ra_syntax/tests/data/parser/inline/ok/0066_match_arm.txt | 83 | ||||
-rw-r--r-- | crates/ra_syntax/tests/data/parser/inline/ok/0118_match_guard.rs | 5 | ||||
-rw-r--r-- | crates/ra_syntax/tests/data/parser/inline/ok/0118_match_guard.txt | 47 |
10 files changed, 152 insertions, 59 deletions
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index 60d997bbe..b01d53e5c 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -215,7 +215,7 @@ pub use ra_syntax::ast::BinOp as BinaryOp; | |||
215 | #[derive(Debug, Clone, Eq, PartialEq)] | 215 | #[derive(Debug, Clone, Eq, PartialEq)] |
216 | pub struct MatchArm { | 216 | pub struct MatchArm { |
217 | pub pats: Vec<PatId>, | 217 | pub pats: Vec<PatId>, |
218 | // guard: Option<ExprId>, // TODO | 218 | pub guard: Option<ExprId>, |
219 | pub expr: ExprId, | 219 | pub expr: ExprId, |
220 | } | 220 | } |
221 | 221 | ||
@@ -511,10 +511,12 @@ impl ExprCollector { | |||
511 | MatchArm { | 511 | MatchArm { |
512 | pats: vec![pat], | 512 | pats: vec![pat], |
513 | expr: then_branch, | 513 | expr: then_branch, |
514 | guard: None, | ||
514 | }, | 515 | }, |
515 | MatchArm { | 516 | MatchArm { |
516 | pats: vec![placeholder_pat], | 517 | pats: vec![placeholder_pat], |
517 | expr: else_branch, | 518 | expr: else_branch, |
519 | guard: None, | ||
518 | }, | 520 | }, |
519 | ]; | 521 | ]; |
520 | self.alloc_expr( | 522 | self.alloc_expr( |
@@ -613,6 +615,10 @@ impl ExprCollector { | |||
613 | .map(|arm| MatchArm { | 615 | .map(|arm| MatchArm { |
614 | pats: arm.pats().map(|p| self.collect_pat(p)).collect(), | 616 | pats: arm.pats().map(|p| self.collect_pat(p)).collect(), |
615 | expr: self.collect_expr_opt(arm.expr()), | 617 | expr: self.collect_expr_opt(arm.expr()), |
618 | guard: arm.guard().map(|guard| { | ||
619 | let e = guard.expr().expect("every guard should have an expr"); | ||
620 | self.collect_expr(e) | ||
621 | }), | ||
616 | }) | 622 | }) |
617 | .collect() | 623 | .collect() |
618 | } else { | 624 | } else { |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 31ea45706..e2c7884b5 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -1395,7 +1395,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1395 | for &pat in &arm.pats { | 1395 | for &pat in &arm.pats { |
1396 | let _pat_ty = self.infer_pat(pat, &input_ty); | 1396 | let _pat_ty = self.infer_pat(pat, &input_ty); |
1397 | } | 1397 | } |
1398 | // TODO type the guard | 1398 | if let Some(guard_expr) = arm.guard { |
1399 | self.infer_expr(guard_expr, &Expectation::has_type(Ty::Bool)); | ||
1400 | } | ||
1399 | self.infer_expr(arm.expr, &expected); | 1401 | self.infer_expr(arm.expr, &expected); |
1400 | } | 1402 | } |
1401 | 1403 | ||
@@ -1468,9 +1470,17 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1468 | cast_ty | 1470 | cast_ty |
1469 | } | 1471 | } |
1470 | Expr::Ref { expr, mutability } => { | 1472 | Expr::Ref { expr, mutability } => { |
1471 | // TODO pass the expectation down | 1473 | let expectation = if let Ty::Ref(ref subty, expected_mutability) = expected.ty { |
1472 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); | 1474 | if expected_mutability == Mutability::Mut && *mutability == Mutability::Shared { |
1475 | // TODO: throw type error - expected mut reference but found shared ref, | ||
1476 | // which cannot be coerced | ||
1477 | } | ||
1478 | Expectation::has_type((**subty).clone()) | ||
1479 | } else { | ||
1480 | Expectation::none() | ||
1481 | }; | ||
1473 | // TODO reference coercions etc. | 1482 | // TODO reference coercions etc. |
1483 | let inner_ty = self.infer_expr(*expr, &expectation); | ||
1474 | Ty::Ref(Arc::new(inner_ty), *mutability) | 1484 | Ty::Ref(Arc::new(inner_ty), *mutability) |
1475 | } | 1485 | } |
1476 | Expr::UnaryOp { expr, op } => { | 1486 | Expr::UnaryOp { expr, op } => { |
diff --git a/crates/ra_hir/src/ty/snapshots/tests__infer_adt_pattern.snap b/crates/ra_hir/src/ty/snapshots/tests__infer_adt_pattern.snap index 2719f592e..48c83cbb2 100644 --- a/crates/ra_hir/src/ty/snapshots/tests__infer_adt_pattern.snap +++ b/crates/ra_hir/src/ty/snapshots/tests__infer_adt_pattern.snap | |||
@@ -1,10 +1,10 @@ | |||
1 | --- | 1 | --- |
2 | created: "2019-01-22T14:44:59.880187500+00:00" | 2 | created: "2019-01-28T21:58:55.559331849+00:00" |
3 | creator: insta@0.4.0 | 3 | creator: insta@0.5.2 |
4 | expression: "&result" | 4 | expression: "&result" |
5 | source: "crates\\ra_hir\\src\\ty\\tests.rs" | 5 | source: crates/ra_hir/src/ty/tests.rs |
6 | --- | 6 | --- |
7 | [68; 262) '{ ... d; }': () | 7 | [68; 289) '{ ... d; }': () |
8 | [78; 79) 'e': E | 8 | [78; 79) 'e': E |
9 | [82; 95) 'E::A { x: 3 }': E | 9 | [82; 95) 'E::A { x: 3 }': E |
10 | [92; 93) '3': usize | 10 | [92; 93) '3': usize |
@@ -15,15 +15,18 @@ source: "crates\\ra_hir\\src\\ty\\tests.rs" | |||
15 | [129; 148) 'E::A {..._var }': E | 15 | [129; 148) 'E::A {..._var }': E |
16 | [139; 146) 'new_var': usize | 16 | [139; 146) 'new_var': usize |
17 | [151; 152) 'e': E | 17 | [151; 152) 'e': E |
18 | [159; 218) 'match ... }': usize | 18 | [159; 245) 'match ... }': usize |
19 | [165; 166) 'e': E | 19 | [165; 166) 'e': E |
20 | [177; 187) 'E::A { x }': E | 20 | [177; 187) 'E::A { x }': E |
21 | [184; 185) 'x': usize | 21 | [184; 185) 'x': usize |
22 | [191; 192) 'x': usize | 22 | [191; 192) 'x': usize |
23 | [202; 206) 'E::B': E | 23 | [202; 206) 'E::B': E |
24 | [210; 211) '1': usize | 24 | [210; 213) 'foo': bool |
25 | [229; 248) 'ref d ...{ .. }': &E | 25 | [217; 218) '1': usize |
26 | [237; 248) 'E::A { .. }': E | 26 | [228; 232) 'E::B': E |
27 | [251; 252) 'e': E | 27 | [236; 238) '10': usize |
28 | [258; 259) 'd': &E | 28 | [256; 275) 'ref d ...{ .. }': &E |
29 | [264; 275) 'E::A { .. }': E | ||
30 | [278; 279) 'e': E | ||
31 | [285; 286) 'd': &E | ||
29 | 32 | ||
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index f74d6f5ea..8aa188059 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -421,7 +421,8 @@ fn test() { | |||
421 | 421 | ||
422 | match e { | 422 | match e { |
423 | E::A { x } => x, | 423 | E::A { x } => x, |
424 | E::B => 1, | 424 | E::B if foo => 1, |
425 | E::B => 10, | ||
425 | }; | 426 | }; |
426 | 427 | ||
427 | let ref d @ E::A { .. } = e; | 428 | let ref d @ E::A { .. } = e; |
diff --git a/crates/ra_syntax/src/ast/generated.rs b/crates/ra_syntax/src/ast/generated.rs index 3ace6533c..4f5a96014 100644 --- a/crates/ra_syntax/src/ast/generated.rs +++ b/crates/ra_syntax/src/ast/generated.rs | |||
@@ -1981,7 +1981,11 @@ impl ToOwned for MatchGuard { | |||
1981 | } | 1981 | } |
1982 | 1982 | ||
1983 | 1983 | ||
1984 | impl MatchGuard {} | 1984 | impl MatchGuard { |
1985 | pub fn expr(&self) -> Option<&Expr> { | ||
1986 | super::child_opt(self) | ||
1987 | } | ||
1988 | } | ||
1985 | 1989 | ||
1986 | // MethodCallExpr | 1990 | // MethodCallExpr |
1987 | #[derive(Debug, PartialEq, Eq, Hash)] | 1991 | #[derive(Debug, PartialEq, Eq, Hash)] |
diff --git a/crates/ra_syntax/src/grammar.ron b/crates/ra_syntax/src/grammar.ron index 85fc79038..e4cad4eb3 100644 --- a/crates/ra_syntax/src/grammar.ron +++ b/crates/ra_syntax/src/grammar.ron | |||
@@ -418,7 +418,7 @@ Grammar( | |||
418 | ], | 418 | ], |
419 | collections: [ [ "pats", "Pat" ] ] | 419 | collections: [ [ "pats", "Pat" ] ] |
420 | ), | 420 | ), |
421 | "MatchGuard": (), | 421 | "MatchGuard": (options: ["Expr"]), |
422 | "StructLit": (options: ["Path", "NamedFieldList", ["spread", "Expr"]]), | 422 | "StructLit": (options: ["Path", "NamedFieldList", ["spread", "Expr"]]), |
423 | "NamedFieldList": (collections: [ ["fields", "NamedField"] ]), | 423 | "NamedFieldList": (collections: [ ["fields", "NamedField"] ]), |
424 | "NamedField": (options: ["NameRef", "Expr"]), | 424 | "NamedField": (options: ["NameRef", "Expr"]), |
diff --git a/crates/ra_syntax/src/grammar/expressions/atom.rs b/crates/ra_syntax/src/grammar/expressions/atom.rs index 6d6d89f70..600774afd 100644 --- a/crates/ra_syntax/src/grammar/expressions/atom.rs +++ b/crates/ra_syntax/src/grammar/expressions/atom.rs | |||
@@ -360,8 +360,8 @@ fn match_arm(p: &mut Parser) -> BlockLike { | |||
360 | while p.eat(PIPE) { | 360 | while p.eat(PIPE) { |
361 | patterns::pattern(p); | 361 | patterns::pattern(p); |
362 | } | 362 | } |
363 | if p.eat(IF_KW) { | 363 | if p.at(IF_KW) { |
364 | expr(p); | 364 | match_guard(p); |
365 | } | 365 | } |
366 | p.expect(FAT_ARROW); | 366 | p.expect(FAT_ARROW); |
367 | let ret = expr_stmt(p); | 367 | let ret = expr_stmt(p); |
@@ -369,6 +369,20 @@ fn match_arm(p: &mut Parser) -> BlockLike { | |||
369 | ret | 369 | ret |
370 | } | 370 | } |
371 | 371 | ||
372 | // test match_guard | ||
373 | // fn foo() { | ||
374 | // match () { | ||
375 | // _ if foo => (), | ||
376 | // } | ||
377 | // } | ||
378 | fn match_guard(p: &mut Parser) -> CompletedMarker { | ||
379 | assert!(p.at(IF_KW)); | ||
380 | let m = p.start(); | ||
381 | p.bump(); | ||
382 | expr(p); | ||
383 | m.complete(p, MATCH_GUARD) | ||
384 | } | ||
385 | |||
372 | // test block_expr | 386 | // test block_expr |
373 | // fn foo() { | 387 | // fn foo() { |
374 | // {}; | 388 | // {}; |
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0066_match_arm.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0066_match_arm.txt index 98e7535a3..b44e61879 100644 --- a/crates/ra_syntax/tests/data/parser/inline/ok/0066_match_arm.txt +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0066_match_arm.txt | |||
@@ -37,32 +37,33 @@ SOURCE_FILE@[0; 167) | |||
37 | PLACEHOLDER_PAT@[51; 52) | 37 | PLACEHOLDER_PAT@[51; 52) |
38 | UNDERSCORE@[51; 52) | 38 | UNDERSCORE@[51; 52) |
39 | WHITESPACE@[52; 53) | 39 | WHITESPACE@[52; 53) |
40 | IF_KW@[53; 55) | 40 | MATCH_GUARD@[53; 77) |
41 | WHITESPACE@[55; 56) | 41 | IF_KW@[53; 55) |
42 | BIN_EXPR@[56; 77) | 42 | WHITESPACE@[55; 56) |
43 | PATH_EXPR@[56; 60) | 43 | BIN_EXPR@[56; 77) |
44 | PATH@[56; 60) | 44 | PATH_EXPR@[56; 60) |
45 | PATH_SEGMENT@[56; 60) | 45 | PATH@[56; 60) |
46 | NAME_REF@[56; 60) | 46 | PATH_SEGMENT@[56; 60) |
47 | IDENT@[56; 60) "Test" | 47 | NAME_REF@[56; 60) |
48 | WHITESPACE@[60; 61) | 48 | IDENT@[56; 60) "Test" |
49 | R_ANGLE@[61; 62) | 49 | WHITESPACE@[60; 61) |
50 | WHITESPACE@[62; 63) | 50 | R_ANGLE@[61; 62) |
51 | STRUCT_LIT@[63; 77) | 51 | WHITESPACE@[62; 63) |
52 | PATH@[63; 67) | 52 | STRUCT_LIT@[63; 77) |
53 | PATH_SEGMENT@[63; 67) | 53 | PATH@[63; 67) |
54 | NAME_REF@[63; 67) | 54 | PATH_SEGMENT@[63; 67) |
55 | IDENT@[63; 67) "Test" | 55 | NAME_REF@[63; 67) |
56 | NAMED_FIELD_LIST@[67; 77) | 56 | IDENT@[63; 67) "Test" |
57 | L_CURLY@[67; 68) | 57 | NAMED_FIELD_LIST@[67; 77) |
58 | NAMED_FIELD@[68; 76) | 58 | L_CURLY@[67; 68) |
59 | NAME_REF@[68; 73) | 59 | NAMED_FIELD@[68; 76) |
60 | IDENT@[68; 73) "field" | 60 | NAME_REF@[68; 73) |
61 | COLON@[73; 74) | 61 | IDENT@[68; 73) "field" |
62 | WHITESPACE@[74; 75) | 62 | COLON@[73; 74) |
63 | LITERAL@[75; 76) | 63 | WHITESPACE@[74; 75) |
64 | INT_NUMBER@[75; 76) "0" | 64 | LITERAL@[75; 76) |
65 | R_CURLY@[76; 77) | 65 | INT_NUMBER@[75; 76) "0" |
66 | R_CURLY@[76; 77) | ||
66 | WHITESPACE@[77; 78) | 67 | WHITESPACE@[77; 78) |
67 | FAT_ARROW@[78; 80) | 68 | FAT_ARROW@[78; 80) |
68 | WHITESPACE@[80; 81) | 69 | WHITESPACE@[80; 81) |
@@ -82,13 +83,14 @@ SOURCE_FILE@[0; 167) | |||
82 | NAME@[97; 98) | 83 | NAME@[97; 98) |
83 | IDENT@[97; 98) "Y" | 84 | IDENT@[97; 98) "Y" |
84 | WHITESPACE@[98; 99) | 85 | WHITESPACE@[98; 99) |
85 | IF_KW@[99; 101) | 86 | MATCH_GUARD@[99; 103) |
86 | WHITESPACE@[101; 102) | 87 | IF_KW@[99; 101) |
87 | PATH_EXPR@[102; 103) | 88 | WHITESPACE@[101; 102) |
88 | PATH@[102; 103) | 89 | PATH_EXPR@[102; 103) |
89 | PATH_SEGMENT@[102; 103) | 90 | PATH@[102; 103) |
90 | NAME_REF@[102; 103) | 91 | PATH_SEGMENT@[102; 103) |
91 | IDENT@[102; 103) "Z" | 92 | NAME_REF@[102; 103) |
93 | IDENT@[102; 103) "Z" | ||
92 | WHITESPACE@[103; 104) | 94 | WHITESPACE@[103; 104) |
93 | FAT_ARROW@[104; 106) | 95 | FAT_ARROW@[104; 106) |
94 | WHITESPACE@[106; 107) | 96 | WHITESPACE@[106; 107) |
@@ -110,13 +112,14 @@ SOURCE_FILE@[0; 167) | |||
110 | NAME@[125; 126) | 112 | NAME@[125; 126) |
111 | IDENT@[125; 126) "Y" | 113 | IDENT@[125; 126) "Y" |
112 | WHITESPACE@[126; 127) | 114 | WHITESPACE@[126; 127) |
113 | IF_KW@[127; 129) | 115 | MATCH_GUARD@[127; 131) |
114 | WHITESPACE@[129; 130) | 116 | IF_KW@[127; 129) |
115 | PATH_EXPR@[130; 131) | 117 | WHITESPACE@[129; 130) |
116 | PATH@[130; 131) | 118 | PATH_EXPR@[130; 131) |
117 | PATH_SEGMENT@[130; 131) | 119 | PATH@[130; 131) |
118 | NAME_REF@[130; 131) | 120 | PATH_SEGMENT@[130; 131) |
119 | IDENT@[130; 131) "Z" | 121 | NAME_REF@[130; 131) |
122 | IDENT@[130; 131) "Z" | ||
120 | WHITESPACE@[131; 132) | 123 | WHITESPACE@[131; 132) |
121 | FAT_ARROW@[132; 134) | 124 | FAT_ARROW@[132; 134) |
122 | WHITESPACE@[134; 135) | 125 | WHITESPACE@[134; 135) |
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0118_match_guard.rs b/crates/ra_syntax/tests/data/parser/inline/ok/0118_match_guard.rs new file mode 100644 index 000000000..f1bd72fc4 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0118_match_guard.rs | |||
@@ -0,0 +1,5 @@ | |||
1 | fn foo() { | ||
2 | match () { | ||
3 | _ if foo => (), | ||
4 | } | ||
5 | } | ||
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0118_match_guard.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0118_match_guard.txt new file mode 100644 index 000000000..27553882d --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0118_match_guard.txt | |||
@@ -0,0 +1,47 @@ | |||
1 | SOURCE_FILE@[0; 58) | ||
2 | FN_DEF@[0; 57) | ||
3 | FN_KW@[0; 2) | ||
4 | WHITESPACE@[2; 3) | ||
5 | NAME@[3; 6) | ||
6 | IDENT@[3; 6) "foo" | ||
7 | PARAM_LIST@[6; 8) | ||
8 | L_PAREN@[6; 7) | ||
9 | R_PAREN@[7; 8) | ||
10 | WHITESPACE@[8; 9) | ||
11 | BLOCK@[9; 57) | ||
12 | L_CURLY@[9; 10) | ||
13 | WHITESPACE@[10; 15) | ||
14 | MATCH_EXPR@[15; 55) | ||
15 | MATCH_KW@[15; 20) | ||
16 | WHITESPACE@[20; 21) | ||
17 | TUPLE_EXPR@[21; 23) | ||
18 | L_PAREN@[21; 22) | ||
19 | R_PAREN@[22; 23) | ||
20 | WHITESPACE@[23; 24) | ||
21 | MATCH_ARM_LIST@[24; 55) | ||
22 | L_CURLY@[24; 25) | ||
23 | WHITESPACE@[25; 34) | ||
24 | MATCH_ARM@[34; 48) | ||
25 | PLACEHOLDER_PAT@[34; 35) | ||
26 | UNDERSCORE@[34; 35) | ||
27 | WHITESPACE@[35; 36) | ||
28 | MATCH_GUARD@[36; 42) | ||
29 | IF_KW@[36; 38) | ||
30 | WHITESPACE@[38; 39) | ||
31 | PATH_EXPR@[39; 42) | ||
32 | PATH@[39; 42) | ||
33 | PATH_SEGMENT@[39; 42) | ||
34 | NAME_REF@[39; 42) | ||
35 | IDENT@[39; 42) "foo" | ||
36 | WHITESPACE@[42; 43) | ||
37 | FAT_ARROW@[43; 45) | ||
38 | WHITESPACE@[45; 46) | ||
39 | TUPLE_EXPR@[46; 48) | ||
40 | L_PAREN@[46; 47) | ||
41 | R_PAREN@[47; 48) | ||
42 | COMMA@[48; 49) | ||
43 | WHITESPACE@[49; 54) | ||
44 | R_CURLY@[54; 55) | ||
45 | WHITESPACE@[55; 56) | ||
46 | R_CURLY@[56; 57) | ||
47 | WHITESPACE@[57; 58) | ||