1 | use super::*; |
2 | use crate::punctuated::Punctuated; |
3 | use proc_macro2::TokenStream; |
4 | |
5 | ast_enum_of_structs! { |
6 | /// The possible types that a Rust value could have. |
7 | /// |
8 | /// # Syntax tree enum |
9 | /// |
10 | /// This type is a [syntax tree enum]. |
11 | /// |
12 | /// [syntax tree enum]: Expr#syntax-tree-enums |
13 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
14 | #[non_exhaustive ] |
15 | pub enum Type { |
16 | /// A fixed size array type: `[T; n]`. |
17 | Array(TypeArray), |
18 | |
19 | /// A bare function type: `fn(usize) -> bool`. |
20 | BareFn(TypeBareFn), |
21 | |
22 | /// A type contained within invisible delimiters. |
23 | Group(TypeGroup), |
24 | |
25 | /// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or |
26 | /// a lifetime. |
27 | ImplTrait(TypeImplTrait), |
28 | |
29 | /// Indication that a type should be inferred by the compiler: `_`. |
30 | Infer(TypeInfer), |
31 | |
32 | /// A macro in the type position. |
33 | Macro(TypeMacro), |
34 | |
35 | /// The never type: `!`. |
36 | Never(TypeNever), |
37 | |
38 | /// A parenthesized type equivalent to the inner type. |
39 | Paren(TypeParen), |
40 | |
41 | /// A path like `std::slice::Iter`, optionally qualified with a |
42 | /// self-type as in `<Vec<T> as SomeTrait>::Associated`. |
43 | Path(TypePath), |
44 | |
45 | /// A raw pointer type: `*const T` or `*mut T`. |
46 | Ptr(TypePtr), |
47 | |
48 | /// A reference type: `&'a T` or `&'a mut T`. |
49 | Reference(TypeReference), |
50 | |
51 | /// A dynamically sized slice type: `[T]`. |
52 | Slice(TypeSlice), |
53 | |
54 | /// A trait object type `dyn Bound1 + Bound2 + Bound3` where `Bound` is a |
55 | /// trait or a lifetime. |
56 | TraitObject(TypeTraitObject), |
57 | |
58 | /// A tuple type: `(A, B, C, String)`. |
59 | Tuple(TypeTuple), |
60 | |
61 | /// Tokens in type position not interpreted by Syn. |
62 | Verbatim(TokenStream), |
63 | |
64 | // For testing exhaustiveness in downstream code, use the following idiom: |
65 | // |
66 | // match ty { |
67 | // Type::Array(ty) => {...} |
68 | // Type::BareFn(ty) => {...} |
69 | // ... |
70 | // Type::Verbatim(ty) => {...} |
71 | // |
72 | // #[cfg_attr(test, deny(non_exhaustive_omitted_patterns))] |
73 | // _ => { /* some sane fallback */ } |
74 | // } |
75 | // |
76 | // This way we fail your tests but don't break your library when adding |
77 | // a variant. You will be notified by a test failure when a variant is |
78 | // added, so that you can add code to handle it, but your library will |
79 | // continue to compile and work for downstream users in the interim. |
80 | } |
81 | } |
82 | |
83 | ast_struct! { |
84 | /// A fixed size array type: `[T; n]`. |
85 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
86 | pub struct TypeArray { |
87 | pub bracket_token: token::Bracket, |
88 | pub elem: Box<Type>, |
89 | pub semi_token: Token![;], |
90 | pub len: Expr, |
91 | } |
92 | } |
93 | |
94 | ast_struct! { |
95 | /// A bare function type: `fn(usize) -> bool`. |
96 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
97 | pub struct TypeBareFn { |
98 | pub lifetimes: Option<BoundLifetimes>, |
99 | pub unsafety: Option<Token![unsafe]>, |
100 | pub abi: Option<Abi>, |
101 | pub fn_token: Token![fn], |
102 | pub paren_token: token::Paren, |
103 | pub inputs: Punctuated<BareFnArg, Token![,]>, |
104 | pub variadic: Option<BareVariadic>, |
105 | pub output: ReturnType, |
106 | } |
107 | } |
108 | |
109 | ast_struct! { |
110 | /// A type contained within invisible delimiters. |
111 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
112 | pub struct TypeGroup { |
113 | pub group_token: token::Group, |
114 | pub elem: Box<Type>, |
115 | } |
116 | } |
117 | |
118 | ast_struct! { |
119 | /// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or |
120 | /// a lifetime. |
121 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
122 | pub struct TypeImplTrait { |
123 | pub impl_token: Token![impl], |
124 | pub bounds: Punctuated<TypeParamBound, Token![+]>, |
125 | } |
126 | } |
127 | |
128 | ast_struct! { |
129 | /// Indication that a type should be inferred by the compiler: `_`. |
130 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
131 | pub struct TypeInfer { |
132 | pub underscore_token: Token![_], |
133 | } |
134 | } |
135 | |
136 | ast_struct! { |
137 | /// A macro in the type position. |
138 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
139 | pub struct TypeMacro { |
140 | pub mac: Macro, |
141 | } |
142 | } |
143 | |
144 | ast_struct! { |
145 | /// The never type: `!`. |
146 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
147 | pub struct TypeNever { |
148 | pub bang_token: Token![!], |
149 | } |
150 | } |
151 | |
152 | ast_struct! { |
153 | /// A parenthesized type equivalent to the inner type. |
154 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
155 | pub struct TypeParen { |
156 | pub paren_token: token::Paren, |
157 | pub elem: Box<Type>, |
158 | } |
159 | } |
160 | |
161 | ast_struct! { |
162 | /// A path like `std::slice::Iter`, optionally qualified with a |
163 | /// self-type as in `<Vec<T> as SomeTrait>::Associated`. |
164 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
165 | pub struct TypePath { |
166 | pub qself: Option<QSelf>, |
167 | pub path: Path, |
168 | } |
169 | } |
170 | |
171 | ast_struct! { |
172 | /// A raw pointer type: `*const T` or `*mut T`. |
173 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
174 | pub struct TypePtr { |
175 | pub star_token: Token![*], |
176 | pub const_token: Option<Token![const]>, |
177 | pub mutability: Option<Token![mut]>, |
178 | pub elem: Box<Type>, |
179 | } |
180 | } |
181 | |
182 | ast_struct! { |
183 | /// A reference type: `&'a T` or `&'a mut T`. |
184 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
185 | pub struct TypeReference { |
186 | pub and_token: Token![&], |
187 | pub lifetime: Option<Lifetime>, |
188 | pub mutability: Option<Token![mut]>, |
189 | pub elem: Box<Type>, |
190 | } |
191 | } |
192 | |
193 | ast_struct! { |
194 | /// A dynamically sized slice type: `[T]`. |
195 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
196 | pub struct TypeSlice { |
197 | pub bracket_token: token::Bracket, |
198 | pub elem: Box<Type>, |
199 | } |
200 | } |
201 | |
202 | ast_struct! { |
203 | /// A trait object type `dyn Bound1 + Bound2 + Bound3` where `Bound` is a |
204 | /// trait or a lifetime. |
205 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
206 | pub struct TypeTraitObject { |
207 | pub dyn_token: Option<Token![dyn]>, |
208 | pub bounds: Punctuated<TypeParamBound, Token![+]>, |
209 | } |
210 | } |
211 | |
212 | ast_struct! { |
213 | /// A tuple type: `(A, B, C, String)`. |
214 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
215 | pub struct TypeTuple { |
216 | pub paren_token: token::Paren, |
217 | pub elems: Punctuated<Type, Token![,]>, |
218 | } |
219 | } |
220 | |
221 | ast_struct! { |
222 | /// The binary interface of a function: `extern "C"`. |
223 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
224 | pub struct Abi { |
225 | pub extern_token: Token![extern], |
226 | pub name: Option<LitStr>, |
227 | } |
228 | } |
229 | |
230 | ast_struct! { |
231 | /// An argument in a function type: the `usize` in `fn(usize) -> bool`. |
232 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
233 | pub struct BareFnArg { |
234 | pub attrs: Vec<Attribute>, |
235 | pub name: Option<(Ident, Token![:])>, |
236 | pub ty: Type, |
237 | } |
238 | } |
239 | |
240 | ast_struct! { |
241 | /// The variadic argument of a function pointer like `fn(usize, ...)`. |
242 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
243 | pub struct BareVariadic { |
244 | pub attrs: Vec<Attribute>, |
245 | pub name: Option<(Ident, Token![:])>, |
246 | pub dots: Token![...], |
247 | pub comma: Option<Token![,]>, |
248 | } |
249 | } |
250 | |
251 | ast_enum! { |
252 | /// Return type of a function signature. |
253 | #[cfg_attr (doc_cfg, doc(cfg(any(feature = "full" , feature = "derive" ))))] |
254 | pub enum ReturnType { |
255 | /// Return type is not specified. |
256 | /// |
257 | /// Functions default to `()` and closures default to type inference. |
258 | Default, |
259 | /// A particular type is returned. |
260 | Type(Token![->], Box<Type>), |
261 | } |
262 | } |
263 | |
264 | #[cfg (feature = "parsing" )] |
265 | pub(crate) mod parsing { |
266 | use super::*; |
267 | use crate::ext::IdentExt; |
268 | use crate::parse::{Parse, ParseStream, Result}; |
269 | use crate::path; |
270 | use proc_macro2::Span; |
271 | |
272 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
273 | impl Parse for Type { |
274 | fn parse(input: ParseStream) -> Result<Self> { |
275 | let allow_plus = true; |
276 | let allow_group_generic = true; |
277 | ambig_ty(input, allow_plus, allow_group_generic) |
278 | } |
279 | } |
280 | |
281 | impl Type { |
282 | /// In some positions, types may not contain the `+` character, to |
283 | /// disambiguate them. For example in the expression `1 as T`, T may not |
284 | /// contain a `+` character. |
285 | /// |
286 | /// This parser does not allow a `+`, while the default parser does. |
287 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
288 | pub fn without_plus(input: ParseStream) -> Result<Self> { |
289 | let allow_plus = false; |
290 | let allow_group_generic = true; |
291 | ambig_ty(input, allow_plus, allow_group_generic) |
292 | } |
293 | } |
294 | |
295 | pub(crate) fn ambig_ty( |
296 | input: ParseStream, |
297 | allow_plus: bool, |
298 | allow_group_generic: bool, |
299 | ) -> Result<Type> { |
300 | let begin = input.fork(); |
301 | |
302 | if input.peek(token::Group) { |
303 | let mut group: TypeGroup = input.parse()?; |
304 | if input.peek(Token![::]) && input.peek3(Ident::peek_any) { |
305 | if let Type::Path(mut ty) = *group.elem { |
306 | Path::parse_rest(input, &mut ty.path, false)?; |
307 | return Ok(Type::Path(ty)); |
308 | } else { |
309 | return Ok(Type::Path(TypePath { |
310 | qself: Some(QSelf { |
311 | lt_token: Token![<](group.group_token.span), |
312 | position: 0, |
313 | as_token: None, |
314 | gt_token: Token![>](group.group_token.span), |
315 | ty: group.elem, |
316 | }), |
317 | path: Path::parse_helper(input, false)?, |
318 | })); |
319 | } |
320 | } else if input.peek(Token![<]) && allow_group_generic |
321 | || input.peek(Token![::]) && input.peek3(Token![<]) |
322 | { |
323 | if let Type::Path(mut ty) = *group.elem { |
324 | let arguments = &mut ty.path.segments.last_mut().unwrap().arguments; |
325 | if arguments.is_none() { |
326 | *arguments = PathArguments::AngleBracketed(input.parse()?); |
327 | Path::parse_rest(input, &mut ty.path, false)?; |
328 | return Ok(Type::Path(ty)); |
329 | } else { |
330 | group.elem = Box::new(Type::Path(ty)); |
331 | } |
332 | } |
333 | } |
334 | return Ok(Type::Group(group)); |
335 | } |
336 | |
337 | let mut lifetimes = None::<BoundLifetimes>; |
338 | let mut lookahead = input.lookahead1(); |
339 | if lookahead.peek(Token![for]) { |
340 | lifetimes = input.parse()?; |
341 | lookahead = input.lookahead1(); |
342 | if !lookahead.peek(Ident) |
343 | && !lookahead.peek(Token![fn]) |
344 | && !lookahead.peek(Token![unsafe]) |
345 | && !lookahead.peek(Token![extern]) |
346 | && !lookahead.peek(Token![super]) |
347 | && !lookahead.peek(Token![self]) |
348 | && !lookahead.peek(Token![Self]) |
349 | && !lookahead.peek(Token![crate]) |
350 | || input.peek(Token![dyn]) |
351 | { |
352 | return Err(lookahead.error()); |
353 | } |
354 | } |
355 | |
356 | if lookahead.peek(token::Paren) { |
357 | let content; |
358 | let paren_token = parenthesized!(content in input); |
359 | if content.is_empty() { |
360 | return Ok(Type::Tuple(TypeTuple { |
361 | paren_token, |
362 | elems: Punctuated::new(), |
363 | })); |
364 | } |
365 | if content.peek(Lifetime) { |
366 | return Ok(Type::Paren(TypeParen { |
367 | paren_token, |
368 | elem: Box::new(Type::TraitObject(content.parse()?)), |
369 | })); |
370 | } |
371 | if content.peek(Token![?]) { |
372 | return Ok(Type::TraitObject(TypeTraitObject { |
373 | dyn_token: None, |
374 | bounds: { |
375 | let mut bounds = Punctuated::new(); |
376 | bounds.push_value(TypeParamBound::Trait(TraitBound { |
377 | paren_token: Some(paren_token), |
378 | ..content.parse()? |
379 | })); |
380 | while let Some(plus) = input.parse()? { |
381 | bounds.push_punct(plus); |
382 | bounds.push_value(input.parse()?); |
383 | } |
384 | bounds |
385 | }, |
386 | })); |
387 | } |
388 | let mut first: Type = content.parse()?; |
389 | if content.peek(Token![,]) { |
390 | return Ok(Type::Tuple(TypeTuple { |
391 | paren_token, |
392 | elems: { |
393 | let mut elems = Punctuated::new(); |
394 | elems.push_value(first); |
395 | elems.push_punct(content.parse()?); |
396 | while !content.is_empty() { |
397 | elems.push_value(content.parse()?); |
398 | if content.is_empty() { |
399 | break; |
400 | } |
401 | elems.push_punct(content.parse()?); |
402 | } |
403 | elems |
404 | }, |
405 | })); |
406 | } |
407 | if allow_plus && input.peek(Token![+]) { |
408 | loop { |
409 | let first = match first { |
410 | Type::Path(TypePath { qself: None, path }) => { |
411 | TypeParamBound::Trait(TraitBound { |
412 | paren_token: Some(paren_token), |
413 | modifier: TraitBoundModifier::None, |
414 | lifetimes: None, |
415 | path, |
416 | }) |
417 | } |
418 | Type::TraitObject(TypeTraitObject { |
419 | dyn_token: None, |
420 | bounds, |
421 | }) => { |
422 | if bounds.len() > 1 || bounds.trailing_punct() { |
423 | first = Type::TraitObject(TypeTraitObject { |
424 | dyn_token: None, |
425 | bounds, |
426 | }); |
427 | break; |
428 | } |
429 | match bounds.into_iter().next().unwrap() { |
430 | TypeParamBound::Trait(trait_bound) => { |
431 | TypeParamBound::Trait(TraitBound { |
432 | paren_token: Some(paren_token), |
433 | ..trait_bound |
434 | }) |
435 | } |
436 | other @ (TypeParamBound::Lifetime(_) |
437 | | TypeParamBound::Verbatim(_)) => other, |
438 | } |
439 | } |
440 | _ => break, |
441 | }; |
442 | return Ok(Type::TraitObject(TypeTraitObject { |
443 | dyn_token: None, |
444 | bounds: { |
445 | let mut bounds = Punctuated::new(); |
446 | bounds.push_value(first); |
447 | while let Some(plus) = input.parse()? { |
448 | bounds.push_punct(plus); |
449 | bounds.push_value(input.parse()?); |
450 | } |
451 | bounds |
452 | }, |
453 | })); |
454 | } |
455 | } |
456 | Ok(Type::Paren(TypeParen { |
457 | paren_token, |
458 | elem: Box::new(first), |
459 | })) |
460 | } else if lookahead.peek(Token![fn]) |
461 | || lookahead.peek(Token![unsafe]) |
462 | || lookahead.peek(Token![extern]) |
463 | { |
464 | let mut bare_fn: TypeBareFn = input.parse()?; |
465 | bare_fn.lifetimes = lifetimes; |
466 | Ok(Type::BareFn(bare_fn)) |
467 | } else if lookahead.peek(Ident) |
468 | || input.peek(Token![super]) |
469 | || input.peek(Token![self]) |
470 | || input.peek(Token![Self]) |
471 | || input.peek(Token![crate]) |
472 | || lookahead.peek(Token![::]) |
473 | || lookahead.peek(Token![<]) |
474 | { |
475 | let ty: TypePath = input.parse()?; |
476 | if ty.qself.is_some() { |
477 | return Ok(Type::Path(ty)); |
478 | } |
479 | |
480 | if input.peek(Token![!]) && !input.peek(Token![!=]) && ty.path.is_mod_style() { |
481 | let bang_token: Token![!] = input.parse()?; |
482 | let (delimiter, tokens) = mac::parse_delimiter(input)?; |
483 | return Ok(Type::Macro(TypeMacro { |
484 | mac: Macro { |
485 | path: ty.path, |
486 | bang_token, |
487 | delimiter, |
488 | tokens, |
489 | }, |
490 | })); |
491 | } |
492 | |
493 | if lifetimes.is_some() || allow_plus && input.peek(Token![+]) { |
494 | let mut bounds = Punctuated::new(); |
495 | bounds.push_value(TypeParamBound::Trait(TraitBound { |
496 | paren_token: None, |
497 | modifier: TraitBoundModifier::None, |
498 | lifetimes, |
499 | path: ty.path, |
500 | })); |
501 | if allow_plus { |
502 | while input.peek(Token![+]) { |
503 | bounds.push_punct(input.parse()?); |
504 | if !(input.peek(Ident::peek_any) |
505 | || input.peek(Token![::]) |
506 | || input.peek(Token![?]) |
507 | || input.peek(Lifetime) |
508 | || input.peek(token::Paren)) |
509 | { |
510 | break; |
511 | } |
512 | bounds.push_value(input.parse()?); |
513 | } |
514 | } |
515 | return Ok(Type::TraitObject(TypeTraitObject { |
516 | dyn_token: None, |
517 | bounds, |
518 | })); |
519 | } |
520 | |
521 | Ok(Type::Path(ty)) |
522 | } else if lookahead.peek(Token![dyn]) { |
523 | let dyn_token: Token![dyn] = input.parse()?; |
524 | let dyn_span = dyn_token.span; |
525 | let star_token: Option<Token![*]> = input.parse()?; |
526 | let bounds = TypeTraitObject::parse_bounds(dyn_span, input, allow_plus)?; |
527 | return Ok(if star_token.is_some() { |
528 | Type::Verbatim(verbatim::between(&begin, input)) |
529 | } else { |
530 | Type::TraitObject(TypeTraitObject { |
531 | dyn_token: Some(dyn_token), |
532 | bounds, |
533 | }) |
534 | }); |
535 | } else if lookahead.peek(token::Bracket) { |
536 | let content; |
537 | let bracket_token = bracketed!(content in input); |
538 | let elem: Type = content.parse()?; |
539 | if content.peek(Token![;]) { |
540 | Ok(Type::Array(TypeArray { |
541 | bracket_token, |
542 | elem: Box::new(elem), |
543 | semi_token: content.parse()?, |
544 | len: content.parse()?, |
545 | })) |
546 | } else { |
547 | Ok(Type::Slice(TypeSlice { |
548 | bracket_token, |
549 | elem: Box::new(elem), |
550 | })) |
551 | } |
552 | } else if lookahead.peek(Token![*]) { |
553 | input.parse().map(Type::Ptr) |
554 | } else if lookahead.peek(Token![&]) { |
555 | input.parse().map(Type::Reference) |
556 | } else if lookahead.peek(Token![!]) && !input.peek(Token![=]) { |
557 | input.parse().map(Type::Never) |
558 | } else if lookahead.peek(Token![impl]) { |
559 | TypeImplTrait::parse(input, allow_plus).map(Type::ImplTrait) |
560 | } else if lookahead.peek(Token![_]) { |
561 | input.parse().map(Type::Infer) |
562 | } else if lookahead.peek(Lifetime) { |
563 | input.parse().map(Type::TraitObject) |
564 | } else { |
565 | Err(lookahead.error()) |
566 | } |
567 | } |
568 | |
569 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
570 | impl Parse for TypeSlice { |
571 | fn parse(input: ParseStream) -> Result<Self> { |
572 | let content; |
573 | Ok(TypeSlice { |
574 | bracket_token: bracketed!(content in input), |
575 | elem: content.parse()?, |
576 | }) |
577 | } |
578 | } |
579 | |
580 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
581 | impl Parse for TypeArray { |
582 | fn parse(input: ParseStream) -> Result<Self> { |
583 | let content; |
584 | Ok(TypeArray { |
585 | bracket_token: bracketed!(content in input), |
586 | elem: content.parse()?, |
587 | semi_token: content.parse()?, |
588 | len: content.parse()?, |
589 | }) |
590 | } |
591 | } |
592 | |
593 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
594 | impl Parse for TypePtr { |
595 | fn parse(input: ParseStream) -> Result<Self> { |
596 | let star_token: Token![*] = input.parse()?; |
597 | |
598 | let lookahead = input.lookahead1(); |
599 | let (const_token, mutability) = if lookahead.peek(Token![const]) { |
600 | (Some(input.parse()?), None) |
601 | } else if lookahead.peek(Token![mut]) { |
602 | (None, Some(input.parse()?)) |
603 | } else { |
604 | return Err(lookahead.error()); |
605 | }; |
606 | |
607 | Ok(TypePtr { |
608 | star_token, |
609 | const_token, |
610 | mutability, |
611 | elem: Box::new(input.call(Type::without_plus)?), |
612 | }) |
613 | } |
614 | } |
615 | |
616 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
617 | impl Parse for TypeReference { |
618 | fn parse(input: ParseStream) -> Result<Self> { |
619 | Ok(TypeReference { |
620 | and_token: input.parse()?, |
621 | lifetime: input.parse()?, |
622 | mutability: input.parse()?, |
623 | // & binds tighter than +, so we don't allow + here. |
624 | elem: Box::new(input.call(Type::without_plus)?), |
625 | }) |
626 | } |
627 | } |
628 | |
629 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
630 | impl Parse for TypeBareFn { |
631 | fn parse(input: ParseStream) -> Result<Self> { |
632 | let args; |
633 | let mut variadic = None; |
634 | |
635 | Ok(TypeBareFn { |
636 | lifetimes: input.parse()?, |
637 | unsafety: input.parse()?, |
638 | abi: input.parse()?, |
639 | fn_token: input.parse()?, |
640 | paren_token: parenthesized!(args in input), |
641 | inputs: { |
642 | let mut inputs = Punctuated::new(); |
643 | |
644 | while !args.is_empty() { |
645 | let attrs = args.call(Attribute::parse_outer)?; |
646 | |
647 | if inputs.empty_or_trailing() |
648 | && (args.peek(Token![...]) |
649 | || args.peek(Ident) |
650 | && args.peek2(Token![:]) |
651 | && args.peek3(Token![...])) |
652 | { |
653 | variadic = Some(parse_bare_variadic(&args, attrs)?); |
654 | break; |
655 | } |
656 | |
657 | let allow_self = inputs.is_empty(); |
658 | let arg = parse_bare_fn_arg(&args, allow_self)?; |
659 | inputs.push_value(BareFnArg { attrs, ..arg }); |
660 | if args.is_empty() { |
661 | break; |
662 | } |
663 | |
664 | let comma = args.parse()?; |
665 | inputs.push_punct(comma); |
666 | } |
667 | |
668 | inputs |
669 | }, |
670 | variadic, |
671 | output: input.call(ReturnType::without_plus)?, |
672 | }) |
673 | } |
674 | } |
675 | |
676 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
677 | impl Parse for TypeNever { |
678 | fn parse(input: ParseStream) -> Result<Self> { |
679 | Ok(TypeNever { |
680 | bang_token: input.parse()?, |
681 | }) |
682 | } |
683 | } |
684 | |
685 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
686 | impl Parse for TypeInfer { |
687 | fn parse(input: ParseStream) -> Result<Self> { |
688 | Ok(TypeInfer { |
689 | underscore_token: input.parse()?, |
690 | }) |
691 | } |
692 | } |
693 | |
694 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
695 | impl Parse for TypeTuple { |
696 | fn parse(input: ParseStream) -> Result<Self> { |
697 | let content; |
698 | let paren_token = parenthesized!(content in input); |
699 | |
700 | if content.is_empty() { |
701 | return Ok(TypeTuple { |
702 | paren_token, |
703 | elems: Punctuated::new(), |
704 | }); |
705 | } |
706 | |
707 | let first: Type = content.parse()?; |
708 | Ok(TypeTuple { |
709 | paren_token, |
710 | elems: { |
711 | let mut elems = Punctuated::new(); |
712 | elems.push_value(first); |
713 | elems.push_punct(content.parse()?); |
714 | while !content.is_empty() { |
715 | elems.push_value(content.parse()?); |
716 | if content.is_empty() { |
717 | break; |
718 | } |
719 | elems.push_punct(content.parse()?); |
720 | } |
721 | elems |
722 | }, |
723 | }) |
724 | } |
725 | } |
726 | |
727 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
728 | impl Parse for TypeMacro { |
729 | fn parse(input: ParseStream) -> Result<Self> { |
730 | Ok(TypeMacro { |
731 | mac: input.parse()?, |
732 | }) |
733 | } |
734 | } |
735 | |
736 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
737 | impl Parse for TypePath { |
738 | fn parse(input: ParseStream) -> Result<Self> { |
739 | let expr_style = false; |
740 | let (qself, path) = path::parsing::qpath(input, expr_style)?; |
741 | Ok(TypePath { qself, path }) |
742 | } |
743 | } |
744 | |
745 | impl ReturnType { |
746 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
747 | pub fn without_plus(input: ParseStream) -> Result<Self> { |
748 | let allow_plus = false; |
749 | Self::parse(input, allow_plus) |
750 | } |
751 | |
752 | pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> { |
753 | if input.peek(Token![->]) { |
754 | let arrow = input.parse()?; |
755 | let allow_group_generic = true; |
756 | let ty = ambig_ty(input, allow_plus, allow_group_generic)?; |
757 | Ok(ReturnType::Type(arrow, Box::new(ty))) |
758 | } else { |
759 | Ok(ReturnType::Default) |
760 | } |
761 | } |
762 | } |
763 | |
764 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
765 | impl Parse for ReturnType { |
766 | fn parse(input: ParseStream) -> Result<Self> { |
767 | let allow_plus = true; |
768 | Self::parse(input, allow_plus) |
769 | } |
770 | } |
771 | |
772 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
773 | impl Parse for TypeTraitObject { |
774 | fn parse(input: ParseStream) -> Result<Self> { |
775 | let allow_plus = true; |
776 | Self::parse(input, allow_plus) |
777 | } |
778 | } |
779 | |
780 | impl TypeTraitObject { |
781 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
782 | pub fn without_plus(input: ParseStream) -> Result<Self> { |
783 | let allow_plus = false; |
784 | Self::parse(input, allow_plus) |
785 | } |
786 | |
787 | // Only allow multiple trait references if allow_plus is true. |
788 | pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> { |
789 | let dyn_token: Option<Token![dyn]> = input.parse()?; |
790 | let dyn_span = match &dyn_token { |
791 | Some(token) => token.span, |
792 | None => input.span(), |
793 | }; |
794 | let bounds = Self::parse_bounds(dyn_span, input, allow_plus)?; |
795 | Ok(TypeTraitObject { dyn_token, bounds }) |
796 | } |
797 | |
798 | fn parse_bounds( |
799 | dyn_span: Span, |
800 | input: ParseStream, |
801 | allow_plus: bool, |
802 | ) -> Result<Punctuated<TypeParamBound, Token![+]>> { |
803 | let bounds = TypeParamBound::parse_multiple(input, allow_plus)?; |
804 | let mut last_lifetime_span = None; |
805 | let mut at_least_one_trait = false; |
806 | for bound in &bounds { |
807 | match bound { |
808 | TypeParamBound::Trait(_) | TypeParamBound::Verbatim(_) => { |
809 | at_least_one_trait = true; |
810 | break; |
811 | } |
812 | TypeParamBound::Lifetime(lifetime) => { |
813 | last_lifetime_span = Some(lifetime.ident.span()); |
814 | } |
815 | } |
816 | } |
817 | // Just lifetimes like `'a + 'b` is not a TraitObject. |
818 | if !at_least_one_trait { |
819 | let msg = "at least one trait is required for an object type" ; |
820 | return Err(error::new2(dyn_span, last_lifetime_span.unwrap(), msg)); |
821 | } |
822 | Ok(bounds) |
823 | } |
824 | } |
825 | |
826 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
827 | impl Parse for TypeImplTrait { |
828 | fn parse(input: ParseStream) -> Result<Self> { |
829 | let allow_plus = true; |
830 | Self::parse(input, allow_plus) |
831 | } |
832 | } |
833 | |
834 | impl TypeImplTrait { |
835 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
836 | pub fn without_plus(input: ParseStream) -> Result<Self> { |
837 | let allow_plus = false; |
838 | Self::parse(input, allow_plus) |
839 | } |
840 | |
841 | pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> { |
842 | let impl_token: Token![impl] = input.parse()?; |
843 | let bounds = TypeParamBound::parse_multiple(input, allow_plus)?; |
844 | let mut last_lifetime_span = None; |
845 | let mut at_least_one_trait = false; |
846 | for bound in &bounds { |
847 | match bound { |
848 | TypeParamBound::Trait(_) | TypeParamBound::Verbatim(_) => { |
849 | at_least_one_trait = true; |
850 | break; |
851 | } |
852 | TypeParamBound::Lifetime(lifetime) => { |
853 | last_lifetime_span = Some(lifetime.ident.span()); |
854 | } |
855 | } |
856 | } |
857 | if !at_least_one_trait { |
858 | let msg = "at least one trait must be specified" ; |
859 | return Err(error::new2( |
860 | impl_token.span, |
861 | last_lifetime_span.unwrap(), |
862 | msg, |
863 | )); |
864 | } |
865 | Ok(TypeImplTrait { impl_token, bounds }) |
866 | } |
867 | } |
868 | |
869 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
870 | impl Parse for TypeGroup { |
871 | fn parse(input: ParseStream) -> Result<Self> { |
872 | let group = crate::group::parse_group(input)?; |
873 | Ok(TypeGroup { |
874 | group_token: group.token, |
875 | elem: group.content.parse()?, |
876 | }) |
877 | } |
878 | } |
879 | |
880 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
881 | impl Parse for TypeParen { |
882 | fn parse(input: ParseStream) -> Result<Self> { |
883 | let allow_plus = false; |
884 | Self::parse(input, allow_plus) |
885 | } |
886 | } |
887 | |
888 | impl TypeParen { |
889 | fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> { |
890 | let content; |
891 | Ok(TypeParen { |
892 | paren_token: parenthesized!(content in input), |
893 | elem: Box::new({ |
894 | let allow_group_generic = true; |
895 | ambig_ty(&content, allow_plus, allow_group_generic)? |
896 | }), |
897 | }) |
898 | } |
899 | } |
900 | |
901 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
902 | impl Parse for BareFnArg { |
903 | fn parse(input: ParseStream) -> Result<Self> { |
904 | let allow_self = false; |
905 | parse_bare_fn_arg(input, allow_self) |
906 | } |
907 | } |
908 | |
909 | fn parse_bare_fn_arg(input: ParseStream, allow_self: bool) -> Result<BareFnArg> { |
910 | let attrs = input.call(Attribute::parse_outer)?; |
911 | |
912 | let begin = input.fork(); |
913 | |
914 | let has_mut_self = allow_self && input.peek(Token![mut]) && input.peek2(Token![self]); |
915 | if has_mut_self { |
916 | input.parse::<Token![mut]>()?; |
917 | } |
918 | |
919 | let mut has_self = false; |
920 | let mut name = if (input.peek(Ident) || input.peek(Token![_]) || { |
921 | has_self = allow_self && input.peek(Token![self]); |
922 | has_self |
923 | }) && input.peek2(Token![:]) |
924 | && !input.peek2(Token![::]) |
925 | { |
926 | let name = input.call(Ident::parse_any)?; |
927 | let colon: Token![:] = input.parse()?; |
928 | Some((name, colon)) |
929 | } else { |
930 | has_self = false; |
931 | None |
932 | }; |
933 | |
934 | let ty = if allow_self && !has_self && input.peek(Token![mut]) && input.peek2(Token![self]) |
935 | { |
936 | input.parse::<Token![mut]>()?; |
937 | input.parse::<Token![self]>()?; |
938 | None |
939 | } else if has_mut_self && name.is_none() { |
940 | input.parse::<Token![self]>()?; |
941 | None |
942 | } else { |
943 | Some(input.parse()?) |
944 | }; |
945 | |
946 | let ty = match ty { |
947 | Some(ty) if !has_mut_self => ty, |
948 | _ => { |
949 | name = None; |
950 | Type::Verbatim(verbatim::between(&begin, input)) |
951 | } |
952 | }; |
953 | |
954 | Ok(BareFnArg { attrs, name, ty }) |
955 | } |
956 | |
957 | fn parse_bare_variadic(input: ParseStream, attrs: Vec<Attribute>) -> Result<BareVariadic> { |
958 | Ok(BareVariadic { |
959 | attrs, |
960 | name: if input.peek(Ident) || input.peek(Token![_]) { |
961 | let name = input.call(Ident::parse_any)?; |
962 | let colon: Token![:] = input.parse()?; |
963 | Some((name, colon)) |
964 | } else { |
965 | None |
966 | }, |
967 | dots: input.parse()?, |
968 | comma: input.parse()?, |
969 | }) |
970 | } |
971 | |
972 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
973 | impl Parse for Abi { |
974 | fn parse(input: ParseStream) -> Result<Self> { |
975 | Ok(Abi { |
976 | extern_token: input.parse()?, |
977 | name: input.parse()?, |
978 | }) |
979 | } |
980 | } |
981 | |
982 | #[cfg_attr (doc_cfg, doc(cfg(feature = "parsing" )))] |
983 | impl Parse for Option<Abi> { |
984 | fn parse(input: ParseStream) -> Result<Self> { |
985 | if input.peek(Token![extern]) { |
986 | input.parse().map(Some) |
987 | } else { |
988 | Ok(None) |
989 | } |
990 | } |
991 | } |
992 | } |
993 | |
994 | #[cfg (feature = "printing" )] |
995 | mod printing { |
996 | use super::*; |
997 | use crate::attr::FilterAttrs; |
998 | use crate::print::TokensOrDefault; |
999 | use proc_macro2::TokenStream; |
1000 | use quote::{ToTokens, TokenStreamExt}; |
1001 | |
1002 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1003 | impl ToTokens for TypeSlice { |
1004 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1005 | self.bracket_token.surround(tokens, |tokens| { |
1006 | self.elem.to_tokens(tokens); |
1007 | }); |
1008 | } |
1009 | } |
1010 | |
1011 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1012 | impl ToTokens for TypeArray { |
1013 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1014 | self.bracket_token.surround(tokens, |tokens| { |
1015 | self.elem.to_tokens(tokens); |
1016 | self.semi_token.to_tokens(tokens); |
1017 | self.len.to_tokens(tokens); |
1018 | }); |
1019 | } |
1020 | } |
1021 | |
1022 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1023 | impl ToTokens for TypePtr { |
1024 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1025 | self.star_token.to_tokens(tokens); |
1026 | match &self.mutability { |
1027 | Some(tok) => tok.to_tokens(tokens), |
1028 | None => { |
1029 | TokensOrDefault(&self.const_token).to_tokens(tokens); |
1030 | } |
1031 | } |
1032 | self.elem.to_tokens(tokens); |
1033 | } |
1034 | } |
1035 | |
1036 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1037 | impl ToTokens for TypeReference { |
1038 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1039 | self.and_token.to_tokens(tokens); |
1040 | self.lifetime.to_tokens(tokens); |
1041 | self.mutability.to_tokens(tokens); |
1042 | self.elem.to_tokens(tokens); |
1043 | } |
1044 | } |
1045 | |
1046 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1047 | impl ToTokens for TypeBareFn { |
1048 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1049 | self.lifetimes.to_tokens(tokens); |
1050 | self.unsafety.to_tokens(tokens); |
1051 | self.abi.to_tokens(tokens); |
1052 | self.fn_token.to_tokens(tokens); |
1053 | self.paren_token.surround(tokens, |tokens| { |
1054 | self.inputs.to_tokens(tokens); |
1055 | if let Some(variadic) = &self.variadic { |
1056 | if !self.inputs.empty_or_trailing() { |
1057 | let span = variadic.dots.spans[0]; |
1058 | Token![,](span).to_tokens(tokens); |
1059 | } |
1060 | variadic.to_tokens(tokens); |
1061 | } |
1062 | }); |
1063 | self.output.to_tokens(tokens); |
1064 | } |
1065 | } |
1066 | |
1067 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1068 | impl ToTokens for TypeNever { |
1069 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1070 | self.bang_token.to_tokens(tokens); |
1071 | } |
1072 | } |
1073 | |
1074 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1075 | impl ToTokens for TypeTuple { |
1076 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1077 | self.paren_token.surround(tokens, |tokens| { |
1078 | self.elems.to_tokens(tokens); |
1079 | // If we only have one argument, we need a trailing comma to |
1080 | // distinguish TypeTuple from TypeParen. |
1081 | if self.elems.len() == 1 && !self.elems.trailing_punct() { |
1082 | <Token![,]>::default().to_tokens(tokens); |
1083 | } |
1084 | }); |
1085 | } |
1086 | } |
1087 | |
1088 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1089 | impl ToTokens for TypePath { |
1090 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1091 | path::printing::print_path(tokens, &self.qself, &self.path); |
1092 | } |
1093 | } |
1094 | |
1095 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1096 | impl ToTokens for TypeTraitObject { |
1097 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1098 | self.dyn_token.to_tokens(tokens); |
1099 | self.bounds.to_tokens(tokens); |
1100 | } |
1101 | } |
1102 | |
1103 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1104 | impl ToTokens for TypeImplTrait { |
1105 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1106 | self.impl_token.to_tokens(tokens); |
1107 | self.bounds.to_tokens(tokens); |
1108 | } |
1109 | } |
1110 | |
1111 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1112 | impl ToTokens for TypeGroup { |
1113 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1114 | self.group_token.surround(tokens, |tokens| { |
1115 | self.elem.to_tokens(tokens); |
1116 | }); |
1117 | } |
1118 | } |
1119 | |
1120 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1121 | impl ToTokens for TypeParen { |
1122 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1123 | self.paren_token.surround(tokens, |tokens| { |
1124 | self.elem.to_tokens(tokens); |
1125 | }); |
1126 | } |
1127 | } |
1128 | |
1129 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1130 | impl ToTokens for TypeInfer { |
1131 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1132 | self.underscore_token.to_tokens(tokens); |
1133 | } |
1134 | } |
1135 | |
1136 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1137 | impl ToTokens for TypeMacro { |
1138 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1139 | self.mac.to_tokens(tokens); |
1140 | } |
1141 | } |
1142 | |
1143 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1144 | impl ToTokens for ReturnType { |
1145 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1146 | match self { |
1147 | ReturnType::Default => {} |
1148 | ReturnType::Type(arrow, ty) => { |
1149 | arrow.to_tokens(tokens); |
1150 | ty.to_tokens(tokens); |
1151 | } |
1152 | } |
1153 | } |
1154 | } |
1155 | |
1156 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1157 | impl ToTokens for BareFnArg { |
1158 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1159 | tokens.append_all(self.attrs.outer()); |
1160 | if let Some((name, colon)) = &self.name { |
1161 | name.to_tokens(tokens); |
1162 | colon.to_tokens(tokens); |
1163 | } |
1164 | self.ty.to_tokens(tokens); |
1165 | } |
1166 | } |
1167 | |
1168 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1169 | impl ToTokens for BareVariadic { |
1170 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1171 | tokens.append_all(self.attrs.outer()); |
1172 | if let Some((name, colon)) = &self.name { |
1173 | name.to_tokens(tokens); |
1174 | colon.to_tokens(tokens); |
1175 | } |
1176 | self.dots.to_tokens(tokens); |
1177 | self.comma.to_tokens(tokens); |
1178 | } |
1179 | } |
1180 | |
1181 | #[cfg_attr (doc_cfg, doc(cfg(feature = "printing" )))] |
1182 | impl ToTokens for Abi { |
1183 | fn to_tokens(&self, tokens: &mut TokenStream) { |
1184 | self.extern_token.to_tokens(tokens); |
1185 | self.name.to_tokens(tokens); |
1186 | } |
1187 | } |
1188 | } |
1189 | |