Skip to content

Commit 3ea4d43

Browse files
committed
Properly parse legacy trait objects with leading ForType
1 parent f312555 commit 3ea4d43

File tree

4 files changed

+63
-9
lines changed

4 files changed

+63
-9
lines changed

crates/parser/src/grammar/type_params.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ fn type_bound(p: &mut Parser) -> bool {
113113
p.eat(T![?]);
114114
match p.current() {
115115
LIFETIME_IDENT => lifetime(p),
116-
T![for] => types::for_type(p),
116+
T![for] => types::for_type(p, false),
117117
_ if paths::is_use_path_start(p) => types::path_type_(p, false),
118118
_ => {
119119
m.abandon(p);

crates/parser/src/grammar/types.rs

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ fn type_with_bounds_cond(p: &mut Parser, allow_bounds: bool) {
4444
T![&] => ref_type(p),
4545
T![_] => infer_type(p),
4646
T![fn] | T![unsafe] | T![extern] => fn_ptr_type(p),
47-
T![for] => for_type(p),
47+
T![for] => for_type(p, allow_bounds),
4848
T![impl] => impl_trait_type(p),
4949
T![dyn] => dyn_trait_type(p),
5050
// Some path types are not allowed to have bounds (no plus)
@@ -227,7 +227,7 @@ pub(super) fn for_binder(p: &mut Parser) {
227227
// type A = for<'a> fn() -> ();
228228
// type B = for<'a> unsafe extern "C" fn(&'a ()) -> ();
229229
// type Obj = for<'a> PartialEq<&'a i32>;
230-
pub(super) fn for_type(p: &mut Parser) {
230+
pub(super) fn for_type(p: &mut Parser, allow_bounds: bool) {
231231
assert!(p.at(T![for]));
232232
let m = p.start();
233233
for_binder(p);
@@ -240,7 +240,13 @@ pub(super) fn for_type(p: &mut Parser) {
240240
}
241241
}
242242
type_no_bounds(p);
243-
m.complete(p, FOR_TYPE);
243+
let completed = m.complete(p, FOR_TYPE);
244+
245+
// test no_dyn_trait_leading_for
246+
// type A = for<'a> Test<'a> + Send;
247+
if allow_bounds {
248+
opt_type_bounds_as_dyn_trait_type(p, completed);
249+
}
244250
}
245251

246252
// test impl_trait_type
@@ -290,7 +296,7 @@ fn path_or_macro_type_(p: &mut Parser, allow_bounds: bool) {
290296
let path = m.complete(p, kind);
291297

292298
if allow_bounds {
293-
opt_path_type_bounds_as_dyn_trait_type(p, path);
299+
opt_type_bounds_as_dyn_trait_type(p, path);
294300
}
295301
}
296302

@@ -304,19 +310,23 @@ pub(super) fn path_type_(p: &mut Parser, allow_bounds: bool) {
304310
// fn foo() -> Box<dyn T + 'f> {}
305311
let path = m.complete(p, PATH_TYPE);
306312
if allow_bounds {
307-
opt_path_type_bounds_as_dyn_trait_type(p, path);
313+
opt_type_bounds_as_dyn_trait_type(p, path);
308314
}
309315
}
310316

311-
/// This turns a parsed PATH_TYPE optionally into a DYN_TRAIT_TYPE
317+
/// This turns a parsed PATH_TYPE or FOR_TYPE optionally into a DYN_TRAIT_TYPE
312318
/// with a TYPE_BOUND_LIST
313-
fn opt_path_type_bounds_as_dyn_trait_type(p: &mut Parser, path_type_marker: CompletedMarker) {
319+
fn opt_type_bounds_as_dyn_trait_type(p: &mut Parser, type_marker: CompletedMarker) {
320+
assert!(matches!(
321+
type_marker.kind(),
322+
SyntaxKind::PATH_TYPE | SyntaxKind::FOR_TYPE | SyntaxKind::MACRO_CALL
323+
));
314324
if !p.at(T![+]) {
315325
return;
316326
}
317327

318328
// First create a TYPE_BOUND from the completed PATH_TYPE
319-
let m = path_type_marker.precede(p).complete(p, TYPE_BOUND);
329+
let m = type_marker.precede(p).complete(p, TYPE_BOUND);
320330

321331
// Next setup a marker for the TYPE_BOUND_LIST
322332
let m = m.precede(p);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
type A = for<'a> Test<'a> + Send;

0 commit comments

Comments
 (0)