Something went wrong. Try again.
Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
Something went wrong. Try again.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480// 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); }), } }}