1use punctuated::Punctuated;
10use super::*;
11use proc_macro2::TokenStream;
12#[cfg(feature = "extra-traits")]
13use std::hash::{Hash, Hasher};
14#[cfg(feature = "extra-traits")]
15use tt::TokenStreamHelper;
16
17ast_enum_of_structs! {
18 pub enum Type {
29 pub Slice(TypeSlice {
34 pub bracket_token: token::Bracket,
35 pub elem: Box<Type>,
36 }),
37
38 pub Array(TypeArray {
43 pub bracket_token: token::Bracket,
44 pub elem: Box<Type>,
45 pub semi_token: Token![;],
46 pub len: Expr,
47 }),
48
49 pub Ptr(TypePtr {
54 pub star_token: Token![*],
55 pub const_token: Option<Token![const]>,
56 pub mutability: Option<Token![mut]>,
57 pub elem: Box<Type>,
58 }),
59
60 pub Reference(TypeReference {
65 pub and_token: Token![&],
66 pub lifetime: Option<Lifetime>,
67 pub mutability: Option<Token![mut]>,
68 pub elem: Box<Type>,
69 }),
70
71 pub BareFn(TypeBareFn {
76 pub unsafety: Option<Token![unsafe]>,
77 pub abi: Option<Abi>,
78 pub fn_token: Token![fn],
79 pub lifetimes: Option<BoundLifetimes>,
80 pub paren_token: token::Paren,
81 pub inputs: Punctuated<BareFnArg, Token![,]>,
82 pub variadic: Option<Token![...]>,
83 pub output: ReturnType,
84 }),
85
86 pub Never(TypeNever {
91 pub bang_token: Token![!],
92 }),
93
94 pub Tuple(TypeTuple {
99 pub paren_token: token::Paren,
100 pub elems: Punctuated<Type, Token![,]>,
101 }),
102
103 pub Path(TypePath {
111 pub qself: Option<QSelf>,
112 pub path: Path,
113 }),
114
115 pub TraitObject(TypeTraitObject {
121 pub dyn_token: Option<Token![dyn]>,
122 pub bounds: Punctuated<TypeParamBound, Token![+]>,
123 }),
124
125 pub ImplTrait(TypeImplTrait {
131 pub impl_token: Token![impl],
132 pub bounds: Punctuated<TypeParamBound, Token![+]>,
133 }),
134
135 pub Paren(TypeParen {
140 pub paren_token: token::Paren,
141 pub elem: Box<Type>,
142 }),
143
144 pub Group(TypeGroup {
149 pub group_token: token::Group,
150 pub elem: Box<Type>,
151 }),
152
153 pub Infer(TypeInfer {
158 pub underscore_token: Token![_],
159 }),
160
161 pub Macro(TypeMacro {
166 pub mac: Macro,
167 }),
168
169 pub Verbatim(TypeVerbatim #manual_extra_traits {
174 pub tts: TokenStream,
175 }),
176 }
177}
178
179#[cfg(feature = "extra-traits")]
180impl Eq for TypeVerbatim {}
181
182#[cfg(feature = "extra-traits")]
183impl PartialEq for TypeVerbatim {
184 fn eq(&self, other: &Self) -> bool {
185 TokenStreamHelper(&self.tts) == TokenStreamHelper(&other.tts)
186 }
187}
188
189#[cfg(feature = "extra-traits")]
190impl Hash for TypeVerbatim {
191 fn hash<H>(&self, state: &mut H)
192 where
193 H: Hasher,
194 {
195 TokenStreamHelper(&self.tts).hash(state);
196 }
197}
198
199ast_struct! {
200 pub struct Abi {
205 pub extern_token: Token![extern],
206 pub name: Option<LitStr>,
207 }
208}
209
210ast_struct! {
211 pub struct BareFnArg {
216 pub name: Option<(BareFnArgName, Token![:])>,
217 pub ty: Type,
218 }
219}
220
221ast_enum! {
222 pub enum BareFnArgName {
227 Named(Ident),
229 Wild(Token![_]),
231 }
232}
233
234ast_enum! {
235 pub enum ReturnType {
240 Default,
244 Type(Token![->], Box<Type>),
246 }
247}
248
249#[cfg(feature = "parsing")]
250pub mod parsing {
251 use super::*;
252 use synom::Synom;
253 use path::parsing::qpath;
254
255 impl Synom for Type {
256 named!(parse -> Self, call!(ambig_ty, true));
257
258 fn description() -> Option<&'static str> {
259 Some("type")
260 }
261 }
262
263 impl Type {
264 named!(pub without_plus -> Self, call!(ambig_ty, false));
270 }
271
272 named!(ambig_ty(allow_plus: bool) -> Type, alt!(
273 syn!(TypeGroup) => { Type::Group }
274 |
275 call!(TypeParen::parse, allow_plus) => { Type::Paren }
277 |
278 syn!(TypeMacro) => { Type::Macro }
280 |
281 call!(TypePath::parse, allow_plus) => { Type::Path }
283 |
284 call!(TypeTraitObject::parse, allow_plus) => { Type::TraitObject }
287 |
288 syn!(TypeSlice) => { Type::Slice }
289 |
290 syn!(TypeArray) => { Type::Array }
291 |
292 syn!(TypePtr) => { Type::Ptr }
293 |
294 syn!(TypeReference) => { Type::Reference }
295 |
296 syn!(TypeBareFn) => { Type::BareFn }
297 |
298 syn!(TypeNever) => { Type::Never }
299 |
300 syn!(TypeTuple) => { Type::Tuple }
301 |
302 syn!(TypeImplTrait) => { Type::ImplTrait }
303 |
304 syn!(TypeInfer) => { Type::Infer }
305 ));
306
307 impl Synom for TypeSlice {
308 named!(parse -> Self, map!(
309 brackets!(syn!(Type)),
310 |(b, ty)| TypeSlice {
311 elem: Box::new(ty),
312 bracket_token: b,
313 }
314 ));
315
316 fn description() -> Option<&'static str> {
317 Some("slice type")
318 }
319 }
320
321 impl Synom for TypeArray {
322 named!(parse -> Self, map!(
323 brackets!(do_parse!(
324 elem: syn!(Type) >>
325 semi: punct!(;) >>
326 len: syn!(Expr) >>
327 (elem, semi, len)
328 )),
329 |(brackets, (elem, semi, len))| {
330 TypeArray {
331 elem: Box::new(elem),
332 len: len,
333 bracket_token: brackets,
334 semi_token: semi,
335 }
336 }
337 ));
338
339 fn description() -> Option<&'static str> {
340 Some("array type")
341 }
342 }
343
344 impl Synom for TypePtr {
345 named!(parse -> Self, do_parse!(
346 star: punct!(*) >>
347 mutability: alt!(
348 keyword!(const) => { |c| (None, Some(c)) }
349 |
350 keyword!(mut) => { |m| (Some(m), None) }
351 ) >>
352 target: call!(Type::without_plus) >>
353 (TypePtr {
354 const_token: mutability.1,
355 star_token: star,
356 mutability: mutability.0,
357 elem: Box::new(target),
358 })
359 ));
360
361 fn description() -> Option<&'static str> {
362 Some("raw pointer type")
363 }
364 }
365
366 impl Synom for TypeReference {
367 named!(parse -> Self, do_parse!(
368 amp: punct!(&) >>
369 life: option!(syn!(Lifetime)) >>
370 mutability: option!(keyword!(mut)) >>
371 target: call!(Type::without_plus) >>
373 (TypeReference {
374 lifetime: life,
375 mutability: mutability,
376 elem: Box::new(target),
377 and_token: amp,
378 })
379 ));
380
381 fn description() -> Option<&'static str> {
382 Some("reference type")
383 }
384 }
385
386 impl Synom for TypeBareFn {
387 named!(parse -> Self, do_parse!(
388 lifetimes: option!(syn!(BoundLifetimes)) >>
389 unsafety: option!(keyword!(unsafe)) >>
390 abi: option!(syn!(Abi)) >>
391 fn_: keyword!(fn) >>
392 parens: parens!(do_parse!(
393 inputs: call!(Punctuated::parse_terminated) >>
394 variadic: option!(cond_reduce!(inputs.empty_or_trailing(), punct!(...))) >>
395 (inputs, variadic)
396 )) >>
397 output: syn!(ReturnType) >>
398 (TypeBareFn {
399 unsafety: unsafety,
400 abi: abi,
401 lifetimes: lifetimes,
402 output: output,
403 variadic: (parens.1).1,
404 fn_token: fn_,
405 paren_token: parens.0,
406 inputs: (parens.1).0,
407 })
408 ));
409
410 fn description() -> Option<&'static str> {
411 Some("`fn` type")
412 }
413 }
414
415 impl Synom for TypeNever {
416 named!(parse -> Self, map!(
417 punct!(!),
418 |b| TypeNever { bang_token: b }
419 ));
420
421 fn description() -> Option<&'static str> {
422 Some("never type: `!`")
423 }
424 }
425
426 impl Synom for TypeInfer {
427 named!(parse -> Self, map!(
428 punct!(_),
429 |u| TypeInfer { underscore_token: u }
430 ));
431
432 fn description() -> Option<&'static str> {
433 Some("inferred type: `_`")
434 }
435 }
436
437 impl Synom for TypeTuple {
438 named!(parse -> Self, do_parse!(
439 data: parens!(Punctuated::parse_terminated) >>
440 (TypeTuple {
441 paren_token: data.0,
442 elems: data.1,
443 })
444 ));
445
446 fn description() -> Option<&'static str> {
447 Some("tuple type")
448 }
449 }
450
451 impl Synom for TypeMacro {
452 named!(parse -> Self, map!(syn!(Macro), |mac| TypeMacro { mac: mac }));
453
454 fn description() -> Option<&'static str> {
455 Some("macro invocation")
456 }
457 }
458
459 impl Synom for TypePath {
460 named!(parse -> Self, call!(Self::parse, false));
461
462 fn description() -> Option<&'static str> {
463 Some("type path")
464 }
465 }
466
467 impl TypePath {
468 named!(parse(allow_plus: bool) -> Self, do_parse!(
469 qpath: qpath >>
470 parenthesized: option!(cond_reduce!(
471 qpath.1.segments.last().unwrap().value().arguments.is_empty(),
472 syn!(ParenthesizedGenericArguments)
473 )) >>
474 cond!(allow_plus, not!(punct!(+))) >>
475 ({
476 let (qself, mut path) = qpath;
477 if let Some(parenthesized) = parenthesized {
478 let parenthesized = PathArguments::Parenthesized(parenthesized);
479 path.segments.last_mut().unwrap().value_mut().arguments = parenthesized;
480 }
481 TypePath { qself: qself, path: path }
482 })
483 ));
484 }
485
486 impl Synom for ReturnType {
487 named!(parse -> Self, alt!(
488 do_parse!(
489 arrow: punct!(->) >>
490 ty: syn!(Type) >>
491 (ReturnType::Type(arrow, Box::new(ty)))
492 )
493 |
494 epsilon!() => { |_| ReturnType::Default }
495 ));
496
497 fn description() -> Option<&'static str> {
498 Some("return type")
499 }
500 }
501
502 impl Synom for TypeTraitObject {
503 named!(parse -> Self, call!(Self::parse, true));
504
505 fn description() -> Option<&'static str> {
506 Some("trait object type")
507 }
508 }
509
510 fn at_least_one_type(bounds: &Punctuated<TypeParamBound, Token![+]>) -> bool {
511 for bound in bounds {
512 if let TypeParamBound::Trait(_) = *bound {
513 return true;
514 }
515 }
516 false
517 }
518
519 impl TypeTraitObject {
520 named!(pub without_plus -> Self, call!(Self::parse, false));
521
522 named!(parse(allow_plus: bool) -> Self, do_parse!(
524 dyn_token: option!(keyword!(dyn)) >>
525 bounds: alt!(
526 cond_reduce!(allow_plus, Punctuated::parse_terminated_nonempty)
527 |
528 syn!(TypeParamBound) => {|x| {
529 let mut bounds = Punctuated::new();
530 bounds.push_value(x);
531 bounds
532 }}
533 ) >>
534 cond_reduce!(at_least_one_type(&bounds)) >>
536 (TypeTraitObject {
537 dyn_token: dyn_token,
538 bounds: bounds,
539 })
540 ));
541 }
542
543 impl Synom for TypeImplTrait {
544 named!(parse -> Self, do_parse!(
545 impl_: keyword!(impl) >>
546 elem: call!(Punctuated::parse_terminated_nonempty) >>
549 (TypeImplTrait {
550 impl_token: impl_,
551 bounds: elem,
552 })
553 ));
554
555 fn description() -> Option<&'static str> {
556 Some("`impl Trait` type")
557 }
558 }
559
560 impl Synom for TypeGroup {
561 named!(parse -> Self, do_parse!(
562 data: grouped!(syn!(Type)) >>
563 (TypeGroup {
564 group_token: data.0,
565 elem: Box::new(data.1),
566 })
567 ));
568
569 fn description() -> Option<&'static str> {
570 Some("type surrounded by invisible delimiters")
571 }
572 }
573
574 impl Synom for TypeParen {
575 named!(parse -> Self, call!(Self::parse, false));
576
577 fn description() -> Option<&'static str> {
578 Some("parenthesized type")
579 }
580 }
581
582 impl TypeParen {
583 named!(parse(allow_plus: bool) -> Self, do_parse!(
584 data: parens!(syn!(Type)) >>
585 cond!(allow_plus, not!(punct!(+))) >>
586 (TypeParen {
587 paren_token: data.0,
588 elem: Box::new(data.1),
589 })
590 ));
591 }
592
593 impl Synom for BareFnArg {
594 named!(parse -> Self, do_parse!(
595 name: option!(do_parse!(
596 name: syn!(BareFnArgName) >>
597 not!(punct!(::)) >>
598 colon: punct!(:) >>
599 (name, colon)
600 )) >>
601 ty: syn!(Type) >>
602 (BareFnArg {
603 name: name,
604 ty: ty,
605 })
606 ));
607
608 fn description() -> Option<&'static str> {
609 Some("function type argument")
610 }
611 }
612
613 impl Synom for BareFnArgName {
614 named!(parse -> Self, alt!(
615 map!(syn!(Ident), BareFnArgName::Named)
616 |
617 map!(punct!(_), BareFnArgName::Wild)
618 ));
619
620 fn description() -> Option<&'static str> {
621 Some("function argument name")
622 }
623 }
624
625 impl Synom for Abi {
626 named!(parse -> Self, do_parse!(
627 extern_: keyword!(extern) >>
628 name: option!(syn!(LitStr)) >>
629 (Abi {
630 extern_token: extern_,
631 name: name,
632 })
633 ));
634
635 fn description() -> Option<&'static str> {
636 Some("`extern` ABI qualifier")
637 }
638 }
639}
640
641#[cfg(feature = "printing")]
642mod printing {
643 use super::*;
644 use quote::{ToTokens, Tokens};
645
646 impl ToTokens for TypeSlice {
647 fn to_tokens(&self, tokens: &mut Tokens) {
648 self.bracket_token.surround(tokens, |tokens| {
649 self.elem.to_tokens(tokens);
650 });
651 }
652 }
653
654 impl ToTokens for TypeArray {
655 fn to_tokens(&self, tokens: &mut Tokens) {
656 self.bracket_token.surround(tokens, |tokens| {
657 self.elem.to_tokens(tokens);
658 self.semi_token.to_tokens(tokens);
659 self.len.to_tokens(tokens);
660 });
661 }
662 }
663
664 impl ToTokens for TypePtr {
665 fn to_tokens(&self, tokens: &mut Tokens) {
666 self.star_token.to_tokens(tokens);
667 match self.mutability {
668 Some(ref tok) => tok.to_tokens(tokens),
669 None => {
670 TokensOrDefault(&self.const_token).to_tokens(tokens);
671 }
672 }
673 self.elem.to_tokens(tokens);
674 }
675 }
676
677 impl ToTokens for TypeReference {
678 fn to_tokens(&self, tokens: &mut Tokens) {
679 self.and_token.to_tokens(tokens);
680 self.lifetime.to_tokens(tokens);
681 self.mutability.to_tokens(tokens);
682 self.elem.to_tokens(tokens);
683 }
684 }
685
686 impl ToTokens for TypeBareFn {
687 fn to_tokens(&self, tokens: &mut Tokens) {
688 self.lifetimes.to_tokens(tokens);
689 self.unsafety.to_tokens(tokens);
690 self.abi.to_tokens(tokens);
691 self.fn_token.to_tokens(tokens);
692 self.paren_token.surround(tokens, |tokens| {
693 self.inputs.to_tokens(tokens);
694 if let Some(ref variadic) = self.variadic {
695 if !self.inputs.empty_or_trailing() {
696 let span = variadic.0[0];
697 <Token![,]>::new(span).to_tokens(tokens);
698 }
699 variadic.to_tokens(tokens);
700 }
701 });
702 self.output.to_tokens(tokens);
703 }
704 }
705
706 impl ToTokens for TypeNever {
707 fn to_tokens(&self, tokens: &mut Tokens) {
708 self.bang_token.to_tokens(tokens);
709 }
710 }
711
712 impl ToTokens for TypeTuple {
713 fn to_tokens(&self, tokens: &mut Tokens) {
714 self.paren_token.surround(tokens, |tokens| {
715 self.elems.to_tokens(tokens);
716 })
717 }
718 }
719
720 impl ToTokens for TypePath {
721 fn to_tokens(&self, tokens: &mut Tokens) {
722 PathTokens(&self.qself, &self.path).to_tokens(tokens);
723 }
724 }
725
726 impl ToTokens for TypeTraitObject {
727 fn to_tokens(&self, tokens: &mut Tokens) {
728 self.dyn_token.to_tokens(tokens);
729 self.bounds.to_tokens(tokens);
730 }
731 }
732
733 impl ToTokens for TypeImplTrait {
734 fn to_tokens(&self, tokens: &mut Tokens) {
735 self.impl_token.to_tokens(tokens);
736 self.bounds.to_tokens(tokens);
737 }
738 }
739
740 impl ToTokens for TypeGroup {
741 fn to_tokens(&self, tokens: &mut Tokens) {
742 self.group_token.surround(tokens, |tokens| {
743 self.elem.to_tokens(tokens);
744 });
745 }
746 }
747
748 impl ToTokens for TypeParen {
749 fn to_tokens(&self, tokens: &mut Tokens) {
750 self.paren_token.surround(tokens, |tokens| {
751 self.elem.to_tokens(tokens);
752 });
753 }
754 }
755
756 impl ToTokens for TypeInfer {
757 fn to_tokens(&self, tokens: &mut Tokens) {
758 self.underscore_token.to_tokens(tokens);
759 }
760 }
761
762 impl ToTokens for TypeMacro {
763 fn to_tokens(&self, tokens: &mut Tokens) {
764 self.mac.to_tokens(tokens);
765 }
766 }
767
768 impl ToTokens for TypeVerbatim {
769 fn to_tokens(&self, tokens: &mut Tokens) {
770 self.tts.to_tokens(tokens);
771 }
772 }
773
774 impl ToTokens for ReturnType {
775 fn to_tokens(&self, tokens: &mut Tokens) {
776 match *self {
777 ReturnType::Default => {}
778 ReturnType::Type(ref arrow, ref ty) => {
779 arrow.to_tokens(tokens);
780 ty.to_tokens(tokens);
781 }
782 }
783 }
784 }
785
786 impl ToTokens for BareFnArg {
787 fn to_tokens(&self, tokens: &mut Tokens) {
788 if let Some((ref name, ref colon)) = self.name {
789 name.to_tokens(tokens);
790 colon.to_tokens(tokens);
791 }
792 self.ty.to_tokens(tokens);
793 }
794 }
795
796 impl ToTokens for BareFnArgName {
797 fn to_tokens(&self, tokens: &mut Tokens) {
798 match *self {
799 BareFnArgName::Named(ref t) => t.to_tokens(tokens),
800 BareFnArgName::Wild(ref t) => t.to_tokens(tokens),
801 }
802 }
803 }
804
805 impl ToTokens for Abi {
806 fn to_tokens(&self, tokens: &mut Tokens) {
807 self.extern_token.to_tokens(tokens);
808 self.name.to_tokens(tokens);
809 }
810 }
811}