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.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958// SPDX-License-Identifier: Apache-2.0 OR MIT
use crate::attr::Attribute;use crate::expr::Member;use crate::ident::Ident;use crate::path::{Path, QSelf};use crate::punctuated::Punctuated;use crate::token;use crate::ty::Type;use proc_macro2::TokenStream;
pub use crate::expr::{ ExprConst as PatConst, ExprLit as PatLit, ExprMacro as PatMacro, ExprPath as PatPath, ExprRange as PatRange,};
ast_enum_of_structs! { /// A pattern in a local binding, function signature, match expression, or /// various other places. /// /// # Syntax tree enum /// /// This type is a [syntax tree enum]. /// /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums #[cfg_attr(docsrs, doc(cfg(feature = "full")))] #[non_exhaustive] pub enum Pat { /// A const block: `const { ... }`. Const(PatConst),
/// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`. Ident(PatIdent),
/// A literal pattern: `0`. Lit(PatLit),
/// A macro in pattern position. Macro(PatMacro),
/// A pattern that matches any one of a set of cases. Or(PatOr),
/// A parenthesized pattern: `(A | B)`. Paren(PatParen),
/// A path pattern like `Color::Red`, optionally qualified with a /// self-type. /// /// Unqualified path patterns can legally refer to variants, structs, /// constants or associated constants. Qualified path patterns like /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to /// associated constants. Path(PatPath),
/// A range pattern: `1..=2`. Range(PatRange),
/// A reference pattern: `&mut var`. Reference(PatReference),
/// The dots in a tuple or slice pattern: `[0, 1, ..]`. Rest(PatRest),
/// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`. Slice(PatSlice),
/// A struct or struct variant pattern: `Variant { x, y, .. }`. Struct(PatStruct),
/// A tuple pattern: `(a, b)`. Tuple(PatTuple),
/// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`. TupleStruct(PatTupleStruct),
/// A type ascription pattern: `foo: f64`. Type(PatType),
/// Tokens in pattern position not interpreted by Syn. Verbatim(TokenStream),
/// A pattern that matches any value: `_`. Wild(PatWild),
// For testing exhaustiveness in downstream code, use the following idiom: // // match pat { // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))] // // Pat::Box(pat) => {...} // Pat::Ident(pat) => {...} // ... // Pat::Wild(pat) => {...} // // _ => { /* 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 pattern that binds a new variable: `ref mut binding @ SUBPATTERN`. /// /// It may also be a unit struct or struct variant (e.g. `None`), or a /// constant; these cannot be distinguished syntactically. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatIdent { pub attrs: Vec<Attribute>, pub by_ref: Option<Token![ref]>, pub mutability: Option<Token![mut]>, pub ident: Ident, pub subpat: Option<(Token![@], Box<Pat>)>, }}
ast_struct! { /// A pattern that matches any one of a set of cases. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatOr { pub attrs: Vec<Attribute>, pub leading_vert: Option<Token![|]>, pub cases: Punctuated<Pat, Token![|]>, }}
ast_struct! { /// A parenthesized pattern: `(A | B)`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatParen { pub attrs: Vec<Attribute>, pub paren_token: token::Paren, pub pat: Box<Pat>, }}
ast_struct! { /// A reference pattern: `&mut var`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatReference { pub attrs: Vec<Attribute>, pub and_token: Token![&], pub mutability: Option<Token![mut]>, pub pat: Box<Pat>, }}
ast_struct! { /// The dots in a tuple or slice pattern: `[0, 1, ..]`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatRest { pub attrs: Vec<Attribute>, pub dot2_token: Token![..], }}
ast_struct! { /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatSlice { pub attrs: Vec<Attribute>, pub bracket_token: token::Bracket, pub elems: Punctuated<Pat, Token![,]>, }}
ast_struct! { /// A struct or struct variant pattern: `Variant { x, y, .. }`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatStruct { pub attrs: Vec<Attribute>, pub qself: Option<QSelf>, pub path: Path, pub brace_token: token::Brace, pub fields: Punctuated<FieldPat, Token![,]>, pub rest: Option<PatRest>, }}
ast_struct! { /// A tuple pattern: `(a, b)`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatTuple { pub attrs: Vec<Attribute>, pub paren_token: token::Paren, pub elems: Punctuated<Pat, Token![,]>, }}
ast_struct! { /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatTupleStruct { pub attrs: Vec<Attribute>, pub qself: Option<QSelf>, pub path: Path, pub paren_token: token::Paren, pub elems: Punctuated<Pat, Token![,]>, }}
ast_struct! { /// A type ascription pattern: `foo: f64`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatType { pub attrs: Vec<Attribute>, pub pat: Box<Pat>, pub colon_token: Token![:], pub ty: Box<Type>, }}
ast_struct! { /// A pattern that matches any value: `_`. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct PatWild { pub attrs: Vec<Attribute>, pub underscore_token: Token![_], }}
ast_struct! { /// A single field in a struct pattern. /// /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token. #[cfg_attr(docsrs, doc(cfg(feature = "full")))] pub struct FieldPat { pub attrs: Vec<Attribute>, pub member: Member, pub colon_token: Option<Token![:]>, pub pat: Box<Pat>, }}
#[cfg(feature = "parsing")]pub(crate) mod parsing { use crate::attr::Attribute; use crate::error::{self, Result}; use crate::expr::{ Expr, ExprConst, ExprLit, ExprMacro, ExprPath, ExprRange, Member, RangeLimits, }; use crate::ext::IdentExt as _; use crate::ident::Ident; use crate::lit::Lit; use crate::mac::{self, Macro}; use crate::parse::{Parse, ParseBuffer, ParseStream}; use crate::pat::{ FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct, PatTuple, PatTupleStruct, PatType, PatWild, }; use crate::path::{self, Path, QSelf}; use crate::punctuated::Punctuated; use crate::stmt::Block; use crate::token; use crate::verbatim; use proc_macro2::TokenStream;
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Pat { /// Parse a pattern that does _not_ involve `|` at the top level. /// /// This parser matches the behavior of the `$:pat_param` macro_rules /// matcher, and on editions prior to Rust 2021, the behavior of /// `$:pat`. /// /// In Rust syntax, some examples of where this syntax would occur are /// in the argument pattern of functions and closures. Patterns using /// `|` are not allowed to occur in these positions. /// /// ```compile_fail /// fn f(Some(_) | None: Option<T>) { /// let _ = |Some(_) | None: Option<T>| {}; /// // ^^^^^^^^^^^^^^^^^^^^^^^^^??? :( /// } /// ``` /// /// ```console /// error: top-level or-patterns are not allowed in function parameters /// --> src/main.rs:1:6 /// | /// 1 | fn f(Some(_) | None: Option<T>) { /// | ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Some(_) | None)` /// ``` pub fn parse_single(input: ParseStream) -> Result<Self> { let begin = input.fork(); let lookahead = input.lookahead1(); if lookahead.peek(Ident) && (input.peek2(Token![::]) || input.peek2(Token![!]) || input.peek2(token::Brace) || input.peek2(token::Paren) || input.peek2(Token![..])) || input.peek(Token![self]) && input.peek2(Token![::]) || lookahead.peek(Token![::]) || lookahead.peek(Token![<]) || input.peek(Token![Self]) || input.peek(Token![super]) || input.peek(Token![crate]) { pat_path_or_macro_or_struct_or_range(input) } else if lookahead.peek(Token![_]) { input.call(pat_wild).map(Pat::Wild) } else if input.peek(Token![box]) { pat_box(begin, input) } else if input.peek(Token![-]) || lookahead.peek(Lit) || lookahead.peek(Token![const]) { pat_lit_or_range(input) } else if lookahead.peek(Token![ref]) || lookahead.peek(Token![mut]) || input.peek(Token![self]) || input.peek(Ident) { input.call(pat_ident).map(Pat::Ident) } else if lookahead.peek(Token![&]) { input.call(pat_reference).map(Pat::Reference) } else if lookahead.peek(token::Paren) { input.call(pat_paren_or_tuple) } else if lookahead.peek(token::Bracket) { input.call(pat_slice).map(Pat::Slice) } else if lookahead.peek(Token![..]) && !input.peek(Token![...]) { pat_range_half_open(input) } else if lookahead.peek(Token![const]) { input.call(pat_const).map(Pat::Verbatim) } else { Err(lookahead.error()) } }
/// Parse a pattern, possibly involving `|`, but not a leading `|`. pub fn parse_multi(input: ParseStream) -> Result<Self> { multi_pat_impl(input, None) }
/// Parse a pattern, possibly involving `|`, possibly including a /// leading `|`. /// /// This parser matches the behavior of the Rust 2021 edition's `$:pat` /// macro_rules matcher. /// /// In Rust syntax, an example of where this syntax would occur is in /// the pattern of a `match` arm, where the language permits an optional /// leading `|`, although it is not idiomatic to write one there in /// handwritten code. /// /// ``` /// # let wat = None; /// match wat { /// | None | Some(false) => {} /// | Some(true) => {} /// } /// ``` /// /// The compiler accepts it only to facilitate some situations in /// macro-generated code where a macro author might need to write: /// /// ``` /// # macro_rules! doc { /// # ($value:expr, ($($conditions1:pat),*), ($($conditions2:pat),*), $then:expr) => { /// match $value { /// $(| $conditions1)* $(| $conditions2)* => $then /// } /// # }; /// # } /// # /// # doc!(true, (true), (false), {}); /// # doc!(true, (), (true, false), {}); /// # doc!(true, (true, false), (), {}); /// ``` /// /// Expressing the same thing correctly in the case that either one (but /// not both) of `$conditions1` and `$conditions2` might be empty, /// without leading `|`, is complex. /// /// Use [`Pat::parse_multi`] instead if you are not intending to support /// macro-generated macro input. pub fn parse_multi_with_leading_vert(input: ParseStream) -> Result<Self> { let leading_vert: Option<Token![|]> = input.parse()?; multi_pat_impl(input, leading_vert) } }
#[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] impl Parse for PatType { fn parse(input: ParseStream) -> Result<Self> { Ok(PatType { attrs: Vec::new(), pat: Box::new(Pat::parse_single(input)?), colon_token: input.parse()?, ty: input.parse()?, }) } }
fn multi_pat_impl(input: ParseStream, leading_vert: Option<Token![|]>) -> Result<Pat> { let mut pat = Pat::parse_single(input)?; if leading_vert.is_some() || input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) { let mut cases = Punctuated::new(); cases.push_value(pat); while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) { let punct = input.parse()?; cases.push_punct(punct); let pat = Pat::parse_single(input)?; cases.push_value(pat); } pat = Pat::Or(PatOr { attrs: Vec::new(), leading_vert, cases, }); } Ok(pat) }
fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> { let expr_style = true; let (qself, path) = path::parsing::qpath(input, expr_style)?;
if qself.is_none() && input.peek(Token![!]) && !input.peek(Token![!=]) && path.is_mod_style() { let bang_token: Token![!] = input.parse()?; let (delimiter, tokens) = mac::parse_delimiter(input)?; return Ok(Pat::Macro(ExprMacro { attrs: Vec::new(), mac: Macro { path, bang_token, delimiter, tokens, }, })); }
if input.peek(token::Brace) { pat_struct(input, qself, path).map(Pat::Struct) } else if input.peek(token::Paren) { pat_tuple_struct(input, qself, path).map(Pat::TupleStruct) } else if input.peek(Token![..]) { pat_range(input, qself, path) } else { Ok(Pat::Path(ExprPath { attrs: Vec::new(), qself, path, })) } }
fn pat_wild(input: ParseStream) -> Result<PatWild> { Ok(PatWild { attrs: Vec::new(), underscore_token: input.parse()?, }) }
fn pat_box(begin: ParseBuffer, input: ParseStream) -> Result<Pat> { input.parse::<Token![box]>()?; Pat::parse_single(input)?; Ok(Pat::Verbatim(verbatim::between(&begin, input))) }
fn pat_ident(input: ParseStream) -> Result<PatIdent> { Ok(PatIdent { attrs: Vec::new(), by_ref: input.parse()?, mutability: input.parse()?, ident: { if input.peek(Token![self]) { input.call(Ident::parse_any)? } else { input.parse()? } }, subpat: { if input.peek(Token![@]) { let at_token: Token![@] = input.parse()?; let subpat = Pat::parse_single(input)?; Some((at_token, Box::new(subpat))) } else { None } }, }) }
fn pat_tuple_struct( input: ParseStream, qself: Option<QSelf>, path: Path, ) -> Result<PatTupleStruct> { let content; let paren_token = parenthesized!(content in input);
let mut elems = Punctuated::new(); while !content.is_empty() { let value = Pat::parse_multi_with_leading_vert(&content)?; elems.push_value(value); if content.is_empty() { break; } let punct = content.parse()?; elems.push_punct(punct); }
Ok(PatTupleStruct { attrs: Vec::new(), qself, path, paren_token, elems, }) }
fn pat_struct(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatStruct> { let content; let brace_token = braced!(content in input);
let mut fields = Punctuated::new(); let mut rest = None; while !content.is_empty() { let attrs = content.call(Attribute::parse_outer)?; if content.peek(Token![..]) { rest = Some(PatRest { attrs, dot2_token: content.parse()?, }); break; } let mut value = content.call(field_pat)?; value.attrs = attrs; fields.push_value(value); if content.is_empty() { break; } let punct: Token![,] = content.parse()?; fields.push_punct(punct); }
Ok(PatStruct { attrs: Vec::new(), qself, path, brace_token, fields, rest, }) }
fn field_pat(input: ParseStream) -> Result<FieldPat> { let begin = input.fork(); let boxed: Option<Token![box]> = input.parse()?; let by_ref: Option<Token![ref]> = input.parse()?; let mutability: Option<Token![mut]> = input.parse()?;
let member = if boxed.is_some() || by_ref.is_some() || mutability.is_some() { input.parse().map(Member::Named) } else { input.parse() }?;
if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:]) || !member.is_named() { return Ok(FieldPat { attrs: Vec::new(), member, colon_token: Some(input.parse()?), pat: Box::new(Pat::parse_multi_with_leading_vert(input)?), }); }
let ident = match member { Member::Named(ident) => ident, Member::Unnamed(_) => unreachable!(), };
let pat = if boxed.is_some() { Pat::Verbatim(verbatim::between(&begin, input)) } else { Pat::Ident(PatIdent { attrs: Vec::new(), by_ref, mutability, ident: ident.clone(), subpat: None, }) };
Ok(FieldPat { attrs: Vec::new(), member: Member::Named(ident), colon_token: None, pat: Box::new(pat), }) }
fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<Pat> { let limits = RangeLimits::parse_obsolete(input)?; let end = input.call(pat_range_bound)?; if let (RangeLimits::Closed(_), None) = (&limits, &end) { return Err(input.error("expected range upper bound")); } Ok(Pat::Range(ExprRange { attrs: Vec::new(), start: Some(Box::new(Expr::Path(ExprPath { attrs: Vec::new(), qself, path, }))), limits, end: end.map(PatRangeBound::into_expr), })) }
fn pat_range_half_open(input: ParseStream) -> Result<Pat> { let limits: RangeLimits = input.parse()?; let end = input.call(pat_range_bound)?; if end.is_some() { Ok(Pat::Range(ExprRange { attrs: Vec::new(), start: None, limits, end: end.map(PatRangeBound::into_expr), })) } else { match limits { RangeLimits::HalfOpen(dot2_token) => Ok(Pat::Rest(PatRest { attrs: Vec::new(), dot2_token, })), RangeLimits::Closed(_) => Err(input.error("expected range upper bound")), } } }
fn pat_paren_or_tuple(input: ParseStream) -> Result<Pat> { let content; let paren_token = parenthesized!(content in input);
let mut elems = Punctuated::new(); while !content.is_empty() { let value = Pat::parse_multi_with_leading_vert(&content)?; if content.is_empty() { if elems.is_empty() && !matches!(value, Pat::Rest(_)) { return Ok(Pat::Paren(PatParen { attrs: Vec::new(), paren_token, pat: Box::new(value), })); } elems.push_value(value); break; } elems.push_value(value); let punct = content.parse()?; elems.push_punct(punct); }
Ok(Pat::Tuple(PatTuple { attrs: Vec::new(), paren_token, elems, })) }
fn pat_reference(input: ParseStream) -> Result<PatReference> { Ok(PatReference { attrs: Vec::new(), and_token: input.parse()?, mutability: input.parse()?, pat: Box::new(Pat::parse_single(input)?), }) }
fn pat_lit_or_range(input: ParseStream) -> Result<Pat> { let start = input.call(pat_range_bound)?.unwrap(); if input.peek(Token![..]) { let limits = RangeLimits::parse_obsolete(input)?; let end = input.call(pat_range_bound)?; if let (RangeLimits::Closed(_), None) = (&limits, &end) { return Err(input.error("expected range upper bound")); } Ok(Pat::Range(ExprRange { attrs: Vec::new(), start: Some(start.into_expr()), limits, end: end.map(PatRangeBound::into_expr), })) } else { Ok(start.into_pat()) } }
// Patterns that can appear on either side of a range pattern. enum PatRangeBound { Const(ExprConst), Lit(ExprLit), Path(ExprPath), }
impl PatRangeBound { fn into_expr(self) -> Box<Expr> { Box::new(match self { PatRangeBound::Const(pat) => Expr::Const(pat), PatRangeBound::Lit(pat) => Expr::Lit(pat), PatRangeBound::Path(pat) => Expr::Path(pat), }) }
fn into_pat(self) -> Pat { match self { PatRangeBound::Const(pat) => Pat::Const(pat), PatRangeBound::Lit(pat) => Pat::Lit(pat), PatRangeBound::Path(pat) => Pat::Path(pat), } } }
fn pat_range_bound(input: ParseStream) -> Result<Option<PatRangeBound>> { if input.is_empty() || input.peek(Token![|]) || input.peek(Token![=]) || input.peek(Token![:]) && !input.peek(Token![::]) || input.peek(Token![,]) || input.peek(Token![;]) || input.peek(Token![if]) { return Ok(None); }
let lookahead = input.lookahead1(); let expr = if lookahead.peek(Lit) { PatRangeBound::Lit(input.parse()?) } else if lookahead.peek(Ident) || lookahead.peek(Token![::]) || lookahead.peek(Token![<]) || lookahead.peek(Token![self]) || lookahead.peek(Token![Self]) || lookahead.peek(Token![super]) || lookahead.peek(Token![crate]) { PatRangeBound::Path(input.parse()?) } else if lookahead.peek(Token![const]) { PatRangeBound::Const(input.parse()?) } else { return Err(lookahead.error()); };
Ok(Some(expr)) }
fn pat_slice(input: ParseStream) -> Result<PatSlice> { let content; let bracket_token = bracketed!(content in input);
let mut elems = Punctuated::new(); while !content.is_empty() { let value = Pat::parse_multi_with_leading_vert(&content)?; match value { Pat::Range(pat) if pat.start.is_none() || pat.end.is_none() => { let (start, end) = match pat.limits { RangeLimits::HalfOpen(dot_dot) => (dot_dot.spans[0], dot_dot.spans[1]), RangeLimits::Closed(dot_dot_eq) => { (dot_dot_eq.spans[0], dot_dot_eq.spans[2]) } }; let msg = "range pattern is not allowed unparenthesized inside slice pattern"; return Err(error::new2(start, end, msg)); } _ => {} } elems.push_value(value); if content.is_empty() { break; } let punct = content.parse()?; elems.push_punct(punct); }
Ok(PatSlice { attrs: Vec::new(), bracket_token, elems, }) }
fn pat_const(input: ParseStream) -> Result<TokenStream> { let begin = input.fork(); input.parse::<Token![const]>()?;
let content; braced!(content in input); content.call(Attribute::parse_inner)?; content.call(Block::parse_within)?;
Ok(verbatim::between(&begin, input)) }}
#[cfg(feature = "printing")]mod printing { use crate::attr::FilterAttrs; use crate::pat::{ FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct, PatTuple, PatTupleStruct, PatType, PatWild, }; use crate::path; use crate::path::printing::PathStyle; use proc_macro2::TokenStream; use quote::{ToTokens, TokenStreamExt};
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatIdent { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.by_ref.to_tokens(tokens); self.mutability.to_tokens(tokens); self.ident.to_tokens(tokens); if let Some((at_token, subpat)) = &self.subpat { at_token.to_tokens(tokens); subpat.to_tokens(tokens); } } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatOr { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.leading_vert.to_tokens(tokens); self.cases.to_tokens(tokens); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatParen { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.paren_token.surround(tokens, |tokens| { self.pat.to_tokens(tokens); }); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatReference { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.and_token.to_tokens(tokens); self.mutability.to_tokens(tokens); self.pat.to_tokens(tokens); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatRest { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.dot2_token.to_tokens(tokens); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatSlice { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.bracket_token.surround(tokens, |tokens| { self.elems.to_tokens(tokens); }); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatStruct { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr); self.brace_token.surround(tokens, |tokens| { self.fields.to_tokens(tokens); // NOTE: We need a comma before the dot2 token if it is present. if !self.fields.empty_or_trailing() && self.rest.is_some() { <Token![,]>::default().to_tokens(tokens); } self.rest.to_tokens(tokens); }); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatTuple { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.paren_token.surround(tokens, |tokens| { self.elems.to_tokens(tokens); // If there is only one element, a trailing comma is needed to // distinguish PatTuple from PatParen, unless this is `(..)` // which is a tuple pattern even without comma. if self.elems.len() == 1 && !self.elems.trailing_punct() && !matches!(self.elems[0], Pat::Rest { .. }) { <Token![,]>::default().to_tokens(tokens); } }); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatTupleStruct { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr); self.paren_token.surround(tokens, |tokens| { self.elems.to_tokens(tokens); }); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatType { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.pat.to_tokens(tokens); self.colon_token.to_tokens(tokens); self.ty.to_tokens(tokens); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for PatWild { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); self.underscore_token.to_tokens(tokens); } }
#[cfg_attr(docsrs, doc(cfg(feature = "printing")))] impl ToTokens for FieldPat { fn to_tokens(&self, tokens: &mut TokenStream) { tokens.append_all(self.attrs.outer()); if let Some(colon_token) = &self.colon_token { self.member.to_tokens(tokens); colon_token.to_tokens(tokens); } self.pat.to_tokens(tokens); } }}