From 5e20a29b4fdc8a2d442d1093681b396dcb4b816b Mon Sep 17 00:00:00 2001 From: Robin Krahl Date: Tue, 7 Jan 2020 11:18:04 +0000 Subject: Add structopt dependency in version 0.3.7 This patch series replaces argparse with structopt in the argument handling code. As a first step, we need structopt as a dependency. Import subrepo structopt/:structopt at efbdda4753592e27bc430fb01f7b9650b2f3174d Import subrepo bitflags/:bitflags at 30668016aca6bd3b02c766e8347e0b4080d4c296 Import subrepo clap/:clap at 784524f7eb193e35f81082cc69454c8c21b948f7 Import subrepo heck/:heck at 093d56fbf001e1506e56dbfa38631d99b1066df1 Import subrepo proc-macro-error/:proc-macro-error at 6c4cfe79a622c5de8ae68557993542be46eacae2 Import subrepo proc-macro2/:proc-macro2 at d5d48eddca4566e5438e8a2cbed4a74e049544de Import subrepo quote/:quote at 727436c6c137b20f0f34dde5d8fda2679b9747ad Import subrepo rustversion/:rustversion at 0c5663313516263059ce9059ef81fc7a1cf655ca Import subrepo syn-mid/:syn-mid at 5d3d85414a9e6674e1857ec22a87b96e04a6851a Import subrepo syn/:syn at e87c27e87f6f4ef8919d0372bdb056d53ef0d8f3 Import subrepo textwrap/:textwrap at abcd618beae3f74841032aa5b53c1086b0a57ca2 Import subrepo unicode-segmentation/:unicode-segmentation at 637c9874c4fe0c205ff27787faf150a40295c6c3 Import subrepo unicode-width/:unicode-width at 3033826f8bf05e82724140a981d5941e48fce393 Import subrepo unicode-xid/:unicode-xid at 4baae9fffb156ba229665b972a9cd5991787ceb7 --- syn/src/ty.rs | 1178 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1178 insertions(+) create mode 100644 syn/src/ty.rs (limited to 'syn/src/ty.rs') diff --git a/syn/src/ty.rs b/syn/src/ty.rs new file mode 100644 index 0000000..b2e086b --- /dev/null +++ b/syn/src/ty.rs @@ -0,0 +1,1178 @@ +use super::*; +use crate::punctuated::Punctuated; +#[cfg(feature = "extra-traits")] +use crate::tt::TokenStreamHelper; +use proc_macro2::TokenStream; +#[cfg(feature = "extra-traits")] +use std::hash::{Hash, Hasher}; + +ast_enum_of_structs! { + /// The possible types that a Rust value could have. + /// + /// *This type is available if Syn is built with the `"derive"` or `"full"` + /// feature.* + /// + /// # Syntax tree enum + /// + /// This type is a [syntax tree enum]. + /// + /// [syntax tree enum]: enum.Expr.html#syntax-tree-enums + // + // TODO: change syntax-tree-enum link to an intra rustdoc link, currently + // blocked on https://github.com/rust-lang/rust/issues/62833 + pub enum Type #manual_extra_traits { + /// A fixed size array type: `[T; n]`. + Array(TypeArray), + + /// A bare function type: `fn(usize) -> bool`. + BareFn(TypeBareFn), + + /// A type contained within invisible delimiters. + Group(TypeGroup), + + /// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or + /// a lifetime. + ImplTrait(TypeImplTrait), + + /// Indication that a type should be inferred by the compiler: `_`. + Infer(TypeInfer), + + /// A macro in the type position. + Macro(TypeMacro), + + /// The never type: `!`. + Never(TypeNever), + + /// A parenthesized type equivalent to the inner type. + Paren(TypeParen), + + /// A path like `std::slice::Iter`, optionally qualified with a + /// self-type as in ` as SomeTrait>::Associated`. + Path(TypePath), + + /// A raw pointer type: `*const T` or `*mut T`. + Ptr(TypePtr), + + /// A reference type: `&'a T` or `&'a mut T`. + Reference(TypeReference), + + /// A dynamically sized slice type: `[T]`. + Slice(TypeSlice), + + /// A trait object type `Bound1 + Bound2 + Bound3` where `Bound` is a + /// trait or a lifetime. + TraitObject(TypeTraitObject), + + /// A tuple type: `(A, B, C, String)`. + Tuple(TypeTuple), + + /// Tokens in type position not interpreted by Syn. + Verbatim(TokenStream), + + #[doc(hidden)] + __Nonexhaustive, + } +} + +ast_struct! { + /// A fixed size array type: `[T; n]`. + /// + /// *This type is available if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct TypeArray { + pub bracket_token: token::Bracket, + pub elem: Box, + pub semi_token: Token![;], + pub len: Expr, + } +} + +ast_struct! { + /// A bare function type: `fn(usize) -> bool`. + /// + /// *This type is available if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct TypeBareFn { + pub lifetimes: Option, + pub unsafety: Option, + pub abi: Option, + pub fn_token: Token![fn], + pub paren_token: token::Paren, + pub inputs: Punctuated, + pub variadic: Option, + pub output: ReturnType, + } +} + +ast_struct! { + /// A type contained within invisible delimiters. + /// + /// *This type is available if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct TypeGroup { + pub group_token: token::Group, + pub elem: Box, + } +} + +ast_struct! { + /// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or + /// a lifetime. + /// + /// *This type is available if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct TypeImplTrait { + pub impl_token: Token![impl], + pub bounds: Punctuated, + } +} + +ast_struct! { + /// Indication that a type should be inferred by the compiler: `_`. + /// + /// *This type is available if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct TypeInfer { + pub underscore_token: Token![_], + } +} + +ast_struct! { + /// A macro in the type position. + /// + /// *This type is available if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct TypeMacro { + pub mac: Macro, + } +} + +ast_struct! { + /// The never type: `!`. + /// + /// *This type is available if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct TypeNever { + pub bang_token: Token![!], + } +} + +ast_struct! { + /// A parenthesized type equivalent to the inner type. + /// + /// *This type is available if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct TypeParen { + pub paren_token: token::Paren, + pub elem: Box, + } +} + +ast_struct! { + /// A path like `std::slice::Iter`, optionally qualified with a + /// self-type as in ` as SomeTrait>::Associated`. + /// + /// *This type is available if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct TypePath { + pub qself: Option, + pub path: Path, + } +} + +ast_struct! { + /// A raw pointer type: `*const T` or `*mut T`. + /// + /// *This type is available if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct TypePtr { + pub star_token: Token![*], + pub const_token: Option, + pub mutability: Option, + pub elem: Box, + } +} + +ast_struct! { + /// A reference type: `&'a T` or `&'a mut T`. + /// + /// *This type is available if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct TypeReference { + pub and_token: Token![&], + pub lifetime: Option, + pub mutability: Option, + pub elem: Box, + } +} + +ast_struct! { + /// A dynamically sized slice type: `[T]`. + /// + /// *This type is available if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct TypeSlice { + pub bracket_token: token::Bracket, + pub elem: Box, + } +} + +ast_struct! { + /// A trait object type `Bound1 + Bound2 + Bound3` where `Bound` is a + /// trait or a lifetime. + /// + /// *This type is available if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct TypeTraitObject { + pub dyn_token: Option, + pub bounds: Punctuated, + } +} + +ast_struct! { + /// A tuple type: `(A, B, C, String)`. + /// + /// *This type is available if Syn is built with the `"derive"` or + /// `"full"` feature.* + pub struct TypeTuple { + pub paren_token: token::Paren, + pub elems: Punctuated, + } +} + +#[cfg(feature = "extra-traits")] +impl Eq for Type {} + +#[cfg(feature = "extra-traits")] +impl PartialEq for Type { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Type::Array(this), Type::Array(other)) => this == other, + (Type::BareFn(this), Type::BareFn(other)) => this == other, + (Type::Group(this), Type::Group(other)) => this == other, + (Type::ImplTrait(this), Type::ImplTrait(other)) => this == other, + (Type::Infer(this), Type::Infer(other)) => this == other, + (Type::Macro(this), Type::Macro(other)) => this == other, + (Type::Never(this), Type::Never(other)) => this == other, + (Type::Paren(this), Type::Paren(other)) => this == other, + (Type::Path(this), Type::Path(other)) => this == other, + (Type::Ptr(this), Type::Ptr(other)) => this == other, + (Type::Reference(this), Type::Reference(other)) => this == other, + (Type::Slice(this), Type::Slice(other)) => this == other, + (Type::TraitObject(this), Type::TraitObject(other)) => this == other, + (Type::Tuple(this), Type::Tuple(other)) => this == other, + (Type::Verbatim(this), Type::Verbatim(other)) => { + TokenStreamHelper(this) == TokenStreamHelper(other) + } + _ => false, + } + } +} + +#[cfg(feature = "extra-traits")] +impl Hash for Type { + fn hash(&self, hash: &mut H) + where + H: Hasher, + { + match self { + Type::Array(ty) => { + hash.write_u8(0); + ty.hash(hash); + } + Type::BareFn(ty) => { + hash.write_u8(1); + ty.hash(hash); + } + Type::Group(ty) => { + hash.write_u8(2); + ty.hash(hash); + } + Type::ImplTrait(ty) => { + hash.write_u8(3); + ty.hash(hash); + } + Type::Infer(ty) => { + hash.write_u8(4); + ty.hash(hash); + } + Type::Macro(ty) => { + hash.write_u8(5); + ty.hash(hash); + } + Type::Never(ty) => { + hash.write_u8(6); + ty.hash(hash); + } + Type::Paren(ty) => { + hash.write_u8(7); + ty.hash(hash); + } + Type::Path(ty) => { + hash.write_u8(8); + ty.hash(hash); + } + Type::Ptr(ty) => { + hash.write_u8(9); + ty.hash(hash); + } + Type::Reference(ty) => { + hash.write_u8(10); + ty.hash(hash); + } + Type::Slice(ty) => { + hash.write_u8(11); + ty.hash(hash); + } + Type::TraitObject(ty) => { + hash.write_u8(12); + ty.hash(hash); + } + Type::Tuple(ty) => { + hash.write_u8(13); + ty.hash(hash); + } + Type::Verbatim(ty) => { + hash.write_u8(14); + TokenStreamHelper(ty).hash(hash); + } + Type::__Nonexhaustive => unreachable!(), + } + } +} + +ast_struct! { + /// The binary interface of a function: `extern "C"`. + /// + /// *This type is available if Syn is built with the `"derive"` or `"full"` + /// feature.* + pub struct Abi { + pub extern_token: Token![extern], + pub name: Option, + } +} + +ast_struct! { + /// An argument in a function type: the `usize` in `fn(usize) -> bool`. + /// + /// *This type is available if Syn is built with the `"derive"` or `"full"` + /// feature.* + pub struct BareFnArg { + pub attrs: Vec, + pub name: Option<(Ident, Token![:])>, + pub ty: Type, + } +} + +ast_struct! { + /// The variadic argument of a foreign function. + /// + /// ```rust + /// # struct c_char; + /// # struct c_int; + /// # + /// extern "C" { + /// fn printf(format: *const c_char, ...) -> c_int; + /// // ^^^ + /// } + /// ``` + /// + /// *This type is available if Syn is built with the `"derive"` or `"full"` + /// feature.* + pub struct Variadic { + pub attrs: Vec, + pub dots: Token![...], + } +} + +ast_enum! { + /// Return type of a function signature. + /// + /// *This type is available if Syn is built with the `"derive"` or `"full"` + /// feature.* + pub enum ReturnType { + /// Return type is not specified. + /// + /// Functions default to `()` and closures default to type inference. + Default, + /// A particular type is returned. + Type(Token![->], Box), + } +} + +#[cfg(feature = "parsing")] +pub mod parsing { + use super::*; + + use crate::ext::IdentExt; + use crate::parse::{Parse, ParseStream, Result}; + use crate::path; + use proc_macro2::{Punct, Spacing, TokenTree}; + use std::iter::FromIterator; + + impl Parse for Type { + fn parse(input: ParseStream) -> Result { + ambig_ty(input, true) + } + } + + impl Type { + /// In some positions, types may not contain the `+` character, to + /// disambiguate them. For example in the expression `1 as T`, T may not + /// contain a `+` character. + /// + /// This parser does not allow a `+`, while the default parser does. + pub fn without_plus(input: ParseStream) -> Result { + ambig_ty(input, false) + } + } + + fn ambig_ty(input: ParseStream, allow_plus: bool) -> Result { + if input.peek(token::Group) { + return input.parse().map(Type::Group); + } + + let mut lifetimes = None::; + let mut lookahead = input.lookahead1(); + if lookahead.peek(Token![for]) { + lifetimes = input.parse()?; + lookahead = input.lookahead1(); + if !lookahead.peek(Ident) + && !lookahead.peek(Token![fn]) + && !lookahead.peek(Token![unsafe]) + && !lookahead.peek(Token![extern]) + && !lookahead.peek(Token![super]) + && !lookahead.peek(Token![self]) + && !lookahead.peek(Token![Self]) + && !lookahead.peek(Token![crate]) + { + return Err(lookahead.error()); + } + } + + if lookahead.peek(token::Paren) { + let content; + let paren_token = parenthesized!(content in input); + if content.is_empty() { + return Ok(Type::Tuple(TypeTuple { + paren_token, + elems: Punctuated::new(), + })); + } + if content.peek(Lifetime) { + return Ok(Type::Paren(TypeParen { + paren_token, + elem: Box::new(Type::TraitObject(content.parse()?)), + })); + } + if content.peek(Token![?]) { + return Ok(Type::TraitObject(TypeTraitObject { + dyn_token: None, + bounds: { + let mut bounds = Punctuated::new(); + bounds.push_value(TypeParamBound::Trait(TraitBound { + paren_token: Some(paren_token), + ..content.parse()? + })); + while let Some(plus) = input.parse()? { + bounds.push_punct(plus); + bounds.push_value(input.parse()?); + } + bounds + }, + })); + } + let mut first: Type = content.parse()?; + if content.peek(Token![,]) { + return Ok(Type::Tuple(TypeTuple { + paren_token, + elems: { + let mut elems = Punctuated::new(); + elems.push_value(first); + elems.push_punct(content.parse()?); + let rest: Punctuated = + content.parse_terminated(Parse::parse)?; + elems.extend(rest); + elems + }, + })); + } + if allow_plus && input.peek(Token![+]) { + loop { + let first = match first { + Type::Path(TypePath { qself: None, path }) => { + TypeParamBound::Trait(TraitBound { + paren_token: Some(paren_token), + modifier: TraitBoundModifier::None, + lifetimes: None, + path, + }) + } + Type::TraitObject(TypeTraitObject { + dyn_token: None, + bounds, + }) => { + if bounds.len() > 1 || bounds.trailing_punct() { + first = Type::TraitObject(TypeTraitObject { + dyn_token: None, + bounds, + }); + break; + } + match bounds.into_iter().next().unwrap() { + TypeParamBound::Trait(trait_bound) => { + TypeParamBound::Trait(TraitBound { + paren_token: Some(paren_token), + ..trait_bound + }) + } + other => other, + } + } + _ => break, + }; + return Ok(Type::TraitObject(TypeTraitObject { + dyn_token: None, + bounds: { + let mut bounds = Punctuated::new(); + bounds.push_value(first); + while let Some(plus) = input.parse()? { + bounds.push_punct(plus); + bounds.push_value(input.parse()?); + } + bounds + }, + })); + } + } + Ok(Type::Paren(TypeParen { + paren_token, + elem: Box::new(first), + })) + } else if lookahead.peek(Token![fn]) + || lookahead.peek(Token![unsafe]) + || lookahead.peek(Token![extern]) && !input.peek2(Token![::]) + { + let mut bare_fn: TypeBareFn = input.parse()?; + bare_fn.lifetimes = lifetimes; + Ok(Type::BareFn(bare_fn)) + } else if lookahead.peek(Ident) + || input.peek(Token![super]) + || input.peek(Token![self]) + || input.peek(Token![Self]) + || input.peek(Token![crate]) + || input.peek(Token![extern]) + || lookahead.peek(Token![::]) + || lookahead.peek(Token![<]) + { + if input.peek(Token![dyn]) { + let mut trait_object: TypeTraitObject = input.parse()?; + if lifetimes.is_some() { + match trait_object.bounds.iter_mut().next().unwrap() { + TypeParamBound::Trait(trait_bound) => { + trait_bound.lifetimes = lifetimes; + } + TypeParamBound::Lifetime(_) => unreachable!(), + } + } + return Ok(Type::TraitObject(trait_object)); + } + + let ty: TypePath = input.parse()?; + if ty.qself.is_some() { + return Ok(Type::Path(ty)); + } + + if input.peek(Token![!]) && !input.peek(Token![!=]) { + let mut contains_arguments = false; + for segment in &ty.path.segments { + match segment.arguments { + PathArguments::None => {} + PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => { + contains_arguments = true; + } + } + } + + if !contains_arguments { + let bang_token: Token![!] = input.parse()?; + let (delimiter, tokens) = mac::parse_delimiter(input)?; + return Ok(Type::Macro(TypeMacro { + mac: Macro { + path: ty.path, + bang_token, + delimiter, + tokens, + }, + })); + } + } + + if lifetimes.is_some() || allow_plus && input.peek(Token![+]) { + let mut bounds = Punctuated::new(); + bounds.push_value(TypeParamBound::Trait(TraitBound { + paren_token: None, + modifier: TraitBoundModifier::None, + lifetimes, + path: ty.path, + })); + if allow_plus { + while input.peek(Token![+]) { + bounds.push_punct(input.parse()?); + if input.peek(Token![>]) { + break; + } + bounds.push_value(input.parse()?); + } + } + return Ok(Type::TraitObject(TypeTraitObject { + dyn_token: None, + bounds, + })); + } + + Ok(Type::Path(ty)) + } else if lookahead.peek(token::Bracket) { + let content; + let bracket_token = bracketed!(content in input); + let elem: Type = content.parse()?; + if content.peek(Token![;]) { + Ok(Type::Array(TypeArray { + bracket_token, + elem: Box::new(elem), + semi_token: content.parse()?, + len: content.parse()?, + })) + } else { + Ok(Type::Slice(TypeSlice { + bracket_token, + elem: Box::new(elem), + })) + } + } else if lookahead.peek(Token![*]) { + input.parse().map(Type::Ptr) + } else if lookahead.peek(Token![&]) { + input.parse().map(Type::Reference) + } else if lookahead.peek(Token![!]) && !input.peek(Token![=]) { + input.parse().map(Type::Never) + } else if lookahead.peek(Token![impl]) { + input.parse().map(Type::ImplTrait) + } else if lookahead.peek(Token![_]) { + input.parse().map(Type::Infer) + } else if lookahead.peek(Lifetime) { + input.parse().map(Type::TraitObject) + } else { + Err(lookahead.error()) + } + } + + impl Parse for TypeSlice { + fn parse(input: ParseStream) -> Result { + let content; + Ok(TypeSlice { + bracket_token: bracketed!(content in input), + elem: content.parse()?, + }) + } + } + + impl Parse for TypeArray { + fn parse(input: ParseStream) -> Result { + let content; + Ok(TypeArray { + bracket_token: bracketed!(content in input), + elem: content.parse()?, + semi_token: content.parse()?, + len: content.parse()?, + }) + } + } + + impl Parse for TypePtr { + fn parse(input: ParseStream) -> Result { + let star_token: Token![*] = input.parse()?; + + let lookahead = input.lookahead1(); + let (const_token, mutability) = if lookahead.peek(Token![const]) { + (Some(input.parse()?), None) + } else if lookahead.peek(Token![mut]) { + (None, Some(input.parse()?)) + } else { + return Err(lookahead.error()); + }; + + Ok(TypePtr { + star_token, + const_token, + mutability, + elem: Box::new(input.call(Type::without_plus)?), + }) + } + } + + impl Parse for TypeReference { + fn parse(input: ParseStream) -> Result { + Ok(TypeReference { + and_token: input.parse()?, + lifetime: input.parse()?, + mutability: input.parse()?, + // & binds tighter than +, so we don't allow + here. + elem: Box::new(input.call(Type::without_plus)?), + }) + } + } + + impl Parse for TypeBareFn { + fn parse(input: ParseStream) -> Result { + let args; + let mut variadic = None; + Ok(TypeBareFn { + lifetimes: input.parse()?, + unsafety: input.parse()?, + abi: input.parse()?, + fn_token: input.parse()?, + paren_token: parenthesized!(args in input), + inputs: { + let mut inputs = Punctuated::new(); + + while !args.is_empty() { + let attrs = args.call(Attribute::parse_outer)?; + + if inputs.empty_or_trailing() && args.peek(Token![...]) { + variadic = Some(Variadic { + attrs, + dots: args.parse()?, + }); + break; + } + + inputs.push_value(BareFnArg { + attrs, + ..args.parse()? + }); + if args.is_empty() { + break; + } + + inputs.push_punct(args.parse()?); + } + + inputs + }, + variadic, + output: input.call(ReturnType::without_plus)?, + }) + } + } + + impl Parse for TypeNever { + fn parse(input: ParseStream) -> Result { + Ok(TypeNever { + bang_token: input.parse()?, + }) + } + } + + impl Parse for TypeInfer { + fn parse(input: ParseStream) -> Result { + Ok(TypeInfer { + underscore_token: input.parse()?, + }) + } + } + + impl Parse for TypeTuple { + fn parse(input: ParseStream) -> Result { + let content; + let paren_token = parenthesized!(content in input); + + if content.is_empty() { + return Ok(TypeTuple { + paren_token, + elems: Punctuated::new(), + }); + } + + let first: Type = content.parse()?; + Ok(TypeTuple { + paren_token, + elems: { + let mut elems = Punctuated::new(); + elems.push_value(first); + elems.push_punct(content.parse()?); + let rest: Punctuated = + content.parse_terminated(Parse::parse)?; + elems.extend(rest); + elems + }, + }) + } + } + + impl Parse for TypeMacro { + fn parse(input: ParseStream) -> Result { + Ok(TypeMacro { + mac: input.parse()?, + }) + } + } + + impl Parse for TypePath { + fn parse(input: ParseStream) -> Result { + let (qself, mut path) = path::parsing::qpath(input, false)?; + + if path.segments.last().unwrap().arguments.is_empty() && input.peek(token::Paren) { + let args: ParenthesizedGenericArguments = input.parse()?; + let parenthesized = PathArguments::Parenthesized(args); + path.segments.last_mut().unwrap().arguments = parenthesized; + } + + Ok(TypePath { qself, path }) + } + } + + impl ReturnType { + pub fn without_plus(input: ParseStream) -> Result { + Self::parse(input, false) + } + + pub fn parse(input: ParseStream, allow_plus: bool) -> Result { + if input.peek(Token![->]) { + let arrow = input.parse()?; + let ty = ambig_ty(input, allow_plus)?; + Ok(ReturnType::Type(arrow, Box::new(ty))) + } else { + Ok(ReturnType::Default) + } + } + } + + impl Parse for ReturnType { + fn parse(input: ParseStream) -> Result { + Self::parse(input, true) + } + } + + impl Parse for TypeTraitObject { + fn parse(input: ParseStream) -> Result { + Self::parse(input, true) + } + } + + fn at_least_one_type(bounds: &Punctuated) -> bool { + for bound in bounds { + if let TypeParamBound::Trait(_) = *bound { + return true; + } + } + false + } + + impl TypeTraitObject { + pub fn without_plus(input: ParseStream) -> Result { + Self::parse(input, false) + } + + // Only allow multiple trait references if allow_plus is true. + pub fn parse(input: ParseStream, allow_plus: bool) -> Result { + Ok(TypeTraitObject { + dyn_token: input.parse()?, + bounds: { + let mut bounds = Punctuated::new(); + if allow_plus { + loop { + bounds.push_value(input.parse()?); + if !input.peek(Token![+]) { + break; + } + bounds.push_punct(input.parse()?); + if input.peek(Token![>]) { + break; + } + } + } else { + bounds.push_value(input.parse()?); + } + // Just lifetimes like `'a + 'b` is not a TraitObject. + if !at_least_one_type(&bounds) { + return Err(input.error("expected at least one type")); + } + bounds + }, + }) + } + } + + impl Parse for TypeImplTrait { + fn parse(input: ParseStream) -> Result { + Ok(TypeImplTrait { + impl_token: input.parse()?, + // NOTE: rust-lang/rust#34511 includes discussion about whether + // or not + should be allowed in ImplTrait directly without (). + bounds: { + let mut bounds = Punctuated::new(); + loop { + bounds.push_value(input.parse()?); + if !input.peek(Token![+]) { + break; + } + bounds.push_punct(input.parse()?); + } + bounds + }, + }) + } + } + + impl Parse for TypeGroup { + fn parse(input: ParseStream) -> Result { + let group = crate::group::parse_group(input)?; + Ok(TypeGroup { + group_token: group.token, + elem: group.content.parse()?, + }) + } + } + + impl Parse for TypeParen { + fn parse(input: ParseStream) -> Result { + Self::parse(input, false) + } + } + + impl TypeParen { + fn parse(input: ParseStream, allow_plus: bool) -> Result { + let content; + Ok(TypeParen { + paren_token: parenthesized!(content in input), + elem: Box::new(ambig_ty(&content, allow_plus)?), + }) + } + } + + impl Parse for BareFnArg { + fn parse(input: ParseStream) -> Result { + Ok(BareFnArg { + attrs: input.call(Attribute::parse_outer)?, + name: { + if (input.peek(Ident) || input.peek(Token![_])) + && input.peek2(Token![:]) + && !input.peek2(Token![::]) + { + let name = input.call(Ident::parse_any)?; + let colon: Token![:] = input.parse()?; + Some((name, colon)) + } else { + None + } + }, + ty: match input.parse::>()? { + Some(dot3) => { + let args = vec![ + TokenTree::Punct(Punct::new('.', Spacing::Joint)), + TokenTree::Punct(Punct::new('.', Spacing::Joint)), + TokenTree::Punct(Punct::new('.', Spacing::Alone)), + ]; + let tokens = TokenStream::from_iter(args.into_iter().zip(&dot3.spans).map( + |(mut arg, span)| { + arg.set_span(*span); + arg + }, + )); + Type::Verbatim(tokens) + } + None => input.parse()?, + }, + }) + } + } + + impl Parse for Abi { + fn parse(input: ParseStream) -> Result { + Ok(Abi { + extern_token: input.parse()?, + name: input.parse()?, + }) + } + } + + impl Parse for Option { + fn parse(input: ParseStream) -> Result { + if input.peek(Token![extern]) { + input.parse().map(Some) + } else { + Ok(None) + } + } + } +} + +#[cfg(feature = "printing")] +mod printing { + use super::*; + + use proc_macro2::TokenStream; + use quote::{ToTokens, TokenStreamExt}; + + use crate::attr::FilterAttrs; + use crate::print::TokensOrDefault; + + impl ToTokens for TypeSlice { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.bracket_token.surround(tokens, |tokens| { + self.elem.to_tokens(tokens); + }); + } + } + + impl ToTokens for TypeArray { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.bracket_token.surround(tokens, |tokens| { + self.elem.to_tokens(tokens); + self.semi_token.to_tokens(tokens); + self.len.to_tokens(tokens); + }); + } + } + + impl ToTokens for TypePtr { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.star_token.to_tokens(tokens); + match &self.mutability { + Some(tok) => tok.to_tokens(tokens), + None => { + TokensOrDefault(&self.const_token).to_tokens(tokens); + } + } + self.elem.to_tokens(tokens); + } + } + + impl ToTokens for TypeReference { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.and_token.to_tokens(tokens); + self.lifetime.to_tokens(tokens); + self.mutability.to_tokens(tokens); + self.elem.to_tokens(tokens); + } + } + + impl ToTokens for TypeBareFn { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.lifetimes.to_tokens(tokens); + self.unsafety.to_tokens(tokens); + self.abi.to_tokens(tokens); + self.fn_token.to_tokens(tokens); + self.paren_token.surround(tokens, |tokens| { + self.inputs.to_tokens(tokens); + if let Some(variadic) = &self.variadic { + if !self.inputs.empty_or_trailing() { + let span = variadic.dots.spans[0]; + Token![,](span).to_tokens(tokens); + } + variadic.to_tokens(tokens); + } + }); + self.output.to_tokens(tokens); + } + } + + impl ToTokens for TypeNever { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.bang_token.to_tokens(tokens); + } + } + + impl ToTokens for TypeTuple { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.paren_token.surround(tokens, |tokens| { + self.elems.to_tokens(tokens); + }); + } + } + + impl ToTokens for TypePath { + fn to_tokens(&self, tokens: &mut TokenStream) { + private::print_path(tokens, &self.qself, &self.path); + } + } + + impl ToTokens for TypeTraitObject { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.dyn_token.to_tokens(tokens); + self.bounds.to_tokens(tokens); + } + } + + impl ToTokens for TypeImplTrait { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.impl_token.to_tokens(tokens); + self.bounds.to_tokens(tokens); + } + } + + impl ToTokens for TypeGroup { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.group_token.surround(tokens, |tokens| { + self.elem.to_tokens(tokens); + }); + } + } + + impl ToTokens for TypeParen { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.paren_token.surround(tokens, |tokens| { + self.elem.to_tokens(tokens); + }); + } + } + + impl ToTokens for TypeInfer { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.underscore_token.to_tokens(tokens); + } + } + + impl ToTokens for TypeMacro { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.mac.to_tokens(tokens); + } + } + + impl ToTokens for ReturnType { + fn to_tokens(&self, tokens: &mut TokenStream) { + match self { + ReturnType::Default => {} + ReturnType::Type(arrow, ty) => { + arrow.to_tokens(tokens); + ty.to_tokens(tokens); + } + } + } + } + + impl ToTokens for BareFnArg { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.append_all(self.attrs.outer()); + if let Some((name, colon)) = &self.name { + name.to_tokens(tokens); + colon.to_tokens(tokens); + } + self.ty.to_tokens(tokens); + } + } + + impl ToTokens for Variadic { + fn to_tokens(&self, tokens: &mut TokenStream) { + tokens.append_all(self.attrs.outer()); + self.dots.to_tokens(tokens); + } + } + + impl ToTokens for Abi { + fn to_tokens(&self, tokens: &mut TokenStream) { + self.extern_token.to_tokens(tokens); + self.name.to_tokens(tokens); + } + } +} -- cgit v1.2.1