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