|
| 1 | +use crate::grammar::paths::WEAK_DYN_PATH_FIRST; |
| 2 | + |
1 | 3 | use super::*;
|
2 | 4 |
|
3 | 5 | pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(TokenSet::new(&[
|
@@ -49,6 +51,13 @@ fn type_with_bounds_cond(p: &mut Parser<'_>, allow_bounds: bool) {
|
49 | 51 | T![dyn] => dyn_trait_type(p),
|
50 | 52 | // Some path types are not allowed to have bounds (no plus)
|
51 | 53 | T![<] => path_type_bounds(p, allow_bounds),
|
| 54 | + T![ident] |
| 55 | + if !p.edition().at_least_2018() |
| 56 | + && p.at_contextual_kw(T![dyn]) |
| 57 | + && WEAK_DYN_PATH_FIRST.contains(p.nth(1)) => |
| 58 | + { |
| 59 | + dyn_trait_type_weak(p) |
| 60 | + } |
52 | 61 | _ if paths::is_path_start(p) => path_or_macro_type_(p, allow_bounds),
|
53 | 62 | LIFETIME_IDENT if p.nth_at(1, T![+]) => bare_dyn_trait_type(p),
|
54 | 63 | _ => {
|
@@ -279,6 +288,18 @@ fn dyn_trait_type(p: &mut Parser<'_>) {
|
279 | 288 | m.complete(p, DYN_TRAIT_TYPE);
|
280 | 289 | }
|
281 | 290 |
|
| 291 | +// test dyn_trait_type_weak 2015 |
| 292 | +// type A = dyn Iterator<Item=Foo<'a>> + 'a; |
| 293 | +// type A = &dyn Iterator<Item=Foo<'a>> + 'a; |
| 294 | +// type A = dyn::Path; |
| 295 | +fn dyn_trait_type_weak(p: &mut Parser<'_>) { |
| 296 | + assert!(p.at_contextual_kw(T![dyn])); |
| 297 | + let m = p.start(); |
| 298 | + p.bump_remap(T![dyn]); |
| 299 | + generic_params::bounds_without_colon(p); |
| 300 | + m.complete(p, DYN_TRAIT_TYPE); |
| 301 | +} |
| 302 | + |
282 | 303 | // test bare_dyn_types_with_leading_lifetime
|
283 | 304 | // type A = 'static + Trait;
|
284 | 305 | // type B = S<'static + Trait>;
|
|
0 commit comments