diff options
author | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-22 13:49:33 +0000 |
---|---|---|
committer | bors[bot] <bors[bot]@users.noreply.github.com> | 2019-01-22 13:49:33 +0000 |
commit | 9e0abfc0c9b9d36c45c9d8567c632c0167b31084 (patch) | |
tree | dca47e7881e8a19507e6effb7642109b2e0be992 | |
parent | e396cb3548c8a36ba505cc08248333c225e56d2a (diff) | |
parent | 84f888e93ddfcaa573f65ddf49180a4665f14b50 (diff) |
Merge #592
592: Allow types to the left of `:` in where predicates r=matklad a=regiontog
Adresses #584
Co-authored-by: Erlend Tobiassen <[email protected]>
5 files changed, 91 insertions, 37 deletions
diff --git a/crates/ra_syntax/src/grammar/type_params.rs b/crates/ra_syntax/src/grammar/type_params.rs index 7db25beba..1ec813b3e 100644 --- a/crates/ra_syntax/src/grammar/type_params.rs +++ b/crates/ra_syntax/src/grammar/type_params.rs | |||
@@ -104,22 +104,36 @@ pub(super) fn opt_where_clause(p: &mut Parser) { | |||
104 | } | 104 | } |
105 | let m = p.start(); | 105 | let m = p.start(); |
106 | p.bump(); | 106 | p.bump(); |
107 | loop { | 107 | |
108 | if !(paths::is_path_start(p) | 108 | while is_where_predicate(p) { |
109 | || p.current() == LIFETIME | 109 | where_predicate(p); |
110 | || p.current() == FOR_KW | 110 | |
111 | || p.current() == L_ANGLE) | 111 | let comma = p.eat(COMMA); |
112 | { | 112 | |
113 | if is_where_clause_end(p) { | ||
113 | break; | 114 | break; |
114 | } | 115 | } |
115 | where_predicate(p); | 116 | |
116 | if p.current() != L_CURLY && p.current() != SEMI && p.current() != EQ { | 117 | if !comma { |
117 | p.expect(COMMA); | 118 | p.error("expected comma"); |
118 | } | 119 | } |
119 | } | 120 | } |
121 | |||
120 | m.complete(p, WHERE_CLAUSE); | 122 | m.complete(p, WHERE_CLAUSE); |
121 | } | 123 | } |
122 | 124 | ||
125 | fn is_where_predicate(p: &mut Parser) -> bool { | ||
126 | match p.current() { | ||
127 | LIFETIME => true, | ||
128 | IMPL_KW => false, | ||
129 | token => types::TYPE_FIRST.contains(token), | ||
130 | } | ||
131 | } | ||
132 | |||
133 | fn is_where_clause_end(p: &mut Parser) -> bool { | ||
134 | p.current() == L_CURLY || p.current() == SEMI || p.current() == EQ | ||
135 | } | ||
136 | |||
123 | fn where_predicate(p: &mut Parser) { | 137 | fn where_predicate(p: &mut Parser) { |
124 | let m = p.start(); | 138 | let m = p.start(); |
125 | match p.current() { | 139 | match p.current() { |
@@ -131,20 +145,17 @@ fn where_predicate(p: &mut Parser) { | |||
131 | p.error("expected colon"); | 145 | p.error("expected colon"); |
132 | } | 146 | } |
133 | } | 147 | } |
148 | IMPL_KW => { | ||
149 | p.error("expected lifetime or type"); | ||
150 | } | ||
134 | _ => { | 151 | _ => { |
135 | // test where_pred_for | 152 | // test where_pred_for |
136 | // fn test<F>() | 153 | // fn test<F>() |
137 | // where | 154 | // where |
138 | // for<'a> F: Fn(&'a str) | 155 | // for<'a> F: Fn(&'a str) |
139 | // { } | 156 | // { } |
140 | if p.at(FOR_KW) { | 157 | types::type_(p); |
141 | types::for_binder(p); | 158 | |
142 | } | ||
143 | if paths::is_path_start(p) || p.at(L_ANGLE) { | ||
144 | types::path_type_(p, false); | ||
145 | } else { | ||
146 | p.error("expected a type"); | ||
147 | } | ||
148 | if p.at(COLON) { | 159 | if p.at(COLON) { |
149 | bounds(p); | 160 | bounds(p); |
150 | } else { | 161 | } else { |
diff --git a/crates/ra_syntax/tests/data/parser/err/0027_incomplere_where_for.txt b/crates/ra_syntax/tests/data/parser/err/0027_incomplere_where_for.txt index 694295a60..8a2a73b9b 100644 --- a/crates/ra_syntax/tests/data/parser/err/0027_incomplere_where_for.txt +++ b/crates/ra_syntax/tests/data/parser/err/0027_incomplere_where_for.txt | |||
@@ -12,14 +12,15 @@ SOURCE_FILE@[0; 30) | |||
12 | WHERE_KW@[13; 18) | 12 | WHERE_KW@[13; 18) |
13 | WHITESPACE@[18; 19) | 13 | WHITESPACE@[18; 19) |
14 | WHERE_PRED@[19; 26) | 14 | WHERE_PRED@[19; 26) |
15 | FOR_KW@[19; 22) | 15 | FOR_TYPE@[19; 26) |
16 | TYPE_PARAM_LIST@[22; 26) | 16 | FOR_KW@[19; 22) |
17 | L_ANGLE@[22; 23) | 17 | TYPE_PARAM_LIST@[22; 26) |
18 | LIFETIME_PARAM@[23; 25) | 18 | L_ANGLE@[22; 23) |
19 | LIFETIME@[23; 25) "'a" | 19 | LIFETIME_PARAM@[23; 25) |
20 | R_ANGLE@[25; 26) | 20 | LIFETIME@[23; 25) "'a" |
21 | err: `expected a type` | 21 | R_ANGLE@[25; 26) |
22 | err: `expected colon` | 22 | err: `expected a path` |
23 | err: `expected colon` | ||
23 | WHITESPACE@[26; 27) | 24 | WHITESPACE@[26; 27) |
24 | BLOCK@[27; 29) | 25 | BLOCK@[27; 29) |
25 | L_CURLY@[27; 28) | 26 | L_CURLY@[27; 28) |
diff --git a/crates/ra_syntax/tests/data/parser/inline/ok/0003_where_pred_for.txt b/crates/ra_syntax/tests/data/parser/inline/ok/0003_where_pred_for.txt index 921bdacf4..41420ea92 100644 --- a/crates/ra_syntax/tests/data/parser/inline/ok/0003_where_pred_for.txt +++ b/crates/ra_syntax/tests/data/parser/inline/ok/0003_where_pred_for.txt | |||
@@ -18,18 +18,19 @@ SOURCE_FILE@[0; 49) | |||
18 | WHERE_KW@[13; 18) | 18 | WHERE_KW@[13; 18) |
19 | WHITESPACE@[18; 22) | 19 | WHITESPACE@[18; 22) |
20 | WHERE_PRED@[22; 44) | 20 | WHERE_PRED@[22; 44) |
21 | FOR_KW@[22; 25) | 21 | FOR_TYPE@[22; 31) |
22 | TYPE_PARAM_LIST@[25; 29) | 22 | FOR_KW@[22; 25) |
23 | L_ANGLE@[25; 26) | 23 | TYPE_PARAM_LIST@[25; 29) |
24 | LIFETIME_PARAM@[26; 28) | 24 | L_ANGLE@[25; 26) |
25 | LIFETIME@[26; 28) "'a" | 25 | LIFETIME_PARAM@[26; 28) |
26 | R_ANGLE@[28; 29) | 26 | LIFETIME@[26; 28) "'a" |
27 | WHITESPACE@[29; 30) | 27 | R_ANGLE@[28; 29) |
28 | PATH_TYPE@[30; 31) | 28 | WHITESPACE@[29; 30) |
29 | PATH@[30; 31) | 29 | PATH_TYPE@[30; 31) |
30 | PATH_SEGMENT@[30; 31) | 30 | PATH@[30; 31) |
31 | NAME_REF@[30; 31) | 31 | PATH_SEGMENT@[30; 31) |
32 | IDENT@[30; 31) "F" | 32 | NAME_REF@[30; 31) |
33 | IDENT@[30; 31) "F" | ||
33 | COLON@[31; 32) | 34 | COLON@[31; 32) |
34 | WHITESPACE@[32; 33) | 35 | WHITESPACE@[32; 33) |
35 | PATH_TYPE@[33; 44) | 36 | PATH_TYPE@[33; 44) |
diff --git a/crates/ra_syntax/tests/data/parser/ok/0038_where_pred_type.rs b/crates/ra_syntax/tests/data/parser/ok/0038_where_pred_type.rs new file mode 100644 index 000000000..8bfc341a5 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/ok/0038_where_pred_type.rs | |||
@@ -0,0 +1 @@ | |||
fn test() where (u64, u64): Foo {} \ No newline at end of file | |||
diff --git a/crates/ra_syntax/tests/data/parser/ok/0038_where_pred_type.txt b/crates/ra_syntax/tests/data/parser/ok/0038_where_pred_type.txt new file mode 100644 index 000000000..4842e9b90 --- /dev/null +++ b/crates/ra_syntax/tests/data/parser/ok/0038_where_pred_type.txt | |||
@@ -0,0 +1,40 @@ | |||
1 | SOURCE_FILE@[0; 34) | ||
2 | FN_DEF@[0; 34) | ||
3 | FN_KW@[0; 2) | ||
4 | WHITESPACE@[2; 3) | ||
5 | NAME@[3; 7) | ||
6 | IDENT@[3; 7) "test" | ||
7 | PARAM_LIST@[7; 9) | ||
8 | L_PAREN@[7; 8) | ||
9 | R_PAREN@[8; 9) | ||
10 | WHITESPACE@[9; 10) | ||
11 | WHERE_CLAUSE@[10; 31) | ||
12 | WHERE_KW@[10; 15) | ||
13 | WHITESPACE@[15; 16) | ||
14 | WHERE_PRED@[16; 31) | ||
15 | TUPLE_TYPE@[16; 26) | ||
16 | L_PAREN@[16; 17) | ||
17 | PATH_TYPE@[17; 20) | ||
18 | PATH@[17; 20) | ||
19 | PATH_SEGMENT@[17; 20) | ||
20 | NAME_REF@[17; 20) | ||
21 | IDENT@[17; 20) "u64" | ||
22 | COMMA@[20; 21) | ||
23 | WHITESPACE@[21; 22) | ||
24 | PATH_TYPE@[22; 25) | ||
25 | PATH@[22; 25) | ||
26 | PATH_SEGMENT@[22; 25) | ||
27 | NAME_REF@[22; 25) | ||
28 | IDENT@[22; 25) "u64" | ||
29 | R_PAREN@[25; 26) | ||
30 | COLON@[26; 27) | ||
31 | WHITESPACE@[27; 28) | ||
32 | PATH_TYPE@[28; 31) | ||
33 | PATH@[28; 31) | ||
34 | PATH_SEGMENT@[28; 31) | ||
35 | NAME_REF@[28; 31) | ||
36 | IDENT@[28; 31) "Foo" | ||
37 | WHITESPACE@[31; 32) | ||
38 | BLOCK@[32; 34) | ||
39 | L_CURLY@[32; 33) | ||
40 | R_CURLY@[33; 34) | ||