Skip to content

Commit e461e53

Browse files
committed
Auto merge of rust-lang#14739 - lowr:fix/type-with-leading-lifetime, r=Veykril
Parse bare dyn types with leading lifetime TIL types may start with a lifetime identifier e.g. `type A = 'static + Trait;`. When parsing types, leading lifetime followed by a plus sign should be parsed as a bare dyn type rather than a generic lifetime argument or error type (which is what we produce today). Although it's no longer accepted since Rust 2021, it wouldn't hurt to support this obsolete syntax.
2 parents 0dd94d3 + 2a509d0 commit e461e53

File tree

4 files changed

+72
-1
lines changed

4 files changed

+72
-1
lines changed

Diff for: crates/parser/src/grammar/generic_args.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ const GENERIC_ARG_FIRST: TokenSet = TokenSet::new(&[
3535
// type T = S<i32>;
3636
fn generic_arg(p: &mut Parser<'_>) -> bool {
3737
match p.current() {
38-
LIFETIME_IDENT => lifetime_arg(p),
38+
LIFETIME_IDENT if !p.nth_at(1, T![+]) => lifetime_arg(p),
3939
T!['{'] | T![true] | T![false] | T![-] => const_arg(p),
4040
k if k.is_literal() => const_arg(p),
4141
// test associated_type_bounds

Diff for: crates/parser/src/grammar/types.rs

+11
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(TokenSet::new(&[
1515
T![impl],
1616
T![dyn],
1717
T![Self],
18+
LIFETIME_IDENT,
1819
]));
1920

2021
pub(super) const TYPE_RECOVERY_SET: TokenSet = TokenSet::new(&[
@@ -49,6 +50,7 @@ fn type_with_bounds_cond(p: &mut Parser<'_>, allow_bounds: bool) {
4950
// Some path types are not allowed to have bounds (no plus)
5051
T![<] => path_type_(p, allow_bounds),
5152
_ if paths::is_path_start(p) => path_or_macro_type_(p, allow_bounds),
53+
LIFETIME_IDENT if p.nth_at(1, T![+]) => bare_dyn_trait_type(p),
5254
_ => {
5355
p.err_recover("expected type", TYPE_RECOVERY_SET);
5456
}
@@ -275,6 +277,15 @@ fn dyn_trait_type(p: &mut Parser<'_>) {
275277
m.complete(p, DYN_TRAIT_TYPE);
276278
}
277279

280+
// test bare_dyn_types_with_leading_lifetime
281+
// type A = 'static + Trait;
282+
// type B = S<'static + Trait>;
283+
fn bare_dyn_trait_type(p: &mut Parser<'_>) {
284+
let m = p.start();
285+
generic_params::bounds_without_colon(p);
286+
m.complete(p, DYN_TRAIT_TYPE);
287+
}
288+
278289
// test path_type
279290
// type A = Foo;
280291
// type B = ::Foo;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
SOURCE_FILE
2+
TYPE_ALIAS
3+
TYPE_KW "type"
4+
WHITESPACE " "
5+
NAME
6+
IDENT "A"
7+
WHITESPACE " "
8+
EQ "="
9+
WHITESPACE " "
10+
DYN_TRAIT_TYPE
11+
TYPE_BOUND_LIST
12+
TYPE_BOUND
13+
LIFETIME
14+
LIFETIME_IDENT "'static"
15+
WHITESPACE " "
16+
PLUS "+"
17+
WHITESPACE " "
18+
TYPE_BOUND
19+
PATH_TYPE
20+
PATH
21+
PATH_SEGMENT
22+
NAME_REF
23+
IDENT "Trait"
24+
SEMICOLON ";"
25+
WHITESPACE "\n"
26+
TYPE_ALIAS
27+
TYPE_KW "type"
28+
WHITESPACE " "
29+
NAME
30+
IDENT "B"
31+
WHITESPACE " "
32+
EQ "="
33+
WHITESPACE " "
34+
PATH_TYPE
35+
PATH
36+
PATH_SEGMENT
37+
NAME_REF
38+
IDENT "S"
39+
GENERIC_ARG_LIST
40+
L_ANGLE "<"
41+
TYPE_ARG
42+
DYN_TRAIT_TYPE
43+
TYPE_BOUND_LIST
44+
TYPE_BOUND
45+
LIFETIME
46+
LIFETIME_IDENT "'static"
47+
WHITESPACE " "
48+
PLUS "+"
49+
WHITESPACE " "
50+
TYPE_BOUND
51+
PATH_TYPE
52+
PATH
53+
PATH_SEGMENT
54+
NAME_REF
55+
IDENT "Trait"
56+
R_ANGLE ">"
57+
SEMICOLON ";"
58+
WHITESPACE "\n"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
type A = 'static + Trait;
2+
type B = S<'static + Trait>;

0 commit comments

Comments
 (0)