aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorMarcus Klaas de Vries <[email protected]>2019-01-28 22:06:11 +0000
committerMarcus Klaas de Vries <[email protected]>2019-01-28 22:09:14 +0000
commit3daca3eb4d843199540edfb1092f57f49938d0f6 (patch)
tree4cdc5c921b024d8b348b73e1a7c3e6a56fc11305 /crates
parent3f4f50baaa21cb2d0f6c102f1ca521946071a8dc (diff)
Infer type of match guard
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/expr.rs8
-rw-r--r--crates/ra_hir/src/ty.rs16
-rw-r--r--crates/ra_hir/src/ty/snapshots/tests__infer_adt_pattern.snap23
-rw-r--r--crates/ra_hir/src/ty/tests.rs3
-rw-r--r--crates/ra_syntax/src/ast/generated.rs6
-rw-r--r--crates/ra_syntax/src/grammar.ron2
-rw-r--r--crates/ra_syntax/src/grammar/expressions/atom.rs18
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0066_match_arm.txt83
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0118_match_guard.rs5
-rw-r--r--crates/ra_syntax/tests/data/parser/inline/ok/0118_match_guard.txt47
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)]
216pub struct MatchArm { 216pub 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---
2created: "2019-01-22T14:44:59.880187500+00:00" 2created: "2019-01-28T21:58:55.559331849+00:00"
3creator: insta@0.4.0 3creator: insta@0.5.2
4expression: "&result" 4expression: "&result"
5source: "crates\\ra_hir\\src\\ty\\tests.rs" 5source: 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
1984impl MatchGuard {} 1984impl 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// }
378fn 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 @@
1fn 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 @@
1SOURCE_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)