1 use crate::grammar::attributes::ATTRIBUTE_FIRST;
2
3 use super::*;
4
opt_generic_param_list(p: &mut Parser<'_>)5 pub(super) fn opt_generic_param_list(p: &mut Parser<'_>) {
6 if p.at(T![<]) {
7 generic_param_list(p);
8 }
9 }
10
11 // test generic_param_list
12 // fn f<T: Clone>() {}
generic_param_list(p: &mut Parser<'_>)13 fn generic_param_list(p: &mut Parser<'_>) {
14 assert!(p.at(T![<]));
15 let m = p.start();
16 delimited(p, T![<], T![>], T![,], GENERIC_PARAM_FIRST.union(ATTRIBUTE_FIRST), |p| {
17 // test generic_param_attribute
18 // fn foo<#[lt_attr] 'a, #[t_attr] T>() {}
19 let m = p.start();
20 attributes::outer_attrs(p);
21 generic_param(p, m)
22 });
23
24 m.complete(p, GENERIC_PARAM_LIST);
25 }
26
27 const GENERIC_PARAM_FIRST: TokenSet = TokenSet::new(&[IDENT, LIFETIME_IDENT, T![const]]);
28
generic_param(p: &mut Parser<'_>, m: Marker) -> bool29 fn generic_param(p: &mut Parser<'_>, m: Marker) -> bool {
30 match p.current() {
31 LIFETIME_IDENT => lifetime_param(p, m),
32 IDENT => type_param(p, m),
33 T![const] => const_param(p, m),
34 _ => {
35 m.abandon(p);
36 p.err_and_bump("expected generic parameter");
37 return false;
38 }
39 }
40 true
41 }
42
43 // test lifetime_param
44 // fn f<'a: 'b>() {}
lifetime_param(p: &mut Parser<'_>, m: Marker)45 fn lifetime_param(p: &mut Parser<'_>, m: Marker) {
46 assert!(p.at(LIFETIME_IDENT));
47 lifetime(p);
48 if p.at(T![:]) {
49 lifetime_bounds(p);
50 }
51 m.complete(p, LIFETIME_PARAM);
52 }
53
54 // test type_param
55 // fn f<T: Clone>() {}
type_param(p: &mut Parser<'_>, m: Marker)56 fn type_param(p: &mut Parser<'_>, m: Marker) {
57 assert!(p.at(IDENT));
58 name(p);
59 if p.at(T![:]) {
60 bounds(p);
61 }
62 if p.at(T![=]) {
63 // test type_param_default
64 // struct S<T = i32>;
65 p.bump(T![=]);
66 types::type_(p);
67 }
68 m.complete(p, TYPE_PARAM);
69 }
70
71 // test const_param
72 // struct S<const N: u32>;
const_param(p: &mut Parser<'_>, m: Marker)73 fn const_param(p: &mut Parser<'_>, m: Marker) {
74 p.bump(T![const]);
75 name(p);
76 if p.at(T![:]) {
77 types::ascription(p);
78 } else {
79 p.error("missing type for const parameter");
80 }
81
82 if p.at(T![=]) {
83 // test const_param_default_literal
84 // struct A<const N: i32 = -1>;
85 p.bump(T![=]);
86
87 // test const_param_default_expression
88 // struct A<const N: i32 = { 1 }>;
89
90 // test const_param_default_path
91 // struct A<const N: i32 = i32::MAX>;
92 generic_args::const_arg_expr(p);
93 }
94
95 m.complete(p, CONST_PARAM);
96 }
97
lifetime_bounds(p: &mut Parser<'_>)98 fn lifetime_bounds(p: &mut Parser<'_>) {
99 assert!(p.at(T![:]));
100 p.bump(T![:]);
101 while p.at(LIFETIME_IDENT) {
102 lifetime(p);
103 if !p.eat(T![+]) {
104 break;
105 }
106 }
107 }
108
109 // test type_param_bounds
110 // struct S<T: 'a + ?Sized + (Copy) + ~const Drop>;
bounds(p: &mut Parser<'_>)111 pub(super) fn bounds(p: &mut Parser<'_>) {
112 assert!(p.at(T![:]));
113 p.bump(T![:]);
114 bounds_without_colon(p);
115 }
116
bounds_without_colon(p: &mut Parser<'_>)117 pub(super) fn bounds_without_colon(p: &mut Parser<'_>) {
118 let m = p.start();
119 bounds_without_colon_m(p, m);
120 }
121
bounds_without_colon_m(p: &mut Parser<'_>, marker: Marker) -> CompletedMarker122 pub(super) fn bounds_without_colon_m(p: &mut Parser<'_>, marker: Marker) -> CompletedMarker {
123 while type_bound(p) {
124 if !p.eat(T![+]) {
125 break;
126 }
127 }
128 marker.complete(p, TYPE_BOUND_LIST)
129 }
130
type_bound(p: &mut Parser<'_>) -> bool131 fn type_bound(p: &mut Parser<'_>) -> bool {
132 let m = p.start();
133 let has_paren = p.eat(T!['(']);
134 match p.current() {
135 LIFETIME_IDENT => lifetime(p),
136 T![for] => types::for_type(p, false),
137 T![?] if p.nth_at(1, T![for]) => {
138 // test question_for_type_trait_bound
139 // fn f<T>() where T: ?for<> Sized {}
140 p.bump_any();
141 types::for_type(p, false)
142 }
143 current => {
144 match current {
145 T![?] => p.bump_any(),
146 T![~] => {
147 p.bump_any();
148 p.expect(T![const]);
149 }
150 _ => (),
151 }
152 if paths::is_use_path_start(p) {
153 types::path_type_(p, false);
154 } else {
155 m.abandon(p);
156 return false;
157 }
158 }
159 }
160 if has_paren {
161 p.expect(T![')']);
162 }
163 m.complete(p, TYPE_BOUND);
164
165 true
166 }
167
168 // test where_clause
169 // fn foo()
170 // where
171 // 'a: 'b + 'c,
172 // T: Clone + Copy + 'static,
173 // Iterator::Item: 'a,
174 // <T as Iterator>::Item: 'a
175 // {}
opt_where_clause(p: &mut Parser<'_>)176 pub(super) fn opt_where_clause(p: &mut Parser<'_>) {
177 if !p.at(T![where]) {
178 return;
179 }
180 let m = p.start();
181 p.bump(T![where]);
182
183 while is_where_predicate(p) {
184 where_predicate(p);
185
186 let comma = p.eat(T![,]);
187
188 match p.current() {
189 T!['{'] | T![;] | T![=] => break,
190 _ => (),
191 }
192
193 if !comma {
194 p.error("expected comma");
195 }
196 }
197
198 m.complete(p, WHERE_CLAUSE);
199
200 fn is_where_predicate(p: &mut Parser<'_>) -> bool {
201 match p.current() {
202 LIFETIME_IDENT => true,
203 T![impl] => false,
204 token => types::TYPE_FIRST.contains(token),
205 }
206 }
207 }
208
where_predicate(p: &mut Parser<'_>)209 fn where_predicate(p: &mut Parser<'_>) {
210 let m = p.start();
211 match p.current() {
212 LIFETIME_IDENT => {
213 lifetime(p);
214 if p.at(T![:]) {
215 bounds(p);
216 } else {
217 p.error("expected colon");
218 }
219 }
220 T![impl] => {
221 p.error("expected lifetime or type");
222 }
223 _ => {
224 if p.at(T![for]) {
225 // test where_pred_for
226 // fn for_trait<F>()
227 // where
228 // for<'a> F: Fn(&'a str)
229 // { }
230 types::for_binder(p);
231 }
232
233 types::type_(p);
234
235 if p.at(T![:]) {
236 bounds(p);
237 } else {
238 p.error("expected colon");
239 }
240 }
241 }
242 m.complete(p, WHERE_PRED);
243 }
244