1 use super::*;
2
opt_generic_arg_list(p: &mut Parser, colon_colon_required: bool)3 pub(super) fn opt_generic_arg_list(p: &mut Parser, colon_colon_required: bool) {
4 let m;
5 if p.at(T![::]) && p.nth(2) == T![<] {
6 m = p.start();
7 p.bump(T![::]);
8 p.bump(T![<]);
9 } else if !colon_colon_required && p.at(T![<]) && p.nth(1) != T![=] {
10 m = p.start();
11 p.bump(T![<]);
12 } else {
13 return;
14 }
15
16 while !p.at(EOF) && !p.at(T![>]) {
17 generic_arg(p);
18 if !p.at(T![>]) && !p.expect(T![,]) {
19 break;
20 }
21 }
22 p.expect(T![>]);
23 m.complete(p, GENERIC_ARG_LIST);
24 }
25
26 // test generic_arg
27 // type T = S<i32>;
generic_arg(p: &mut Parser)28 fn generic_arg(p: &mut Parser) {
29 match p.current() {
30 LIFETIME_IDENT => lifetime_arg(p),
31 T!['{'] | T![true] | T![false] | T![-] => const_arg(p),
32 k if k.is_literal() => const_arg(p),
33 // test associated_type_bounds
34 // fn print_all<T: Iterator<Item, Item::Item, Item::<true>, Item: Display, Item<'a> = Item>>(printables: T) {}
35
36 // test macro_inside_generic_arg
37 // type A = Foo<syn::Token![_]>;
38 IDENT if [T![<], T![=], T![:]].contains(&p.nth(1)) && !p.nth_at(1, T![::]) => {
39 let m = p.start();
40 name_ref(p);
41 opt_generic_arg_list(p, false);
42 match p.current() {
43 // test assoc_type_eq
44 // type T = StreamingIterator<Item<'a> = &'a T>;
45 T![=] => {
46 p.bump_any();
47 types::type_(p);
48 m.complete(p, ASSOC_TYPE_ARG);
49 }
50 // test assoc_type_bound
51 // type T = StreamingIterator<Item<'a>: Clone>;
52 T![:] if !p.at(T![::]) => {
53 generic_params::bounds(p);
54 m.complete(p, ASSOC_TYPE_ARG);
55 }
56 _ => {
57 let m = m.complete(p, PATH_SEGMENT).precede(p).complete(p, PATH);
58 let m = paths::type_path_for_qualifier(p, m);
59 m.precede(p).complete(p, PATH_TYPE).precede(p).complete(p, TYPE_ARG);
60 }
61 }
62 }
63 _ => type_arg(p),
64 }
65 }
66
67 // test lifetime_arg
68 // type T = S<'static>;
lifetime_arg(p: &mut Parser)69 fn lifetime_arg(p: &mut Parser) {
70 let m = p.start();
71 lifetime(p);
72 m.complete(p, LIFETIME_ARG);
73 }
74
75 // test const_arg
76 // type T = S<92>;
const_arg(p: &mut Parser)77 pub(super) fn const_arg(p: &mut Parser) {
78 let m = p.start();
79 match p.current() {
80 // test const_arg_block
81 // type T = S<{90 + 2}>;
82 T!['{'] => {
83 expressions::block_expr(p);
84 m.complete(p, CONST_ARG);
85 }
86 // test const_arg_literal
87 // type T = S<"hello", 0xdeadbeef>;
88 k if k.is_literal() => {
89 expressions::literal(p);
90 m.complete(p, CONST_ARG);
91 }
92 // test const_arg_bool_literal
93 // type T = S<true>;
94 T![true] | T![false] => {
95 expressions::literal(p);
96 m.complete(p, CONST_ARG);
97 }
98 // test const_arg_negative_number
99 // type T = S<-92>;
100 T![-] => {
101 let lm = p.start();
102 p.bump(T![-]);
103 expressions::literal(p);
104 lm.complete(p, PREFIX_EXPR);
105 m.complete(p, CONST_ARG);
106 }
107 // test const_arg_path
108 // struct S<const N: u32 = u32::MAX>;
109 _ => {
110 let lm = p.start();
111 paths::use_path(p);
112 lm.complete(p, PATH_EXPR);
113 m.complete(p, CONST_ARG);
114 }
115 }
116 }
117
type_arg(p: &mut Parser)118 fn type_arg(p: &mut Parser) {
119 let m = p.start();
120 types::type_(p);
121 m.complete(p, TYPE_ARG);
122 }
123