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.
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274// SPDX-License-Identifier: Apache-2.0 OR MIT
use crate::attr::Attribute;use crate::expr::Expr;use crate::generics::{BoundLifetimes, TypeParamBound};use crate::ident::Ident;use crate::lifetime::Lifetime;use crate::lit::LitStr;use crate::mac::Macro;use crate::path::{Path, QSelf};use crate::punctuated::Punctuated;use crate::token;use proc_macro2::TokenStream;
ast_enum_of_structs! { /// The possible types that a Rust value could have. /// /// # 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 Type { /// A fixed size array type: `[T; n]`. Array(TypeArray),
/// A bare function type: `fn(usize) -> bool`. BareFn(TypeBareFn),
/// A type contained within invisible delimiters. Group(TypeGroup),
/// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or /// a lifetime. ImplTrait(TypeImplTrait),
/// Indication that a type should be inferred by the compiler: `_`. Infer(TypeInfer),
/// A macro in the type position. Macro(TypeMacro),
/// The never type: `!`. Never(TypeNever),
/// A parenthesized type equivalent to the inner type. Paren(TypeParen),
/// A path like `std::slice::Iter`, optionally qualified with a /// self-type as in `<Vec<T> as SomeTrait>::Associated`. Path(TypePath),
/// A raw pointer type: `*const T` or `*mut T`. Ptr(TypePtr),
/// A reference type: `&'a T` or `&'a mut T`. Reference(TypeReference),
/// A dynamically sized slice type: `[T]`. Slice(TypeSlice),
/// A trait object type `dyn Bound1 + Bound2 + Bound3` where `Bound` is a /// trait or a lifetime. TraitObject(TypeTraitObject),
/// A tuple type: `(A, B, C, String)`. Tuple(TypeTuple),
/// Tokens in type position not interpreted by Syn. Verbatim(TokenStream),
// For testing exhaustiveness in downstream code, use the following idiom: // // match ty { // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))] // // Type::Array(ty) => {...} // Type::BareFn(ty) => {...} // ... // Type::Verbatim(ty) => {...} // // _ => { /* some sane fallback */ } // } // // This way we fail your tests but don't break your library when adding // a variant. You will be notified by a test failure when a variant is // added, so that you can add code to handle it, but your library will // continue to compile and work for downstream users in the interim. }}
ast_struct! { /// A fixed size array type: `[T; n]`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeArray { pub bracket_token: token::Bracket, pub elem: Box<Type>, pub semi_token: Token![;], pub len: Expr, }}
ast_struct! { /// A bare function type: `fn(usize) -> bool`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeBareFn { pub lifetimes: Option<BoundLifetimes>, pub unsafety: Option<Token![unsafe]>, pub abi: Option<Abi>, pub fn_token: Token![fn], pub paren_token: token::Paren, pub inputs: Punctuated<BareFnArg, Token![,]>, pub variadic: Option<BareVariadic>, pub output: ReturnType, }}
ast_struct! { /// A type contained within invisible delimiters. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeGroup { pub group_token: token::Group, pub elem: Box<Type>, }}
ast_struct! { /// An `impl Bound1 + Bound2 + Bound3` type where `Bound` is a trait or /// a lifetime. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeImplTrait { pub impl_token: Token![impl], pub bounds: Punctuated<TypeParamBound, Token![+]>, }}
ast_struct! { /// Indication that a type should be inferred by the compiler: `_`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeInfer { pub underscore_token: Token![_], }}
ast_struct! { /// A macro in the type position. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeMacro { pub mac: Macro, }}
ast_struct! { /// The never type: `!`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeNever { pub bang_token: Token![!], }}
ast_struct! { /// A parenthesized type equivalent to the inner type. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeParen { pub paren_token: token::Paren, pub elem: Box<Type>, }}
ast_struct! { /// A path like `std::slice::Iter`, optionally qualified with a /// self-type as in `<Vec<T> as SomeTrait>::Associated`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypePath { pub qself: Option<QSelf>, pub path: Path, }}
ast_struct! { /// A raw pointer type: `*const T` or `*mut T`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypePtr { pub star_token: Token![*], pub const_token: Option<Token![const]>, pub mutability: Option<Token![mut]>, pub elem: Box<Type>, }}
ast_struct! { /// A reference type: `&'a T` or `&'a mut T`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeReference { pub and_token: Token![&], pub lifetime: Option<Lifetime>, pub mutability: Option<Token![mut]>, pub elem: Box<Type>, }}
ast_struct! { /// A dynamically sized slice type: `[T]`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeSlice { pub bracket_token: token::Bracket, pub elem: Box<Type>, }}
ast_struct! { /// A trait object type `dyn Bound1 + Bound2 + Bound3` where `Bound` is a /// trait or a lifetime. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeTraitObject { pub dyn_token: Option<Token![dyn]>, pub bounds: Punctuated<TypeParamBound, Token![+]>, }}
ast_struct! { /// A tuple type: `(A, B, C, String)`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct TypeTuple { pub paren_token: token::Paren, pub elems: Punctuated<Type, Token![,]>, }}
ast_struct! { /// The binary interface of a function: `extern "C"`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct Abi { pub extern_token: Token![extern], pub name: Option<LitStr>, }}
ast_struct! { /// An argument in a function type: the `usize` in `fn(usize) -> bool`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct BareFnArg { pub attrs: Vec<Attribute>, pub name: Option<(Ident, Token![:])>, pub ty: Type, }}
ast_struct! { /// The variadic argument of a function pointer like `fn(usize, ...)`. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub struct BareVariadic { pub attrs: Vec<Attribute>, pub name: Option<(Ident, Token![:])>, pub dots: Token![...], pub comma: Option<Token![,]>, }}
ast_enum! { /// Return type of a function signature. #[cfg_attr(docsrs, doc(cfg(any(feature = "full", feature = "derive"))))] pub enum ReturnType { /// Return type is not specified. /// /// Functions default to `()` and closures default to type inference. Default, /// A particular type is returned. Type(Token![->], Box<Type>), }}
#[cfg(feature = "parsing")]pub(crate) mod parsing { use crate::attr::Attribute; use crate::error::{self, Result}; use crate::ext::IdentExt as _; use crate::generics::{BoundLifetimes, TraitBound, TraitBoundModifier, TypeParamBound}; use crate::ident::Ident; use crate::lifetime::Lifetime; use crate::mac::{self, Macro}; use crate::parse::{Parse, ParseStream}; use crate::path; use crate::path::{Path, PathArguments, QSelf}; use crate::punctuated::Punctuated; use crate::token; use crate::ty::{ Abi, BareFnArg, BareVariadic, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup, TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference, TypeSlice, TypeTraitObject, TypeTuple, }; use crate::verbatim; use proc_macro2::Span;
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Type { fn parse(input: ParseStream) -> Result<Self> { let allow_plus = true; let allow_group_generic = true; ambig_ty(input, allow_plus, allow_group_generic) } }
impl Type { /// In some positions, types may not contain the `+` character, to /// disambiguate them. For example in the expression `1 as T`, T may not /// contain a `+` character. /// /// This parser does not allow a `+`, while the default parser does. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn without_plus(input: ParseStream) -> Result<Self> { let allow_plus = false; let allow_group_generic = true; ambig_ty(input, allow_plus, allow_group_generic) } }
pub(crate) fn ambig_ty( input: ParseStream, allow_plus: bool, allow_group_generic: bool, ) -> Result<Type> { let begin = input.fork();
if input.peek(token::Group) { let mut group: TypeGroup = input.parse()?; if input.peek(Token![::]) && input.peek3(Ident::peek_any) { if let Type::Path(mut ty) = *group.elem { Path::parse_rest(input, &mut ty.path, false)?; return Ok(Type::Path(ty)); } else { return Ok(Type::Path(TypePath { qself: Some(QSelf { lt_token: Token, position: 0, as_token: None, gt_token: Token, ty: group.elem, }), path: Path::parse_helper(input, false)?, })); } } else if input.peek(Token![<]) && allow_group_generic || input.peek(Token![::]) && input.peek3(Token![<]) { if let Type::Path(mut ty) = *group.elem { let arguments = &mut ty.path.segments.last_mut().unwrap().arguments; if arguments.is_none() { *arguments = PathArguments::AngleBracketed(input.parse()?); Path::parse_rest(input, &mut ty.path, false)?; return Ok(Type::Path(ty)); } else { group.elem = Box::new(Type::Path(ty)); } } } return Ok(Type::Group(group)); }
let mut lifetimes = None::<BoundLifetimes>; let mut lookahead = input.lookahead1(); if lookahead.peek(Token![for]) { lifetimes = input.parse()?; lookahead = input.lookahead1(); if !lookahead.peek(Ident) && !lookahead.peek(Token![fn]) && !lookahead.peek(Token![unsafe]) && !lookahead.peek(Token![extern]) && !lookahead.peek(Token![super]) && !lookahead.peek(Token![self]) && !lookahead.peek(Token![Self]) && !lookahead.peek(Token![crate]) || input.peek(Token![dyn]) { return Err(lookahead.error()); } }
if lookahead.peek(token::Paren) { let content; let paren_token = parenthesized!(content in input); if content.is_empty() { return Ok(Type::Tuple(TypeTuple { paren_token, elems: Punctuated::new(), })); } if content.peek(Lifetime) { return Ok(Type::Paren(TypeParen { paren_token, elem: Box::new(Type::TraitObject(content.parse()?)), })); } if content.peek(Token![?]) { return Ok(Type::TraitObject(TypeTraitObject { dyn_token: None, bounds: { let mut bounds = Punctuated::new(); bounds.push_value(TypeParamBound::Trait(TraitBound { paren_token: Some(paren_token), ..content.parse()? })); while let Some(plus) = input.parse()? { bounds.push_punct(plus); bounds.push_value({ let allow_precise_capture = false; let allow_const = false; TypeParamBound::parse_single( input, allow_precise_capture, allow_const, )? }); } bounds }, })); } let mut first: Type = content.parse()?; if content.peek(Token![,]) { return Ok(Type::Tuple(TypeTuple { paren_token, elems: { let mut elems = Punctuated::new(); elems.push_value(first); elems.push_punct(content.parse()?); while !content.is_empty() { elems.push_value(content.parse()?); if content.is_empty() { break; } elems.push_punct(content.parse()?); } elems }, })); } if allow_plus && input.peek(Token![+]) { loop { let first = match first { Type::Path(TypePath { qself: None, path }) => { TypeParamBound::Trait(TraitBound { paren_token: Some(paren_token), modifier: TraitBoundModifier::None, lifetimes: None, path, }) } Type::TraitObject(TypeTraitObject { dyn_token: None, bounds, }) => { if bounds.len() > 1 || bounds.trailing_punct() { first = Type::TraitObject(TypeTraitObject { dyn_token: None, bounds, }); break; } match bounds.into_iter().next().unwrap() { TypeParamBound::Trait(trait_bound) => { TypeParamBound::Trait(TraitBound { paren_token: Some(paren_token), ..trait_bound }) } other @ (TypeParamBound::Lifetime(_) | TypeParamBound::PreciseCapture(_) | TypeParamBound::Verbatim(_)) => other, } } _ => break, }; return Ok(Type::TraitObject(TypeTraitObject { dyn_token: None, bounds: { let mut bounds = Punctuated::new(); bounds.push_value(first); while let Some(plus) = input.parse()? { bounds.push_punct(plus); bounds.push_value({ let allow_precise_capture = false; let allow_const = false; TypeParamBound::parse_single( input, allow_precise_capture, allow_const, )? }); } bounds }, })); } } Ok(Type::Paren(TypeParen { paren_token, elem: Box::new(first), })) } else if lookahead.peek(Token![fn]) || lookahead.peek(Token![unsafe]) || lookahead.peek(Token![extern]) { let mut bare_fn: TypeBareFn = input.parse()?; bare_fn.lifetimes = lifetimes; Ok(Type::BareFn(bare_fn)) } else if lookahead.peek(Ident) || input.peek(Token![super]) || input.peek(Token![self]) || input.peek(Token![Self]) || input.peek(Token![crate]) || lookahead.peek(Token![::]) || lookahead.peek(Token![<]) { let ty: TypePath = input.parse()?; if ty.qself.is_some() { return Ok(Type::Path(ty)); }
if input.peek(Token![!]) && !input.peek(Token![!=]) && ty.path.is_mod_style() { let bang_token: Token![!] = input.parse()?; let (delimiter, tokens) = mac::parse_delimiter(input)?; return Ok(Type::Macro(TypeMacro { mac: Macro { path: ty.path, bang_token, delimiter, tokens, }, })); }
if lifetimes.is_some() || allow_plus && input.peek(Token![+]) { let mut bounds = Punctuated::new(); bounds.push_value(TypeParamBound::Trait(TraitBound { paren_token: None, modifier: TraitBoundModifier::None, lifetimes, path: ty.path, })); if allow_plus { while input.peek(Token![+]) { bounds.push_punct(input.parse()?); if !(input.peek(Ident::peek_any) || input.peek(Token![::]) || input.peek(Token![?]) || input.peek(Lifetime) || input.peek(token::Paren)) { break; } bounds.push_value({ let allow_precise_capture = false; let allow_const = false; TypeParamBound::parse_single(input, allow_precise_capture, allow_const)? }); } } return Ok(Type::TraitObject(TypeTraitObject { dyn_token: None, bounds, })); }
Ok(Type::Path(ty)) } else if lookahead.peek(Token![dyn]) { let dyn_token: Token![dyn] = input.parse()?; let dyn_span = dyn_token.span; let star_token: Option<Token![*]> = input.parse()?; let bounds = TypeTraitObject::parse_bounds(dyn_span, input, allow_plus)?; Ok(if star_token.is_some() { Type::Verbatim(verbatim::between(&begin, input)) } else { Type::TraitObject(TypeTraitObject { dyn_token: Some(dyn_token), bounds, }) }) } else if lookahead.peek(token::Bracket) { let content; let bracket_token = bracketed!(content in input); let elem: Type = content.parse()?; if content.peek(Token![;]) { Ok(Type::Array(TypeArray { bracket_token, elem: Box::new(elem), semi_token: content.parse()?, len: content.parse()?, })) } else { Ok(Type::Slice(TypeSlice { bracket_token, elem: Box::new(elem), })) } } else if lookahead.peek(Token![*]) { input.parse().map(Type::Ptr) } else if lookahead.peek(Token![&]) { input.parse().map(Type::Reference) } else if lookahead.peek(Token![!]) && !input.peek(Token![=]) { input.parse().map(Type::Never) } else if lookahead.peek(Token![impl]) { TypeImplTrait::parse(input, allow_plus).map(Type::ImplTrait) } else if lookahead.peek(Token![_]) { input.parse().map(Type::Infer) } else if lookahead.peek(Lifetime) { input.parse().map(Type::TraitObject) } else { Err(lookahead.error()) } }
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeSlice { fn parse(input: ParseStream) -> Result<Self> { let content; Ok(TypeSlice { bracket_token: bracketed!(content in input), elem: content.parse()?, }) } }
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeArray { fn parse(input: ParseStream) -> Result<Self> { let content; Ok(TypeArray { bracket_token: bracketed!(content in input), elem: content.parse()?, semi_token: content.parse()?, len: content.parse()?, }) } }
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypePtr { fn parse(input: ParseStream) -> Result<Self> { let star_token: Token![*] = input.parse()?;
let lookahead = input.lookahead1(); let (const_token, mutability) = if lookahead.peek(Token![const]) { (Some(input.parse()?), None) } else if lookahead.peek(Token![mut]) { (None, Some(input.parse()?)) } else { return Err(lookahead.error()); };
Ok(TypePtr { star_token, const_token, mutability, elem: Box::new(input.call(Type::without_plus)?), }) } }
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeReference { fn parse(input: ParseStream) -> Result<Self> { Ok(TypeReference { and_token: input.parse()?, lifetime: input.parse()?, mutability: input.parse()?, // & binds tighter than +, so we don't allow + here. elem: Box::new(input.call(Type::without_plus)?), }) } }
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeBareFn { fn parse(input: ParseStream) -> Result<Self> { let args; let mut variadic = None;
Ok(TypeBareFn { lifetimes: input.parse()?, unsafety: input.parse()?, abi: input.parse()?, fn_token: input.parse()?, paren_token: parenthesized!(args in input), inputs: { let mut inputs = Punctuated::new();
while !args.is_empty() { let attrs = args.call(Attribute::parse_outer)?;
if inputs.empty_or_trailing() && (args.peek(Token![...]) || (args.peek(Ident) || args.peek(Token![_])) && args.peek2(Token![:]) && args.peek3(Token![...])) { variadic = Some(parse_bare_variadic(&args, attrs)?); break; }
let allow_self = inputs.is_empty(); let arg = parse_bare_fn_arg(&args, allow_self)?; inputs.push_value(BareFnArg { attrs, ..arg }); if args.is_empty() { break; }
let comma = args.parse()?; inputs.push_punct(comma); }
inputs }, variadic, output: input.call(ReturnType::without_plus)?, }) } }
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeNever { fn parse(input: ParseStream) -> Result<Self> { Ok(TypeNever { bang_token: input.parse()?, }) } }
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeInfer { fn parse(input: ParseStream) -> Result<Self> { Ok(TypeInfer { underscore_token: input.parse()?, }) } }
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeTuple { fn parse(input: ParseStream) -> Result<Self> { let content; let paren_token = parenthesized!(content in input);
if content.is_empty() { return Ok(TypeTuple { paren_token, elems: Punctuated::new(), }); }
let first: Type = content.parse()?; Ok(TypeTuple { paren_token, elems: { let mut elems = Punctuated::new(); elems.push_value(first); elems.push_punct(content.parse()?); while !content.is_empty() { elems.push_value(content.parse()?); if content.is_empty() { break; } elems.push_punct(content.parse()?); } elems }, }) } }
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeMacro { fn parse(input: ParseStream) -> Result<Self> { Ok(TypeMacro { mac: input.parse()?, }) } }
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypePath { fn parse(input: ParseStream) -> Result<Self> { let expr_style = false; let (qself, path) = path::parsing::qpath(input, expr_style)?; Ok(TypePath { qself, path }) } }
impl ReturnType { #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn without_plus(input: ParseStream) -> Result<Self> { let allow_plus = false; Self::parse(input, allow_plus) }
pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> { if input.peek(Token![->]) { let arrow = input.parse()?; let allow_group_generic = true; let ty = ambig_ty(input, allow_plus, allow_group_generic)?; Ok(ReturnType::Type(arrow, Box::new(ty))) } else { Ok(ReturnType::Default) } } }
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for ReturnType { fn parse(input: ParseStream) -> Result<Self> { let allow_plus = true; Self::parse(input, allow_plus) } }
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeTraitObject { fn parse(input: ParseStream) -> Result<Self> { let allow_plus = true; Self::parse(input, allow_plus) } }
impl TypeTraitObject { #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn without_plus(input: ParseStream) -> Result<Self> { let allow_plus = false; Self::parse(input, allow_plus) }
// Only allow multiple trait references if allow_plus is true. pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> { let dyn_token: Option<Token![dyn]> = input.parse()?; let dyn_span = match &dyn_token { Some(token) => token.span, None => input.span(), }; let bounds = Self::parse_bounds(dyn_span, input, allow_plus)?; Ok(TypeTraitObject { dyn_token, bounds }) }
fn parse_bounds( dyn_span: Span, input: ParseStream, allow_plus: bool, ) -> Result<Punctuated<TypeParamBound, Token![+]>> { let allow_precise_capture = false; let allow_const = false; let bounds = TypeParamBound::parse_multiple( input, allow_plus, allow_precise_capture, allow_const, )?; let mut last_lifetime_span = None; let mut at_least_one_trait = false; for bound in &bounds { match bound { TypeParamBound::Trait(_) => { at_least_one_trait = true; break; } TypeParamBound::Lifetime(lifetime) => { last_lifetime_span = Some(lifetime.ident.span()); } TypeParamBound::PreciseCapture(_) | TypeParamBound::Verbatim(_) => { unreachable!() } } } // Just lifetimes like `'a + 'b` is not a TraitObject. if !at_least_one_trait { let msg = "at least one trait is required for an object type"; return Err(error::new2(dyn_span, last_lifetime_span.unwrap(), msg)); } Ok(bounds) } }
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeImplTrait { fn parse(input: ParseStream) -> Result<Self> { let allow_plus = true; Self::parse(input, allow_plus) } }
impl TypeImplTrait { #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] pub fn without_plus(input: ParseStream) -> Result<Self> { let allow_plus = false; Self::parse(input, allow_plus) }
pub(crate) fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> { let impl_token: Token![impl] = input.parse()?; let allow_precise_capture = true; let allow_const = true; let bounds = TypeParamBound::parse_multiple( input, allow_plus, allow_precise_capture, allow_const, )?; let mut last_nontrait_span = None; let mut at_least_one_trait = false; for bound in &bounds { match bound { TypeParamBound::Trait(_) => { at_least_one_trait = true; break; } TypeParamBound::Lifetime(lifetime) => { last_nontrait_span = Some(lifetime.ident.span()); } TypeParamBound::PreciseCapture(precise_capture) => { #[cfg(feature = "full")] { last_nontrait_span = Some(precise_capture.gt_token.span); } #[cfg(not(feature = "full"))] { _ = precise_capture; unreachable!(); } } TypeParamBound::Verbatim(_) => { // `[const] Trait` at_least_one_trait = true; break; } } } if !at_least_one_trait { let msg = "at least one trait must be specified"; return Err(error::new2( impl_token.span, last_nontrait_span.unwrap(), msg, )); } Ok(TypeImplTrait { impl_token, bounds }) } }
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeGroup { fn parse(input: ParseStream) -> Result<Self> { let group = crate::group::parse_group(input)?; Ok(TypeGroup { group_token: group.token, elem: group.content.parse()?, }) } }
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for TypeParen { fn parse(input: ParseStream) -> Result<Self> { let allow_plus = false; Self::parse(input, allow_plus) } }
impl TypeParen { fn parse(input: ParseStream, allow_plus: bool) -> Result<Self> { let content; Ok(TypeParen { paren_token: parenthesized!(content in input), elem: Box::new({ let allow_group_generic = true; ambig_ty(&content, allow_plus, allow_group_generic)? }), }) } }
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for BareFnArg { fn parse(input: ParseStream) -> Result<Self> { let allow_self = false; parse_bare_fn_arg(input, allow_self) } }
fn parse_bare_fn_arg(input: ParseStream, allow_self: bool) -> Result<BareFnArg> { let attrs = input.call(Attribute::parse_outer)?;
let begin = input.fork();
let has_mut_self = allow_self && input.peek(Token![mut]) && input.peek2(Token![self]); if has_mut_self { input.parse::<Token![mut]>()?; }
let mut has_self = false; let mut name = if (input.peek(Ident) || input.peek(Token![_]) || { has_self = allow_self && input.peek(Token![self]); has_self }) && input.peek2(Token![:]) && !input.peek2(Token![::]) { let name = input.call(Ident::parse_any)?; let colon: Token![:] = input.parse()?; Some((name, colon)) } else { has_self = false; None };
let ty = if allow_self && !has_self && input.peek(Token![mut]) && input.peek2(Token![self]) { input.parse::<Token![mut]>()?; input.parse::<Token![self]>()?; None } else if has_mut_self && name.is_none() { input.parse::<Token![self]>()?; None } else { Some(input.parse()?) };
let ty = match ty { Some(ty) if !has_mut_self => ty, _ => { name = None; Type::Verbatim(verbatim::between(&begin, input)) } };
Ok(BareFnArg { attrs, name, ty }) }
fn parse_bare_variadic(input: ParseStream, attrs: Vec<Attribute>) -> Result<BareVariadic> { Ok(BareVariadic { attrs, name: if input.peek(Ident) || input.peek(Token![_]) { let name = input.call(Ident::parse_any)?; let colon: Token![:] = input.parse()?; Some((name, colon)) } else { None }, dots: input.parse()?, comma: input.parse()?, }) }
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Abi { fn parse(input: ParseStream) -> Result<Self> { Ok(Abi { extern_token: input.parse()?, name: input.parse()?, }) } }
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for Option<Abi> { fn parse(input: ParseStream) -> Result<Self> { if input.peek(Token![extern]) { input.parse().map(Some) } else { Ok(None) } } }}
#[cfg(feature = "printing")]mod printing { use crate::attr::FilterAttrs; use crate::path; use crate::path::printing::PathStyle; use crate::print::TokensOrDefault; use crate::ty::{ Abi, BareFnArg, BareVariadic, ReturnType, TypeArray, TypeBareFn, TypeGroup, TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference, TypeSlice, TypeTraitObject, TypeTuple, }; use proc_macro2::TokenStream; use quote::{ToTokens, TokenStreamExt};
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeSlice { fn to_tokens(&self, tokens: &mut TokenStream) { self.bracket_token.surround(tokens, |tokens| { self.elem.to_tokens(tokens); }); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeArray { fn to_tokens(&self, tokens: &mut TokenStream) { self.bracket_token.surround(tokens, |tokens| { self.elem.to_tokens(tokens); self.semi_token.to_tokens(tokens); self.len.to_tokens(tokens); }); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypePtr { fn to_tokens(&self, tokens: &mut TokenStream) { self.star_token.to_tokens(tokens); match &self.mutability { Some(tok) => tok.to_tokens(tokens), None => { TokensOrDefault(&self.const_token).to_tokens(tokens); } } self.elem.to_tokens(tokens); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeReference { fn to_tokens(&self, tokens: &mut TokenStream) { self.and_token.to_tokens(tokens); self.lifetime.to_tokens(tokens); self.mutability.to_tokens(tokens); self.elem.to_tokens(tokens); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeBareFn { fn to_tokens(&self, tokens: &mut TokenStream) { self.lifetimes.to_tokens(tokens); self.unsafety.to_tokens(tokens); self.abi.to_tokens(tokens); self.fn_token.to_tokens(tokens); self.paren_token.surround(tokens, |tokens| { self.inputs.to_tokens(tokens); if let Some(variadic) = &self.variadic { if !self.inputs.empty_or_trailing() { let span = variadic.dots.spans[0]; Token.to_tokens(tokens); } variadic.to_tokens(tokens); } }); self.output.to_tokens(tokens); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeNever { fn to_tokens(&self, tokens: &mut TokenStream) { self.bang_token.to_tokens(tokens); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeTuple { fn to_tokens(&self, tokens: &mut TokenStream) { self.paren_token.surround(tokens, |tokens| { self.elems.to_tokens(tokens); // If we only have one argument, we need a trailing comma to // distinguish TypeTuple from TypeParen. if self.elems.len() == 1 && !self.elems.trailing_punct() { <Token![,]>::default().to_tokens(tokens); } }); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypePath { fn to_tokens(&self, tokens: &mut TokenStream) { path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::AsWritten); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeTraitObject { fn to_tokens(&self, tokens: &mut TokenStream) { self.dyn_token.to_tokens(tokens); self.bounds.to_tokens(tokens); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeImplTrait { fn to_tokens(&self, tokens: &mut TokenStream) { self.impl_token.to_tokens(tokens); self.bounds.to_tokens(tokens); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeGroup { fn to_tokens(&self, tokens: &mut TokenStream) { self.group_token.surround(tokens, |tokens| { self.elem.to_tokens(tokens); }); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeParen { fn to_tokens(&self, tokens: &mut TokenStream) { self.paren_token.surround(tokens, |tokens| { self.elem.to_tokens(tokens); }); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeInfer { fn to_tokens(&self, tokens: &mut TokenStream) { self.underscore_token.to_tokens(tokens); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for TypeMacro { fn to_tokens(&self, tokens: &mut TokenStream) { self.mac.to_tokens(tokens); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for ReturnType { fn to_tokens(&self, tokens: &mut TokenStream) { match self { ReturnType::Default => {} ReturnType::Type(arrow, ty) => { arrow.to_tokens(tokens); ty.to_tokens(tokens); } } } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for BareFnArg { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); if let Some((name, colon)) = &self.name { name.to_tokens(tokens); colon.to_tokens(tokens); } self.ty.to_tokens(tokens); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for BareVariadic { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); if let Some((name, colon)) = &self.name { name.to_tokens(tokens); colon.to_tokens(tokens); } self.dots.to_tokens(tokens); self.comma.to_tokens(tokens); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for Abi { fn to_tokens(&self, tokens: &mut TokenStream) { self.extern_token.to_tokens(tokens); self.name.to_tokens(tokens); } }}