1fad3a1d3Sopenharmony_ciuse super::*; 2fad3a1d3Sopenharmony_ciuse crate::punctuated::Punctuated; 3fad3a1d3Sopenharmony_ci 4fad3a1d3Sopenharmony_ciast_struct! { 5fad3a1d3Sopenharmony_ci /// A path at which a named item is exported (e.g. `std::collections::HashMap`). 6fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 7fad3a1d3Sopenharmony_ci pub struct Path { 8fad3a1d3Sopenharmony_ci pub leading_colon: Option<Token![::]>, 9fad3a1d3Sopenharmony_ci pub segments: Punctuated<PathSegment, Token![::]>, 10fad3a1d3Sopenharmony_ci } 11fad3a1d3Sopenharmony_ci} 12fad3a1d3Sopenharmony_ci 13fad3a1d3Sopenharmony_ciimpl<T> From<T> for Path 14fad3a1d3Sopenharmony_ciwhere 15fad3a1d3Sopenharmony_ci T: Into<PathSegment>, 16fad3a1d3Sopenharmony_ci{ 17fad3a1d3Sopenharmony_ci fn from(segment: T) -> Self { 18fad3a1d3Sopenharmony_ci let mut path = Path { 19fad3a1d3Sopenharmony_ci leading_colon: None, 20fad3a1d3Sopenharmony_ci segments: Punctuated::new(), 21fad3a1d3Sopenharmony_ci }; 22fad3a1d3Sopenharmony_ci path.segments.push_value(segment.into()); 23fad3a1d3Sopenharmony_ci path 24fad3a1d3Sopenharmony_ci } 25fad3a1d3Sopenharmony_ci} 26fad3a1d3Sopenharmony_ci 27fad3a1d3Sopenharmony_ciimpl Path { 28fad3a1d3Sopenharmony_ci /// Determines whether this is a path of length 1 equal to the given 29fad3a1d3Sopenharmony_ci /// ident. 30fad3a1d3Sopenharmony_ci /// 31fad3a1d3Sopenharmony_ci /// For them to compare equal, it must be the case that: 32fad3a1d3Sopenharmony_ci /// 33fad3a1d3Sopenharmony_ci /// - the path has no leading colon, 34fad3a1d3Sopenharmony_ci /// - the number of path segments is 1, 35fad3a1d3Sopenharmony_ci /// - the first path segment has no angle bracketed or parenthesized 36fad3a1d3Sopenharmony_ci /// path arguments, and 37fad3a1d3Sopenharmony_ci /// - the ident of the first path segment is equal to the given one. 38fad3a1d3Sopenharmony_ci /// 39fad3a1d3Sopenharmony_ci /// # Example 40fad3a1d3Sopenharmony_ci /// 41fad3a1d3Sopenharmony_ci /// ``` 42fad3a1d3Sopenharmony_ci /// use proc_macro2::TokenStream; 43fad3a1d3Sopenharmony_ci /// use syn::{Attribute, Error, Meta, Result}; 44fad3a1d3Sopenharmony_ci /// 45fad3a1d3Sopenharmony_ci /// fn get_serde_meta_item(attr: &Attribute) -> Result<Option<&TokenStream>> { 46fad3a1d3Sopenharmony_ci /// if attr.path().is_ident("serde") { 47fad3a1d3Sopenharmony_ci /// match &attr.meta { 48fad3a1d3Sopenharmony_ci /// Meta::List(meta) => Ok(Some(&meta.tokens)), 49fad3a1d3Sopenharmony_ci /// bad => Err(Error::new_spanned(bad, "unrecognized attribute")), 50fad3a1d3Sopenharmony_ci /// } 51fad3a1d3Sopenharmony_ci /// } else { 52fad3a1d3Sopenharmony_ci /// Ok(None) 53fad3a1d3Sopenharmony_ci /// } 54fad3a1d3Sopenharmony_ci /// } 55fad3a1d3Sopenharmony_ci /// ``` 56fad3a1d3Sopenharmony_ci pub fn is_ident<I>(&self, ident: &I) -> bool 57fad3a1d3Sopenharmony_ci where 58fad3a1d3Sopenharmony_ci I: ?Sized, 59fad3a1d3Sopenharmony_ci Ident: PartialEq<I>, 60fad3a1d3Sopenharmony_ci { 61fad3a1d3Sopenharmony_ci match self.get_ident() { 62fad3a1d3Sopenharmony_ci Some(id) => id == ident, 63fad3a1d3Sopenharmony_ci None => false, 64fad3a1d3Sopenharmony_ci } 65fad3a1d3Sopenharmony_ci } 66fad3a1d3Sopenharmony_ci 67fad3a1d3Sopenharmony_ci /// If this path consists of a single ident, returns the ident. 68fad3a1d3Sopenharmony_ci /// 69fad3a1d3Sopenharmony_ci /// A path is considered an ident if: 70fad3a1d3Sopenharmony_ci /// 71fad3a1d3Sopenharmony_ci /// - the path has no leading colon, 72fad3a1d3Sopenharmony_ci /// - the number of path segments is 1, and 73fad3a1d3Sopenharmony_ci /// - the first path segment has no angle bracketed or parenthesized 74fad3a1d3Sopenharmony_ci /// path arguments. 75fad3a1d3Sopenharmony_ci pub fn get_ident(&self) -> Option<&Ident> { 76fad3a1d3Sopenharmony_ci if self.leading_colon.is_none() 77fad3a1d3Sopenharmony_ci && self.segments.len() == 1 78fad3a1d3Sopenharmony_ci && self.segments[0].arguments.is_none() 79fad3a1d3Sopenharmony_ci { 80fad3a1d3Sopenharmony_ci Some(&self.segments[0].ident) 81fad3a1d3Sopenharmony_ci } else { 82fad3a1d3Sopenharmony_ci None 83fad3a1d3Sopenharmony_ci } 84fad3a1d3Sopenharmony_ci } 85fad3a1d3Sopenharmony_ci 86fad3a1d3Sopenharmony_ci /// An error if this path is not a single ident, as defined in `get_ident`. 87fad3a1d3Sopenharmony_ci #[cfg(feature = "parsing")] 88fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 89fad3a1d3Sopenharmony_ci pub fn require_ident(&self) -> Result<&Ident> { 90fad3a1d3Sopenharmony_ci self.get_ident().ok_or_else(|| { 91fad3a1d3Sopenharmony_ci crate::error::new2( 92fad3a1d3Sopenharmony_ci self.segments.first().unwrap().ident.span(), 93fad3a1d3Sopenharmony_ci self.segments.last().unwrap().ident.span(), 94fad3a1d3Sopenharmony_ci "expected this path to be an identifier", 95fad3a1d3Sopenharmony_ci ) 96fad3a1d3Sopenharmony_ci }) 97fad3a1d3Sopenharmony_ci } 98fad3a1d3Sopenharmony_ci} 99fad3a1d3Sopenharmony_ci 100fad3a1d3Sopenharmony_ciast_struct! { 101fad3a1d3Sopenharmony_ci /// A segment of a path together with any path arguments on that segment. 102fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 103fad3a1d3Sopenharmony_ci pub struct PathSegment { 104fad3a1d3Sopenharmony_ci pub ident: Ident, 105fad3a1d3Sopenharmony_ci pub arguments: PathArguments, 106fad3a1d3Sopenharmony_ci } 107fad3a1d3Sopenharmony_ci} 108fad3a1d3Sopenharmony_ci 109fad3a1d3Sopenharmony_ciimpl<T> From<T> for PathSegment 110fad3a1d3Sopenharmony_ciwhere 111fad3a1d3Sopenharmony_ci T: Into<Ident>, 112fad3a1d3Sopenharmony_ci{ 113fad3a1d3Sopenharmony_ci fn from(ident: T) -> Self { 114fad3a1d3Sopenharmony_ci PathSegment { 115fad3a1d3Sopenharmony_ci ident: ident.into(), 116fad3a1d3Sopenharmony_ci arguments: PathArguments::None, 117fad3a1d3Sopenharmony_ci } 118fad3a1d3Sopenharmony_ci } 119fad3a1d3Sopenharmony_ci} 120fad3a1d3Sopenharmony_ci 121fad3a1d3Sopenharmony_ciast_enum! { 122fad3a1d3Sopenharmony_ci /// Angle bracketed or parenthesized arguments of a path segment. 123fad3a1d3Sopenharmony_ci /// 124fad3a1d3Sopenharmony_ci /// ## Angle bracketed 125fad3a1d3Sopenharmony_ci /// 126fad3a1d3Sopenharmony_ci /// The `<'a, T>` in `std::slice::iter<'a, T>`. 127fad3a1d3Sopenharmony_ci /// 128fad3a1d3Sopenharmony_ci /// ## Parenthesized 129fad3a1d3Sopenharmony_ci /// 130fad3a1d3Sopenharmony_ci /// The `(A, B) -> C` in `Fn(A, B) -> C`. 131fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 132fad3a1d3Sopenharmony_ci pub enum PathArguments { 133fad3a1d3Sopenharmony_ci None, 134fad3a1d3Sopenharmony_ci /// The `<'a, T>` in `std::slice::iter<'a, T>`. 135fad3a1d3Sopenharmony_ci AngleBracketed(AngleBracketedGenericArguments), 136fad3a1d3Sopenharmony_ci /// The `(A, B) -> C` in `Fn(A, B) -> C`. 137fad3a1d3Sopenharmony_ci Parenthesized(ParenthesizedGenericArguments), 138fad3a1d3Sopenharmony_ci } 139fad3a1d3Sopenharmony_ci} 140fad3a1d3Sopenharmony_ci 141fad3a1d3Sopenharmony_ciimpl Default for PathArguments { 142fad3a1d3Sopenharmony_ci fn default() -> Self { 143fad3a1d3Sopenharmony_ci PathArguments::None 144fad3a1d3Sopenharmony_ci } 145fad3a1d3Sopenharmony_ci} 146fad3a1d3Sopenharmony_ci 147fad3a1d3Sopenharmony_ciimpl PathArguments { 148fad3a1d3Sopenharmony_ci pub fn is_empty(&self) -> bool { 149fad3a1d3Sopenharmony_ci match self { 150fad3a1d3Sopenharmony_ci PathArguments::None => true, 151fad3a1d3Sopenharmony_ci PathArguments::AngleBracketed(bracketed) => bracketed.args.is_empty(), 152fad3a1d3Sopenharmony_ci PathArguments::Parenthesized(_) => false, 153fad3a1d3Sopenharmony_ci } 154fad3a1d3Sopenharmony_ci } 155fad3a1d3Sopenharmony_ci 156fad3a1d3Sopenharmony_ci pub fn is_none(&self) -> bool { 157fad3a1d3Sopenharmony_ci match self { 158fad3a1d3Sopenharmony_ci PathArguments::None => true, 159fad3a1d3Sopenharmony_ci PathArguments::AngleBracketed(_) | PathArguments::Parenthesized(_) => false, 160fad3a1d3Sopenharmony_ci } 161fad3a1d3Sopenharmony_ci } 162fad3a1d3Sopenharmony_ci} 163fad3a1d3Sopenharmony_ci 164fad3a1d3Sopenharmony_ciast_enum! { 165fad3a1d3Sopenharmony_ci /// An individual generic argument, like `'a`, `T`, or `Item = T`. 166fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 167fad3a1d3Sopenharmony_ci #[non_exhaustive] 168fad3a1d3Sopenharmony_ci pub enum GenericArgument { 169fad3a1d3Sopenharmony_ci /// A lifetime argument. 170fad3a1d3Sopenharmony_ci Lifetime(Lifetime), 171fad3a1d3Sopenharmony_ci /// A type argument. 172fad3a1d3Sopenharmony_ci Type(Type), 173fad3a1d3Sopenharmony_ci /// A const expression. Must be inside of a block. 174fad3a1d3Sopenharmony_ci /// 175fad3a1d3Sopenharmony_ci /// NOTE: Identity expressions are represented as Type arguments, as 176fad3a1d3Sopenharmony_ci /// they are indistinguishable syntactically. 177fad3a1d3Sopenharmony_ci Const(Expr), 178fad3a1d3Sopenharmony_ci /// A binding (equality constraint) on an associated type: the `Item = 179fad3a1d3Sopenharmony_ci /// u8` in `Iterator<Item = u8>`. 180fad3a1d3Sopenharmony_ci AssocType(AssocType), 181fad3a1d3Sopenharmony_ci /// An equality constraint on an associated constant: the `PANIC = 182fad3a1d3Sopenharmony_ci /// false` in `Trait<PANIC = false>`. 183fad3a1d3Sopenharmony_ci AssocConst(AssocConst), 184fad3a1d3Sopenharmony_ci /// An associated type bound: `Iterator<Item: Display>`. 185fad3a1d3Sopenharmony_ci Constraint(Constraint), 186fad3a1d3Sopenharmony_ci } 187fad3a1d3Sopenharmony_ci} 188fad3a1d3Sopenharmony_ci 189fad3a1d3Sopenharmony_ciast_struct! { 190fad3a1d3Sopenharmony_ci /// Angle bracketed arguments of a path segment: the `<K, V>` in `HashMap<K, 191fad3a1d3Sopenharmony_ci /// V>`. 192fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 193fad3a1d3Sopenharmony_ci pub struct AngleBracketedGenericArguments { 194fad3a1d3Sopenharmony_ci pub colon2_token: Option<Token![::]>, 195fad3a1d3Sopenharmony_ci pub lt_token: Token![<], 196fad3a1d3Sopenharmony_ci pub args: Punctuated<GenericArgument, Token![,]>, 197fad3a1d3Sopenharmony_ci pub gt_token: Token![>], 198fad3a1d3Sopenharmony_ci } 199fad3a1d3Sopenharmony_ci} 200fad3a1d3Sopenharmony_ci 201fad3a1d3Sopenharmony_ciast_struct! { 202fad3a1d3Sopenharmony_ci /// A binding (equality constraint) on an associated type: the `Item = u8` 203fad3a1d3Sopenharmony_ci /// in `Iterator<Item = u8>`. 204fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 205fad3a1d3Sopenharmony_ci pub struct AssocType { 206fad3a1d3Sopenharmony_ci pub ident: Ident, 207fad3a1d3Sopenharmony_ci pub generics: Option<AngleBracketedGenericArguments>, 208fad3a1d3Sopenharmony_ci pub eq_token: Token![=], 209fad3a1d3Sopenharmony_ci pub ty: Type, 210fad3a1d3Sopenharmony_ci } 211fad3a1d3Sopenharmony_ci} 212fad3a1d3Sopenharmony_ci 213fad3a1d3Sopenharmony_ciast_struct! { 214fad3a1d3Sopenharmony_ci /// An equality constraint on an associated constant: the `PANIC = false` in 215fad3a1d3Sopenharmony_ci /// `Trait<PANIC = false>`. 216fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 217fad3a1d3Sopenharmony_ci pub struct AssocConst { 218fad3a1d3Sopenharmony_ci pub ident: Ident, 219fad3a1d3Sopenharmony_ci pub generics: Option<AngleBracketedGenericArguments>, 220fad3a1d3Sopenharmony_ci pub eq_token: Token![=], 221fad3a1d3Sopenharmony_ci pub value: Expr, 222fad3a1d3Sopenharmony_ci } 223fad3a1d3Sopenharmony_ci} 224fad3a1d3Sopenharmony_ci 225fad3a1d3Sopenharmony_ciast_struct! { 226fad3a1d3Sopenharmony_ci /// An associated type bound: `Iterator<Item: Display>`. 227fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 228fad3a1d3Sopenharmony_ci pub struct Constraint { 229fad3a1d3Sopenharmony_ci pub ident: Ident, 230fad3a1d3Sopenharmony_ci pub generics: Option<AngleBracketedGenericArguments>, 231fad3a1d3Sopenharmony_ci pub colon_token: Token![:], 232fad3a1d3Sopenharmony_ci pub bounds: Punctuated<TypeParamBound, Token![+]>, 233fad3a1d3Sopenharmony_ci } 234fad3a1d3Sopenharmony_ci} 235fad3a1d3Sopenharmony_ci 236fad3a1d3Sopenharmony_ciast_struct! { 237fad3a1d3Sopenharmony_ci /// Arguments of a function path segment: the `(A, B) -> C` in `Fn(A,B) -> 238fad3a1d3Sopenharmony_ci /// C`. 239fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 240fad3a1d3Sopenharmony_ci pub struct ParenthesizedGenericArguments { 241fad3a1d3Sopenharmony_ci pub paren_token: token::Paren, 242fad3a1d3Sopenharmony_ci /// `(A, B)` 243fad3a1d3Sopenharmony_ci pub inputs: Punctuated<Type, Token![,]>, 244fad3a1d3Sopenharmony_ci /// `C` 245fad3a1d3Sopenharmony_ci pub output: ReturnType, 246fad3a1d3Sopenharmony_ci } 247fad3a1d3Sopenharmony_ci} 248fad3a1d3Sopenharmony_ci 249fad3a1d3Sopenharmony_ciast_struct! { 250fad3a1d3Sopenharmony_ci /// The explicit Self type in a qualified path: the `T` in `<T as 251fad3a1d3Sopenharmony_ci /// Display>::fmt`. 252fad3a1d3Sopenharmony_ci /// 253fad3a1d3Sopenharmony_ci /// The actual path, including the trait and the associated item, is stored 254fad3a1d3Sopenharmony_ci /// separately. The `position` field represents the index of the associated 255fad3a1d3Sopenharmony_ci /// item qualified with this Self type. 256fad3a1d3Sopenharmony_ci /// 257fad3a1d3Sopenharmony_ci /// ```text 258fad3a1d3Sopenharmony_ci /// <Vec<T> as a::b::Trait>::AssociatedItem 259fad3a1d3Sopenharmony_ci /// ^~~~~~ ~~~~~~~~~~~~~~^ 260fad3a1d3Sopenharmony_ci /// ty position = 3 261fad3a1d3Sopenharmony_ci /// 262fad3a1d3Sopenharmony_ci /// <Vec<T>>::AssociatedItem 263fad3a1d3Sopenharmony_ci /// ^~~~~~ ^ 264fad3a1d3Sopenharmony_ci /// ty position = 0 265fad3a1d3Sopenharmony_ci /// ``` 266fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(any(feature = "full", feature = "derive"))))] 267fad3a1d3Sopenharmony_ci pub struct QSelf { 268fad3a1d3Sopenharmony_ci pub lt_token: Token![<], 269fad3a1d3Sopenharmony_ci pub ty: Box<Type>, 270fad3a1d3Sopenharmony_ci pub position: usize, 271fad3a1d3Sopenharmony_ci pub as_token: Option<Token![as]>, 272fad3a1d3Sopenharmony_ci pub gt_token: Token![>], 273fad3a1d3Sopenharmony_ci } 274fad3a1d3Sopenharmony_ci} 275fad3a1d3Sopenharmony_ci 276fad3a1d3Sopenharmony_ci#[cfg(feature = "parsing")] 277fad3a1d3Sopenharmony_cipub(crate) mod parsing { 278fad3a1d3Sopenharmony_ci use super::*; 279fad3a1d3Sopenharmony_ci 280fad3a1d3Sopenharmony_ci use crate::ext::IdentExt as _; 281fad3a1d3Sopenharmony_ci use crate::parse::{Parse, ParseStream, Result}; 282fad3a1d3Sopenharmony_ci 283fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 284fad3a1d3Sopenharmony_ci impl Parse for Path { 285fad3a1d3Sopenharmony_ci fn parse(input: ParseStream) -> Result<Self> { 286fad3a1d3Sopenharmony_ci Self::parse_helper(input, false) 287fad3a1d3Sopenharmony_ci } 288fad3a1d3Sopenharmony_ci } 289fad3a1d3Sopenharmony_ci 290fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 291fad3a1d3Sopenharmony_ci impl Parse for GenericArgument { 292fad3a1d3Sopenharmony_ci fn parse(input: ParseStream) -> Result<Self> { 293fad3a1d3Sopenharmony_ci if input.peek(Lifetime) && !input.peek2(Token![+]) { 294fad3a1d3Sopenharmony_ci return Ok(GenericArgument::Lifetime(input.parse()?)); 295fad3a1d3Sopenharmony_ci } 296fad3a1d3Sopenharmony_ci 297fad3a1d3Sopenharmony_ci if input.peek(Lit) || input.peek(token::Brace) { 298fad3a1d3Sopenharmony_ci return const_argument(input).map(GenericArgument::Const); 299fad3a1d3Sopenharmony_ci } 300fad3a1d3Sopenharmony_ci 301fad3a1d3Sopenharmony_ci let mut argument: Type = input.parse()?; 302fad3a1d3Sopenharmony_ci 303fad3a1d3Sopenharmony_ci match argument { 304fad3a1d3Sopenharmony_ci Type::Path(mut ty) 305fad3a1d3Sopenharmony_ci if ty.qself.is_none() 306fad3a1d3Sopenharmony_ci && ty.path.leading_colon.is_none() 307fad3a1d3Sopenharmony_ci && ty.path.segments.len() == 1 308fad3a1d3Sopenharmony_ci && match &ty.path.segments[0].arguments { 309fad3a1d3Sopenharmony_ci PathArguments::None | PathArguments::AngleBracketed(_) => true, 310fad3a1d3Sopenharmony_ci PathArguments::Parenthesized(_) => false, 311fad3a1d3Sopenharmony_ci } => 312fad3a1d3Sopenharmony_ci { 313fad3a1d3Sopenharmony_ci if let Some(eq_token) = input.parse::<Option<Token![=]>>()? { 314fad3a1d3Sopenharmony_ci let segment = ty.path.segments.pop().unwrap().into_value(); 315fad3a1d3Sopenharmony_ci let ident = segment.ident; 316fad3a1d3Sopenharmony_ci let generics = match segment.arguments { 317fad3a1d3Sopenharmony_ci PathArguments::None => None, 318fad3a1d3Sopenharmony_ci PathArguments::AngleBracketed(arguments) => Some(arguments), 319fad3a1d3Sopenharmony_ci PathArguments::Parenthesized(_) => unreachable!(), 320fad3a1d3Sopenharmony_ci }; 321fad3a1d3Sopenharmony_ci return if input.peek(Lit) || input.peek(token::Brace) { 322fad3a1d3Sopenharmony_ci Ok(GenericArgument::AssocConst(AssocConst { 323fad3a1d3Sopenharmony_ci ident, 324fad3a1d3Sopenharmony_ci generics, 325fad3a1d3Sopenharmony_ci eq_token, 326fad3a1d3Sopenharmony_ci value: const_argument(input)?, 327fad3a1d3Sopenharmony_ci })) 328fad3a1d3Sopenharmony_ci } else { 329fad3a1d3Sopenharmony_ci Ok(GenericArgument::AssocType(AssocType { 330fad3a1d3Sopenharmony_ci ident, 331fad3a1d3Sopenharmony_ci generics, 332fad3a1d3Sopenharmony_ci eq_token, 333fad3a1d3Sopenharmony_ci ty: input.parse()?, 334fad3a1d3Sopenharmony_ci })) 335fad3a1d3Sopenharmony_ci }; 336fad3a1d3Sopenharmony_ci } 337fad3a1d3Sopenharmony_ci 338fad3a1d3Sopenharmony_ci #[cfg(feature = "full")] 339fad3a1d3Sopenharmony_ci if let Some(colon_token) = input.parse::<Option<Token![:]>>()? { 340fad3a1d3Sopenharmony_ci let segment = ty.path.segments.pop().unwrap().into_value(); 341fad3a1d3Sopenharmony_ci return Ok(GenericArgument::Constraint(Constraint { 342fad3a1d3Sopenharmony_ci ident: segment.ident, 343fad3a1d3Sopenharmony_ci generics: match segment.arguments { 344fad3a1d3Sopenharmony_ci PathArguments::None => None, 345fad3a1d3Sopenharmony_ci PathArguments::AngleBracketed(arguments) => Some(arguments), 346fad3a1d3Sopenharmony_ci PathArguments::Parenthesized(_) => unreachable!(), 347fad3a1d3Sopenharmony_ci }, 348fad3a1d3Sopenharmony_ci colon_token, 349fad3a1d3Sopenharmony_ci bounds: { 350fad3a1d3Sopenharmony_ci let mut bounds = Punctuated::new(); 351fad3a1d3Sopenharmony_ci loop { 352fad3a1d3Sopenharmony_ci if input.peek(Token![,]) || input.peek(Token![>]) { 353fad3a1d3Sopenharmony_ci break; 354fad3a1d3Sopenharmony_ci } 355fad3a1d3Sopenharmony_ci let value: TypeParamBound = input.parse()?; 356fad3a1d3Sopenharmony_ci bounds.push_value(value); 357fad3a1d3Sopenharmony_ci if !input.peek(Token![+]) { 358fad3a1d3Sopenharmony_ci break; 359fad3a1d3Sopenharmony_ci } 360fad3a1d3Sopenharmony_ci let punct: Token![+] = input.parse()?; 361fad3a1d3Sopenharmony_ci bounds.push_punct(punct); 362fad3a1d3Sopenharmony_ci } 363fad3a1d3Sopenharmony_ci bounds 364fad3a1d3Sopenharmony_ci }, 365fad3a1d3Sopenharmony_ci })); 366fad3a1d3Sopenharmony_ci } 367fad3a1d3Sopenharmony_ci 368fad3a1d3Sopenharmony_ci argument = Type::Path(ty); 369fad3a1d3Sopenharmony_ci } 370fad3a1d3Sopenharmony_ci _ => {} 371fad3a1d3Sopenharmony_ci } 372fad3a1d3Sopenharmony_ci 373fad3a1d3Sopenharmony_ci Ok(GenericArgument::Type(argument)) 374fad3a1d3Sopenharmony_ci } 375fad3a1d3Sopenharmony_ci } 376fad3a1d3Sopenharmony_ci 377fad3a1d3Sopenharmony_ci pub(crate) fn const_argument(input: ParseStream) -> Result<Expr> { 378fad3a1d3Sopenharmony_ci let lookahead = input.lookahead1(); 379fad3a1d3Sopenharmony_ci 380fad3a1d3Sopenharmony_ci if input.peek(Lit) { 381fad3a1d3Sopenharmony_ci let lit = input.parse()?; 382fad3a1d3Sopenharmony_ci return Ok(Expr::Lit(lit)); 383fad3a1d3Sopenharmony_ci } 384fad3a1d3Sopenharmony_ci 385fad3a1d3Sopenharmony_ci if input.peek(Ident) { 386fad3a1d3Sopenharmony_ci let ident: Ident = input.parse()?; 387fad3a1d3Sopenharmony_ci return Ok(Expr::Path(ExprPath { 388fad3a1d3Sopenharmony_ci attrs: Vec::new(), 389fad3a1d3Sopenharmony_ci qself: None, 390fad3a1d3Sopenharmony_ci path: Path::from(ident), 391fad3a1d3Sopenharmony_ci })); 392fad3a1d3Sopenharmony_ci } 393fad3a1d3Sopenharmony_ci 394fad3a1d3Sopenharmony_ci if input.peek(token::Brace) { 395fad3a1d3Sopenharmony_ci #[cfg(feature = "full")] 396fad3a1d3Sopenharmony_ci { 397fad3a1d3Sopenharmony_ci let block: ExprBlock = input.parse()?; 398fad3a1d3Sopenharmony_ci return Ok(Expr::Block(block)); 399fad3a1d3Sopenharmony_ci } 400fad3a1d3Sopenharmony_ci 401fad3a1d3Sopenharmony_ci #[cfg(not(feature = "full"))] 402fad3a1d3Sopenharmony_ci { 403fad3a1d3Sopenharmony_ci let begin = input.fork(); 404fad3a1d3Sopenharmony_ci let content; 405fad3a1d3Sopenharmony_ci braced!(content in input); 406fad3a1d3Sopenharmony_ci content.parse::<Expr>()?; 407fad3a1d3Sopenharmony_ci let verbatim = verbatim::between(&begin, input); 408fad3a1d3Sopenharmony_ci return Ok(Expr::Verbatim(verbatim)); 409fad3a1d3Sopenharmony_ci } 410fad3a1d3Sopenharmony_ci } 411fad3a1d3Sopenharmony_ci 412fad3a1d3Sopenharmony_ci Err(lookahead.error()) 413fad3a1d3Sopenharmony_ci } 414fad3a1d3Sopenharmony_ci 415fad3a1d3Sopenharmony_ci impl AngleBracketedGenericArguments { 416fad3a1d3Sopenharmony_ci /// Parse `::<…>` with mandatory leading `::`. 417fad3a1d3Sopenharmony_ci /// 418fad3a1d3Sopenharmony_ci /// The ordinary [`Parse`] impl for `AngleBracketedGenericArguments` 419fad3a1d3Sopenharmony_ci /// parses optional leading `::`. 420fad3a1d3Sopenharmony_ci #[cfg(feature = "full")] 421fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "full"))))] 422fad3a1d3Sopenharmony_ci pub fn parse_turbofish(input: ParseStream) -> Result<Self> { 423fad3a1d3Sopenharmony_ci let colon2_token: Token![::] = input.parse()?; 424fad3a1d3Sopenharmony_ci Self::do_parse(Some(colon2_token), input) 425fad3a1d3Sopenharmony_ci } 426fad3a1d3Sopenharmony_ci 427fad3a1d3Sopenharmony_ci pub(crate) fn do_parse( 428fad3a1d3Sopenharmony_ci colon2_token: Option<Token![::]>, 429fad3a1d3Sopenharmony_ci input: ParseStream, 430fad3a1d3Sopenharmony_ci ) -> Result<Self> { 431fad3a1d3Sopenharmony_ci Ok(AngleBracketedGenericArguments { 432fad3a1d3Sopenharmony_ci colon2_token, 433fad3a1d3Sopenharmony_ci lt_token: input.parse()?, 434fad3a1d3Sopenharmony_ci args: { 435fad3a1d3Sopenharmony_ci let mut args = Punctuated::new(); 436fad3a1d3Sopenharmony_ci loop { 437fad3a1d3Sopenharmony_ci if input.peek(Token![>]) { 438fad3a1d3Sopenharmony_ci break; 439fad3a1d3Sopenharmony_ci } 440fad3a1d3Sopenharmony_ci let value: GenericArgument = input.parse()?; 441fad3a1d3Sopenharmony_ci args.push_value(value); 442fad3a1d3Sopenharmony_ci if input.peek(Token![>]) { 443fad3a1d3Sopenharmony_ci break; 444fad3a1d3Sopenharmony_ci } 445fad3a1d3Sopenharmony_ci let punct: Token![,] = input.parse()?; 446fad3a1d3Sopenharmony_ci args.push_punct(punct); 447fad3a1d3Sopenharmony_ci } 448fad3a1d3Sopenharmony_ci args 449fad3a1d3Sopenharmony_ci }, 450fad3a1d3Sopenharmony_ci gt_token: input.parse()?, 451fad3a1d3Sopenharmony_ci }) 452fad3a1d3Sopenharmony_ci } 453fad3a1d3Sopenharmony_ci } 454fad3a1d3Sopenharmony_ci 455fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 456fad3a1d3Sopenharmony_ci impl Parse for AngleBracketedGenericArguments { 457fad3a1d3Sopenharmony_ci fn parse(input: ParseStream) -> Result<Self> { 458fad3a1d3Sopenharmony_ci let colon2_token: Option<Token![::]> = input.parse()?; 459fad3a1d3Sopenharmony_ci Self::do_parse(colon2_token, input) 460fad3a1d3Sopenharmony_ci } 461fad3a1d3Sopenharmony_ci } 462fad3a1d3Sopenharmony_ci 463fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 464fad3a1d3Sopenharmony_ci impl Parse for ParenthesizedGenericArguments { 465fad3a1d3Sopenharmony_ci fn parse(input: ParseStream) -> Result<Self> { 466fad3a1d3Sopenharmony_ci let content; 467fad3a1d3Sopenharmony_ci Ok(ParenthesizedGenericArguments { 468fad3a1d3Sopenharmony_ci paren_token: parenthesized!(content in input), 469fad3a1d3Sopenharmony_ci inputs: content.parse_terminated(Type::parse, Token![,])?, 470fad3a1d3Sopenharmony_ci output: input.call(ReturnType::without_plus)?, 471fad3a1d3Sopenharmony_ci }) 472fad3a1d3Sopenharmony_ci } 473fad3a1d3Sopenharmony_ci } 474fad3a1d3Sopenharmony_ci 475fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 476fad3a1d3Sopenharmony_ci impl Parse for PathSegment { 477fad3a1d3Sopenharmony_ci fn parse(input: ParseStream) -> Result<Self> { 478fad3a1d3Sopenharmony_ci Self::parse_helper(input, false) 479fad3a1d3Sopenharmony_ci } 480fad3a1d3Sopenharmony_ci } 481fad3a1d3Sopenharmony_ci 482fad3a1d3Sopenharmony_ci impl PathSegment { 483fad3a1d3Sopenharmony_ci fn parse_helper(input: ParseStream, expr_style: bool) -> Result<Self> { 484fad3a1d3Sopenharmony_ci if input.peek(Token![super]) 485fad3a1d3Sopenharmony_ci || input.peek(Token![self]) 486fad3a1d3Sopenharmony_ci || input.peek(Token![crate]) 487fad3a1d3Sopenharmony_ci || cfg!(feature = "full") && input.peek(Token![try]) 488fad3a1d3Sopenharmony_ci { 489fad3a1d3Sopenharmony_ci let ident = input.call(Ident::parse_any)?; 490fad3a1d3Sopenharmony_ci return Ok(PathSegment::from(ident)); 491fad3a1d3Sopenharmony_ci } 492fad3a1d3Sopenharmony_ci 493fad3a1d3Sopenharmony_ci let ident = if input.peek(Token![Self]) { 494fad3a1d3Sopenharmony_ci input.call(Ident::parse_any)? 495fad3a1d3Sopenharmony_ci } else { 496fad3a1d3Sopenharmony_ci input.parse()? 497fad3a1d3Sopenharmony_ci }; 498fad3a1d3Sopenharmony_ci 499fad3a1d3Sopenharmony_ci if !expr_style && input.peek(Token![<]) && !input.peek(Token![<=]) 500fad3a1d3Sopenharmony_ci || input.peek(Token![::]) && input.peek3(Token![<]) 501fad3a1d3Sopenharmony_ci { 502fad3a1d3Sopenharmony_ci Ok(PathSegment { 503fad3a1d3Sopenharmony_ci ident, 504fad3a1d3Sopenharmony_ci arguments: PathArguments::AngleBracketed(input.parse()?), 505fad3a1d3Sopenharmony_ci }) 506fad3a1d3Sopenharmony_ci } else { 507fad3a1d3Sopenharmony_ci Ok(PathSegment::from(ident)) 508fad3a1d3Sopenharmony_ci } 509fad3a1d3Sopenharmony_ci } 510fad3a1d3Sopenharmony_ci } 511fad3a1d3Sopenharmony_ci 512fad3a1d3Sopenharmony_ci impl Path { 513fad3a1d3Sopenharmony_ci /// Parse a `Path` containing no path arguments on any of its segments. 514fad3a1d3Sopenharmony_ci /// 515fad3a1d3Sopenharmony_ci /// # Example 516fad3a1d3Sopenharmony_ci /// 517fad3a1d3Sopenharmony_ci /// ``` 518fad3a1d3Sopenharmony_ci /// use syn::{Path, Result, Token}; 519fad3a1d3Sopenharmony_ci /// use syn::parse::{Parse, ParseStream}; 520fad3a1d3Sopenharmony_ci /// 521fad3a1d3Sopenharmony_ci /// // A simplified single `use` statement like: 522fad3a1d3Sopenharmony_ci /// // 523fad3a1d3Sopenharmony_ci /// // use std::collections::HashMap; 524fad3a1d3Sopenharmony_ci /// // 525fad3a1d3Sopenharmony_ci /// // Note that generic parameters are not allowed in a `use` statement 526fad3a1d3Sopenharmony_ci /// // so the following must not be accepted. 527fad3a1d3Sopenharmony_ci /// // 528fad3a1d3Sopenharmony_ci /// // use a::<b>::c; 529fad3a1d3Sopenharmony_ci /// struct SingleUse { 530fad3a1d3Sopenharmony_ci /// use_token: Token![use], 531fad3a1d3Sopenharmony_ci /// path: Path, 532fad3a1d3Sopenharmony_ci /// } 533fad3a1d3Sopenharmony_ci /// 534fad3a1d3Sopenharmony_ci /// impl Parse for SingleUse { 535fad3a1d3Sopenharmony_ci /// fn parse(input: ParseStream) -> Result<Self> { 536fad3a1d3Sopenharmony_ci /// Ok(SingleUse { 537fad3a1d3Sopenharmony_ci /// use_token: input.parse()?, 538fad3a1d3Sopenharmony_ci /// path: input.call(Path::parse_mod_style)?, 539fad3a1d3Sopenharmony_ci /// }) 540fad3a1d3Sopenharmony_ci /// } 541fad3a1d3Sopenharmony_ci /// } 542fad3a1d3Sopenharmony_ci /// ``` 543fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(feature = "parsing")))] 544fad3a1d3Sopenharmony_ci pub fn parse_mod_style(input: ParseStream) -> Result<Self> { 545fad3a1d3Sopenharmony_ci Ok(Path { 546fad3a1d3Sopenharmony_ci leading_colon: input.parse()?, 547fad3a1d3Sopenharmony_ci segments: { 548fad3a1d3Sopenharmony_ci let mut segments = Punctuated::new(); 549fad3a1d3Sopenharmony_ci loop { 550fad3a1d3Sopenharmony_ci if !input.peek(Ident) 551fad3a1d3Sopenharmony_ci && !input.peek(Token![super]) 552fad3a1d3Sopenharmony_ci && !input.peek(Token![self]) 553fad3a1d3Sopenharmony_ci && !input.peek(Token![Self]) 554fad3a1d3Sopenharmony_ci && !input.peek(Token![crate]) 555fad3a1d3Sopenharmony_ci { 556fad3a1d3Sopenharmony_ci break; 557fad3a1d3Sopenharmony_ci } 558fad3a1d3Sopenharmony_ci let ident = Ident::parse_any(input)?; 559fad3a1d3Sopenharmony_ci segments.push_value(PathSegment::from(ident)); 560fad3a1d3Sopenharmony_ci if !input.peek(Token![::]) { 561fad3a1d3Sopenharmony_ci break; 562fad3a1d3Sopenharmony_ci } 563fad3a1d3Sopenharmony_ci let punct = input.parse()?; 564fad3a1d3Sopenharmony_ci segments.push_punct(punct); 565fad3a1d3Sopenharmony_ci } 566fad3a1d3Sopenharmony_ci if segments.is_empty() { 567fad3a1d3Sopenharmony_ci return Err(input.parse::<Ident>().unwrap_err()); 568fad3a1d3Sopenharmony_ci } else if segments.trailing_punct() { 569fad3a1d3Sopenharmony_ci return Err(input.error("expected path segment after `::`")); 570fad3a1d3Sopenharmony_ci } 571fad3a1d3Sopenharmony_ci segments 572fad3a1d3Sopenharmony_ci }, 573fad3a1d3Sopenharmony_ci }) 574fad3a1d3Sopenharmony_ci } 575fad3a1d3Sopenharmony_ci 576fad3a1d3Sopenharmony_ci pub(crate) fn parse_helper(input: ParseStream, expr_style: bool) -> Result<Self> { 577fad3a1d3Sopenharmony_ci let mut path = Path { 578fad3a1d3Sopenharmony_ci leading_colon: input.parse()?, 579fad3a1d3Sopenharmony_ci segments: { 580fad3a1d3Sopenharmony_ci let mut segments = Punctuated::new(); 581fad3a1d3Sopenharmony_ci let value = PathSegment::parse_helper(input, expr_style)?; 582fad3a1d3Sopenharmony_ci segments.push_value(value); 583fad3a1d3Sopenharmony_ci segments 584fad3a1d3Sopenharmony_ci }, 585fad3a1d3Sopenharmony_ci }; 586fad3a1d3Sopenharmony_ci Path::parse_rest(input, &mut path, expr_style)?; 587fad3a1d3Sopenharmony_ci Ok(path) 588fad3a1d3Sopenharmony_ci } 589fad3a1d3Sopenharmony_ci 590fad3a1d3Sopenharmony_ci pub(crate) fn parse_rest( 591fad3a1d3Sopenharmony_ci input: ParseStream, 592fad3a1d3Sopenharmony_ci path: &mut Self, 593fad3a1d3Sopenharmony_ci expr_style: bool, 594fad3a1d3Sopenharmony_ci ) -> Result<()> { 595fad3a1d3Sopenharmony_ci while input.peek(Token![::]) && !input.peek3(token::Paren) { 596fad3a1d3Sopenharmony_ci let punct: Token![::] = input.parse()?; 597fad3a1d3Sopenharmony_ci path.segments.push_punct(punct); 598fad3a1d3Sopenharmony_ci let value = PathSegment::parse_helper(input, expr_style)?; 599fad3a1d3Sopenharmony_ci path.segments.push_value(value); 600fad3a1d3Sopenharmony_ci } 601fad3a1d3Sopenharmony_ci Ok(()) 602fad3a1d3Sopenharmony_ci } 603fad3a1d3Sopenharmony_ci 604fad3a1d3Sopenharmony_ci pub(crate) fn is_mod_style(&self) -> bool { 605fad3a1d3Sopenharmony_ci self.segments 606fad3a1d3Sopenharmony_ci .iter() 607fad3a1d3Sopenharmony_ci .all(|segment| segment.arguments.is_none()) 608fad3a1d3Sopenharmony_ci } 609fad3a1d3Sopenharmony_ci } 610fad3a1d3Sopenharmony_ci 611fad3a1d3Sopenharmony_ci pub(crate) fn qpath(input: ParseStream, expr_style: bool) -> Result<(Option<QSelf>, Path)> { 612fad3a1d3Sopenharmony_ci if input.peek(Token![<]) { 613fad3a1d3Sopenharmony_ci let lt_token: Token![<] = input.parse()?; 614fad3a1d3Sopenharmony_ci let this: Type = input.parse()?; 615fad3a1d3Sopenharmony_ci let path = if input.peek(Token![as]) { 616fad3a1d3Sopenharmony_ci let as_token: Token![as] = input.parse()?; 617fad3a1d3Sopenharmony_ci let path: Path = input.parse()?; 618fad3a1d3Sopenharmony_ci Some((as_token, path)) 619fad3a1d3Sopenharmony_ci } else { 620fad3a1d3Sopenharmony_ci None 621fad3a1d3Sopenharmony_ci }; 622fad3a1d3Sopenharmony_ci let gt_token: Token![>] = input.parse()?; 623fad3a1d3Sopenharmony_ci let colon2_token: Token![::] = input.parse()?; 624fad3a1d3Sopenharmony_ci let mut rest = Punctuated::new(); 625fad3a1d3Sopenharmony_ci loop { 626fad3a1d3Sopenharmony_ci let path = PathSegment::parse_helper(input, expr_style)?; 627fad3a1d3Sopenharmony_ci rest.push_value(path); 628fad3a1d3Sopenharmony_ci if !input.peek(Token![::]) { 629fad3a1d3Sopenharmony_ci break; 630fad3a1d3Sopenharmony_ci } 631fad3a1d3Sopenharmony_ci let punct: Token![::] = input.parse()?; 632fad3a1d3Sopenharmony_ci rest.push_punct(punct); 633fad3a1d3Sopenharmony_ci } 634fad3a1d3Sopenharmony_ci let (position, as_token, path) = match path { 635fad3a1d3Sopenharmony_ci Some((as_token, mut path)) => { 636fad3a1d3Sopenharmony_ci let pos = path.segments.len(); 637fad3a1d3Sopenharmony_ci path.segments.push_punct(colon2_token); 638fad3a1d3Sopenharmony_ci path.segments.extend(rest.into_pairs()); 639fad3a1d3Sopenharmony_ci (pos, Some(as_token), path) 640fad3a1d3Sopenharmony_ci } 641fad3a1d3Sopenharmony_ci None => { 642fad3a1d3Sopenharmony_ci let path = Path { 643fad3a1d3Sopenharmony_ci leading_colon: Some(colon2_token), 644fad3a1d3Sopenharmony_ci segments: rest, 645fad3a1d3Sopenharmony_ci }; 646fad3a1d3Sopenharmony_ci (0, None, path) 647fad3a1d3Sopenharmony_ci } 648fad3a1d3Sopenharmony_ci }; 649fad3a1d3Sopenharmony_ci let qself = QSelf { 650fad3a1d3Sopenharmony_ci lt_token, 651fad3a1d3Sopenharmony_ci ty: Box::new(this), 652fad3a1d3Sopenharmony_ci position, 653fad3a1d3Sopenharmony_ci as_token, 654fad3a1d3Sopenharmony_ci gt_token, 655fad3a1d3Sopenharmony_ci }; 656fad3a1d3Sopenharmony_ci Ok((Some(qself), path)) 657fad3a1d3Sopenharmony_ci } else { 658fad3a1d3Sopenharmony_ci let path = Path::parse_helper(input, expr_style)?; 659fad3a1d3Sopenharmony_ci Ok((None, path)) 660fad3a1d3Sopenharmony_ci } 661fad3a1d3Sopenharmony_ci } 662fad3a1d3Sopenharmony_ci} 663fad3a1d3Sopenharmony_ci 664fad3a1d3Sopenharmony_ci#[cfg(feature = "printing")] 665fad3a1d3Sopenharmony_cipub(crate) mod printing { 666fad3a1d3Sopenharmony_ci use super::*; 667fad3a1d3Sopenharmony_ci use crate::print::TokensOrDefault; 668fad3a1d3Sopenharmony_ci #[cfg(feature = "parsing")] 669fad3a1d3Sopenharmony_ci use crate::spanned::Spanned; 670fad3a1d3Sopenharmony_ci #[cfg(feature = "parsing")] 671fad3a1d3Sopenharmony_ci use proc_macro2::Span; 672fad3a1d3Sopenharmony_ci use proc_macro2::TokenStream; 673fad3a1d3Sopenharmony_ci use quote::ToTokens; 674fad3a1d3Sopenharmony_ci use std::cmp; 675fad3a1d3Sopenharmony_ci 676fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 677fad3a1d3Sopenharmony_ci impl ToTokens for Path { 678fad3a1d3Sopenharmony_ci fn to_tokens(&self, tokens: &mut TokenStream) { 679fad3a1d3Sopenharmony_ci self.leading_colon.to_tokens(tokens); 680fad3a1d3Sopenharmony_ci self.segments.to_tokens(tokens); 681fad3a1d3Sopenharmony_ci } 682fad3a1d3Sopenharmony_ci } 683fad3a1d3Sopenharmony_ci 684fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 685fad3a1d3Sopenharmony_ci impl ToTokens for PathSegment { 686fad3a1d3Sopenharmony_ci fn to_tokens(&self, tokens: &mut TokenStream) { 687fad3a1d3Sopenharmony_ci self.ident.to_tokens(tokens); 688fad3a1d3Sopenharmony_ci self.arguments.to_tokens(tokens); 689fad3a1d3Sopenharmony_ci } 690fad3a1d3Sopenharmony_ci } 691fad3a1d3Sopenharmony_ci 692fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 693fad3a1d3Sopenharmony_ci impl ToTokens for PathArguments { 694fad3a1d3Sopenharmony_ci fn to_tokens(&self, tokens: &mut TokenStream) { 695fad3a1d3Sopenharmony_ci match self { 696fad3a1d3Sopenharmony_ci PathArguments::None => {} 697fad3a1d3Sopenharmony_ci PathArguments::AngleBracketed(arguments) => { 698fad3a1d3Sopenharmony_ci arguments.to_tokens(tokens); 699fad3a1d3Sopenharmony_ci } 700fad3a1d3Sopenharmony_ci PathArguments::Parenthesized(arguments) => { 701fad3a1d3Sopenharmony_ci arguments.to_tokens(tokens); 702fad3a1d3Sopenharmony_ci } 703fad3a1d3Sopenharmony_ci } 704fad3a1d3Sopenharmony_ci } 705fad3a1d3Sopenharmony_ci } 706fad3a1d3Sopenharmony_ci 707fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 708fad3a1d3Sopenharmony_ci impl ToTokens for GenericArgument { 709fad3a1d3Sopenharmony_ci #[allow(clippy::match_same_arms)] 710fad3a1d3Sopenharmony_ci fn to_tokens(&self, tokens: &mut TokenStream) { 711fad3a1d3Sopenharmony_ci match self { 712fad3a1d3Sopenharmony_ci GenericArgument::Lifetime(lt) => lt.to_tokens(tokens), 713fad3a1d3Sopenharmony_ci GenericArgument::Type(ty) => ty.to_tokens(tokens), 714fad3a1d3Sopenharmony_ci GenericArgument::Const(expr) => match expr { 715fad3a1d3Sopenharmony_ci Expr::Lit(expr) => expr.to_tokens(tokens), 716fad3a1d3Sopenharmony_ci 717fad3a1d3Sopenharmony_ci Expr::Path(expr) 718fad3a1d3Sopenharmony_ci if expr.attrs.is_empty() 719fad3a1d3Sopenharmony_ci && expr.qself.is_none() 720fad3a1d3Sopenharmony_ci && expr.path.get_ident().is_some() => 721fad3a1d3Sopenharmony_ci { 722fad3a1d3Sopenharmony_ci expr.to_tokens(tokens); 723fad3a1d3Sopenharmony_ci } 724fad3a1d3Sopenharmony_ci 725fad3a1d3Sopenharmony_ci #[cfg(feature = "full")] 726fad3a1d3Sopenharmony_ci Expr::Block(expr) => expr.to_tokens(tokens), 727fad3a1d3Sopenharmony_ci 728fad3a1d3Sopenharmony_ci #[cfg(not(feature = "full"))] 729fad3a1d3Sopenharmony_ci Expr::Verbatim(expr) => expr.to_tokens(tokens), 730fad3a1d3Sopenharmony_ci 731fad3a1d3Sopenharmony_ci // ERROR CORRECTION: Add braces to make sure that the 732fad3a1d3Sopenharmony_ci // generated code is valid. 733fad3a1d3Sopenharmony_ci _ => token::Brace::default().surround(tokens, |tokens| { 734fad3a1d3Sopenharmony_ci expr.to_tokens(tokens); 735fad3a1d3Sopenharmony_ci }), 736fad3a1d3Sopenharmony_ci }, 737fad3a1d3Sopenharmony_ci GenericArgument::AssocType(assoc) => assoc.to_tokens(tokens), 738fad3a1d3Sopenharmony_ci GenericArgument::AssocConst(assoc) => assoc.to_tokens(tokens), 739fad3a1d3Sopenharmony_ci GenericArgument::Constraint(constraint) => constraint.to_tokens(tokens), 740fad3a1d3Sopenharmony_ci } 741fad3a1d3Sopenharmony_ci } 742fad3a1d3Sopenharmony_ci } 743fad3a1d3Sopenharmony_ci 744fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 745fad3a1d3Sopenharmony_ci impl ToTokens for AngleBracketedGenericArguments { 746fad3a1d3Sopenharmony_ci fn to_tokens(&self, tokens: &mut TokenStream) { 747fad3a1d3Sopenharmony_ci self.colon2_token.to_tokens(tokens); 748fad3a1d3Sopenharmony_ci self.lt_token.to_tokens(tokens); 749fad3a1d3Sopenharmony_ci 750fad3a1d3Sopenharmony_ci // Print lifetimes before types/consts/bindings, regardless of their 751fad3a1d3Sopenharmony_ci // order in self.args. 752fad3a1d3Sopenharmony_ci let mut trailing_or_empty = true; 753fad3a1d3Sopenharmony_ci for param in self.args.pairs() { 754fad3a1d3Sopenharmony_ci match param.value() { 755fad3a1d3Sopenharmony_ci GenericArgument::Lifetime(_) => { 756fad3a1d3Sopenharmony_ci param.to_tokens(tokens); 757fad3a1d3Sopenharmony_ci trailing_or_empty = param.punct().is_some(); 758fad3a1d3Sopenharmony_ci } 759fad3a1d3Sopenharmony_ci GenericArgument::Type(_) 760fad3a1d3Sopenharmony_ci | GenericArgument::Const(_) 761fad3a1d3Sopenharmony_ci | GenericArgument::AssocType(_) 762fad3a1d3Sopenharmony_ci | GenericArgument::AssocConst(_) 763fad3a1d3Sopenharmony_ci | GenericArgument::Constraint(_) => {} 764fad3a1d3Sopenharmony_ci } 765fad3a1d3Sopenharmony_ci } 766fad3a1d3Sopenharmony_ci for param in self.args.pairs() { 767fad3a1d3Sopenharmony_ci match param.value() { 768fad3a1d3Sopenharmony_ci GenericArgument::Type(_) 769fad3a1d3Sopenharmony_ci | GenericArgument::Const(_) 770fad3a1d3Sopenharmony_ci | GenericArgument::AssocType(_) 771fad3a1d3Sopenharmony_ci | GenericArgument::AssocConst(_) 772fad3a1d3Sopenharmony_ci | GenericArgument::Constraint(_) => { 773fad3a1d3Sopenharmony_ci if !trailing_or_empty { 774fad3a1d3Sopenharmony_ci <Token![,]>::default().to_tokens(tokens); 775fad3a1d3Sopenharmony_ci } 776fad3a1d3Sopenharmony_ci param.to_tokens(tokens); 777fad3a1d3Sopenharmony_ci trailing_or_empty = param.punct().is_some(); 778fad3a1d3Sopenharmony_ci } 779fad3a1d3Sopenharmony_ci GenericArgument::Lifetime(_) => {} 780fad3a1d3Sopenharmony_ci } 781fad3a1d3Sopenharmony_ci } 782fad3a1d3Sopenharmony_ci 783fad3a1d3Sopenharmony_ci self.gt_token.to_tokens(tokens); 784fad3a1d3Sopenharmony_ci } 785fad3a1d3Sopenharmony_ci } 786fad3a1d3Sopenharmony_ci 787fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 788fad3a1d3Sopenharmony_ci impl ToTokens for AssocType { 789fad3a1d3Sopenharmony_ci fn to_tokens(&self, tokens: &mut TokenStream) { 790fad3a1d3Sopenharmony_ci self.ident.to_tokens(tokens); 791fad3a1d3Sopenharmony_ci self.generics.to_tokens(tokens); 792fad3a1d3Sopenharmony_ci self.eq_token.to_tokens(tokens); 793fad3a1d3Sopenharmony_ci self.ty.to_tokens(tokens); 794fad3a1d3Sopenharmony_ci } 795fad3a1d3Sopenharmony_ci } 796fad3a1d3Sopenharmony_ci 797fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 798fad3a1d3Sopenharmony_ci impl ToTokens for AssocConst { 799fad3a1d3Sopenharmony_ci fn to_tokens(&self, tokens: &mut TokenStream) { 800fad3a1d3Sopenharmony_ci self.ident.to_tokens(tokens); 801fad3a1d3Sopenharmony_ci self.generics.to_tokens(tokens); 802fad3a1d3Sopenharmony_ci self.eq_token.to_tokens(tokens); 803fad3a1d3Sopenharmony_ci self.value.to_tokens(tokens); 804fad3a1d3Sopenharmony_ci } 805fad3a1d3Sopenharmony_ci } 806fad3a1d3Sopenharmony_ci 807fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 808fad3a1d3Sopenharmony_ci impl ToTokens for Constraint { 809fad3a1d3Sopenharmony_ci fn to_tokens(&self, tokens: &mut TokenStream) { 810fad3a1d3Sopenharmony_ci self.ident.to_tokens(tokens); 811fad3a1d3Sopenharmony_ci self.generics.to_tokens(tokens); 812fad3a1d3Sopenharmony_ci self.colon_token.to_tokens(tokens); 813fad3a1d3Sopenharmony_ci self.bounds.to_tokens(tokens); 814fad3a1d3Sopenharmony_ci } 815fad3a1d3Sopenharmony_ci } 816fad3a1d3Sopenharmony_ci 817fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(feature = "printing")))] 818fad3a1d3Sopenharmony_ci impl ToTokens for ParenthesizedGenericArguments { 819fad3a1d3Sopenharmony_ci fn to_tokens(&self, tokens: &mut TokenStream) { 820fad3a1d3Sopenharmony_ci self.paren_token.surround(tokens, |tokens| { 821fad3a1d3Sopenharmony_ci self.inputs.to_tokens(tokens); 822fad3a1d3Sopenharmony_ci }); 823fad3a1d3Sopenharmony_ci self.output.to_tokens(tokens); 824fad3a1d3Sopenharmony_ci } 825fad3a1d3Sopenharmony_ci } 826fad3a1d3Sopenharmony_ci 827fad3a1d3Sopenharmony_ci pub(crate) fn print_path(tokens: &mut TokenStream, qself: &Option<QSelf>, path: &Path) { 828fad3a1d3Sopenharmony_ci let qself = match qself { 829fad3a1d3Sopenharmony_ci Some(qself) => qself, 830fad3a1d3Sopenharmony_ci None => { 831fad3a1d3Sopenharmony_ci path.to_tokens(tokens); 832fad3a1d3Sopenharmony_ci return; 833fad3a1d3Sopenharmony_ci } 834fad3a1d3Sopenharmony_ci }; 835fad3a1d3Sopenharmony_ci qself.lt_token.to_tokens(tokens); 836fad3a1d3Sopenharmony_ci qself.ty.to_tokens(tokens); 837fad3a1d3Sopenharmony_ci 838fad3a1d3Sopenharmony_ci let pos = cmp::min(qself.position, path.segments.len()); 839fad3a1d3Sopenharmony_ci let mut segments = path.segments.pairs(); 840fad3a1d3Sopenharmony_ci if pos > 0 { 841fad3a1d3Sopenharmony_ci TokensOrDefault(&qself.as_token).to_tokens(tokens); 842fad3a1d3Sopenharmony_ci path.leading_colon.to_tokens(tokens); 843fad3a1d3Sopenharmony_ci for (i, segment) in segments.by_ref().take(pos).enumerate() { 844fad3a1d3Sopenharmony_ci if i + 1 == pos { 845fad3a1d3Sopenharmony_ci segment.value().to_tokens(tokens); 846fad3a1d3Sopenharmony_ci qself.gt_token.to_tokens(tokens); 847fad3a1d3Sopenharmony_ci segment.punct().to_tokens(tokens); 848fad3a1d3Sopenharmony_ci } else { 849fad3a1d3Sopenharmony_ci segment.to_tokens(tokens); 850fad3a1d3Sopenharmony_ci } 851fad3a1d3Sopenharmony_ci } 852fad3a1d3Sopenharmony_ci } else { 853fad3a1d3Sopenharmony_ci qself.gt_token.to_tokens(tokens); 854fad3a1d3Sopenharmony_ci path.leading_colon.to_tokens(tokens); 855fad3a1d3Sopenharmony_ci } 856fad3a1d3Sopenharmony_ci for segment in segments { 857fad3a1d3Sopenharmony_ci segment.to_tokens(tokens); 858fad3a1d3Sopenharmony_ci } 859fad3a1d3Sopenharmony_ci } 860fad3a1d3Sopenharmony_ci 861fad3a1d3Sopenharmony_ci #[cfg(feature = "parsing")] 862fad3a1d3Sopenharmony_ci #[cfg_attr(doc_cfg, doc(cfg(all(feature = "parsing", feature = "printing"))))] 863fad3a1d3Sopenharmony_ci impl Spanned for QSelf { 864fad3a1d3Sopenharmony_ci fn span(&self) -> Span { 865fad3a1d3Sopenharmony_ci struct QSelfDelimiters<'a>(&'a QSelf); 866fad3a1d3Sopenharmony_ci 867fad3a1d3Sopenharmony_ci impl<'a> ToTokens for QSelfDelimiters<'a> { 868fad3a1d3Sopenharmony_ci fn to_tokens(&self, tokens: &mut TokenStream) { 869fad3a1d3Sopenharmony_ci self.0.lt_token.to_tokens(tokens); 870fad3a1d3Sopenharmony_ci self.0.gt_token.to_tokens(tokens); 871fad3a1d3Sopenharmony_ci } 872fad3a1d3Sopenharmony_ci } 873fad3a1d3Sopenharmony_ci 874fad3a1d3Sopenharmony_ci QSelfDelimiters(self).span() 875fad3a1d3Sopenharmony_ci } 876fad3a1d3Sopenharmony_ci } 877fad3a1d3Sopenharmony_ci} 878