Skip to content

Commit 506e1dd

Browse files
committed
Separating parsing of for in predicates and types
1 parent 560b98b commit 506e1dd

File tree

12 files changed

+507
-291
lines changed

12 files changed

+507
-291
lines changed

crates/ra_parser/src/grammar/type_params.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,30 @@ fn where_predicate(p: &mut Parser) {
191191
}
192192
_ => {
193193
// test where_pred_for
194-
// fn test<F>()
194+
// fn for_trait<F>()
195195
// where
196196
// for<'a> F: Fn(&'a str)
197197
// { }
198+
// fn for_ref<F>()
199+
// where
200+
// for<'a> &'a F: Debug
201+
// { }
202+
// fn for_parens<F>()
203+
// where
204+
// for<'a> (&'a F): Fn(&'a str)
205+
// { }
206+
// fn for_slice<F>()
207+
// where
208+
// for<'a> [&'a F]: Eq
209+
// { }
210+
// fn for_qpath<T>(_t: &T)
211+
// where
212+
// for<'a> <&'a T as Baz>::Foo: Iterator
213+
// { }
214+
if p.at(T![for]) {
215+
types::for_binder(p);
216+
}
217+
198218
types::type_(p);
199219

200220
if p.at(T![:]) {

crates/ra_parser/src/grammar/types.rs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -216,19 +216,20 @@ pub(super) fn for_binder(p: &mut Parser) {
216216

217217
// test for_type
218218
// type A = for<'a> fn() -> ();
219-
// fn foo<T>(_t: &T) where for<'a> &'a T: Iterator {}
220-
// fn bar<T>(_t: &T) where for<'a> &'a mut T: Iterator {}
221-
// fn baz<T>(_t: &T) where for<'a> <&'a T as Baz>::Foo: Iterator {}
219+
// type B = for<'a> unsafe extern "C" fn(&'a ()) -> ();
222220
pub(super) fn for_type(p: &mut Parser) {
223221
assert!(p.at(T![for]));
224222
let m = p.start();
225223
for_binder(p);
226224
match p.current() {
227-
T![fn] | T![unsafe] | T![extern] => fn_pointer_type(p),
228-
T![&] => reference_type(p),
229-
_ if paths::is_path_start(p) => path_type_(p, false),
230-
_ => p.error("expected a path"),
225+
T![fn] | T![unsafe] | T![extern] => {}
226+
// OK: legacy trait object format
227+
_ if paths::is_use_path_start(p) => {}
228+
_ => {
229+
p.error("expected a function pointer or path");
230+
}
231231
}
232+
type_no_bounds(p);
232233
m.complete(p, FOR_TYPE);
233234
}
234235

crates/ra_syntax/src/ast.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -285,6 +285,8 @@ where
285285
let pred = predicates.next().unwrap();
286286
let mut bounds = pred.type_bound_list().unwrap().bounds();
287287

288+
assert!(pred.for_token().is_none());
289+
assert!(pred.type_param_list().is_none());
288290
assert_eq!("T", pred.type_ref().unwrap().syntax().text().to_string());
289291
assert_bound("Clone", bounds.next());
290292
assert_bound("Copy", bounds.next());
@@ -322,6 +324,8 @@ where
322324
let pred = predicates.next().unwrap();
323325
let mut bounds = pred.type_bound_list().unwrap().bounds();
324326

325-
assert_eq!("for<'a> F", pred.type_ref().unwrap().syntax().text().to_string());
327+
assert!(pred.for_token().is_some());
328+
assert_eq!("<'a>", pred.type_param_list().unwrap().syntax().text().to_string());
329+
assert_eq!("F", pred.type_ref().unwrap().syntax().text().to_string());
326330
assert_bound("Fn(&'a str)", bounds.next());
327331
}

crates/ra_syntax/src/ast/generated/nodes.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2052,6 +2052,8 @@ pub struct WherePred {
20522052
}
20532053
impl ast::TypeBoundsOwner for WherePred {}
20542054
impl WherePred {
2055+
pub fn for_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![for]) }
2056+
pub fn type_param_list(&self) -> Option<TypeParamList> { support::child(&self.syntax) }
20552057
pub fn lifetime_token(&self) -> Option<SyntaxToken> {
20562058
support::token(&self.syntax, T![lifetime])
20572059
}

crates/ra_syntax/test_data/parser/err/0027_incomplere_where_for.rast

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,16 @@ SOURCE_FILE@0..30
1212
WHERE_KW@13..18 "where"
1313
WHITESPACE@18..19 " "
1414
WHERE_PRED@19..26
15-
FOR_TYPE@19..26
16-
FOR_KW@19..22 "for"
17-
TYPE_PARAM_LIST@22..26
18-
L_ANGLE@22..23 "<"
19-
LIFETIME_PARAM@23..25
20-
LIFETIME@23..25 "\'a"
21-
R_ANGLE@25..26 ">"
15+
FOR_KW@19..22 "for"
16+
TYPE_PARAM_LIST@22..26
17+
L_ANGLE@22..23 "<"
18+
LIFETIME_PARAM@23..25
19+
LIFETIME@23..25 "\'a"
20+
R_ANGLE@25..26 ">"
2221
WHITESPACE@26..27 "\n"
2322
BLOCK_EXPR@27..29
2423
L_CURLY@27..28 "{"
2524
R_CURLY@28..29 "}"
2625
WHITESPACE@29..30 "\n"
27-
error 26..26: expected a path
26+
error 26..26: expected type
2827
error 26..26: expected colon
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
SOURCE_FILE@0..79
2+
TYPE_ALIAS_DEF@0..25
3+
TYPE_KW@0..4 "type"
4+
WHITESPACE@4..5 " "
5+
NAME@5..6
6+
IDENT@5..6 "A"
7+
WHITESPACE@6..7 " "
8+
EQ@7..8 "="
9+
WHITESPACE@8..9 " "
10+
FOR_TYPE@9..24
11+
FOR_KW@9..12 "for"
12+
TYPE_PARAM_LIST@12..16
13+
L_ANGLE@12..13 "<"
14+
LIFETIME_PARAM@13..15
15+
LIFETIME@13..15 "\'a"
16+
R_ANGLE@15..16 ">"
17+
WHITESPACE@16..17 " "
18+
REFERENCE_TYPE@17..24
19+
AMP@17..18 "&"
20+
LIFETIME@18..20 "\'a"
21+
WHITESPACE@20..21 " "
22+
PATH_TYPE@21..24
23+
PATH@21..24
24+
PATH_SEGMENT@21..24
25+
NAME_REF@21..24
26+
IDENT@21..24 "u32"
27+
SEMICOLON@24..25 ";"
28+
WHITESPACE@25..26 "\n"
29+
TYPE_ALIAS_DEF@26..54
30+
TYPE_KW@26..30 "type"
31+
WHITESPACE@30..31 " "
32+
NAME@31..32
33+
IDENT@31..32 "B"
34+
WHITESPACE@32..33 " "
35+
EQ@33..34 "="
36+
WHITESPACE@34..35 " "
37+
FOR_TYPE@35..53
38+
FOR_KW@35..38 "for"
39+
TYPE_PARAM_LIST@38..42
40+
L_ANGLE@38..39 "<"
41+
LIFETIME_PARAM@39..41
42+
LIFETIME@39..41 "\'a"
43+
R_ANGLE@41..42 ">"
44+
WHITESPACE@42..43 " "
45+
TUPLE_TYPE@43..53
46+
L_PAREN@43..44 "("
47+
REFERENCE_TYPE@44..51
48+
AMP@44..45 "&"
49+
LIFETIME@45..47 "\'a"
50+
WHITESPACE@47..48 " "
51+
PATH_TYPE@48..51
52+
PATH@48..51
53+
PATH_SEGMENT@48..51
54+
NAME_REF@48..51
55+
IDENT@48..51 "u32"
56+
COMMA@51..52 ","
57+
R_PAREN@52..53 ")"
58+
SEMICOLON@53..54 ";"
59+
WHITESPACE@54..55 "\n"
60+
TYPE_ALIAS_DEF@55..78
61+
TYPE_KW@55..59 "type"
62+
WHITESPACE@59..60 " "
63+
NAME@60..61
64+
IDENT@60..61 "B"
65+
WHITESPACE@61..62 " "
66+
EQ@62..63 "="
67+
WHITESPACE@63..64 " "
68+
FOR_TYPE@64..77
69+
FOR_KW@64..67 "for"
70+
TYPE_PARAM_LIST@67..71
71+
L_ANGLE@67..68 "<"
72+
LIFETIME_PARAM@68..70
73+
LIFETIME@68..70 "\'a"
74+
R_ANGLE@70..71 ">"
75+
WHITESPACE@71..72 " "
76+
SLICE_TYPE@72..77
77+
L_BRACK@72..73 "["
78+
PATH_TYPE@73..76
79+
PATH@73..76
80+
PATH_SEGMENT@73..76
81+
NAME_REF@73..76
82+
IDENT@73..76 "u32"
83+
R_BRACK@76..77 "]"
84+
SEMICOLON@77..78 ";"
85+
WHITESPACE@78..79 "\n"
86+
error 16..16: expected a function pointer or path
87+
error 42..42: expected a function pointer or path
88+
error 71..71: expected a function pointer or path
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
type A = for<'a> &'a u32;
2+
type B = for<'a> (&'a u32,);
3+
type B = for<'a> [u32];

0 commit comments

Comments
 (0)