parser/grammar/
types.rs
1use super::*;
2
3pub(super) const TYPE_FIRST: TokenSet = paths::PATH_FIRST.union(TokenSet::new(&[
4 T!['('],
5 T!['['],
6 T![<],
7 T![!],
8 T![*],
9 T![&],
10 T![_],
11 T![fn],
12 T![unsafe],
13 T![extern],
14 T![for],
15 T![impl],
16 T![dyn],
17 T![Self],
18 LIFETIME_IDENT,
19]));
20
21pub(super) const TYPE_RECOVERY_SET: TokenSet = TokenSet::new(&[
22 T![')'],
23 T![>],
24 T![,],
25 T![pub],
28]);
29
30pub(crate) fn type_(p: &mut Parser<'_>) {
31 type_with_bounds_cond(p, true);
32}
33
34pub(super) fn type_no_bounds(p: &mut Parser<'_>) {
35 type_with_bounds_cond(p, false);
36}
37
38fn type_with_bounds_cond(p: &mut Parser<'_>, allow_bounds: bool) {
39 match p.current() {
40 T!['('] => paren_or_tuple_type(p),
41 T![!] => never_type(p),
42 T![*] => ptr_type(p),
43 T!['['] => array_or_slice_type(p),
44 T![&] => ref_type(p),
45 T![_] => infer_type(p),
46 T![fn] | T![unsafe] | T![extern] => fn_ptr_type(p),
47 T![for] => for_type(p, allow_bounds),
48 T![impl] => impl_trait_type(p),
49 T![dyn] => dyn_trait_type(p),
50 T![<] => path_type_bounds(p, allow_bounds),
52 T![ident] if !p.edition().at_least_2018() && is_dyn_weak(p) => dyn_trait_type_weak(p),
53 _ if paths::is_path_start(p) => path_or_macro_type(p, allow_bounds),
54 LIFETIME_IDENT if p.nth_at(1, T![+]) => bare_dyn_trait_type(p),
55 _ => {
56 p.err_recover("expected type", TYPE_RECOVERY_SET);
57 }
58 }
59}
60
61pub(crate) fn is_dyn_weak(p: &Parser<'_>) -> bool {
62 const WEAK_DYN_PATH_FIRST: TokenSet = TokenSet::new(&[
63 IDENT,
64 T![self],
65 T![super],
66 T![crate],
67 T![Self],
68 T![lifetime_ident],
69 T![?],
70 T![for],
71 T!['('],
72 ]);
73
74 p.at_contextual_kw(T![dyn]) && {
75 let la = p.nth(1);
76 WEAK_DYN_PATH_FIRST.contains(la) && (la != T![:] || la != T![<])
77 }
78}
79
80pub(super) fn ascription(p: &mut Parser<'_>) {
81 assert!(p.at(T![:]));
82 p.bump(T![:]);
83 if p.at(T![=]) {
84 p.error("missing type");
87 return;
88 }
89 type_(p);
90}
91
92fn paren_or_tuple_type(p: &mut Parser<'_>) {
93 assert!(p.at(T!['(']));
94 let m = p.start();
95 p.bump(T!['(']);
96 let mut n_types: u32 = 0;
97 let mut trailing_comma: bool = false;
98 while !p.at(EOF) && !p.at(T![')']) {
99 n_types += 1;
100 type_(p);
101 if p.eat(T![,]) {
102 trailing_comma = true;
103 } else {
104 trailing_comma = false;
105 break;
106 }
107 }
108 p.expect(T![')']);
109
110 let kind = if n_types == 1 && !trailing_comma {
111 PAREN_TYPE
114 } else {
115 TUPLE_TYPE
121 };
122 m.complete(p, kind);
123}
124
125fn never_type(p: &mut Parser<'_>) {
128 assert!(p.at(T![!]));
129 let m = p.start();
130 p.bump(T![!]);
131 m.complete(p, NEVER_TYPE);
132}
133
134fn ptr_type(p: &mut Parser<'_>) {
135 assert!(p.at(T![*]));
136 let m = p.start();
137 p.bump(T![*]);
138
139 match p.current() {
140 T![mut] | T![const] => p.bump_any(),
144 _ => {
145 p.error(
148 "expected mut or const in raw pointer type \
149 (use `*mut T` or `*const T` as appropriate)",
150 );
151 }
152 };
153
154 type_no_bounds(p);
155 m.complete(p, PTR_TYPE);
156}
157
158fn array_or_slice_type(p: &mut Parser<'_>) {
159 assert!(p.at(T!['[']));
160 let m = p.start();
161 p.bump(T!['[']);
162
163 type_(p);
164 let kind = match p.current() {
165 T![']'] => {
168 p.bump(T![']']);
169 SLICE_TYPE
170 }
171
172 T![;] => {
175 p.bump(T![;]);
176 let m = p.start();
177 expressions::expr(p);
178 m.complete(p, CONST_ARG);
179 p.expect(T![']']);
180 ARRAY_TYPE
181 }
182 _ => {
185 p.error("expected `;` or `]`");
186 SLICE_TYPE
187 }
188 };
189 m.complete(p, kind);
190}
191
192fn ref_type(p: &mut Parser<'_>) {
197 assert!(p.at(T![&]));
198 let m = p.start();
199 p.bump(T![&]);
200 if p.at(LIFETIME_IDENT) {
201 lifetime(p);
202 }
203 p.eat(T![mut]);
204 type_no_bounds(p);
205 m.complete(p, REF_TYPE);
206}
207
208fn infer_type(p: &mut Parser<'_>) {
211 assert!(p.at(T![_]));
212 let m = p.start();
213 p.bump(T![_]);
214 m.complete(p, INFER_TYPE);
215}
216
217fn fn_ptr_type(p: &mut Parser<'_>) {
223 let m = p.start();
224 p.eat(T![unsafe]);
225 if p.at(T![extern]) {
226 abi(p);
227 }
228 if !p.eat(T![fn]) {
231 m.abandon(p);
232 p.error("expected `fn`");
233 return;
234 }
235 if p.at(T!['(']) {
236 params::param_list_fn_ptr(p);
237 } else {
238 p.error("expected parameters");
239 }
240 opt_ret_type(p);
243 m.complete(p, FN_PTR_TYPE);
244}
245
246pub(super) fn for_binder(p: &mut Parser<'_>) {
247 assert!(p.at(T![for]));
248 p.bump(T![for]);
249 if p.at(T![<]) {
250 generic_params::opt_generic_param_list(p);
251 } else {
252 p.error("expected `<`");
253 }
254}
255
256pub(super) fn for_type(p: &mut Parser<'_>, allow_bounds: bool) {
261 assert!(p.at(T![for]));
262 let m = p.start();
263 for_binder(p);
264 match p.current() {
265 T![fn] | T![unsafe] | T![extern] => {}
266 _ if paths::is_use_path_start(p) => {}
268 _ => {
269 p.error("expected a function pointer or path");
270 }
271 }
272 type_no_bounds(p);
273 let completed = m.complete(p, FOR_TYPE);
274
275 if allow_bounds {
278 opt_type_bounds_as_dyn_trait_type(p, completed);
279 }
280}
281
282fn impl_trait_type(p: &mut Parser<'_>) {
285 assert!(p.at(T![impl]));
286 let m = p.start();
287 p.bump(T![impl]);
288 generic_params::bounds_without_colon(p);
289 m.complete(p, IMPL_TRAIT_TYPE);
290}
291
292fn dyn_trait_type(p: &mut Parser<'_>) {
295 assert!(p.at(T![dyn]));
296 let m = p.start();
297 p.bump(T![dyn]);
298 generic_params::bounds_without_colon(p);
299 m.complete(p, DYN_TRAIT_TYPE);
300}
301
302fn dyn_trait_type_weak(p: &mut Parser<'_>) {
312 assert!(p.at_contextual_kw(T![dyn]));
313 let m = p.start();
314 p.bump_remap(T![dyn]);
315 generic_params::bounds_without_colon(p);
316 m.complete(p, DYN_TRAIT_TYPE);
317}
318
319fn bare_dyn_trait_type(p: &mut Parser<'_>) {
323 let m = p.start();
324 generic_params::bounds_without_colon(p);
325 m.complete(p, DYN_TRAIT_TYPE);
326}
327
328pub(super) fn path_type(p: &mut Parser<'_>) {
334 path_type_bounds(p, true);
335}
336
337fn path_or_macro_type(p: &mut Parser<'_>, allow_bounds: bool) {
341 assert!(paths::is_path_start(p));
342 let r = p.start();
343 let m = p.start();
344
345 paths::type_path(p);
346
347 let kind = if p.at(T![!]) && !p.at(T![!=]) {
348 items::macro_call_after_excl(p);
349 m.complete(p, MACRO_CALL);
350 MACRO_TYPE
351 } else {
352 m.abandon(p);
353 PATH_TYPE
354 };
355
356 let path = r.complete(p, kind);
357
358 if allow_bounds {
359 opt_type_bounds_as_dyn_trait_type(p, path);
360 }
361}
362
363pub(super) fn path_type_bounds(p: &mut Parser<'_>, allow_bounds: bool) {
364 assert!(paths::is_path_start(p));
365 let m = p.start();
366 paths::type_path(p);
367
368 let path = m.complete(p, PATH_TYPE);
372 if allow_bounds {
373 opt_type_bounds_as_dyn_trait_type(p, path);
374 }
375}
376
377pub(super) fn opt_type_bounds_as_dyn_trait_type(
380 p: &mut Parser<'_>,
381 type_marker: CompletedMarker,
382) -> CompletedMarker {
383 assert!(matches!(
384 type_marker.kind(),
385 SyntaxKind::PATH_TYPE | SyntaxKind::FOR_TYPE | SyntaxKind::MACRO_TYPE
386 ));
387 if !p.at(T![+]) {
388 return type_marker;
389 }
390
391 let m = type_marker.precede(p).complete(p, TYPE_BOUND);
393
394 let m = m.precede(p);
396
397 p.eat(T![+]);
400
401 let m = generic_params::bounds_without_colon_m(p, m);
403
404 m.precede(p).complete(p, DYN_TRAIT_TYPE)
406}