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