diff --git a/crates/parser/src/grammar/generic_args.rs b/crates/parser/src/grammar/generic_args.rs index 55794954a82..4cac04a32a4 100644 --- a/crates/parser/src/grammar/generic_args.rs +++ b/crates/parser/src/grammar/generic_args.rs @@ -35,7 +35,7 @@ pub(super) fn opt_generic_arg_list(p: &mut Parser<'_>, colon_colon_required: boo // type T = S; fn generic_arg(p: &mut Parser<'_>) -> bool { match p.current() { - LIFETIME_IDENT => lifetime_arg(p), + LIFETIME_IDENT if !p.nth_at(1, T![+]) => lifetime_arg(p), T!['{'] | T![true] | T![false] | T![-] => const_arg(p), k if k.is_literal() => const_arg(p), // test associated_type_bounds diff --git a/crates/parser/src/grammar/types.rs b/crates/parser/src/grammar/types.rs index 5ae16475b65..26dac87956c 100644 --- a/crates/parser/src/grammar/types.rs +++ b/crates/parser/src/grammar/types.rs @@ -15,6 +15,7 @@ T![impl], T![dyn], T![Self], + LIFETIME_IDENT, ])); pub(super) const TYPE_RECOVERY_SET: TokenSet = TokenSet::new(&[ @@ -49,6 +50,7 @@ fn type_with_bounds_cond(p: &mut Parser<'_>, allow_bounds: bool) { // Some path types are not allowed to have bounds (no plus) T![<] => path_type_(p, allow_bounds), _ if paths::is_path_start(p) => path_or_macro_type_(p, allow_bounds), + LIFETIME_IDENT if p.nth_at(1, T![+]) => bare_dyn_trait_type(p), _ => { p.err_recover("expected type", TYPE_RECOVERY_SET); } @@ -275,6 +277,15 @@ fn dyn_trait_type(p: &mut Parser<'_>) { m.complete(p, DYN_TRAIT_TYPE); } +// test bare_dyn_types_with_leading_lifetime +// type A = 'static + Trait; +// type B = S<'static + Trait>; +fn bare_dyn_trait_type(p: &mut Parser<'_>) { + let m = p.start(); + generic_params::bounds_without_colon(p); + m.complete(p, DYN_TRAIT_TYPE); +} + // test path_type // type A = Foo; // type B = ::Foo; diff --git a/crates/parser/test_data/parser/inline/ok/0208_bare_dyn_types_with_leading_lifetime.rast b/crates/parser/test_data/parser/inline/ok/0208_bare_dyn_types_with_leading_lifetime.rast new file mode 100644 index 00000000000..d7e67fbcd15 --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/0208_bare_dyn_types_with_leading_lifetime.rast @@ -0,0 +1,58 @@ +SOURCE_FILE + TYPE_ALIAS + TYPE_KW "type" + WHITESPACE " " + NAME + IDENT "A" + WHITESPACE " " + EQ "=" + WHITESPACE " " + DYN_TRAIT_TYPE + TYPE_BOUND_LIST + TYPE_BOUND + LIFETIME + LIFETIME_IDENT "'static" + WHITESPACE " " + PLUS "+" + WHITESPACE " " + TYPE_BOUND + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + IDENT "Trait" + SEMICOLON ";" + WHITESPACE "\n" + TYPE_ALIAS + TYPE_KW "type" + WHITESPACE " " + NAME + IDENT "B" + WHITESPACE " " + EQ "=" + WHITESPACE " " + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + IDENT "S" + GENERIC_ARG_LIST + L_ANGLE "<" + TYPE_ARG + DYN_TRAIT_TYPE + TYPE_BOUND_LIST + TYPE_BOUND + LIFETIME + LIFETIME_IDENT "'static" + WHITESPACE " " + PLUS "+" + WHITESPACE " " + TYPE_BOUND + PATH_TYPE + PATH + PATH_SEGMENT + NAME_REF + IDENT "Trait" + R_ANGLE ">" + SEMICOLON ";" + WHITESPACE "\n" diff --git a/crates/parser/test_data/parser/inline/ok/0208_bare_dyn_types_with_leading_lifetime.rs b/crates/parser/test_data/parser/inline/ok/0208_bare_dyn_types_with_leading_lifetime.rs new file mode 100644 index 00000000000..3e9a9a29ddc --- /dev/null +++ b/crates/parser/test_data/parser/inline/ok/0208_bare_dyn_types_with_leading_lifetime.rs @@ -0,0 +1,2 @@ +type A = 'static + Trait; +type B = S<'static + Trait>;