ra_ap_parser/grammar/
types.rs1use 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![']'],
26 T!['}'],
27 T![>],
28 T![,],
29 T![pub],
33]);
34
35pub(crate) fn type_(p: &mut Parser<'_>) {
36 type_with_bounds_cond(p, true);
37}
38
39pub(super) fn type_no_bounds(p: &mut Parser<'_>) {
40 type_with_bounds_cond(p, false);
41}
42
43fn type_with_bounds_cond(p: &mut Parser<'_>, allow_bounds: bool) {
44 match p.current() {
45 T!['('] => paren_or_tuple_type(p),
46 T![!] => never_type(p),
47 T![*] => ptr_type(p),
48 T!['['] => array_or_slice_type(p),
49 T![&] => ref_type(p),
50 T![_] => infer_type(p),
51 T![fn] | T![unsafe] | T![extern] => fn_ptr_type(p),
52 T![for] => for_type(p, allow_bounds),
53 T![impl] => impl_trait_type(p),
54 T![dyn] => dyn_trait_type(p),
55 T![<] => path_type_bounds(p, allow_bounds),
57 T![ident] if !p.current_edition().at_least_2018() && is_dyn_weak(p) => {
58 dyn_trait_type_weak(p)
59 }
60 _ if paths::is_path_start(p) => path_or_macro_type(p, allow_bounds),
61 LIFETIME_IDENT if p.nth_at(1, T![+]) => bare_dyn_trait_type(p),
62 _ => {
63 p.err_recover("expected type", TYPE_RECOVERY_SET);
64 }
65 }
66}
67
68pub(crate) fn is_dyn_weak(p: &Parser<'_>) -> bool {
69 const WEAK_DYN_PATH_FIRST: TokenSet = TokenSet::new(&[
70 IDENT,
71 T![self],
72 T![super],
73 T![crate],
74 T![Self],
75 T![lifetime_ident],
76 T![?],
77 T![for],
78 T!['('],
79 ]);
80
81 p.at_contextual_kw(T![dyn]) && {
82 let la = p.nth(1);
83 WEAK_DYN_PATH_FIRST.contains(la) && (la != T![:] || la != T![<])
84 }
85}
86
87pub(super) fn ascription(p: &mut Parser<'_>) {
88 assert!(p.at(T![:]));
89 p.bump(T![:]);
90 if p.at(T![=]) {
91 p.error("missing type");
94 return;
95 }
96 type_(p);
97}
98
99fn paren_or_tuple_type(p: &mut Parser<'_>) {
100 assert!(p.at(T!['(']));
101 let m = p.start();
102 p.bump(T!['(']);
103 let mut n_types: u32 = 0;
104 let mut trailing_comma: bool = false;
105 while !p.at(EOF) && !p.at(T![')']) {
106 n_types += 1;
107 type_(p);
108 if p.eat(T![,]) {
109 trailing_comma = true;
110 } else {
111 trailing_comma = false;
112 break;
113 }
114 }
115 p.expect(T![')']);
116
117 let kind = if n_types == 1 && !trailing_comma {
118 PAREN_TYPE
121 } else {
122 TUPLE_TYPE
128 };
129 m.complete(p, kind);
130}
131
132fn never_type(p: &mut Parser<'_>) {
135 assert!(p.at(T![!]));
136 let m = p.start();
137 p.bump(T![!]);
138 m.complete(p, NEVER_TYPE);
139}
140
141fn ptr_type(p: &mut Parser<'_>) {
142 assert!(p.at(T![*]));
143 let m = p.start();
144 p.bump(T![*]);
145
146 match p.current() {
147 T![mut] | T![const] => p.bump_any(),
151 _ => {
152 p.error(
155 "expected mut or const in raw pointer type \
156 (use `*mut T` or `*const T` as appropriate)",
157 );
158 }
159 };
160
161 type_no_bounds(p);
162 m.complete(p, PTR_TYPE);
163}
164
165fn array_or_slice_type(p: &mut Parser<'_>) {
166 assert!(p.at(T!['[']));
167 let m = p.start();
168 p.bump(T!['[']);
169
170 type_(p);
171 let kind = match p.current() {
172 T![']'] => {
175 p.bump(T![']']);
176 SLICE_TYPE
177 }
178
179 T![;] => {
182 p.bump(T![;]);
183 let m = p.start();
184 expressions::expr(p);
185 m.complete(p, CONST_ARG);
186 p.expect(T![']']);
187 ARRAY_TYPE
188 }
189 _ => {
192 p.error("expected `;` or `]`");
193 SLICE_TYPE
194 }
195 };
196 m.complete(p, kind);
197}
198
199fn ref_type(p: &mut Parser<'_>) {
204 assert!(p.at(T![&]));
205 let m = p.start();
206 p.bump(T![&]);
207 if p.at(LIFETIME_IDENT) {
208 lifetime(p);
209 }
210 p.eat(T![mut]);
211 type_no_bounds(p);
212 m.complete(p, REF_TYPE);
213}
214
215fn infer_type(p: &mut Parser<'_>) {
218 assert!(p.at(T![_]));
219 let m = p.start();
220 p.bump(T![_]);
221 m.complete(p, INFER_TYPE);
222}
223
224fn fn_ptr_type(p: &mut Parser<'_>) {
230 let m = p.start();
231 p.eat(T![unsafe]);
232 if p.at(T![extern]) {
233 abi(p);
234 }
235 if !p.eat(T![fn]) {
238 m.abandon(p);
239 p.error("expected `fn`");
240 return;
241 }
242 if p.at(T!['(']) {
243 params::param_list_fn_ptr(p);
244 } else {
245 p.error("expected parameters");
246 }
247 opt_ret_type(p);
250 m.complete(p, FN_PTR_TYPE);
251}
252
253pub(super) fn for_binder(p: &mut Parser<'_>) {
254 let m = p.start();
255 p.bump(T![for]);
256 if p.at(T![<]) {
257 generic_params::generic_param_list(p);
258 } else {
259 p.error("expected `<`");
260 }
261 m.complete(p, FOR_BINDER);
262}
263
264pub(super) fn for_type(p: &mut Parser<'_>, allow_bounds: bool) {
269 assert!(p.at(T![for]));
270 let m = p.start();
271 for_binder(p);
272 match p.current() {
273 T![fn] | T![unsafe] | T![extern] => {}
274 _ if paths::is_use_path_start(p) => {}
276 _ => {
277 p.error("expected a function pointer or path");
278 }
279 }
280 type_no_bounds(p);
281 let completed = m.complete(p, FOR_TYPE);
282
283 if allow_bounds {
286 opt_type_bounds_as_dyn_trait_type(p, completed);
287 }
288}
289
290fn impl_trait_type(p: &mut Parser<'_>) {
293 assert!(p.at(T![impl]));
294 let m = p.start();
295 p.bump(T![impl]);
296 generic_params::bounds_without_colon(p);
297 m.complete(p, IMPL_TRAIT_TYPE);
298}
299
300fn dyn_trait_type(p: &mut Parser<'_>) {
303 assert!(p.at(T![dyn]));
304 let m = p.start();
305 p.bump(T![dyn]);
306 generic_params::bounds_without_colon(p);
307 m.complete(p, DYN_TRAIT_TYPE);
308}
309
310fn dyn_trait_type_weak(p: &mut Parser<'_>) {
320 assert!(p.at_contextual_kw(T![dyn]));
321 let m = p.start();
322 p.bump_remap(T![dyn]);
323 generic_params::bounds_without_colon(p);
324 m.complete(p, DYN_TRAIT_TYPE);
325}
326
327fn bare_dyn_trait_type(p: &mut Parser<'_>) {
331 let m = p.start();
332 generic_params::bounds_without_colon(p);
333 m.complete(p, DYN_TRAIT_TYPE);
334}
335
336fn path_or_macro_type(p: &mut Parser<'_>, allow_bounds: bool) {
340 assert!(paths::is_path_start(p));
341 let r = p.start();
342 let m = p.start();
343
344 paths::type_path(p);
345
346 let kind = if p.at(T![!]) && !p.at(T![!=]) {
347 items::macro_call_after_excl(p);
348 m.complete(p, MACRO_CALL);
349 MACRO_TYPE
350 } else {
351 m.abandon(p);
352 PATH_TYPE
353 };
354
355 let path = r.complete(p, kind);
356
357 if allow_bounds {
358 opt_type_bounds_as_dyn_trait_type(p, path);
359 }
360}
361
362pub(super) fn path_type_bounds(p: &mut Parser<'_>, allow_bounds: bool) {
368 assert!(paths::is_path_start(p));
369 let m = p.start();
370 paths::type_path(p);
371
372 let path = m.complete(p, PATH_TYPE);
376 if allow_bounds {
377 opt_type_bounds_as_dyn_trait_type(p, path);
378 }
379}
380
381pub(super) fn opt_type_bounds_as_dyn_trait_type(
384 p: &mut Parser<'_>,
385 type_marker: CompletedMarker,
386) -> CompletedMarker {
387 assert!(matches!(
388 type_marker.kind(),
389 SyntaxKind::PATH_TYPE | SyntaxKind::FOR_TYPE | SyntaxKind::MACRO_TYPE
390 ));
391 if !p.at(T![+]) {
392 return type_marker;
393 }
394
395 let m = type_marker.precede(p).complete(p, TYPE_BOUND);
397
398 let m = m.precede(p);
400
401 p.eat(T![+]);
404
405 let m = generic_params::bounds_without_colon_m(p, m);
407
408 m.precede(p).complete(p, DYN_TRAIT_TYPE)
410}