| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479 |
- // SPDX-License-Identifier: Apache-2.0 OR MIT
- use crate::attr::Attribute;
- use crate::expr::Expr;
- use crate::ident::Ident;
- use crate::lifetime::Lifetime;
- use crate::path::Path;
- use crate::punctuated::{Iter, IterMut, Punctuated};
- use crate::token;
- use crate::ty::Type;
- use proc_macro2::TokenStream;
- #[cfg(all(feature = "printing", feature = "extra-traits"))]
- use std::fmt::{self, Debug};
- #[cfg(all(feature = "printing", feature = "extra-traits"))]
- use std::hash::{Hash, Hasher};
- ast_struct! {
- /// Lifetimes and type parameters attached to a declaration of a function,
- /// enum, trait, etc.
- ///
- /// This struct represents two distinct optional syntactic elements,
- /// [generic parameters] and [where clause]. In some locations of the
- /// grammar, there may be other tokens in between these two things.
- ///
- /// [generic parameters]: https://doc.rust-lang.org/stable/reference/items/generics.html#generic-parameters
- /// [where clause]: https://doc.rust-lang.org/stable/reference/items/generics.html#where-clauses
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct Generics {
- pub lt_token: Option<Token![<]>,
- pub params: Punctuated<GenericParam, Token![,]>,
- pub gt_token: Option<Token![>]>,
- pub where_clause: Option<WhereClause>,
- }
- }
- ast_enum_of_structs! {
- /// A generic type parameter, lifetime, or const generic: `T: Into<String>`,
- /// `'a: 'b`, `const LEN: usize`.
- ///
- /// # Syntax tree enum
- ///
- /// This type is a [syntax tree enum].
- ///
- /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub enum GenericParam {
- /// A lifetime parameter: `'a: 'b + 'c + 'd`.
- Lifetime(LifetimeParam),
- /// A generic type parameter: `T: Into<String>`.
- Type(TypeParam),
- /// A const generic parameter: `const LENGTH: usize`.
- Const(ConstParam),
- }
- }
- ast_struct! {
- /// A lifetime definition: `'a: 'b + 'c + 'd`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct LifetimeParam {
- pub attrs: Vec<Attribute>,
- pub lifetime: Lifetime,
- pub colon_token: Option<Token![:]>,
- pub bounds: Punctuated<Lifetime, Token![+]>,
- }
- }
- ast_struct! {
- /// A generic type parameter: `T: Into<String>`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct TypeParam {
- pub attrs: Vec<Attribute>,
- pub ident: Ident,
- pub colon_token: Option<Token![:]>,
- pub bounds: Punctuated<TypeParamBound, Token![+]>,
- pub eq_token: Option<Token![=]>,
- pub default: Option<Type>,
- }
- }
- ast_struct! {
- /// A const generic parameter: `const LENGTH: usize`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct ConstParam {
- pub attrs: Vec<Attribute>,
- pub const_token: Token![const],
- pub ident: Ident,
- pub colon_token: Token![:],
- pub ty: Type,
- pub eq_token: Option<Token![=]>,
- pub default: Option<Expr>,
- }
- }
- impl Default for Generics {
- fn default() -> Self {
- Generics {
- lt_token: None,
- params: Punctuated::new(),
- gt_token: None,
- where_clause: None,
- }
- }
- }
- impl Generics {
- return_impl_trait! {
- /// Iterator over the lifetime parameters in `self.params`.
- pub fn lifetimes(&self) -> impl Iterator<Item = &LifetimeParam> [Lifetimes] {
- Lifetimes(self.params.iter())
- }
- }
- return_impl_trait! {
- /// Iterator over the lifetime parameters in `self.params`.
- pub fn lifetimes_mut(&mut self) -> impl Iterator<Item = &mut LifetimeParam> [LifetimesMut] {
- LifetimesMut(self.params.iter_mut())
- }
- }
- return_impl_trait! {
- /// Iterator over the type parameters in `self.params`.
- pub fn type_params(&self) -> impl Iterator<Item = &TypeParam> [TypeParams] {
- TypeParams(self.params.iter())
- }
- }
- return_impl_trait! {
- /// Iterator over the type parameters in `self.params`.
- pub fn type_params_mut(&mut self) -> impl Iterator<Item = &mut TypeParam> [TypeParamsMut] {
- TypeParamsMut(self.params.iter_mut())
- }
- }
- return_impl_trait! {
- /// Iterator over the constant parameters in `self.params`.
- pub fn const_params(&self) -> impl Iterator<Item = &ConstParam> [ConstParams] {
- ConstParams(self.params.iter())
- }
- }
- return_impl_trait! {
- /// Iterator over the constant parameters in `self.params`.
- pub fn const_params_mut(&mut self) -> impl Iterator<Item = &mut ConstParam> [ConstParamsMut] {
- ConstParamsMut(self.params.iter_mut())
- }
- }
- /// Initializes an empty `where`-clause if there is not one present already.
- pub fn make_where_clause(&mut self) -> &mut WhereClause {
- self.where_clause.get_or_insert_with(|| WhereClause {
- where_token: <Token![where]>::default(),
- predicates: Punctuated::new(),
- })
- }
- /// Split a type's generics into the pieces required for impl'ing a trait
- /// for that type.
- ///
- /// ```
- /// # use proc_macro2::{Span, Ident};
- /// # use quote::quote;
- /// #
- /// # let generics: syn::Generics = Default::default();
- /// # let name = Ident::new("MyType", Span::call_site());
- /// #
- /// let (impl_generics, ty_generics, where_clause) = generics.split_for_impl();
- /// quote! {
- /// impl #impl_generics MyTrait for #name #ty_generics #where_clause {
- /// // ...
- /// }
- /// }
- /// # ;
- /// ```
- #[cfg(feature = "printing")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- pub fn split_for_impl(&self) -> (ImplGenerics, TypeGenerics, Option<&WhereClause>) {
- (
- ImplGenerics(self),
- TypeGenerics(self),
- self.where_clause.as_ref(),
- )
- }
- }
- pub struct Lifetimes<'a>(Iter<'a, GenericParam>);
- impl<'a> Iterator for Lifetimes<'a> {
- type Item = &'a LifetimeParam;
- fn next(&mut self) -> Option<Self::Item> {
- if let GenericParam::Lifetime(lifetime) = self.0.next()? {
- Some(lifetime)
- } else {
- self.next()
- }
- }
- }
- pub struct LifetimesMut<'a>(IterMut<'a, GenericParam>);
- impl<'a> Iterator for LifetimesMut<'a> {
- type Item = &'a mut LifetimeParam;
- fn next(&mut self) -> Option<Self::Item> {
- if let GenericParam::Lifetime(lifetime) = self.0.next()? {
- Some(lifetime)
- } else {
- self.next()
- }
- }
- }
- pub struct TypeParams<'a>(Iter<'a, GenericParam>);
- impl<'a> Iterator for TypeParams<'a> {
- type Item = &'a TypeParam;
- fn next(&mut self) -> Option<Self::Item> {
- if let GenericParam::Type(type_param) = self.0.next()? {
- Some(type_param)
- } else {
- self.next()
- }
- }
- }
- pub struct TypeParamsMut<'a>(IterMut<'a, GenericParam>);
- impl<'a> Iterator for TypeParamsMut<'a> {
- type Item = &'a mut TypeParam;
- fn next(&mut self) -> Option<Self::Item> {
- if let GenericParam::Type(type_param) = self.0.next()? {
- Some(type_param)
- } else {
- self.next()
- }
- }
- }
- pub struct ConstParams<'a>(Iter<'a, GenericParam>);
- impl<'a> Iterator for ConstParams<'a> {
- type Item = &'a ConstParam;
- fn next(&mut self) -> Option<Self::Item> {
- if let GenericParam::Const(const_param) = self.0.next()? {
- Some(const_param)
- } else {
- self.next()
- }
- }
- }
- pub struct ConstParamsMut<'a>(IterMut<'a, GenericParam>);
- impl<'a> Iterator for ConstParamsMut<'a> {
- type Item = &'a mut ConstParam;
- fn next(&mut self) -> Option<Self::Item> {
- if let GenericParam::Const(const_param) = self.0.next()? {
- Some(const_param)
- } else {
- self.next()
- }
- }
- }
- /// Returned by `Generics::split_for_impl`.
- #[cfg(feature = "printing")]
- #[cfg_attr(
- docsrs,
- doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing")))
- )]
- pub struct ImplGenerics<'a>(&'a Generics);
- /// Returned by `Generics::split_for_impl`.
- #[cfg(feature = "printing")]
- #[cfg_attr(
- docsrs,
- doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing")))
- )]
- pub struct TypeGenerics<'a>(&'a Generics);
- /// Returned by `TypeGenerics::as_turbofish`.
- #[cfg(feature = "printing")]
- #[cfg_attr(
- docsrs,
- doc(cfg(all(any(feature = "full", feature = "derive"), feature = "printing")))
- )]
- pub struct Turbofish<'a>(&'a Generics);
- #[cfg(feature = "printing")]
- macro_rules! generics_wrapper_impls {
- ($ty:ident) => {
- #[cfg(feature = "clone-impls")]
- #[cfg_attr(docsrs, doc(cfg(feature = "clone-impls")))]
- impl<'a> Clone for $ty<'a> {
- fn clone(&self) -> Self {
- $ty(self.0)
- }
- }
- #[cfg(feature = "extra-traits")]
- #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
- impl<'a> Debug for $ty<'a> {
- fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
- formatter
- .debug_tuple(stringify!($ty))
- .field(self.0)
- .finish()
- }
- }
- #[cfg(feature = "extra-traits")]
- #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
- impl<'a> Eq for $ty<'a> {}
- #[cfg(feature = "extra-traits")]
- #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
- impl<'a> PartialEq for $ty<'a> {
- fn eq(&self, other: &Self) -> bool {
- self.0 == other.0
- }
- }
- #[cfg(feature = "extra-traits")]
- #[cfg_attr(docsrs, doc(cfg(feature = "extra-traits")))]
- impl<'a> Hash for $ty<'a> {
- fn hash<H: Hasher>(&self, state: &mut H) {
- self.0.hash(state);
- }
- }
- };
- }
- #[cfg(feature = "printing")]
- generics_wrapper_impls!(ImplGenerics);
- #[cfg(feature = "printing")]
- generics_wrapper_impls!(TypeGenerics);
- #[cfg(feature = "printing")]
- generics_wrapper_impls!(Turbofish);
- #[cfg(feature = "printing")]
- impl<'a> TypeGenerics<'a> {
- /// Turn a type's generics like `<X, Y>` into a turbofish like `::<X, Y>`.
- pub fn as_turbofish(&self) -> Turbofish<'a> {
- Turbofish(self.0)
- }
- }
- ast_struct! {
- /// A set of bound lifetimes: `for<'a, 'b, 'c>`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct BoundLifetimes {
- pub for_token: Token![for],
- pub lt_token: Token![<],
- pub lifetimes: Punctuated<GenericParam, Token![,]>,
- pub gt_token: Token![>],
- }
- }
- impl Default for BoundLifetimes {
- fn default() -> Self {
- BoundLifetimes {
- for_token: Default::default(),
- lt_token: Default::default(),
- lifetimes: Punctuated::new(),
- gt_token: Default::default(),
- }
- }
- }
- impl LifetimeParam {
- pub fn new(lifetime: Lifetime) -> Self {
- LifetimeParam {
- attrs: Vec::new(),
- lifetime,
- colon_token: None,
- bounds: Punctuated::new(),
- }
- }
- }
- impl From<Ident> for TypeParam {
- fn from(ident: Ident) -> Self {
- TypeParam {
- attrs: vec![],
- ident,
- colon_token: None,
- bounds: Punctuated::new(),
- eq_token: None,
- default: None,
- }
- }
- }
- ast_enum_of_structs! {
- /// A trait or lifetime used as a bound on a type parameter.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- #[non_exhaustive]
- pub enum TypeParamBound {
- Trait(TraitBound),
- Lifetime(Lifetime),
- PreciseCapture(PreciseCapture),
- Verbatim(TokenStream),
- }
- }
- ast_struct! {
- /// A trait used as a bound on a type parameter.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct TraitBound {
- pub paren_token: Option<token::Paren>,
- pub modifier: TraitBoundModifier,
- /// The `for<'a>` in `for<'a> Foo<&'a T>`
- pub lifetimes: Option<BoundLifetimes>,
- /// The `Foo<&'a T>` in `for<'a> Foo<&'a T>`
- pub path: Path,
- }
- }
- ast_enum! {
- /// A modifier on a trait bound, currently only used for the `?` in
- /// `?Sized`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub enum TraitBoundModifier {
- None,
- Maybe(Token![?]),
- }
- }
- ast_struct! {
- /// Precise capturing bound: the 'use<…>' in `impl Trait +
- /// use<'a, T>`.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- pub struct PreciseCapture #full {
- pub use_token: Token![use],
- pub lt_token: Token![<],
- pub params: Punctuated<CapturedParam, Token![,]>,
- pub gt_token: Token![>],
- }
- }
- #[cfg(feature = "full")]
- ast_enum! {
- /// Single parameter in a precise capturing bound.
- #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
- #[non_exhaustive]
- pub enum CapturedParam {
- /// A lifetime parameter in precise capturing bound: `fn f<'a>() -> impl
- /// Trait + use<'a>`.
- Lifetime(Lifetime),
- /// A type parameter or const generic parameter in precise capturing
- /// bound: `fn f<T>() -> impl Trait + use<T>` or `fn f<const K: T>() ->
- /// impl Trait + use<K>`.
- Ident(Ident),
- }
- }
- ast_struct! {
- /// A `where` clause in a definition: `where T: Deserialize<'de>, D:
- /// 'static`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct WhereClause {
- pub where_token: Token![where],
- pub predicates: Punctuated<WherePredicate, Token![,]>,
- }
- }
- ast_enum_of_structs! {
- /// A single predicate in a `where` clause: `T: Deserialize<'de>`.
- ///
- /// # Syntax tree enum
- ///
- /// This type is a [syntax tree enum].
- ///
- /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- #[non_exhaustive]
- pub enum WherePredicate {
- /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`.
- Lifetime(PredicateLifetime),
- /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`.
- Type(PredicateType),
- }
- }
- ast_struct! {
- /// A lifetime predicate in a `where` clause: `'a: 'b + 'c`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct PredicateLifetime {
- pub lifetime: Lifetime,
- pub colon_token: Token![:],
- pub bounds: Punctuated<Lifetime, Token![+]>,
- }
- }
- ast_struct! {
- /// A type predicate in a `where` clause: `for<'c> Foo<'c>: Trait<'c>`.
- #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))]
- pub struct PredicateType {
- /// Any lifetimes from a `for` binding
- pub lifetimes: Option<BoundLifetimes>,
- /// The type being bounded
- pub bounded_ty: Type,
- pub colon_token: Token![:],
- /// Trait and lifetime bounds (`Clone+Send+'static`)
- pub bounds: Punctuated<TypeParamBound, Token![+]>,
- }
- }
- #[cfg(feature = "parsing")]
- pub(crate) mod parsing {
- use crate::attr::Attribute;
- #[cfg(feature = "full")]
- use crate::error;
- use crate::error::{Error, Result};
- use crate::ext::IdentExt as _;
- use crate::generics::{
- BoundLifetimes, ConstParam, GenericParam, Generics, LifetimeParam, PredicateLifetime,
- PredicateType, TraitBound, TraitBoundModifier, TypeParam, TypeParamBound, WhereClause,
- WherePredicate,
- };
- #[cfg(feature = "full")]
- use crate::generics::{CapturedParam, PreciseCapture};
- use crate::ident::Ident;
- use crate::lifetime::Lifetime;
- use crate::parse::{Parse, ParseStream};
- use crate::path::{self, ParenthesizedGenericArguments, Path, PathArguments};
- use crate::punctuated::Punctuated;
- use crate::token;
- use crate::ty::Type;
- use crate::verbatim;
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for Generics {
- fn parse(input: ParseStream) -> Result<Self> {
- if !input.peek(Token![<]) {
- return Ok(Generics::default());
- }
- let lt_token: Token![<] = input.parse()?;
- let mut params = Punctuated::new();
- loop {
- if input.peek(Token![>]) {
- break;
- }
- let attrs = input.call(Attribute::parse_outer)?;
- let lookahead = input.lookahead1();
- if lookahead.peek(Lifetime) {
- params.push_value(GenericParam::Lifetime(LifetimeParam {
- attrs,
- ..input.parse()?
- }));
- } else if lookahead.peek(Ident) {
- params.push_value(GenericParam::Type(TypeParam {
- attrs,
- ..input.parse()?
- }));
- } else if lookahead.peek(Token![const]) {
- params.push_value(GenericParam::Const(ConstParam {
- attrs,
- ..input.parse()?
- }));
- } else if input.peek(Token![_]) {
- params.push_value(GenericParam::Type(TypeParam {
- attrs,
- ident: input.call(Ident::parse_any)?,
- colon_token: None,
- bounds: Punctuated::new(),
- eq_token: None,
- default: None,
- }));
- } else {
- return Err(lookahead.error());
- }
- if input.peek(Token![>]) {
- break;
- }
- let punct = input.parse()?;
- params.push_punct(punct);
- }
- let gt_token: Token![>] = input.parse()?;
- Ok(Generics {
- lt_token: Some(lt_token),
- params,
- gt_token: Some(gt_token),
- where_clause: None,
- })
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for GenericParam {
- fn parse(input: ParseStream) -> Result<Self> {
- let attrs = input.call(Attribute::parse_outer)?;
- let lookahead = input.lookahead1();
- if lookahead.peek(Ident) {
- Ok(GenericParam::Type(TypeParam {
- attrs,
- ..input.parse()?
- }))
- } else if lookahead.peek(Lifetime) {
- Ok(GenericParam::Lifetime(LifetimeParam {
- attrs,
- ..input.parse()?
- }))
- } else if lookahead.peek(Token![const]) {
- Ok(GenericParam::Const(ConstParam {
- attrs,
- ..input.parse()?
- }))
- } else {
- Err(lookahead.error())
- }
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for LifetimeParam {
- fn parse(input: ParseStream) -> Result<Self> {
- let has_colon;
- Ok(LifetimeParam {
- attrs: input.call(Attribute::parse_outer)?,
- lifetime: input.parse()?,
- colon_token: {
- if input.peek(Token![:]) {
- has_colon = true;
- Some(input.parse()?)
- } else {
- has_colon = false;
- None
- }
- },
- bounds: {
- let mut bounds = Punctuated::new();
- if has_colon {
- loop {
- if input.peek(Token![,]) || input.peek(Token![>]) {
- break;
- }
- let value = input.parse()?;
- bounds.push_value(value);
- if !input.peek(Token![+]) {
- break;
- }
- let punct = input.parse()?;
- bounds.push_punct(punct);
- }
- }
- bounds
- },
- })
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for BoundLifetimes {
- fn parse(input: ParseStream) -> Result<Self> {
- Ok(BoundLifetimes {
- for_token: input.parse()?,
- lt_token: input.parse()?,
- lifetimes: {
- let mut lifetimes = Punctuated::new();
- while !input.peek(Token![>]) {
- lifetimes.push_value(input.parse()?);
- if input.peek(Token![>]) {
- break;
- }
- lifetimes.push_punct(input.parse()?);
- }
- lifetimes
- },
- gt_token: input.parse()?,
- })
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for Option<BoundLifetimes> {
- fn parse(input: ParseStream) -> Result<Self> {
- if input.peek(Token![for]) {
- input.parse().map(Some)
- } else {
- Ok(None)
- }
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for TypeParam {
- fn parse(input: ParseStream) -> Result<Self> {
- let attrs = input.call(Attribute::parse_outer)?;
- let ident: Ident = input.parse()?;
- let colon_token: Option<Token![:]> = input.parse()?;
- let mut bounds = Punctuated::new();
- if colon_token.is_some() {
- loop {
- if input.peek(Token![,]) || input.peek(Token![>]) || input.peek(Token![=]) {
- break;
- }
- bounds.push_value({
- let allow_precise_capture = false;
- let allow_const = true;
- TypeParamBound::parse_single(input, allow_precise_capture, allow_const)?
- });
- if !input.peek(Token![+]) {
- break;
- }
- let punct: Token![+] = input.parse()?;
- bounds.push_punct(punct);
- }
- }
- let eq_token: Option<Token![=]> = input.parse()?;
- let default = if eq_token.is_some() {
- Some(input.parse::<Type>()?)
- } else {
- None
- };
- Ok(TypeParam {
- attrs,
- ident,
- colon_token,
- bounds,
- eq_token,
- default,
- })
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for TypeParamBound {
- fn parse(input: ParseStream) -> Result<Self> {
- let allow_precise_capture = true;
- let allow_const = true;
- Self::parse_single(input, allow_precise_capture, allow_const)
- }
- }
- impl TypeParamBound {
- pub(crate) fn parse_single(
- input: ParseStream,
- #[cfg_attr(not(feature = "full"), allow(unused_variables))] allow_precise_capture: bool,
- allow_const: bool,
- ) -> Result<Self> {
- if input.peek(Lifetime) {
- return input.parse().map(TypeParamBound::Lifetime);
- }
- #[cfg(feature = "full")]
- {
- if input.peek(Token![use]) {
- let precise_capture: PreciseCapture = input.parse()?;
- return if allow_precise_capture {
- Ok(TypeParamBound::PreciseCapture(precise_capture))
- } else {
- let msg = "`use<...>` precise capturing syntax is not allowed here";
- Err(error::new2(
- precise_capture.use_token.span,
- precise_capture.gt_token.span,
- msg,
- ))
- };
- }
- }
- let begin = input.fork();
- let content;
- let (paren_token, content) = if input.peek(token::Paren) {
- (Some(parenthesized!(content in input)), &content)
- } else {
- (None, input)
- };
- if let Some(mut bound) = TraitBound::do_parse(content, allow_const)? {
- bound.paren_token = paren_token;
- Ok(TypeParamBound::Trait(bound))
- } else {
- Ok(TypeParamBound::Verbatim(verbatim::between(&begin, input)))
- }
- }
- pub(crate) fn parse_multiple(
- input: ParseStream,
- allow_plus: bool,
- allow_precise_capture: bool,
- allow_const: bool,
- ) -> Result<Punctuated<Self, Token![+]>> {
- let mut bounds = Punctuated::new();
- loop {
- let bound = Self::parse_single(input, allow_precise_capture, allow_const)?;
- bounds.push_value(bound);
- if !(allow_plus && input.peek(Token![+])) {
- break;
- }
- bounds.push_punct(input.parse()?);
- if !(input.peek(Ident::peek_any)
- || input.peek(Token![::])
- || input.peek(Token![?])
- || input.peek(Lifetime)
- || input.peek(token::Paren)
- || (allow_const && (input.peek(token::Bracket) || input.peek(Token![const]))))
- {
- break;
- }
- }
- Ok(bounds)
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for TraitBound {
- fn parse(input: ParseStream) -> Result<Self> {
- let allow_const = false;
- Self::do_parse(input, allow_const).map(Option::unwrap)
- }
- }
- impl TraitBound {
- fn do_parse(input: ParseStream, allow_const: bool) -> Result<Option<Self>> {
- let mut lifetimes: Option<BoundLifetimes> = input.parse()?;
- let is_conditionally_const = cfg!(feature = "full") && input.peek(token::Bracket);
- let is_unconditionally_const = cfg!(feature = "full") && input.peek(Token![const]);
- if is_conditionally_const {
- let conditionally_const;
- let bracket_token = bracketed!(conditionally_const in input);
- conditionally_const.parse::<Token![const]>()?;
- if !allow_const {
- let msg = "`[const]` is not allowed here";
- return Err(Error::new(bracket_token.span.join(), msg));
- }
- } else if is_unconditionally_const {
- let const_token: Token![const] = input.parse()?;
- if !allow_const {
- let msg = "`const` is not allowed here";
- return Err(Error::new(const_token.span, msg));
- }
- }
- let modifier: TraitBoundModifier = input.parse()?;
- if lifetimes.is_none() && matches!(modifier, TraitBoundModifier::Maybe(_)) {
- lifetimes = input.parse()?;
- }
- let mut path: Path = input.parse()?;
- if path.segments.last().unwrap().arguments.is_empty()
- && (input.peek(token::Paren) || input.peek(Token![::]) && input.peek3(token::Paren))
- {
- input.parse::<Option<Token![::]>>()?;
- let args: ParenthesizedGenericArguments = input.parse()?;
- let parenthesized = PathArguments::Parenthesized(args);
- path.segments.last_mut().unwrap().arguments = parenthesized;
- }
- if lifetimes.is_some() {
- match modifier {
- TraitBoundModifier::None => {}
- TraitBoundModifier::Maybe(maybe) => {
- let msg = "`for<...>` binder not allowed with `?` trait polarity modifier";
- return Err(Error::new(maybe.span, msg));
- }
- }
- }
- if is_conditionally_const || is_unconditionally_const {
- Ok(None)
- } else {
- Ok(Some(TraitBound {
- paren_token: None,
- modifier,
- lifetimes,
- path,
- }))
- }
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for TraitBoundModifier {
- fn parse(input: ParseStream) -> Result<Self> {
- if input.peek(Token![?]) {
- input.parse().map(TraitBoundModifier::Maybe)
- } else {
- Ok(TraitBoundModifier::None)
- }
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for ConstParam {
- fn parse(input: ParseStream) -> Result<Self> {
- let mut default = None;
- Ok(ConstParam {
- attrs: input.call(Attribute::parse_outer)?,
- const_token: input.parse()?,
- ident: input.parse()?,
- colon_token: input.parse()?,
- ty: input.parse()?,
- eq_token: {
- if input.peek(Token![=]) {
- let eq_token = input.parse()?;
- default = Some(path::parsing::const_argument(input)?);
- Some(eq_token)
- } else {
- None
- }
- },
- default,
- })
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for WhereClause {
- fn parse(input: ParseStream) -> Result<Self> {
- let where_token: Token![where] = input.parse()?;
- if choose_generics_over_qpath(input) {
- return Err(input
- .error("generic parameters on `where` clauses are reserved for future use"));
- }
- Ok(WhereClause {
- where_token,
- predicates: {
- let mut predicates = Punctuated::new();
- loop {
- if input.is_empty()
- || input.peek(token::Brace)
- || input.peek(Token![,])
- || input.peek(Token![;])
- || input.peek(Token![:]) && !input.peek(Token![::])
- || input.peek(Token![=])
- {
- break;
- }
- let value = input.parse()?;
- predicates.push_value(value);
- if !input.peek(Token![,]) {
- break;
- }
- let punct = input.parse()?;
- predicates.push_punct(punct);
- }
- predicates
- },
- })
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for Option<WhereClause> {
- fn parse(input: ParseStream) -> Result<Self> {
- if input.peek(Token![where]) {
- input.parse().map(Some)
- } else {
- Ok(None)
- }
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for WherePredicate {
- fn parse(input: ParseStream) -> Result<Self> {
- if input.peek(Lifetime) && input.peek2(Token![:]) {
- Ok(WherePredicate::Lifetime(PredicateLifetime {
- lifetime: input.parse()?,
- colon_token: input.parse()?,
- bounds: {
- let mut bounds = Punctuated::new();
- loop {
- if input.is_empty()
- || input.peek(token::Brace)
- || input.peek(Token![,])
- || input.peek(Token![;])
- || input.peek(Token![:])
- || input.peek(Token![=])
- {
- break;
- }
- let value = input.parse()?;
- bounds.push_value(value);
- if !input.peek(Token![+]) {
- break;
- }
- let punct = input.parse()?;
- bounds.push_punct(punct);
- }
- bounds
- },
- }))
- } else {
- Ok(WherePredicate::Type(PredicateType {
- lifetimes: input.parse()?,
- bounded_ty: input.parse()?,
- colon_token: input.parse()?,
- bounds: {
- let mut bounds = Punctuated::new();
- loop {
- if input.is_empty()
- || input.peek(token::Brace)
- || input.peek(Token![,])
- || input.peek(Token![;])
- || input.peek(Token![:]) && !input.peek(Token![::])
- || input.peek(Token![=])
- {
- break;
- }
- bounds.push_value({
- let allow_precise_capture = false;
- let allow_const = true;
- TypeParamBound::parse_single(
- input,
- allow_precise_capture,
- allow_const,
- )?
- });
- if !input.peek(Token![+]) {
- break;
- }
- let punct = input.parse()?;
- bounds.push_punct(punct);
- }
- bounds
- },
- }))
- }
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for PreciseCapture {
- fn parse(input: ParseStream) -> Result<Self> {
- let use_token: Token![use] = input.parse()?;
- let lt_token: Token![<] = input.parse()?;
- let mut params = Punctuated::new();
- loop {
- let lookahead = input.lookahead1();
- params.push_value(
- if lookahead.peek(Lifetime) || lookahead.peek(Ident) || input.peek(Token![Self])
- {
- input.parse::<CapturedParam>()?
- } else if lookahead.peek(Token![>]) {
- break;
- } else {
- return Err(lookahead.error());
- },
- );
- let lookahead = input.lookahead1();
- params.push_punct(if lookahead.peek(Token![,]) {
- input.parse::<Token![,]>()?
- } else if lookahead.peek(Token![>]) {
- break;
- } else {
- return Err(lookahead.error());
- });
- }
- let gt_token: Token![>] = input.parse()?;
- Ok(PreciseCapture {
- use_token,
- lt_token,
- params,
- gt_token,
- })
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
- impl Parse for CapturedParam {
- fn parse(input: ParseStream) -> Result<Self> {
- let lookahead = input.lookahead1();
- if lookahead.peek(Lifetime) {
- input.parse().map(CapturedParam::Lifetime)
- } else if lookahead.peek(Ident) || input.peek(Token![Self]) {
- input.call(Ident::parse_any).map(CapturedParam::Ident)
- } else {
- Err(lookahead.error())
- }
- }
- }
- pub(crate) fn choose_generics_over_qpath(input: ParseStream) -> bool {
- // Rust syntax has an ambiguity between generic parameters and qualified
- // paths. In `impl <T> :: Thing<T, U> {}` this may either be a generic
- // inherent impl `impl<T> ::Thing<T, U>` or a non-generic inherent impl
- // for an associated type `impl <T>::Thing<T, U>`.
- //
- // After `<` the following continuations can only begin generics, not a
- // qualified path:
- //
- // `<` `>` - empty generic parameters
- // `<` `#` - generic parameters with attribute
- // `<` LIFETIME `>` - single lifetime parameter
- // `<` (LIFETIME|IDENT) `,` - first generic parameter in a list
- // `<` (LIFETIME|IDENT) `:` - generic parameter with bounds
- // `<` (LIFETIME|IDENT) `=` - generic parameter with a default
- // `<` const - generic const parameter
- //
- // The only truly ambiguous case is:
- //
- // `<` IDENT `>` `::` IDENT ...
- //
- // which we disambiguate in favor of generics because this is almost
- // always the expected one in the context of real-world code.
- input.peek(Token![<])
- && (input.peek2(Token![>])
- || input.peek2(Token![#])
- || (input.peek2(Lifetime) || input.peek2(Ident))
- && (input.peek3(Token![>])
- || input.peek3(Token![,])
- || input.peek3(Token![:]) && !input.peek3(Token![::])
- || input.peek3(Token![=]))
- || input.peek2(Token![const]))
- }
- #[cfg(feature = "full")]
- pub(crate) fn choose_generics_over_qpath_after_keyword(input: ParseStream) -> bool {
- let input = input.fork();
- input.call(Ident::parse_any).unwrap(); // `impl` or `for` or `where`
- choose_generics_over_qpath(&input)
- }
- }
- #[cfg(feature = "printing")]
- pub(crate) mod printing {
- use crate::attr::FilterAttrs;
- #[cfg(feature = "full")]
- use crate::expr;
- use crate::expr::Expr;
- #[cfg(feature = "full")]
- use crate::fixup::FixupContext;
- use crate::generics::{
- BoundLifetimes, ConstParam, GenericParam, Generics, ImplGenerics, LifetimeParam,
- PredicateLifetime, PredicateType, TraitBound, TraitBoundModifier, Turbofish, TypeGenerics,
- TypeParam, WhereClause,
- };
- #[cfg(feature = "full")]
- use crate::generics::{CapturedParam, PreciseCapture};
- use crate::print::TokensOrDefault;
- use crate::token;
- use proc_macro2::TokenStream;
- use quote::{ToTokens, TokenStreamExt};
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for Generics {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- if self.params.is_empty() {
- return;
- }
- TokensOrDefault(&self.lt_token).to_tokens(tokens);
- // Print lifetimes before types and consts, regardless of their
- // order in self.params.
- let mut trailing_or_empty = true;
- for param in self.params.pairs() {
- if let GenericParam::Lifetime(_) = **param.value() {
- param.to_tokens(tokens);
- trailing_or_empty = param.punct().is_some();
- }
- }
- for param in self.params.pairs() {
- match param.value() {
- GenericParam::Type(_) | GenericParam::Const(_) => {
- if !trailing_or_empty {
- <Token![,]>::default().to_tokens(tokens);
- trailing_or_empty = true;
- }
- param.to_tokens(tokens);
- }
- GenericParam::Lifetime(_) => {}
- }
- }
- TokensOrDefault(&self.gt_token).to_tokens(tokens);
- }
- }
- impl<'a> ToTokens for ImplGenerics<'a> {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- if self.0.params.is_empty() {
- return;
- }
- TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
- // Print lifetimes before types and consts, regardless of their
- // order in self.params.
- let mut trailing_or_empty = true;
- for param in self.0.params.pairs() {
- if let GenericParam::Lifetime(_) = **param.value() {
- param.to_tokens(tokens);
- trailing_or_empty = param.punct().is_some();
- }
- }
- for param in self.0.params.pairs() {
- if let GenericParam::Lifetime(_) = **param.value() {
- continue;
- }
- if !trailing_or_empty {
- <Token![,]>::default().to_tokens(tokens);
- trailing_or_empty = true;
- }
- match param.value() {
- GenericParam::Lifetime(_) => unreachable!(),
- GenericParam::Type(param) => {
- // Leave off the type parameter defaults
- tokens.append_all(param.attrs.outer());
- param.ident.to_tokens(tokens);
- if !param.bounds.is_empty() {
- TokensOrDefault(¶m.colon_token).to_tokens(tokens);
- param.bounds.to_tokens(tokens);
- }
- }
- GenericParam::Const(param) => {
- // Leave off the const parameter defaults
- tokens.append_all(param.attrs.outer());
- param.const_token.to_tokens(tokens);
- param.ident.to_tokens(tokens);
- param.colon_token.to_tokens(tokens);
- param.ty.to_tokens(tokens);
- }
- }
- param.punct().to_tokens(tokens);
- }
- TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
- }
- }
- impl<'a> ToTokens for TypeGenerics<'a> {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- if self.0.params.is_empty() {
- return;
- }
- TokensOrDefault(&self.0.lt_token).to_tokens(tokens);
- // Print lifetimes before types and consts, regardless of their
- // order in self.params.
- let mut trailing_or_empty = true;
- for param in self.0.params.pairs() {
- if let GenericParam::Lifetime(def) = *param.value() {
- // Leave off the lifetime bounds and attributes
- def.lifetime.to_tokens(tokens);
- param.punct().to_tokens(tokens);
- trailing_or_empty = param.punct().is_some();
- }
- }
- for param in self.0.params.pairs() {
- if let GenericParam::Lifetime(_) = **param.value() {
- continue;
- }
- if !trailing_or_empty {
- <Token![,]>::default().to_tokens(tokens);
- trailing_or_empty = true;
- }
- match param.value() {
- GenericParam::Lifetime(_) => unreachable!(),
- GenericParam::Type(param) => {
- // Leave off the type parameter defaults
- param.ident.to_tokens(tokens);
- }
- GenericParam::Const(param) => {
- // Leave off the const parameter defaults
- param.ident.to_tokens(tokens);
- }
- }
- param.punct().to_tokens(tokens);
- }
- TokensOrDefault(&self.0.gt_token).to_tokens(tokens);
- }
- }
- impl<'a> ToTokens for Turbofish<'a> {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- if !self.0.params.is_empty() {
- <Token![::]>::default().to_tokens(tokens);
- TypeGenerics(self.0).to_tokens(tokens);
- }
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for BoundLifetimes {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- self.for_token.to_tokens(tokens);
- self.lt_token.to_tokens(tokens);
- self.lifetimes.to_tokens(tokens);
- self.gt_token.to_tokens(tokens);
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for LifetimeParam {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append_all(self.attrs.outer());
- self.lifetime.to_tokens(tokens);
- if !self.bounds.is_empty() {
- TokensOrDefault(&self.colon_token).to_tokens(tokens);
- self.bounds.to_tokens(tokens);
- }
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for TypeParam {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append_all(self.attrs.outer());
- self.ident.to_tokens(tokens);
- if !self.bounds.is_empty() {
- TokensOrDefault(&self.colon_token).to_tokens(tokens);
- self.bounds.to_tokens(tokens);
- }
- if let Some(default) = &self.default {
- TokensOrDefault(&self.eq_token).to_tokens(tokens);
- default.to_tokens(tokens);
- }
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for TraitBound {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- let to_tokens = |tokens: &mut TokenStream| {
- self.modifier.to_tokens(tokens);
- self.lifetimes.to_tokens(tokens);
- self.path.to_tokens(tokens);
- };
- match &self.paren_token {
- Some(paren) => paren.surround(tokens, to_tokens),
- None => to_tokens(tokens),
- }
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for TraitBoundModifier {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- match self {
- TraitBoundModifier::None => {}
- TraitBoundModifier::Maybe(t) => t.to_tokens(tokens),
- }
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for ConstParam {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- tokens.append_all(self.attrs.outer());
- self.const_token.to_tokens(tokens);
- self.ident.to_tokens(tokens);
- self.colon_token.to_tokens(tokens);
- self.ty.to_tokens(tokens);
- if let Some(default) = &self.default {
- TokensOrDefault(&self.eq_token).to_tokens(tokens);
- print_const_argument(default, tokens);
- }
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for WhereClause {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- if !self.predicates.is_empty() {
- self.where_token.to_tokens(tokens);
- self.predicates.to_tokens(tokens);
- }
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for PredicateLifetime {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- self.lifetime.to_tokens(tokens);
- self.colon_token.to_tokens(tokens);
- self.bounds.to_tokens(tokens);
- }
- }
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for PredicateType {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- self.lifetimes.to_tokens(tokens);
- self.bounded_ty.to_tokens(tokens);
- self.colon_token.to_tokens(tokens);
- self.bounds.to_tokens(tokens);
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for PreciseCapture {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- self.use_token.to_tokens(tokens);
- self.lt_token.to_tokens(tokens);
- // Print lifetimes before types and consts, regardless of their
- // order in self.params.
- let mut trailing_or_empty = true;
- for param in self.params.pairs() {
- if let CapturedParam::Lifetime(_) = **param.value() {
- param.to_tokens(tokens);
- trailing_or_empty = param.punct().is_some();
- }
- }
- for param in self.params.pairs() {
- if let CapturedParam::Ident(_) = **param.value() {
- if !trailing_or_empty {
- <Token![,]>::default().to_tokens(tokens);
- trailing_or_empty = true;
- }
- param.to_tokens(tokens);
- }
- }
- self.gt_token.to_tokens(tokens);
- }
- }
- #[cfg(feature = "full")]
- #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
- impl ToTokens for CapturedParam {
- fn to_tokens(&self, tokens: &mut TokenStream) {
- match self {
- CapturedParam::Lifetime(lifetime) => lifetime.to_tokens(tokens),
- CapturedParam::Ident(ident) => ident.to_tokens(tokens),
- }
- }
- }
- pub(crate) fn print_const_argument(expr: &Expr, tokens: &mut TokenStream) {
- match expr {
- Expr::Lit(expr) => expr.to_tokens(tokens),
- Expr::Path(expr)
- if expr.attrs.is_empty()
- && expr.qself.is_none()
- && expr.path.get_ident().is_some() =>
- {
- expr.to_tokens(tokens);
- }
- #[cfg(feature = "full")]
- Expr::Block(expr) => expr.to_tokens(tokens),
- #[cfg(not(feature = "full"))]
- Expr::Verbatim(expr) => expr.to_tokens(tokens),
- // ERROR CORRECTION: Add braces to make sure that the
- // generated code is valid.
- _ => token::Brace::default().surround(tokens, |tokens| {
- #[cfg(feature = "full")]
- expr::printing::print_expr(expr, tokens, FixupContext::new_stmt());
- #[cfg(not(feature = "full"))]
- expr.to_tokens(tokens);
- }),
- }
- }
- }
|