Skip to content

Commit 36353bb

Browse files
Merge #4833
4833: Separating parsing of `for` in predicates and types r=matklad a=matthewjasper We now correctly accept `for<'a> (&'a F): Fn(&'a str)` in a where clause and correctly reject `for<'a> &'a u32` as a type. Co-authored-by: Matthew Jasper <[email protected]>
2 parents bd61ad7 + 8622e4c commit 36353bb

File tree

14 files changed

+843
-291
lines changed

14 files changed

+843
-291
lines changed

crates/ra_parser/src/grammar/type_params.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,14 @@ 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+
if p.at(T![for]) {
199+
types::for_binder(p);
200+
}
201+
198202
types::type_(p);
199203

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

crates/ra_parser/src/grammar/types.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -216,19 +216,21 @@ 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 ()) -> ();
220+
// type Obj = for<'a> PartialEq<&'a i32>;
222221
pub(super) fn for_type(p: &mut Parser) {
223222
assert!(p.at(T![for]));
224223
let m = p.start();
225224
for_binder(p);
226225
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"),
226+
T![fn] | T![unsafe] | T![extern] => {}
227+
// OK: legacy trait object format
228+
_ if paths::is_use_path_start(p) => {}
229+
_ => {
230+
p.error("expected a function pointer or path");
231+
}
231232
}
233+
type_no_bounds(p);
232234
m.complete(p, FOR_TYPE);
233235
}
234236

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 @@ [email protected]
1212
1313
1414
15-
16-
17-
18-
19-
20-
21-
15+
16+
17+
18+
19+
20+
2221
2322
2423
2524
2625
27-
error 26..26: expected a path
26+
error 26..26: expected type
2827
error 26..26: expected colon
Lines changed: 240 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,240 @@
1+
2+
3+
4+
5+
6+
7+
8+
9+
10+
11+
12+
13+
14+
15+
16+
17+
18+
19+
20+
21+
22+
23+
24+
25+
26+
27+
28+
29+
30+
31+
32+
33+
34+
35+
36+
37+
38+
39+
40+
41+
42+
43+
44+
45+
46+
47+
48+
49+
50+
51+
52+
53+
54+
55+
56+
57+
58+
59+
60+
61+
62+
63+
64+
[email protected] "ForSlice"
65+
66+
67+
68+
69+
70+
71+
72+
73+
74+
75+
76+
77+
78+
79+
80+
81+
82+
83+
84+
85+
86+
87+
88+
89+
90+
[email protected] "ForForFn"
91+
92+
93+
94+
95+
96+
97+
98+
99+
100+
101+
102+
103+
104+
105+
106+
107+
108+
109+
110+
111+
112+
113+
114+
115+
116+
117+
118+
119+
120+
121+
122+
123+
124+
125+
126+
127+
128+
129+
130+
131+
132+
133+
134+
135+
136+
137+
138+
139+
140+
141+
142+
143+
[email protected] "for_for_for"
144+
145+
146+
147+
148+
149+
150+
151+
152+
153+
154+
155+
156+
157+
158+
159+
160+
161+
162+
163+
164+
165+
166+
167+
168+
169+
170+
171+
172+
173+
174+
175+
176+
177+
178+
179+
180+
181+
182+
183+
184+
185+
186+
187+
188+
189+
190+
191+
192+
193+
194+
195+
196+
197+
198+
199+
200+
201+
202+
203+
204+
205+
206+
207+
208+
209+
210+
211+
212+
213+
214+
215+
216+
217+
218+
219+
220+
221+
222+
223+
224+
225+
226+
227+
228+
229+
230+
231+
232+
233+
234+
235+
236+
error 21..21: expected a function pointer or path
237+
error 52..52: expected a function pointer or path
238+
error 88..88: expected a function pointer or path
239+
error 119..119: expected a function pointer or path
240+
error 195..195: expected a function pointer or path
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
type ForRef = for<'a> &'a u32;
2+
type ForTup = for<'a> (&'a u32,);
3+
type ForSlice = for<'a> [u32];
4+
type ForForFn = for<'a> for<'b> fn(&'a i32, &'b i32);
5+
fn for_for_for<T>()
6+
where
7+
for<'a> for<'b> for<'c> fn(&'a T, &'b T, &'c T): Copy,
8+
{
9+
}

0 commit comments

Comments
 (0)