1*69942c0aSMiguel Ojeda // SPDX-License-Identifier: Apache-2.0 OR MIT 2*69942c0aSMiguel Ojeda 3808c999fSMiguel Ojeda #[cfg(feature = "parsing")] 4808c999fSMiguel Ojeda use crate::error::Result; 5808c999fSMiguel Ojeda use crate::expr::Expr; 6808c999fSMiguel Ojeda use crate::generics::TypeParamBound; 7808c999fSMiguel Ojeda use crate::ident::Ident; 8808c999fSMiguel Ojeda use crate::lifetime::Lifetime; 9808c999fSMiguel Ojeda use crate::punctuated::Punctuated; 10808c999fSMiguel Ojeda use crate::token; 11808c999fSMiguel Ojeda use crate::ty::{ReturnType, Type}; 12808c999fSMiguel Ojeda 13808c999fSMiguel Ojeda ast_struct! { 14808c999fSMiguel Ojeda /// A path at which a named item is exported (e.g. `std::collections::HashMap`). 15808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 16808c999fSMiguel Ojeda pub struct Path { 17808c999fSMiguel Ojeda pub leading_colon: Option<Token![::]>, 18808c999fSMiguel Ojeda pub segments: Punctuated<PathSegment, Token![::]>, 19808c999fSMiguel Ojeda } 20808c999fSMiguel Ojeda } 21808c999fSMiguel Ojeda 22808c999fSMiguel Ojeda impl<T> From<T> for Path 23808c999fSMiguel Ojeda where 24808c999fSMiguel Ojeda T: Into<PathSegment>, 25808c999fSMiguel Ojeda { from(segment: T) -> Self26808c999fSMiguel Ojeda fn from(segment: T) -> Self { 27808c999fSMiguel Ojeda let mut path = Path { 28808c999fSMiguel Ojeda leading_colon: None, 29808c999fSMiguel Ojeda segments: Punctuated::new(), 30808c999fSMiguel Ojeda }; 31808c999fSMiguel Ojeda path.segments.push_value(segment.into()); 32808c999fSMiguel Ojeda path 33808c999fSMiguel Ojeda } 34808c999fSMiguel Ojeda } 35808c999fSMiguel Ojeda 36808c999fSMiguel Ojeda impl Path { 37808c999fSMiguel Ojeda /// Determines whether this is a path of length 1 equal to the given 38808c999fSMiguel Ojeda /// ident. 39808c999fSMiguel Ojeda /// 40808c999fSMiguel Ojeda /// For them to compare equal, it must be the case that: 41808c999fSMiguel Ojeda /// 42808c999fSMiguel Ojeda /// - the path has no leading colon, 43808c999fSMiguel Ojeda /// - the number of path segments is 1, 44808c999fSMiguel Ojeda /// - the first path segment has no angle bracketed or parenthesized 45808c999fSMiguel Ojeda /// path arguments, and 46808c999fSMiguel Ojeda /// - the ident of the first path segment is equal to the given one. 47808c999fSMiguel Ojeda /// 48808c999fSMiguel Ojeda /// # Example 49808c999fSMiguel Ojeda /// 50808c999fSMiguel Ojeda /// ``` 51808c999fSMiguel Ojeda /// use proc_macro2::TokenStream; 52808c999fSMiguel Ojeda /// use syn::{Attribute, Error, Meta, Result}; 53808c999fSMiguel Ojeda /// 54808c999fSMiguel Ojeda /// fn get_serde_meta_item(attr: &Attribute) -> Result<Option<&TokenStream>> { 55808c999fSMiguel Ojeda /// if attr.path().is_ident("serde") { 56808c999fSMiguel Ojeda /// match &attr.meta { 57808c999fSMiguel Ojeda /// Meta::List(meta) => Ok(Some(&meta.tokens)), 58808c999fSMiguel Ojeda /// bad => Err(Error::new_spanned(bad, "unrecognized attribute")), 59808c999fSMiguel Ojeda /// } 60808c999fSMiguel Ojeda /// } else { 61808c999fSMiguel Ojeda /// Ok(None) 62808c999fSMiguel Ojeda /// } 63808c999fSMiguel Ojeda /// } 64808c999fSMiguel Ojeda /// ``` is_ident<I>(&self, ident: &I) -> bool where I: ?Sized, Ident: PartialEq<I>,65808c999fSMiguel Ojeda pub fn is_ident<I>(&self, ident: &I) -> bool 66808c999fSMiguel Ojeda where 67808c999fSMiguel Ojeda I: ?Sized, 68808c999fSMiguel Ojeda Ident: PartialEq<I>, 69808c999fSMiguel Ojeda { 70808c999fSMiguel Ojeda match self.get_ident() { 71808c999fSMiguel Ojeda Some(id) => id == ident, 72808c999fSMiguel Ojeda None => false, 73808c999fSMiguel Ojeda } 74808c999fSMiguel Ojeda } 75808c999fSMiguel Ojeda 76808c999fSMiguel Ojeda /// If this path consists of a single ident, returns the ident. 77808c999fSMiguel Ojeda /// 78808c999fSMiguel Ojeda /// A path is considered an ident if: 79808c999fSMiguel Ojeda /// 80808c999fSMiguel Ojeda /// - the path has no leading colon, 81808c999fSMiguel Ojeda /// - the number of path segments is 1, and 82808c999fSMiguel Ojeda /// - the first path segment has no angle bracketed or parenthesized 83808c999fSMiguel Ojeda /// path arguments. get_ident(&self) -> Option<&Ident>84808c999fSMiguel Ojeda pub fn get_ident(&self) -> Option<&Ident> { 85808c999fSMiguel Ojeda if self.leading_colon.is_none() 86808c999fSMiguel Ojeda && self.segments.len() == 1 87808c999fSMiguel Ojeda && self.segments[0].arguments.is_none() 88808c999fSMiguel Ojeda { 89808c999fSMiguel Ojeda Some(&self.segments[0].ident) 90808c999fSMiguel Ojeda } else { 91808c999fSMiguel Ojeda None 92808c999fSMiguel Ojeda } 93808c999fSMiguel Ojeda } 94808c999fSMiguel Ojeda 95808c999fSMiguel Ojeda /// An error if this path is not a single ident, as defined in `get_ident`. 96808c999fSMiguel Ojeda #[cfg(feature = "parsing")] 97808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] require_ident(&self) -> Result<&Ident>98808c999fSMiguel Ojeda pub fn require_ident(&self) -> Result<&Ident> { 99808c999fSMiguel Ojeda self.get_ident().ok_or_else(|| { 100808c999fSMiguel Ojeda crate::error::new2( 101808c999fSMiguel Ojeda self.segments.first().unwrap().ident.span(), 102808c999fSMiguel Ojeda self.segments.last().unwrap().ident.span(), 103808c999fSMiguel Ojeda "expected this path to be an identifier", 104808c999fSMiguel Ojeda ) 105808c999fSMiguel Ojeda }) 106808c999fSMiguel Ojeda } 107808c999fSMiguel Ojeda } 108808c999fSMiguel Ojeda 109808c999fSMiguel Ojeda ast_struct! { 110808c999fSMiguel Ojeda /// A segment of a path together with any path arguments on that segment. 111808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 112808c999fSMiguel Ojeda pub struct PathSegment { 113808c999fSMiguel Ojeda pub ident: Ident, 114808c999fSMiguel Ojeda pub arguments: PathArguments, 115808c999fSMiguel Ojeda } 116808c999fSMiguel Ojeda } 117808c999fSMiguel Ojeda 118808c999fSMiguel Ojeda impl<T> From<T> for PathSegment 119808c999fSMiguel Ojeda where 120808c999fSMiguel Ojeda T: Into<Ident>, 121808c999fSMiguel Ojeda { from(ident: T) -> Self122808c999fSMiguel Ojeda fn from(ident: T) -> Self { 123808c999fSMiguel Ojeda PathSegment { 124808c999fSMiguel Ojeda ident: ident.into(), 125808c999fSMiguel Ojeda arguments: PathArguments::None, 126808c999fSMiguel Ojeda } 127808c999fSMiguel Ojeda } 128808c999fSMiguel Ojeda } 129808c999fSMiguel Ojeda 130808c999fSMiguel Ojeda ast_enum! { 131808c999fSMiguel Ojeda /// Angle bracketed or parenthesized arguments of a path segment. 132808c999fSMiguel Ojeda /// 133808c999fSMiguel Ojeda /// ## Angle bracketed 134808c999fSMiguel Ojeda /// 135808c999fSMiguel Ojeda /// The `<'a, T>` in `std::slice::iter<'a, T>`. 136808c999fSMiguel Ojeda /// 137808c999fSMiguel Ojeda /// ## Parenthesized 138808c999fSMiguel Ojeda /// 139808c999fSMiguel Ojeda /// The `(A, B) -> C` in `Fn(A, B) -> C`. 140808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 141808c999fSMiguel Ojeda pub enum PathArguments { 142808c999fSMiguel Ojeda None, 143808c999fSMiguel Ojeda /// The `<'a, T>` in `std::slice::iter<'a, T>`. 144808c999fSMiguel Ojeda AngleBracketed(AngleBracketedGenericArguments), 145808c999fSMiguel Ojeda /// The `(A, B) -> C` in `Fn(A, B) -> C`. 146808c999fSMiguel Ojeda Parenthesized(ParenthesizedGenericArguments), 147808c999fSMiguel Ojeda } 148808c999fSMiguel Ojeda } 149808c999fSMiguel Ojeda 150808c999fSMiguel Ojeda impl Default for PathArguments { default() -> Self151808c999fSMiguel Ojeda fn default() -> Self { 152808c999fSMiguel Ojeda PathArguments::None 153808c999fSMiguel Ojeda } 154808c999fSMiguel Ojeda } 155808c999fSMiguel Ojeda 156808c999fSMiguel Ojeda impl PathArguments { is_empty(&self) -> bool157808c999fSMiguel Ojeda pub fn is_empty(&self) -> bool { 158808c999fSMiguel Ojeda match self { 159808c999fSMiguel Ojeda PathArguments::None => true, 160808c999fSMiguel Ojeda PathArguments::AngleBracketed(bracketed) => bracketed.args.is_empty(), 161808c999fSMiguel Ojeda PathArguments::Parenthesized(_) => false, 162808c999fSMiguel Ojeda } 163808c999fSMiguel Ojeda } 164808c999fSMiguel Ojeda is_none(&self) -> bool165808c999fSMiguel Ojeda pub fn is_none(&self) -> bool { 166808c999fSMiguel Ojeda match self { 167808c999fSMiguel Ojeda PathArguments::None => true, 168808c999fSMiguel Ojeda PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => false, 169808c999fSMiguel Ojeda } 170808c999fSMiguel Ojeda } 171808c999fSMiguel Ojeda } 172808c999fSMiguel Ojeda 173808c999fSMiguel Ojeda ast_enum! { 174808c999fSMiguel Ojeda /// An individual generic argument, like `'a`, `T`, or `Item = T`. 175808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 176808c999fSMiguel Ojeda #[non_exhaustive] 177808c999fSMiguel Ojeda pub enum GenericArgument { 178808c999fSMiguel Ojeda /// A lifetime argument. 179808c999fSMiguel Ojeda Lifetime(Lifetime), 180808c999fSMiguel Ojeda /// A type argument. 181808c999fSMiguel Ojeda Type(Type), 182808c999fSMiguel Ojeda /// A const expression. Must be inside of a block. 183808c999fSMiguel Ojeda /// 184808c999fSMiguel Ojeda /// NOTE: Identity expressions are represented as Type arguments, as 185808c999fSMiguel Ojeda /// they are indistinguishable syntactically. 186808c999fSMiguel Ojeda Const(Expr), 187808c999fSMiguel Ojeda /// A binding (equality constraint) on an associated type: the `Item = 188808c999fSMiguel Ojeda /// u8` in `Iterator<Item = u8>`. 189808c999fSMiguel Ojeda AssocType(AssocType), 190808c999fSMiguel Ojeda /// An equality constraint on an associated constant: the `PANIC = 191808c999fSMiguel Ojeda /// false` in `Trait<PANIC = false>`. 192808c999fSMiguel Ojeda AssocConst(AssocConst), 193808c999fSMiguel Ojeda /// An associated type bound: `Iterator<Item: Display>`. 194808c999fSMiguel Ojeda Constraint(Constraint), 195808c999fSMiguel Ojeda } 196808c999fSMiguel Ojeda } 197808c999fSMiguel Ojeda 198808c999fSMiguel Ojeda ast_struct! { 199808c999fSMiguel Ojeda /// Angle bracketed arguments of a path segment: the `<K, V>` in `HashMap<K, 200808c999fSMiguel Ojeda /// V>`. 201808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 202808c999fSMiguel Ojeda pub struct AngleBracketedGenericArguments { 203808c999fSMiguel Ojeda pub colon2_token: Option<Token![::]>, 204808c999fSMiguel Ojeda pub lt_token: Token![<], 205808c999fSMiguel Ojeda pub args: Punctuated<GenericArgument, Token![,]>, 206808c999fSMiguel Ojeda pub gt_token: Token![>], 207808c999fSMiguel Ojeda } 208808c999fSMiguel Ojeda } 209808c999fSMiguel Ojeda 210808c999fSMiguel Ojeda ast_struct! { 211808c999fSMiguel Ojeda /// A binding (equality constraint) on an associated type: the `Item = u8` 212808c999fSMiguel Ojeda /// in `Iterator<Item = u8>`. 213808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 214808c999fSMiguel Ojeda pub struct AssocType { 215808c999fSMiguel Ojeda pub ident: Ident, 216808c999fSMiguel Ojeda pub generics: Option<AngleBracketedGenericArguments>, 217808c999fSMiguel Ojeda pub eq_token: Token![=], 218808c999fSMiguel Ojeda pub ty: Type, 219808c999fSMiguel Ojeda } 220808c999fSMiguel Ojeda } 221808c999fSMiguel Ojeda 222808c999fSMiguel Ojeda ast_struct! { 223808c999fSMiguel Ojeda /// An equality constraint on an associated constant: the `PANIC = false` in 224808c999fSMiguel Ojeda /// `Trait<PANIC = false>`. 225808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 226808c999fSMiguel Ojeda pub struct AssocConst { 227808c999fSMiguel Ojeda pub ident: Ident, 228808c999fSMiguel Ojeda pub generics: Option<AngleBracketedGenericArguments>, 229808c999fSMiguel Ojeda pub eq_token: Token![=], 230808c999fSMiguel Ojeda pub value: Expr, 231808c999fSMiguel Ojeda } 232808c999fSMiguel Ojeda } 233808c999fSMiguel Ojeda 234808c999fSMiguel Ojeda ast_struct! { 235808c999fSMiguel Ojeda /// An associated type bound: `Iterator<Item: Display>`. 236808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 237808c999fSMiguel Ojeda pub struct Constraint { 238808c999fSMiguel Ojeda pub ident: Ident, 239808c999fSMiguel Ojeda pub generics: Option<AngleBracketedGenericArguments>, 240808c999fSMiguel Ojeda pub colon_token: Token![:], 241808c999fSMiguel Ojeda pub bounds: Punctuated<TypeParamBound, Token![+]>, 242808c999fSMiguel Ojeda } 243808c999fSMiguel Ojeda } 244808c999fSMiguel Ojeda 245808c999fSMiguel Ojeda ast_struct! { 246808c999fSMiguel Ojeda /// Arguments of a function path segment: the `(A, B) -> C` in `Fn(A,B) -> 247808c999fSMiguel Ojeda /// C`. 248808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 249808c999fSMiguel Ojeda pub struct ParenthesizedGenericArguments { 250808c999fSMiguel Ojeda pub paren_token: token::Paren, 251808c999fSMiguel Ojeda /// `(A, B)` 252808c999fSMiguel Ojeda pub inputs: Punctuated<Type, Token![,]>, 253808c999fSMiguel Ojeda /// `C` 254808c999fSMiguel Ojeda pub output: ReturnType, 255808c999fSMiguel Ojeda } 256808c999fSMiguel Ojeda } 257808c999fSMiguel Ojeda 258808c999fSMiguel Ojeda ast_struct! { 259808c999fSMiguel Ojeda /// The explicit Self type in a qualified path: the `T` in `<T as 260808c999fSMiguel Ojeda /// Display>::fmt`. 261808c999fSMiguel Ojeda /// 262808c999fSMiguel Ojeda /// The actual path, including the trait and the associated item, is stored 263808c999fSMiguel Ojeda /// separately. The `position` field represents the index of the associated 264808c999fSMiguel Ojeda /// item qualified with this Self type. 265808c999fSMiguel Ojeda /// 266808c999fSMiguel Ojeda /// ```text 267808c999fSMiguel Ojeda /// <Vec<T> as a::b::Trait>::AssociatedItem 268808c999fSMiguel Ojeda /// ^~~~~~ ~~~~~~~~~~~~~~^ 269808c999fSMiguel Ojeda /// ty position = 3 270808c999fSMiguel Ojeda /// 271808c999fSMiguel Ojeda /// <Vec<T>>::AssociatedItem 272808c999fSMiguel Ojeda /// ^~~~~~ ^ 273808c999fSMiguel Ojeda /// ty position = 0 274808c999fSMiguel Ojeda /// ``` 275808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] 276808c999fSMiguel Ojeda pub struct QSelf { 277808c999fSMiguel Ojeda pub lt_token: Token![<], 278808c999fSMiguel Ojeda pub ty: Box<Type>, 279808c999fSMiguel Ojeda pub position: usize, 280808c999fSMiguel Ojeda pub as_token: Option<Token![as]>, 281808c999fSMiguel Ojeda pub gt_token: Token![>], 282808c999fSMiguel Ojeda } 283808c999fSMiguel Ojeda } 284808c999fSMiguel Ojeda 285808c999fSMiguel Ojeda #[cfg(feature = "parsing")] 286808c999fSMiguel Ojeda pub(crate) mod parsing { 287808c999fSMiguel Ojeda use crate::error::Result; 288808c999fSMiguel Ojeda #[cfg(feature = "full")] 289808c999fSMiguel Ojeda use crate::expr::ExprBlock; 290808c999fSMiguel Ojeda use crate::expr::{Expr, ExprPath}; 291808c999fSMiguel Ojeda use crate::ext::IdentExt as _; 292808c999fSMiguel Ojeda #[cfg(feature = "full")] 293808c999fSMiguel Ojeda use crate::generics::TypeParamBound; 294808c999fSMiguel Ojeda use crate::ident::Ident; 295808c999fSMiguel Ojeda use crate::lifetime::Lifetime; 296808c999fSMiguel Ojeda use crate::lit::Lit; 297808c999fSMiguel Ojeda use crate::parse::{Parse, ParseStream}; 298808c999fSMiguel Ojeda #[cfg(feature = "full")] 299808c999fSMiguel Ojeda use crate::path::Constraint; 300808c999fSMiguel Ojeda use crate::path::{ 301808c999fSMiguel Ojeda AngleBracketedGenericArguments, AssocConst, AssocType, GenericArgument, 302808c999fSMiguel Ojeda ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf, 303808c999fSMiguel Ojeda }; 304808c999fSMiguel Ojeda use crate::punctuated::Punctuated; 305808c999fSMiguel Ojeda use crate::token; 306808c999fSMiguel Ojeda use crate::ty::{ReturnType, Type}; 307808c999fSMiguel Ojeda #[cfg(not(feature = "full"))] 308808c999fSMiguel Ojeda use crate::verbatim; 309808c999fSMiguel Ojeda 310808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 311808c999fSMiguel Ojeda impl Parse for Path { parse(input: ParseStream) -> Result<Self>312808c999fSMiguel Ojeda fn parse(input: ParseStream) -> Result<Self> { 313808c999fSMiguel Ojeda Self::parse_helper(input, false) 314808c999fSMiguel Ojeda } 315808c999fSMiguel Ojeda } 316808c999fSMiguel Ojeda 317808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 318808c999fSMiguel Ojeda impl Parse for GenericArgument { parse(input: ParseStream) -> Result<Self>319808c999fSMiguel Ojeda fn parse(input: ParseStream) -> Result<Self> { 320808c999fSMiguel Ojeda if input.peek(Lifetime) && !input.peek2(Token![+]) { 321808c999fSMiguel Ojeda return Ok(GenericArgument::Lifetime(input.parse()?)); 322808c999fSMiguel Ojeda } 323808c999fSMiguel Ojeda 324808c999fSMiguel Ojeda if input.peek(Lit) || input.peek(token::Brace) { 325808c999fSMiguel Ojeda return const_argument(input).map(GenericArgument::Const); 326808c999fSMiguel Ojeda } 327808c999fSMiguel Ojeda 328808c999fSMiguel Ojeda let mut argument: Type = input.parse()?; 329808c999fSMiguel Ojeda 330808c999fSMiguel Ojeda match argument { 331808c999fSMiguel Ojeda Type::Path(mut ty) 332808c999fSMiguel Ojeda if ty.qself.is_none() 333808c999fSMiguel Ojeda && ty.path.leading_colon.is_none() 334808c999fSMiguel Ojeda && ty.path.segments.len() == 1 335808c999fSMiguel Ojeda && match &ty.path.segments[0].arguments { 336808c999fSMiguel Ojeda PathArguments::None | PathArguments::AngleBracketed(_) => true, 337808c999fSMiguel Ojeda PathArguments::Parenthesized(_) => false, 338808c999fSMiguel Ojeda } => 339808c999fSMiguel Ojeda { 340808c999fSMiguel Ojeda if let Some(eq_token) = input.parse::<Option<Token![=]>>()? { 341808c999fSMiguel Ojeda let segment = ty.path.segments.pop().unwrap().into_value(); 342808c999fSMiguel Ojeda let ident = segment.ident; 343808c999fSMiguel Ojeda let generics = match segment.arguments { 344808c999fSMiguel Ojeda PathArguments::None => None, 345808c999fSMiguel Ojeda PathArguments::AngleBracketed(arguments) => Some(arguments), 346808c999fSMiguel Ojeda PathArguments::Parenthesized(_) => unreachable!(), 347808c999fSMiguel Ojeda }; 348808c999fSMiguel Ojeda return if input.peek(Lit) || input.peek(token::Brace) { 349808c999fSMiguel Ojeda Ok(GenericArgument::AssocConst(AssocConst { 350808c999fSMiguel Ojeda ident, 351808c999fSMiguel Ojeda generics, 352808c999fSMiguel Ojeda eq_token, 353808c999fSMiguel Ojeda value: const_argument(input)?, 354808c999fSMiguel Ojeda })) 355808c999fSMiguel Ojeda } else { 356808c999fSMiguel Ojeda Ok(GenericArgument::AssocType(AssocType { 357808c999fSMiguel Ojeda ident, 358808c999fSMiguel Ojeda generics, 359808c999fSMiguel Ojeda eq_token, 360808c999fSMiguel Ojeda ty: input.parse()?, 361808c999fSMiguel Ojeda })) 362808c999fSMiguel Ojeda }; 363808c999fSMiguel Ojeda } 364808c999fSMiguel Ojeda 365808c999fSMiguel Ojeda #[cfg(feature = "full")] 366808c999fSMiguel Ojeda if let Some(colon_token) = input.parse::<Option<Token![:]>>()? { 367808c999fSMiguel Ojeda let segment = ty.path.segments.pop().unwrap().into_value(); 368808c999fSMiguel Ojeda return Ok(GenericArgument::Constraint(Constraint { 369808c999fSMiguel Ojeda ident: segment.ident, 370808c999fSMiguel Ojeda generics: match segment.arguments { 371808c999fSMiguel Ojeda PathArguments::None => None, 372808c999fSMiguel Ojeda PathArguments::AngleBracketed(arguments) => Some(arguments), 373808c999fSMiguel Ojeda PathArguments::Parenthesized(_) => unreachable!(), 374808c999fSMiguel Ojeda }, 375808c999fSMiguel Ojeda colon_token, 376808c999fSMiguel Ojeda bounds: { 377808c999fSMiguel Ojeda let mut bounds = Punctuated::new(); 378808c999fSMiguel Ojeda loop { 379808c999fSMiguel Ojeda if input.peek(Token![,]) || input.peek(Token![>]) { 380808c999fSMiguel Ojeda break; 381808c999fSMiguel Ojeda } 382808c999fSMiguel Ojeda bounds.push_value({ 383808c999fSMiguel Ojeda let allow_precise_capture = false; 384808c999fSMiguel Ojeda let allow_const = true; 385808c999fSMiguel Ojeda TypeParamBound::parse_single( 386808c999fSMiguel Ojeda input, 387808c999fSMiguel Ojeda allow_precise_capture, 388808c999fSMiguel Ojeda allow_const, 389808c999fSMiguel Ojeda )? 390808c999fSMiguel Ojeda }); 391808c999fSMiguel Ojeda if !input.peek(Token![+]) { 392808c999fSMiguel Ojeda break; 393808c999fSMiguel Ojeda } 394808c999fSMiguel Ojeda let punct: Token![+] = input.parse()?; 395808c999fSMiguel Ojeda bounds.push_punct(punct); 396808c999fSMiguel Ojeda } 397808c999fSMiguel Ojeda bounds 398808c999fSMiguel Ojeda }, 399808c999fSMiguel Ojeda })); 400808c999fSMiguel Ojeda } 401808c999fSMiguel Ojeda 402808c999fSMiguel Ojeda argument = Type::Path(ty); 403808c999fSMiguel Ojeda } 404808c999fSMiguel Ojeda _ => {} 405808c999fSMiguel Ojeda } 406808c999fSMiguel Ojeda 407808c999fSMiguel Ojeda Ok(GenericArgument::Type(argument)) 408808c999fSMiguel Ojeda } 409808c999fSMiguel Ojeda } 410808c999fSMiguel Ojeda const_argument(input: ParseStream) -> Result<Expr>411808c999fSMiguel Ojeda pub(crate) fn const_argument(input: ParseStream) -> Result<Expr> { 412808c999fSMiguel Ojeda let lookahead = input.lookahead1(); 413808c999fSMiguel Ojeda 414808c999fSMiguel Ojeda if input.peek(Lit) { 415808c999fSMiguel Ojeda let lit = input.parse()?; 416808c999fSMiguel Ojeda return Ok(Expr::Lit(lit)); 417808c999fSMiguel Ojeda } 418808c999fSMiguel Ojeda 419808c999fSMiguel Ojeda if input.peek(Ident) { 420808c999fSMiguel Ojeda let ident: Ident = input.parse()?; 421808c999fSMiguel Ojeda return Ok(Expr::Path(ExprPath { 422808c999fSMiguel Ojeda attrs: Vec::new(), 423808c999fSMiguel Ojeda qself: None, 424808c999fSMiguel Ojeda path: Path::from(ident), 425808c999fSMiguel Ojeda })); 426808c999fSMiguel Ojeda } 427808c999fSMiguel Ojeda 428808c999fSMiguel Ojeda if input.peek(token::Brace) { 429808c999fSMiguel Ojeda #[cfg(feature = "full")] 430808c999fSMiguel Ojeda { 431808c999fSMiguel Ojeda let block: ExprBlock = input.parse()?; 432808c999fSMiguel Ojeda return Ok(Expr::Block(block)); 433808c999fSMiguel Ojeda } 434808c999fSMiguel Ojeda 435808c999fSMiguel Ojeda #[cfg(not(feature = "full"))] 436808c999fSMiguel Ojeda { 437808c999fSMiguel Ojeda let begin = input.fork(); 438808c999fSMiguel Ojeda let content; 439808c999fSMiguel Ojeda braced!(content in input); 440808c999fSMiguel Ojeda content.parse::<Expr>()?; 441808c999fSMiguel Ojeda let verbatim = verbatim::between(&begin, input); 442808c999fSMiguel Ojeda return Ok(Expr::Verbatim(verbatim)); 443808c999fSMiguel Ojeda } 444808c999fSMiguel Ojeda } 445808c999fSMiguel Ojeda 446808c999fSMiguel Ojeda Err(lookahead.error()) 447808c999fSMiguel Ojeda } 448808c999fSMiguel Ojeda 449808c999fSMiguel Ojeda impl AngleBracketedGenericArguments { 450808c999fSMiguel Ojeda /// Parse `::<…>` with mandatory leading `::`. 451808c999fSMiguel Ojeda /// 452808c999fSMiguel Ojeda /// The ordinary [`Parse`] impl for `AngleBracketedGenericArguments` 453808c999fSMiguel Ojeda /// parses optional leading `::`. 454808c999fSMiguel Ojeda #[cfg(feature = "full")] 455808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "full"))))] parse_turbofish(input: ParseStream) -> Result<Self>456808c999fSMiguel Ojeda pub fn parse_turbofish(input: ParseStream) -> Result<Self> { 457808c999fSMiguel Ojeda let colon2_token: Token![::] = input.parse()?; 458808c999fSMiguel Ojeda Self::do_parse(Some(colon2_token), input) 459808c999fSMiguel Ojeda } 460808c999fSMiguel Ojeda do_parse( colon2_token: Option<Token![::]>, input: ParseStream, ) -> Result<Self>461808c999fSMiguel Ojeda pub(crate) fn do_parse( 462808c999fSMiguel Ojeda colon2_token: Option<Token![::]>, 463808c999fSMiguel Ojeda input: ParseStream, 464808c999fSMiguel Ojeda ) -> Result<Self> { 465808c999fSMiguel Ojeda Ok(AngleBracketedGenericArguments { 466808c999fSMiguel Ojeda colon2_token, 467808c999fSMiguel Ojeda lt_token: input.parse()?, 468808c999fSMiguel Ojeda args: { 469808c999fSMiguel Ojeda let mut args = Punctuated::new(); 470808c999fSMiguel Ojeda loop { 471808c999fSMiguel Ojeda if input.peek(Token![>]) { 472808c999fSMiguel Ojeda break; 473808c999fSMiguel Ojeda } 474808c999fSMiguel Ojeda let value: GenericArgument = input.parse()?; 475808c999fSMiguel Ojeda args.push_value(value); 476808c999fSMiguel Ojeda if input.peek(Token![>]) { 477808c999fSMiguel Ojeda break; 478808c999fSMiguel Ojeda } 479808c999fSMiguel Ojeda let punct: Token![,] = input.parse()?; 480808c999fSMiguel Ojeda args.push_punct(punct); 481808c999fSMiguel Ojeda } 482808c999fSMiguel Ojeda args 483808c999fSMiguel Ojeda }, 484808c999fSMiguel Ojeda gt_token: input.parse()?, 485808c999fSMiguel Ojeda }) 486808c999fSMiguel Ojeda } 487808c999fSMiguel Ojeda } 488808c999fSMiguel Ojeda 489808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 490808c999fSMiguel Ojeda impl Parse for AngleBracketedGenericArguments { parse(input: ParseStream) -> Result<Self>491808c999fSMiguel Ojeda fn parse(input: ParseStream) -> Result<Self> { 492808c999fSMiguel Ojeda let colon2_token: Option<Token![::]> = input.parse()?; 493808c999fSMiguel Ojeda Self::do_parse(colon2_token, input) 494808c999fSMiguel Ojeda } 495808c999fSMiguel Ojeda } 496808c999fSMiguel Ojeda 497808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 498808c999fSMiguel Ojeda impl Parse for ParenthesizedGenericArguments { parse(input: ParseStream) -> Result<Self>499808c999fSMiguel Ojeda fn parse(input: ParseStream) -> Result<Self> { 500808c999fSMiguel Ojeda let content; 501808c999fSMiguel Ojeda Ok(ParenthesizedGenericArguments { 502808c999fSMiguel Ojeda paren_token: parenthesized!(content in input), 503808c999fSMiguel Ojeda inputs: content.parse_terminated(Type::parse, Token![,])?, 504808c999fSMiguel Ojeda output: input.call(ReturnType::without_plus)?, 505808c999fSMiguel Ojeda }) 506808c999fSMiguel Ojeda } 507808c999fSMiguel Ojeda } 508808c999fSMiguel Ojeda 509808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 510808c999fSMiguel Ojeda impl Parse for PathSegment { parse(input: ParseStream) -> Result<Self>511808c999fSMiguel Ojeda fn parse(input: ParseStream) -> Result<Self> { 512808c999fSMiguel Ojeda Self::parse_helper(input, false) 513808c999fSMiguel Ojeda } 514808c999fSMiguel Ojeda } 515808c999fSMiguel Ojeda 516808c999fSMiguel Ojeda impl PathSegment { parse_helper(input: ParseStream, expr_style: bool) -> Result<Self>517808c999fSMiguel Ojeda fn parse_helper(input: ParseStream, expr_style: bool) -> Result<Self> { 518808c999fSMiguel Ojeda if input.peek(Token![super]) 519808c999fSMiguel Ojeda || input.peek(Token![self]) 520808c999fSMiguel Ojeda || input.peek(Token![crate]) 521808c999fSMiguel Ojeda || cfg!(feature = "full") && input.peek(Token![try]) 522808c999fSMiguel Ojeda { 523808c999fSMiguel Ojeda let ident = input.call(Ident::parse_any)?; 524808c999fSMiguel Ojeda return Ok(PathSegment::from(ident)); 525808c999fSMiguel Ojeda } 526808c999fSMiguel Ojeda 527808c999fSMiguel Ojeda let ident = if input.peek(Token![Self]) { 528808c999fSMiguel Ojeda input.call(Ident::parse_any)? 529808c999fSMiguel Ojeda } else { 530808c999fSMiguel Ojeda input.parse()? 531808c999fSMiguel Ojeda }; 532808c999fSMiguel Ojeda 533808c999fSMiguel Ojeda if !expr_style 534808c999fSMiguel Ojeda && input.peek(Token![<]) 535808c999fSMiguel Ojeda && !input.peek(Token![<=]) 536808c999fSMiguel Ojeda && !input.peek(Token![<<=]) 537808c999fSMiguel Ojeda || input.peek(Token![::]) && input.peek3(Token![<]) 538808c999fSMiguel Ojeda { 539808c999fSMiguel Ojeda Ok(PathSegment { 540808c999fSMiguel Ojeda ident, 541808c999fSMiguel Ojeda arguments: PathArguments::AngleBracketed(input.parse()?), 542808c999fSMiguel Ojeda }) 543808c999fSMiguel Ojeda } else { 544808c999fSMiguel Ojeda Ok(PathSegment::from(ident)) 545808c999fSMiguel Ojeda } 546808c999fSMiguel Ojeda } 547808c999fSMiguel Ojeda } 548808c999fSMiguel Ojeda 549808c999fSMiguel Ojeda impl Path { 550808c999fSMiguel Ojeda /// Parse a `Path` containing no path arguments on any of its segments. 551808c999fSMiguel Ojeda /// 552808c999fSMiguel Ojeda /// # Example 553808c999fSMiguel Ojeda /// 554808c999fSMiguel Ojeda /// ``` 555808c999fSMiguel Ojeda /// use syn::{Path, Result, Token}; 556808c999fSMiguel Ojeda /// use syn::parse::{Parse, ParseStream}; 557808c999fSMiguel Ojeda /// 558808c999fSMiguel Ojeda /// // A simplified single `use` statement like: 559808c999fSMiguel Ojeda /// // 560808c999fSMiguel Ojeda /// // use std::collections::HashMap; 561808c999fSMiguel Ojeda /// // 562808c999fSMiguel Ojeda /// // Note that generic parameters are not allowed in a `use` statement 563808c999fSMiguel Ojeda /// // so the following must not be accepted. 564808c999fSMiguel Ojeda /// // 565808c999fSMiguel Ojeda /// // use a::<b>::c; 566808c999fSMiguel Ojeda /// struct SingleUse { 567808c999fSMiguel Ojeda /// use_token: Token![use], 568808c999fSMiguel Ojeda /// path: Path, 569808c999fSMiguel Ojeda /// } 570808c999fSMiguel Ojeda /// 571808c999fSMiguel Ojeda /// impl Parse for SingleUse { 572808c999fSMiguel Ojeda /// fn parse(input: ParseStream) -> Result<Self> { 573808c999fSMiguel Ojeda /// Ok(SingleUse { 574808c999fSMiguel Ojeda /// use_token: input.parse()?, 575808c999fSMiguel Ojeda /// path: input.call(Path::parse_mod_style)?, 576808c999fSMiguel Ojeda /// }) 577808c999fSMiguel Ojeda /// } 578808c999fSMiguel Ojeda /// } 579808c999fSMiguel Ojeda /// ``` 580808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] parse_mod_style(input: ParseStream) -> Result<Self>581808c999fSMiguel Ojeda pub fn parse_mod_style(input: ParseStream) -> Result<Self> { 582808c999fSMiguel Ojeda Ok(Path { 583808c999fSMiguel Ojeda leading_colon: input.parse()?, 584808c999fSMiguel Ojeda segments: { 585808c999fSMiguel Ojeda let mut segments = Punctuated::new(); 586808c999fSMiguel Ojeda loop { 587808c999fSMiguel Ojeda if !input.peek(Ident) 588808c999fSMiguel Ojeda && !input.peek(Token![super]) 589808c999fSMiguel Ojeda && !input.peek(Token![self]) 590808c999fSMiguel Ojeda && !input.peek(Token![Self]) 591808c999fSMiguel Ojeda && !input.peek(Token![crate]) 592808c999fSMiguel Ojeda { 593808c999fSMiguel Ojeda break; 594808c999fSMiguel Ojeda } 595808c999fSMiguel Ojeda let ident = Ident::parse_any(input)?; 596808c999fSMiguel Ojeda segments.push_value(PathSegment::from(ident)); 597808c999fSMiguel Ojeda if !input.peek(Token![::]) { 598808c999fSMiguel Ojeda break; 599808c999fSMiguel Ojeda } 600808c999fSMiguel Ojeda let punct = input.parse()?; 601808c999fSMiguel Ojeda segments.push_punct(punct); 602808c999fSMiguel Ojeda } 603808c999fSMiguel Ojeda if segments.is_empty() { 604808c999fSMiguel Ojeda return Err(input.parse::<Ident>().unwrap_err()); 605808c999fSMiguel Ojeda } else if segments.trailing_punct() { 606808c999fSMiguel Ojeda return Err(input.error("expected path segment after `::`")); 607808c999fSMiguel Ojeda } 608808c999fSMiguel Ojeda segments 609808c999fSMiguel Ojeda }, 610808c999fSMiguel Ojeda }) 611808c999fSMiguel Ojeda } 612808c999fSMiguel Ojeda parse_helper(input: ParseStream, expr_style: bool) -> Result<Self>613808c999fSMiguel Ojeda pub(crate) fn parse_helper(input: ParseStream, expr_style: bool) -> Result<Self> { 614808c999fSMiguel Ojeda let mut path = Path { 615808c999fSMiguel Ojeda leading_colon: input.parse()?, 616808c999fSMiguel Ojeda segments: { 617808c999fSMiguel Ojeda let mut segments = Punctuated::new(); 618808c999fSMiguel Ojeda let value = PathSegment::parse_helper(input, expr_style)?; 619808c999fSMiguel Ojeda segments.push_value(value); 620808c999fSMiguel Ojeda segments 621808c999fSMiguel Ojeda }, 622808c999fSMiguel Ojeda }; 623808c999fSMiguel Ojeda Path::parse_rest(input, &mut path, expr_style)?; 624808c999fSMiguel Ojeda Ok(path) 625808c999fSMiguel Ojeda } 626808c999fSMiguel Ojeda parse_rest( input: ParseStream, path: &mut Self, expr_style: bool, ) -> Result<()>627808c999fSMiguel Ojeda pub(crate) fn parse_rest( 628808c999fSMiguel Ojeda input: ParseStream, 629808c999fSMiguel Ojeda path: &mut Self, 630808c999fSMiguel Ojeda expr_style: bool, 631808c999fSMiguel Ojeda ) -> Result<()> { 632808c999fSMiguel Ojeda while input.peek(Token![::]) && !input.peek3(token::Paren) { 633808c999fSMiguel Ojeda let punct: Token![::] = input.parse()?; 634808c999fSMiguel Ojeda path.segments.push_punct(punct); 635808c999fSMiguel Ojeda let value = PathSegment::parse_helper(input, expr_style)?; 636808c999fSMiguel Ojeda path.segments.push_value(value); 637808c999fSMiguel Ojeda } 638808c999fSMiguel Ojeda Ok(()) 639808c999fSMiguel Ojeda } 640808c999fSMiguel Ojeda is_mod_style(&self) -> bool641808c999fSMiguel Ojeda pub(crate) fn is_mod_style(&self) -> bool { 642808c999fSMiguel Ojeda self.segments 643808c999fSMiguel Ojeda .iter() 644808c999fSMiguel Ojeda .all(|segment| segment.arguments.is_none()) 645808c999fSMiguel Ojeda } 646808c999fSMiguel Ojeda } 647808c999fSMiguel Ojeda qpath(input: ParseStream, expr_style: bool) -> Result<(Option<QSelf>, Path)>648808c999fSMiguel Ojeda pub(crate) fn qpath(input: ParseStream, expr_style: bool) -> Result<(Option<QSelf>, Path)> { 649808c999fSMiguel Ojeda if input.peek(Token![<]) { 650808c999fSMiguel Ojeda let lt_token: Token![<] = input.parse()?; 651808c999fSMiguel Ojeda let this: Type = input.parse()?; 652808c999fSMiguel Ojeda let path = if input.peek(Token![as]) { 653808c999fSMiguel Ojeda let as_token: Token![as] = input.parse()?; 654808c999fSMiguel Ojeda let path: Path = input.parse()?; 655808c999fSMiguel Ojeda Some((as_token, path)) 656808c999fSMiguel Ojeda } else { 657808c999fSMiguel Ojeda None 658808c999fSMiguel Ojeda }; 659808c999fSMiguel Ojeda let gt_token: Token![>] = input.parse()?; 660808c999fSMiguel Ojeda let colon2_token: Token![::] = input.parse()?; 661808c999fSMiguel Ojeda let mut rest = Punctuated::new(); 662808c999fSMiguel Ojeda loop { 663808c999fSMiguel Ojeda let path = PathSegment::parse_helper(input, expr_style)?; 664808c999fSMiguel Ojeda rest.push_value(path); 665808c999fSMiguel Ojeda if !input.peek(Token![::]) { 666808c999fSMiguel Ojeda break; 667808c999fSMiguel Ojeda } 668808c999fSMiguel Ojeda let punct: Token![::] = input.parse()?; 669808c999fSMiguel Ojeda rest.push_punct(punct); 670808c999fSMiguel Ojeda } 671808c999fSMiguel Ojeda let (position, as_token, path) = match path { 672808c999fSMiguel Ojeda Some((as_token, mut path)) => { 673808c999fSMiguel Ojeda let pos = path.segments.len(); 674808c999fSMiguel Ojeda path.segments.push_punct(colon2_token); 675808c999fSMiguel Ojeda path.segments.extend(rest.into_pairs()); 676808c999fSMiguel Ojeda (pos, Some(as_token), path) 677808c999fSMiguel Ojeda } 678808c999fSMiguel Ojeda None => { 679808c999fSMiguel Ojeda let path = Path { 680808c999fSMiguel Ojeda leading_colon: Some(colon2_token), 681808c999fSMiguel Ojeda segments: rest, 682808c999fSMiguel Ojeda }; 683808c999fSMiguel Ojeda (0, None, path) 684808c999fSMiguel Ojeda } 685808c999fSMiguel Ojeda }; 686808c999fSMiguel Ojeda let qself = QSelf { 687808c999fSMiguel Ojeda lt_token, 688808c999fSMiguel Ojeda ty: Box::new(this), 689808c999fSMiguel Ojeda position, 690808c999fSMiguel Ojeda as_token, 691808c999fSMiguel Ojeda gt_token, 692808c999fSMiguel Ojeda }; 693808c999fSMiguel Ojeda Ok((Some(qself), path)) 694808c999fSMiguel Ojeda } else { 695808c999fSMiguel Ojeda let path = Path::parse_helper(input, expr_style)?; 696808c999fSMiguel Ojeda Ok((None, path)) 697808c999fSMiguel Ojeda } 698808c999fSMiguel Ojeda } 699808c999fSMiguel Ojeda } 700808c999fSMiguel Ojeda 701808c999fSMiguel Ojeda #[cfg(feature = "printing")] 702808c999fSMiguel Ojeda pub(crate) mod printing { 703808c999fSMiguel Ojeda use crate::generics; 704808c999fSMiguel Ojeda use crate::path::{ 705808c999fSMiguel Ojeda AngleBracketedGenericArguments, AssocConst, AssocType, Constraint, GenericArgument, 706808c999fSMiguel Ojeda ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf, 707808c999fSMiguel Ojeda }; 708808c999fSMiguel Ojeda use crate::print::TokensOrDefault; 709808c999fSMiguel Ojeda #[cfg(feature = "parsing")] 710808c999fSMiguel Ojeda use crate::spanned::Spanned; 711808c999fSMiguel Ojeda #[cfg(feature = "parsing")] 712808c999fSMiguel Ojeda use proc_macro2::Span; 713808c999fSMiguel Ojeda use proc_macro2::TokenStream; 714808c999fSMiguel Ojeda use quote::ToTokens; 715808c999fSMiguel Ojeda use std::cmp; 716808c999fSMiguel Ojeda 717808c999fSMiguel Ojeda pub(crate) enum PathStyle { 718808c999fSMiguel Ojeda Expr, 719808c999fSMiguel Ojeda Mod, 720808c999fSMiguel Ojeda AsWritten, 721808c999fSMiguel Ojeda } 722808c999fSMiguel Ojeda 723808c999fSMiguel Ojeda impl Copy for PathStyle {} 724808c999fSMiguel Ojeda 725808c999fSMiguel Ojeda impl Clone for PathStyle { clone(&self) -> Self726808c999fSMiguel Ojeda fn clone(&self) -> Self { 727808c999fSMiguel Ojeda *self 728808c999fSMiguel Ojeda } 729808c999fSMiguel Ojeda } 730808c999fSMiguel Ojeda 731808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 732808c999fSMiguel Ojeda impl ToTokens for Path { to_tokens(&self, tokens: &mut TokenStream)733808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 734808c999fSMiguel Ojeda print_path(tokens, self, PathStyle::AsWritten); 735808c999fSMiguel Ojeda } 736808c999fSMiguel Ojeda } 737808c999fSMiguel Ojeda print_path(tokens: &mut TokenStream, path: &Path, style: PathStyle)738808c999fSMiguel Ojeda pub(crate) fn print_path(tokens: &mut TokenStream, path: &Path, style: PathStyle) { 739808c999fSMiguel Ojeda path.leading_colon.to_tokens(tokens); 740808c999fSMiguel Ojeda for segment in path.segments.pairs() { 741808c999fSMiguel Ojeda print_path_segment(tokens, segment.value(), style); 742808c999fSMiguel Ojeda segment.punct().to_tokens(tokens); 743808c999fSMiguel Ojeda } 744808c999fSMiguel Ojeda } 745808c999fSMiguel Ojeda 746808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 747808c999fSMiguel Ojeda impl ToTokens for PathSegment { to_tokens(&self, tokens: &mut TokenStream)748808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 749808c999fSMiguel Ojeda print_path_segment(tokens, self, PathStyle::AsWritten); 750808c999fSMiguel Ojeda } 751808c999fSMiguel Ojeda } 752808c999fSMiguel Ojeda print_path_segment(tokens: &mut TokenStream, segment: &PathSegment, style: PathStyle)753808c999fSMiguel Ojeda fn print_path_segment(tokens: &mut TokenStream, segment: &PathSegment, style: PathStyle) { 754808c999fSMiguel Ojeda segment.ident.to_tokens(tokens); 755808c999fSMiguel Ojeda print_path_arguments(tokens, &segment.arguments, style); 756808c999fSMiguel Ojeda } 757808c999fSMiguel Ojeda 758808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 759808c999fSMiguel Ojeda impl ToTokens for PathArguments { to_tokens(&self, tokens: &mut TokenStream)760808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 761808c999fSMiguel Ojeda print_path_arguments(tokens, self, PathStyle::AsWritten); 762808c999fSMiguel Ojeda } 763808c999fSMiguel Ojeda } 764808c999fSMiguel Ojeda print_path_arguments(tokens: &mut TokenStream, arguments: &PathArguments, style: PathStyle)765808c999fSMiguel Ojeda fn print_path_arguments(tokens: &mut TokenStream, arguments: &PathArguments, style: PathStyle) { 766808c999fSMiguel Ojeda match arguments { 767808c999fSMiguel Ojeda PathArguments::None => {} 768808c999fSMiguel Ojeda PathArguments::AngleBracketed(arguments) => { 769808c999fSMiguel Ojeda print_angle_bracketed_generic_arguments(tokens, arguments, style); 770808c999fSMiguel Ojeda } 771808c999fSMiguel Ojeda PathArguments::Parenthesized(arguments) => { 772808c999fSMiguel Ojeda print_parenthesized_generic_arguments(tokens, arguments, style); 773808c999fSMiguel Ojeda } 774808c999fSMiguel Ojeda } 775808c999fSMiguel Ojeda } 776808c999fSMiguel Ojeda 777808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 778808c999fSMiguel Ojeda impl ToTokens for GenericArgument { 779808c999fSMiguel Ojeda #[allow(clippy::match_same_arms)] to_tokens(&self, tokens: &mut TokenStream)780808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 781808c999fSMiguel Ojeda match self { 782808c999fSMiguel Ojeda GenericArgument::Lifetime(lt) => lt.to_tokens(tokens), 783808c999fSMiguel Ojeda GenericArgument::Type(ty) => ty.to_tokens(tokens), 784808c999fSMiguel Ojeda GenericArgument::Const(expr) => { 785808c999fSMiguel Ojeda generics::printing::print_const_argument(expr, tokens); 786808c999fSMiguel Ojeda } 787808c999fSMiguel Ojeda GenericArgument::AssocType(assoc) => assoc.to_tokens(tokens), 788808c999fSMiguel Ojeda GenericArgument::AssocConst(assoc) => assoc.to_tokens(tokens), 789808c999fSMiguel Ojeda GenericArgument::Constraint(constraint) => constraint.to_tokens(tokens), 790808c999fSMiguel Ojeda } 791808c999fSMiguel Ojeda } 792808c999fSMiguel Ojeda } 793808c999fSMiguel Ojeda 794808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 795808c999fSMiguel Ojeda impl ToTokens for AngleBracketedGenericArguments { to_tokens(&self, tokens: &mut TokenStream)796808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 797808c999fSMiguel Ojeda print_angle_bracketed_generic_arguments(tokens, self, PathStyle::AsWritten); 798808c999fSMiguel Ojeda } 799808c999fSMiguel Ojeda } 800808c999fSMiguel Ojeda print_angle_bracketed_generic_arguments( tokens: &mut TokenStream, arguments: &AngleBracketedGenericArguments, style: PathStyle, )801808c999fSMiguel Ojeda pub(crate) fn print_angle_bracketed_generic_arguments( 802808c999fSMiguel Ojeda tokens: &mut TokenStream, 803808c999fSMiguel Ojeda arguments: &AngleBracketedGenericArguments, 804808c999fSMiguel Ojeda style: PathStyle, 805808c999fSMiguel Ojeda ) { 806808c999fSMiguel Ojeda if let PathStyle::Mod = style { 807808c999fSMiguel Ojeda return; 808808c999fSMiguel Ojeda } 809808c999fSMiguel Ojeda 810808c999fSMiguel Ojeda conditionally_print_turbofish(tokens, &arguments.colon2_token, style); 811808c999fSMiguel Ojeda arguments.lt_token.to_tokens(tokens); 812808c999fSMiguel Ojeda 813808c999fSMiguel Ojeda // Print lifetimes before types/consts/bindings, regardless of their 814808c999fSMiguel Ojeda // order in args. 815808c999fSMiguel Ojeda let mut trailing_or_empty = true; 816808c999fSMiguel Ojeda for param in arguments.args.pairs() { 817808c999fSMiguel Ojeda match param.value() { 818808c999fSMiguel Ojeda GenericArgument::Lifetime(_) => { 819808c999fSMiguel Ojeda param.to_tokens(tokens); 820808c999fSMiguel Ojeda trailing_or_empty = param.punct().is_some(); 821808c999fSMiguel Ojeda } 822808c999fSMiguel Ojeda GenericArgument::Type(_) 823808c999fSMiguel Ojeda | GenericArgument::Const(_) 824808c999fSMiguel Ojeda | GenericArgument::AssocType(_) 825808c999fSMiguel Ojeda | GenericArgument::AssocConst(_) 826808c999fSMiguel Ojeda | GenericArgument::Constraint(_) => {} 827808c999fSMiguel Ojeda } 828808c999fSMiguel Ojeda } 829808c999fSMiguel Ojeda for param in arguments.args.pairs() { 830808c999fSMiguel Ojeda match param.value() { 831808c999fSMiguel Ojeda GenericArgument::Type(_) 832808c999fSMiguel Ojeda | GenericArgument::Const(_) 833808c999fSMiguel Ojeda | GenericArgument::AssocType(_) 834808c999fSMiguel Ojeda | GenericArgument::AssocConst(_) 835808c999fSMiguel Ojeda | GenericArgument::Constraint(_) => { 836808c999fSMiguel Ojeda if !trailing_or_empty { 837808c999fSMiguel Ojeda <Token![,]>::default().to_tokens(tokens); 838808c999fSMiguel Ojeda } 839808c999fSMiguel Ojeda param.to_tokens(tokens); 840808c999fSMiguel Ojeda trailing_or_empty = param.punct().is_some(); 841808c999fSMiguel Ojeda } 842808c999fSMiguel Ojeda GenericArgument::Lifetime(_) => {} 843808c999fSMiguel Ojeda } 844808c999fSMiguel Ojeda } 845808c999fSMiguel Ojeda 846808c999fSMiguel Ojeda arguments.gt_token.to_tokens(tokens); 847808c999fSMiguel Ojeda } 848808c999fSMiguel Ojeda 849808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 850808c999fSMiguel Ojeda impl ToTokens for AssocType { to_tokens(&self, tokens: &mut TokenStream)851808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 852808c999fSMiguel Ojeda self.ident.to_tokens(tokens); 853808c999fSMiguel Ojeda self.generics.to_tokens(tokens); 854808c999fSMiguel Ojeda self.eq_token.to_tokens(tokens); 855808c999fSMiguel Ojeda self.ty.to_tokens(tokens); 856808c999fSMiguel Ojeda } 857808c999fSMiguel Ojeda } 858808c999fSMiguel Ojeda 859808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 860808c999fSMiguel Ojeda impl ToTokens for AssocConst { to_tokens(&self, tokens: &mut TokenStream)861808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 862808c999fSMiguel Ojeda self.ident.to_tokens(tokens); 863808c999fSMiguel Ojeda self.generics.to_tokens(tokens); 864808c999fSMiguel Ojeda self.eq_token.to_tokens(tokens); 865808c999fSMiguel Ojeda generics::printing::print_const_argument(&self.value, tokens); 866808c999fSMiguel Ojeda } 867808c999fSMiguel Ojeda } 868808c999fSMiguel Ojeda 869808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 870808c999fSMiguel Ojeda impl ToTokens for Constraint { to_tokens(&self, tokens: &mut TokenStream)871808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 872808c999fSMiguel Ojeda self.ident.to_tokens(tokens); 873808c999fSMiguel Ojeda self.generics.to_tokens(tokens); 874808c999fSMiguel Ojeda self.colon_token.to_tokens(tokens); 875808c999fSMiguel Ojeda self.bounds.to_tokens(tokens); 876808c999fSMiguel Ojeda } 877808c999fSMiguel Ojeda } 878808c999fSMiguel Ojeda 879808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 880808c999fSMiguel Ojeda impl ToTokens for ParenthesizedGenericArguments { to_tokens(&self, tokens: &mut TokenStream)881808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 882808c999fSMiguel Ojeda print_parenthesized_generic_arguments(tokens, self, PathStyle::AsWritten); 883808c999fSMiguel Ojeda } 884808c999fSMiguel Ojeda } 885808c999fSMiguel Ojeda print_parenthesized_generic_arguments( tokens: &mut TokenStream, arguments: &ParenthesizedGenericArguments, style: PathStyle, )886808c999fSMiguel Ojeda fn print_parenthesized_generic_arguments( 887808c999fSMiguel Ojeda tokens: &mut TokenStream, 888808c999fSMiguel Ojeda arguments: &ParenthesizedGenericArguments, 889808c999fSMiguel Ojeda style: PathStyle, 890808c999fSMiguel Ojeda ) { 891808c999fSMiguel Ojeda if let PathStyle::Mod = style { 892808c999fSMiguel Ojeda return; 893808c999fSMiguel Ojeda } 894808c999fSMiguel Ojeda 895808c999fSMiguel Ojeda conditionally_print_turbofish(tokens, &None, style); 896808c999fSMiguel Ojeda arguments.paren_token.surround(tokens, |tokens| { 897808c999fSMiguel Ojeda arguments.inputs.to_tokens(tokens); 898808c999fSMiguel Ojeda }); 899808c999fSMiguel Ojeda arguments.output.to_tokens(tokens); 900808c999fSMiguel Ojeda } 901808c999fSMiguel Ojeda print_qpath( tokens: &mut TokenStream, qself: &Option<QSelf>, path: &Path, style: PathStyle, )902808c999fSMiguel Ojeda pub(crate) fn print_qpath( 903808c999fSMiguel Ojeda tokens: &mut TokenStream, 904808c999fSMiguel Ojeda qself: &Option<QSelf>, 905808c999fSMiguel Ojeda path: &Path, 906808c999fSMiguel Ojeda style: PathStyle, 907808c999fSMiguel Ojeda ) { 908808c999fSMiguel Ojeda let qself = match qself { 909808c999fSMiguel Ojeda Some(qself) => qself, 910808c999fSMiguel Ojeda None => { 911808c999fSMiguel Ojeda print_path(tokens, path, style); 912808c999fSMiguel Ojeda return; 913808c999fSMiguel Ojeda } 914808c999fSMiguel Ojeda }; 915808c999fSMiguel Ojeda qself.lt_token.to_tokens(tokens); 916808c999fSMiguel Ojeda qself.ty.to_tokens(tokens); 917808c999fSMiguel Ojeda 918808c999fSMiguel Ojeda let pos = cmp::min(qself.position, path.segments.len()); 919808c999fSMiguel Ojeda let mut segments = path.segments.pairs(); 920808c999fSMiguel Ojeda if pos > 0 { 921808c999fSMiguel Ojeda TokensOrDefault(&qself.as_token).to_tokens(tokens); 922808c999fSMiguel Ojeda path.leading_colon.to_tokens(tokens); 923808c999fSMiguel Ojeda for (i, segment) in segments.by_ref().take(pos).enumerate() { 924808c999fSMiguel Ojeda print_path_segment(tokens, segment.value(), PathStyle::AsWritten); 925808c999fSMiguel Ojeda if i + 1 == pos { 926808c999fSMiguel Ojeda qself.gt_token.to_tokens(tokens); 927808c999fSMiguel Ojeda } 928808c999fSMiguel Ojeda segment.punct().to_tokens(tokens); 929808c999fSMiguel Ojeda } 930808c999fSMiguel Ojeda } else { 931808c999fSMiguel Ojeda qself.gt_token.to_tokens(tokens); 932808c999fSMiguel Ojeda path.leading_colon.to_tokens(tokens); 933808c999fSMiguel Ojeda } 934808c999fSMiguel Ojeda for segment in segments { 935808c999fSMiguel Ojeda print_path_segment(tokens, segment.value(), style); 936808c999fSMiguel Ojeda segment.punct().to_tokens(tokens); 937808c999fSMiguel Ojeda } 938808c999fSMiguel Ojeda } 939808c999fSMiguel Ojeda conditionally_print_turbofish( tokens: &mut TokenStream, colon2_token: &Option<Token![::]>, style: PathStyle, )940808c999fSMiguel Ojeda fn conditionally_print_turbofish( 941808c999fSMiguel Ojeda tokens: &mut TokenStream, 942808c999fSMiguel Ojeda colon2_token: &Option<Token![::]>, 943808c999fSMiguel Ojeda style: PathStyle, 944808c999fSMiguel Ojeda ) { 945808c999fSMiguel Ojeda match style { 946808c999fSMiguel Ojeda PathStyle::Expr => TokensOrDefault(colon2_token).to_tokens(tokens), 947808c999fSMiguel Ojeda PathStyle::Mod => unreachable!(), 948808c999fSMiguel Ojeda PathStyle::AsWritten => colon2_token.to_tokens(tokens), 949808c999fSMiguel Ojeda } 950808c999fSMiguel Ojeda } 951808c999fSMiguel Ojeda 952808c999fSMiguel Ojeda #[cfg(feature = "parsing")] 953808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(all(feature = "parsing", feature = "printing"))))] 954808c999fSMiguel Ojeda impl Spanned for QSelf { span(&self) -> Span955808c999fSMiguel Ojeda fn span(&self) -> Span { 956808c999fSMiguel Ojeda struct QSelfDelimiters<'a>(&'a QSelf); 957808c999fSMiguel Ojeda 958808c999fSMiguel Ojeda impl<'a> ToTokens for QSelfDelimiters<'a> { 959808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 960808c999fSMiguel Ojeda self.0.lt_token.to_tokens(tokens); 961808c999fSMiguel Ojeda self.0.gt_token.to_tokens(tokens); 962808c999fSMiguel Ojeda } 963808c999fSMiguel Ojeda } 964808c999fSMiguel Ojeda 965808c999fSMiguel Ojeda QSelfDelimiters(self).span() 966808c999fSMiguel Ojeda } 967808c999fSMiguel Ojeda } 968808c999fSMiguel Ojeda } 969