1*69942c0aSMiguel Ojeda // SPDX-License-Identifier: Apache-2.0 OR MIT 2*69942c0aSMiguel Ojeda 3808c999fSMiguel Ojeda use crate::attr::Attribute; 4808c999fSMiguel Ojeda use crate::expr::Member; 5808c999fSMiguel Ojeda use crate::ident::Ident; 6808c999fSMiguel Ojeda use crate::path::{Path, QSelf}; 7808c999fSMiguel Ojeda use crate::punctuated::Punctuated; 8808c999fSMiguel Ojeda use crate::token; 9808c999fSMiguel Ojeda use crate::ty::Type; 10808c999fSMiguel Ojeda use proc_macro2::TokenStream; 11808c999fSMiguel Ojeda 12808c999fSMiguel Ojeda pub use crate::expr::{ 13808c999fSMiguel Ojeda ExprConst as PatConst, ExprLit as PatLit, ExprMacro as PatMacro, ExprPath as PatPath, 14808c999fSMiguel Ojeda ExprRange as PatRange, 15808c999fSMiguel Ojeda }; 16808c999fSMiguel Ojeda 17808c999fSMiguel Ojeda ast_enum_of_structs! { 18808c999fSMiguel Ojeda /// A pattern in a local binding, function signature, match expression, or 19808c999fSMiguel Ojeda /// various other places. 20808c999fSMiguel Ojeda /// 21808c999fSMiguel Ojeda /// # Syntax tree enum 22808c999fSMiguel Ojeda /// 23808c999fSMiguel Ojeda /// This type is a [syntax tree enum]. 24808c999fSMiguel Ojeda /// 25808c999fSMiguel Ojeda /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums 26808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 27808c999fSMiguel Ojeda #[non_exhaustive] 28808c999fSMiguel Ojeda pub enum Pat { 29808c999fSMiguel Ojeda /// A const block: `const { ... }`. 30808c999fSMiguel Ojeda Const(PatConst), 31808c999fSMiguel Ojeda 32808c999fSMiguel Ojeda /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`. 33808c999fSMiguel Ojeda Ident(PatIdent), 34808c999fSMiguel Ojeda 35808c999fSMiguel Ojeda /// A literal pattern: `0`. 36808c999fSMiguel Ojeda Lit(PatLit), 37808c999fSMiguel Ojeda 38808c999fSMiguel Ojeda /// A macro in pattern position. 39808c999fSMiguel Ojeda Macro(PatMacro), 40808c999fSMiguel Ojeda 41808c999fSMiguel Ojeda /// A pattern that matches any one of a set of cases. 42808c999fSMiguel Ojeda Or(PatOr), 43808c999fSMiguel Ojeda 44808c999fSMiguel Ojeda /// A parenthesized pattern: `(A | B)`. 45808c999fSMiguel Ojeda Paren(PatParen), 46808c999fSMiguel Ojeda 47808c999fSMiguel Ojeda /// A path pattern like `Color::Red`, optionally qualified with a 48808c999fSMiguel Ojeda /// self-type. 49808c999fSMiguel Ojeda /// 50808c999fSMiguel Ojeda /// Unqualified path patterns can legally refer to variants, structs, 51808c999fSMiguel Ojeda /// constants or associated constants. Qualified path patterns like 52808c999fSMiguel Ojeda /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to 53808c999fSMiguel Ojeda /// associated constants. 54808c999fSMiguel Ojeda Path(PatPath), 55808c999fSMiguel Ojeda 56808c999fSMiguel Ojeda /// A range pattern: `1..=2`. 57808c999fSMiguel Ojeda Range(PatRange), 58808c999fSMiguel Ojeda 59808c999fSMiguel Ojeda /// A reference pattern: `&mut var`. 60808c999fSMiguel Ojeda Reference(PatReference), 61808c999fSMiguel Ojeda 62808c999fSMiguel Ojeda /// The dots in a tuple or slice pattern: `[0, 1, ..]`. 63808c999fSMiguel Ojeda Rest(PatRest), 64808c999fSMiguel Ojeda 65808c999fSMiguel Ojeda /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`. 66808c999fSMiguel Ojeda Slice(PatSlice), 67808c999fSMiguel Ojeda 68808c999fSMiguel Ojeda /// A struct or struct variant pattern: `Variant { x, y, .. }`. 69808c999fSMiguel Ojeda Struct(PatStruct), 70808c999fSMiguel Ojeda 71808c999fSMiguel Ojeda /// A tuple pattern: `(a, b)`. 72808c999fSMiguel Ojeda Tuple(PatTuple), 73808c999fSMiguel Ojeda 74808c999fSMiguel Ojeda /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`. 75808c999fSMiguel Ojeda TupleStruct(PatTupleStruct), 76808c999fSMiguel Ojeda 77808c999fSMiguel Ojeda /// A type ascription pattern: `foo: f64`. 78808c999fSMiguel Ojeda Type(PatType), 79808c999fSMiguel Ojeda 80808c999fSMiguel Ojeda /// Tokens in pattern position not interpreted by Syn. 81808c999fSMiguel Ojeda Verbatim(TokenStream), 82808c999fSMiguel Ojeda 83808c999fSMiguel Ojeda /// A pattern that matches any value: `_`. 84808c999fSMiguel Ojeda Wild(PatWild), 85808c999fSMiguel Ojeda 86808c999fSMiguel Ojeda // For testing exhaustiveness in downstream code, use the following idiom: 87808c999fSMiguel Ojeda // 88808c999fSMiguel Ojeda // match pat { 89808c999fSMiguel Ojeda // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))] 90808c999fSMiguel Ojeda // 91808c999fSMiguel Ojeda // Pat::Box(pat) => {...} 92808c999fSMiguel Ojeda // Pat::Ident(pat) => {...} 93808c999fSMiguel Ojeda // ... 94808c999fSMiguel Ojeda // Pat::Wild(pat) => {...} 95808c999fSMiguel Ojeda // 96808c999fSMiguel Ojeda // _ => { /* some sane fallback */ } 97808c999fSMiguel Ojeda // } 98808c999fSMiguel Ojeda // 99808c999fSMiguel Ojeda // This way we fail your tests but don't break your library when adding 100808c999fSMiguel Ojeda // a variant. You will be notified by a test failure when a variant is 101808c999fSMiguel Ojeda // added, so that you can add code to handle it, but your library will 102808c999fSMiguel Ojeda // continue to compile and work for downstream users in the interim. 103808c999fSMiguel Ojeda } 104808c999fSMiguel Ojeda } 105808c999fSMiguel Ojeda 106808c999fSMiguel Ojeda ast_struct! { 107808c999fSMiguel Ojeda /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`. 108808c999fSMiguel Ojeda /// 109808c999fSMiguel Ojeda /// It may also be a unit struct or struct variant (e.g. `None`), or a 110808c999fSMiguel Ojeda /// constant; these cannot be distinguished syntactically. 111808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 112808c999fSMiguel Ojeda pub struct PatIdent { 113808c999fSMiguel Ojeda pub attrs: Vec<Attribute>, 114808c999fSMiguel Ojeda pub by_ref: Option<Token![ref]>, 115808c999fSMiguel Ojeda pub mutability: Option<Token![mut]>, 116808c999fSMiguel Ojeda pub ident: Ident, 117808c999fSMiguel Ojeda pub subpat: Option<(Token![@], Box<Pat>)>, 118808c999fSMiguel Ojeda } 119808c999fSMiguel Ojeda } 120808c999fSMiguel Ojeda 121808c999fSMiguel Ojeda ast_struct! { 122808c999fSMiguel Ojeda /// A pattern that matches any one of a set of cases. 123808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 124808c999fSMiguel Ojeda pub struct PatOr { 125808c999fSMiguel Ojeda pub attrs: Vec<Attribute>, 126808c999fSMiguel Ojeda pub leading_vert: Option<Token![|]>, 127808c999fSMiguel Ojeda pub cases: Punctuated<Pat, Token![|]>, 128808c999fSMiguel Ojeda } 129808c999fSMiguel Ojeda } 130808c999fSMiguel Ojeda 131808c999fSMiguel Ojeda ast_struct! { 132808c999fSMiguel Ojeda /// A parenthesized pattern: `(A | B)`. 133808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 134808c999fSMiguel Ojeda pub struct PatParen { 135808c999fSMiguel Ojeda pub attrs: Vec<Attribute>, 136808c999fSMiguel Ojeda pub paren_token: token::Paren, 137808c999fSMiguel Ojeda pub pat: Box<Pat>, 138808c999fSMiguel Ojeda } 139808c999fSMiguel Ojeda } 140808c999fSMiguel Ojeda 141808c999fSMiguel Ojeda ast_struct! { 142808c999fSMiguel Ojeda /// A reference pattern: `&mut var`. 143808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 144808c999fSMiguel Ojeda pub struct PatReference { 145808c999fSMiguel Ojeda pub attrs: Vec<Attribute>, 146808c999fSMiguel Ojeda pub and_token: Token![&], 147808c999fSMiguel Ojeda pub mutability: Option<Token![mut]>, 148808c999fSMiguel Ojeda pub pat: Box<Pat>, 149808c999fSMiguel Ojeda } 150808c999fSMiguel Ojeda } 151808c999fSMiguel Ojeda 152808c999fSMiguel Ojeda ast_struct! { 153808c999fSMiguel Ojeda /// The dots in a tuple or slice pattern: `[0, 1, ..]`. 154808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 155808c999fSMiguel Ojeda pub struct PatRest { 156808c999fSMiguel Ojeda pub attrs: Vec<Attribute>, 157808c999fSMiguel Ojeda pub dot2_token: Token![..], 158808c999fSMiguel Ojeda } 159808c999fSMiguel Ojeda } 160808c999fSMiguel Ojeda 161808c999fSMiguel Ojeda ast_struct! { 162808c999fSMiguel Ojeda /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`. 163808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 164808c999fSMiguel Ojeda pub struct PatSlice { 165808c999fSMiguel Ojeda pub attrs: Vec<Attribute>, 166808c999fSMiguel Ojeda pub bracket_token: token::Bracket, 167808c999fSMiguel Ojeda pub elems: Punctuated<Pat, Token![,]>, 168808c999fSMiguel Ojeda } 169808c999fSMiguel Ojeda } 170808c999fSMiguel Ojeda 171808c999fSMiguel Ojeda ast_struct! { 172808c999fSMiguel Ojeda /// A struct or struct variant pattern: `Variant { x, y, .. }`. 173808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 174808c999fSMiguel Ojeda pub struct PatStruct { 175808c999fSMiguel Ojeda pub attrs: Vec<Attribute>, 176808c999fSMiguel Ojeda pub qself: Option<QSelf>, 177808c999fSMiguel Ojeda pub path: Path, 178808c999fSMiguel Ojeda pub brace_token: token::Brace, 179808c999fSMiguel Ojeda pub fields: Punctuated<FieldPat, Token![,]>, 180808c999fSMiguel Ojeda pub rest: Option<PatRest>, 181808c999fSMiguel Ojeda } 182808c999fSMiguel Ojeda } 183808c999fSMiguel Ojeda 184808c999fSMiguel Ojeda ast_struct! { 185808c999fSMiguel Ojeda /// A tuple pattern: `(a, b)`. 186808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 187808c999fSMiguel Ojeda pub struct PatTuple { 188808c999fSMiguel Ojeda pub attrs: Vec<Attribute>, 189808c999fSMiguel Ojeda pub paren_token: token::Paren, 190808c999fSMiguel Ojeda pub elems: Punctuated<Pat, Token![,]>, 191808c999fSMiguel Ojeda } 192808c999fSMiguel Ojeda } 193808c999fSMiguel Ojeda 194808c999fSMiguel Ojeda ast_struct! { 195808c999fSMiguel Ojeda /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`. 196808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 197808c999fSMiguel Ojeda pub struct PatTupleStruct { 198808c999fSMiguel Ojeda pub attrs: Vec<Attribute>, 199808c999fSMiguel Ojeda pub qself: Option<QSelf>, 200808c999fSMiguel Ojeda pub path: Path, 201808c999fSMiguel Ojeda pub paren_token: token::Paren, 202808c999fSMiguel Ojeda pub elems: Punctuated<Pat, Token![,]>, 203808c999fSMiguel Ojeda } 204808c999fSMiguel Ojeda } 205808c999fSMiguel Ojeda 206808c999fSMiguel Ojeda ast_struct! { 207808c999fSMiguel Ojeda /// A type ascription pattern: `foo: f64`. 208808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 209808c999fSMiguel Ojeda pub struct PatType { 210808c999fSMiguel Ojeda pub attrs: Vec<Attribute>, 211808c999fSMiguel Ojeda pub pat: Box<Pat>, 212808c999fSMiguel Ojeda pub colon_token: Token![:], 213808c999fSMiguel Ojeda pub ty: Box<Type>, 214808c999fSMiguel Ojeda } 215808c999fSMiguel Ojeda } 216808c999fSMiguel Ojeda 217808c999fSMiguel Ojeda ast_struct! { 218808c999fSMiguel Ojeda /// A pattern that matches any value: `_`. 219808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 220808c999fSMiguel Ojeda pub struct PatWild { 221808c999fSMiguel Ojeda pub attrs: Vec<Attribute>, 222808c999fSMiguel Ojeda pub underscore_token: Token![_], 223808c999fSMiguel Ojeda } 224808c999fSMiguel Ojeda } 225808c999fSMiguel Ojeda 226808c999fSMiguel Ojeda ast_struct! { 227808c999fSMiguel Ojeda /// A single field in a struct pattern. 228808c999fSMiguel Ojeda /// 229808c999fSMiguel Ojeda /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated 230808c999fSMiguel Ojeda /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token. 231808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "full")))] 232808c999fSMiguel Ojeda pub struct FieldPat { 233808c999fSMiguel Ojeda pub attrs: Vec<Attribute>, 234808c999fSMiguel Ojeda pub member: Member, 235808c999fSMiguel Ojeda pub colon_token: Option<Token![:]>, 236808c999fSMiguel Ojeda pub pat: Box<Pat>, 237808c999fSMiguel Ojeda } 238808c999fSMiguel Ojeda } 239808c999fSMiguel Ojeda 240808c999fSMiguel Ojeda #[cfg(feature = "parsing")] 241808c999fSMiguel Ojeda pub(crate) mod parsing { 242808c999fSMiguel Ojeda use crate::attr::Attribute; 243808c999fSMiguel Ojeda use crate::error::{self, Result}; 244808c999fSMiguel Ojeda use crate::expr::{ 245808c999fSMiguel Ojeda Expr, ExprConst, ExprLit, ExprMacro, ExprPath, ExprRange, Member, RangeLimits, 246808c999fSMiguel Ojeda }; 247808c999fSMiguel Ojeda use crate::ext::IdentExt as _; 248808c999fSMiguel Ojeda use crate::ident::Ident; 249808c999fSMiguel Ojeda use crate::lit::Lit; 250808c999fSMiguel Ojeda use crate::mac::{self, Macro}; 251808c999fSMiguel Ojeda use crate::parse::{Parse, ParseBuffer, ParseStream}; 252808c999fSMiguel Ojeda use crate::pat::{ 253808c999fSMiguel Ojeda FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct, 254808c999fSMiguel Ojeda PatTuple, PatTupleStruct, PatType, PatWild, 255808c999fSMiguel Ojeda }; 256808c999fSMiguel Ojeda use crate::path::{self, Path, QSelf}; 257808c999fSMiguel Ojeda use crate::punctuated::Punctuated; 258808c999fSMiguel Ojeda use crate::stmt::Block; 259808c999fSMiguel Ojeda use crate::token; 260808c999fSMiguel Ojeda use crate::verbatim; 261808c999fSMiguel Ojeda use proc_macro2::TokenStream; 262808c999fSMiguel Ojeda 263808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 264808c999fSMiguel Ojeda impl Pat { 265808c999fSMiguel Ojeda /// Parse a pattern that does _not_ involve `|` at the top level. 266808c999fSMiguel Ojeda /// 267808c999fSMiguel Ojeda /// This parser matches the behavior of the `$:pat_param` macro_rules 268808c999fSMiguel Ojeda /// matcher, and on editions prior to Rust 2021, the behavior of 269808c999fSMiguel Ojeda /// `$:pat`. 270808c999fSMiguel Ojeda /// 271808c999fSMiguel Ojeda /// In Rust syntax, some examples of where this syntax would occur are 272808c999fSMiguel Ojeda /// in the argument pattern of functions and closures. Patterns using 273808c999fSMiguel Ojeda /// `|` are not allowed to occur in these positions. 274808c999fSMiguel Ojeda /// 275808c999fSMiguel Ojeda /// ```compile_fail 276808c999fSMiguel Ojeda /// fn f(Some(_) | None: Option<T>) { 277808c999fSMiguel Ojeda /// let _ = |Some(_) | None: Option<T>| {}; 278808c999fSMiguel Ojeda /// // ^^^^^^^^^^^^^^^^^^^^^^^^^??? :( 279808c999fSMiguel Ojeda /// } 280808c999fSMiguel Ojeda /// ``` 281808c999fSMiguel Ojeda /// 282808c999fSMiguel Ojeda /// ```console 283808c999fSMiguel Ojeda /// error: top-level or-patterns are not allowed in function parameters 284808c999fSMiguel Ojeda /// --> src/main.rs:1:6 285808c999fSMiguel Ojeda /// | 286808c999fSMiguel Ojeda /// 1 | fn f(Some(_) | None: Option<T>) { 287808c999fSMiguel Ojeda /// | ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Some(_) | None)` 288808c999fSMiguel Ojeda /// ``` parse_single(input: ParseStream) -> Result<Self>289808c999fSMiguel Ojeda pub fn parse_single(input: ParseStream) -> Result<Self> { 290808c999fSMiguel Ojeda let begin = input.fork(); 291808c999fSMiguel Ojeda let lookahead = input.lookahead1(); 292808c999fSMiguel Ojeda if lookahead.peek(Ident) 293808c999fSMiguel Ojeda && (input.peek2(Token![::]) 294808c999fSMiguel Ojeda || input.peek2(Token![!]) 295808c999fSMiguel Ojeda || input.peek2(token::Brace) 296808c999fSMiguel Ojeda || input.peek2(token::Paren) 297808c999fSMiguel Ojeda || input.peek2(Token![..])) 298808c999fSMiguel Ojeda || input.peek(Token![self]) && input.peek2(Token![::]) 299808c999fSMiguel Ojeda || lookahead.peek(Token![::]) 300808c999fSMiguel Ojeda || lookahead.peek(Token![<]) 301808c999fSMiguel Ojeda || input.peek(Token![Self]) 302808c999fSMiguel Ojeda || input.peek(Token![super]) 303808c999fSMiguel Ojeda || input.peek(Token![crate]) 304808c999fSMiguel Ojeda { 305808c999fSMiguel Ojeda pat_path_or_macro_or_struct_or_range(input) 306808c999fSMiguel Ojeda } else if lookahead.peek(Token![_]) { 307808c999fSMiguel Ojeda input.call(pat_wild).map(Pat::Wild) 308808c999fSMiguel Ojeda } else if input.peek(Token![box]) { 309808c999fSMiguel Ojeda pat_box(begin, input) 310808c999fSMiguel Ojeda } else if input.peek(Token![-]) || lookahead.peek(Lit) || lookahead.peek(Token![const]) 311808c999fSMiguel Ojeda { 312808c999fSMiguel Ojeda pat_lit_or_range(input) 313808c999fSMiguel Ojeda } else if lookahead.peek(Token![ref]) 314808c999fSMiguel Ojeda || lookahead.peek(Token![mut]) 315808c999fSMiguel Ojeda || input.peek(Token![self]) 316808c999fSMiguel Ojeda || input.peek(Ident) 317808c999fSMiguel Ojeda { 318808c999fSMiguel Ojeda input.call(pat_ident).map(Pat::Ident) 319808c999fSMiguel Ojeda } else if lookahead.peek(Token![&]) { 320808c999fSMiguel Ojeda input.call(pat_reference).map(Pat::Reference) 321808c999fSMiguel Ojeda } else if lookahead.peek(token::Paren) { 322808c999fSMiguel Ojeda input.call(pat_paren_or_tuple) 323808c999fSMiguel Ojeda } else if lookahead.peek(token::Bracket) { 324808c999fSMiguel Ojeda input.call(pat_slice).map(Pat::Slice) 325808c999fSMiguel Ojeda } else if lookahead.peek(Token![..]) && !input.peek(Token![...]) { 326808c999fSMiguel Ojeda pat_range_half_open(input) 327808c999fSMiguel Ojeda } else if lookahead.peek(Token![const]) { 328808c999fSMiguel Ojeda input.call(pat_const).map(Pat::Verbatim) 329808c999fSMiguel Ojeda } else { 330808c999fSMiguel Ojeda Err(lookahead.error()) 331808c999fSMiguel Ojeda } 332808c999fSMiguel Ojeda } 333808c999fSMiguel Ojeda 334808c999fSMiguel Ojeda /// Parse a pattern, possibly involving `|`, but not a leading `|`. parse_multi(input: ParseStream) -> Result<Self>335808c999fSMiguel Ojeda pub fn parse_multi(input: ParseStream) -> Result<Self> { 336808c999fSMiguel Ojeda multi_pat_impl(input, None) 337808c999fSMiguel Ojeda } 338808c999fSMiguel Ojeda 339808c999fSMiguel Ojeda /// Parse a pattern, possibly involving `|`, possibly including a 340808c999fSMiguel Ojeda /// leading `|`. 341808c999fSMiguel Ojeda /// 342808c999fSMiguel Ojeda /// This parser matches the behavior of the Rust 2021 edition's `$:pat` 343808c999fSMiguel Ojeda /// macro_rules matcher. 344808c999fSMiguel Ojeda /// 345808c999fSMiguel Ojeda /// In Rust syntax, an example of where this syntax would occur is in 346808c999fSMiguel Ojeda /// the pattern of a `match` arm, where the language permits an optional 347808c999fSMiguel Ojeda /// leading `|`, although it is not idiomatic to write one there in 348808c999fSMiguel Ojeda /// handwritten code. 349808c999fSMiguel Ojeda /// 350808c999fSMiguel Ojeda /// ``` 351808c999fSMiguel Ojeda /// # let wat = None; 352808c999fSMiguel Ojeda /// match wat { 353808c999fSMiguel Ojeda /// | None | Some(false) => {} 354808c999fSMiguel Ojeda /// | Some(true) => {} 355808c999fSMiguel Ojeda /// } 356808c999fSMiguel Ojeda /// ``` 357808c999fSMiguel Ojeda /// 358808c999fSMiguel Ojeda /// The compiler accepts it only to facilitate some situations in 359808c999fSMiguel Ojeda /// macro-generated code where a macro author might need to write: 360808c999fSMiguel Ojeda /// 361808c999fSMiguel Ojeda /// ``` 362808c999fSMiguel Ojeda /// # macro_rules! doc { 363808c999fSMiguel Ojeda /// # ($value:expr, ($($conditions1:pat),*), ($($conditions2:pat),*), $then:expr) => { 364808c999fSMiguel Ojeda /// match $value { 365808c999fSMiguel Ojeda /// $(| $conditions1)* $(| $conditions2)* => $then 366808c999fSMiguel Ojeda /// } 367808c999fSMiguel Ojeda /// # }; 368808c999fSMiguel Ojeda /// # } 369808c999fSMiguel Ojeda /// # 370808c999fSMiguel Ojeda /// # doc!(true, (true), (false), {}); 371808c999fSMiguel Ojeda /// # doc!(true, (), (true, false), {}); 372808c999fSMiguel Ojeda /// # doc!(true, (true, false), (), {}); 373808c999fSMiguel Ojeda /// ``` 374808c999fSMiguel Ojeda /// 375808c999fSMiguel Ojeda /// Expressing the same thing correctly in the case that either one (but 376808c999fSMiguel Ojeda /// not both) of `$conditions1` and `$conditions2` might be empty, 377808c999fSMiguel Ojeda /// without leading `|`, is complex. 378808c999fSMiguel Ojeda /// 379808c999fSMiguel Ojeda /// Use [`Pat::parse_multi`] instead if you are not intending to support 380808c999fSMiguel Ojeda /// macro-generated macro input. parse_multi_with_leading_vert(input: ParseStream) -> Result<Self>381808c999fSMiguel Ojeda pub fn parse_multi_with_leading_vert(input: ParseStream) -> Result<Self> { 382808c999fSMiguel Ojeda let leading_vert: Option<Token![|]> = input.parse()?; 383808c999fSMiguel Ojeda multi_pat_impl(input, leading_vert) 384808c999fSMiguel Ojeda } 385808c999fSMiguel Ojeda } 386808c999fSMiguel Ojeda 387808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))] 388808c999fSMiguel Ojeda impl Parse for PatType { parse(input: ParseStream) -> Result<Self>389808c999fSMiguel Ojeda fn parse(input: ParseStream) -> Result<Self> { 390808c999fSMiguel Ojeda Ok(PatType { 391808c999fSMiguel Ojeda attrs: Vec::new(), 392808c999fSMiguel Ojeda pat: Box::new(Pat::parse_single(input)?), 393808c999fSMiguel Ojeda colon_token: input.parse()?, 394808c999fSMiguel Ojeda ty: input.parse()?, 395808c999fSMiguel Ojeda }) 396808c999fSMiguel Ojeda } 397808c999fSMiguel Ojeda } 398808c999fSMiguel Ojeda multi_pat_impl(input: ParseStream, leading_vert: Option<Token![|]>) -> Result<Pat>399808c999fSMiguel Ojeda fn multi_pat_impl(input: ParseStream, leading_vert: Option<Token![|]>) -> Result<Pat> { 400808c999fSMiguel Ojeda let mut pat = Pat::parse_single(input)?; 401808c999fSMiguel Ojeda if leading_vert.is_some() 402808c999fSMiguel Ojeda || input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) 403808c999fSMiguel Ojeda { 404808c999fSMiguel Ojeda let mut cases = Punctuated::new(); 405808c999fSMiguel Ojeda cases.push_value(pat); 406808c999fSMiguel Ojeda while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) { 407808c999fSMiguel Ojeda let punct = input.parse()?; 408808c999fSMiguel Ojeda cases.push_punct(punct); 409808c999fSMiguel Ojeda let pat = Pat::parse_single(input)?; 410808c999fSMiguel Ojeda cases.push_value(pat); 411808c999fSMiguel Ojeda } 412808c999fSMiguel Ojeda pat = Pat::Or(PatOr { 413808c999fSMiguel Ojeda attrs: Vec::new(), 414808c999fSMiguel Ojeda leading_vert, 415808c999fSMiguel Ojeda cases, 416808c999fSMiguel Ojeda }); 417808c999fSMiguel Ojeda } 418808c999fSMiguel Ojeda Ok(pat) 419808c999fSMiguel Ojeda } 420808c999fSMiguel Ojeda pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat>421808c999fSMiguel Ojeda fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> { 422808c999fSMiguel Ojeda let expr_style = true; 423808c999fSMiguel Ojeda let (qself, path) = path::parsing::qpath(input, expr_style)?; 424808c999fSMiguel Ojeda 425808c999fSMiguel Ojeda if qself.is_none() 426808c999fSMiguel Ojeda && input.peek(Token![!]) 427808c999fSMiguel Ojeda && !input.peek(Token![!=]) 428808c999fSMiguel Ojeda && path.is_mod_style() 429808c999fSMiguel Ojeda { 430808c999fSMiguel Ojeda let bang_token: Token![!] = input.parse()?; 431808c999fSMiguel Ojeda let (delimiter, tokens) = mac::parse_delimiter(input)?; 432808c999fSMiguel Ojeda return Ok(Pat::Macro(ExprMacro { 433808c999fSMiguel Ojeda attrs: Vec::new(), 434808c999fSMiguel Ojeda mac: Macro { 435808c999fSMiguel Ojeda path, 436808c999fSMiguel Ojeda bang_token, 437808c999fSMiguel Ojeda delimiter, 438808c999fSMiguel Ojeda tokens, 439808c999fSMiguel Ojeda }, 440808c999fSMiguel Ojeda })); 441808c999fSMiguel Ojeda } 442808c999fSMiguel Ojeda 443808c999fSMiguel Ojeda if input.peek(token::Brace) { 444808c999fSMiguel Ojeda pat_struct(input, qself, path).map(Pat::Struct) 445808c999fSMiguel Ojeda } else if input.peek(token::Paren) { 446808c999fSMiguel Ojeda pat_tuple_struct(input, qself, path).map(Pat::TupleStruct) 447808c999fSMiguel Ojeda } else if input.peek(Token![..]) { 448808c999fSMiguel Ojeda pat_range(input, qself, path) 449808c999fSMiguel Ojeda } else { 450808c999fSMiguel Ojeda Ok(Pat::Path(ExprPath { 451808c999fSMiguel Ojeda attrs: Vec::new(), 452808c999fSMiguel Ojeda qself, 453808c999fSMiguel Ojeda path, 454808c999fSMiguel Ojeda })) 455808c999fSMiguel Ojeda } 456808c999fSMiguel Ojeda } 457808c999fSMiguel Ojeda pat_wild(input: ParseStream) -> Result<PatWild>458808c999fSMiguel Ojeda fn pat_wild(input: ParseStream) -> Result<PatWild> { 459808c999fSMiguel Ojeda Ok(PatWild { 460808c999fSMiguel Ojeda attrs: Vec::new(), 461808c999fSMiguel Ojeda underscore_token: input.parse()?, 462808c999fSMiguel Ojeda }) 463808c999fSMiguel Ojeda } 464808c999fSMiguel Ojeda pat_box(begin: ParseBuffer, input: ParseStream) -> Result<Pat>465808c999fSMiguel Ojeda fn pat_box(begin: ParseBuffer, input: ParseStream) -> Result<Pat> { 466808c999fSMiguel Ojeda input.parse::<Token![box]>()?; 467808c999fSMiguel Ojeda Pat::parse_single(input)?; 468808c999fSMiguel Ojeda Ok(Pat::Verbatim(verbatim::between(&begin, input))) 469808c999fSMiguel Ojeda } 470808c999fSMiguel Ojeda pat_ident(input: ParseStream) -> Result<PatIdent>471808c999fSMiguel Ojeda fn pat_ident(input: ParseStream) -> Result<PatIdent> { 472808c999fSMiguel Ojeda Ok(PatIdent { 473808c999fSMiguel Ojeda attrs: Vec::new(), 474808c999fSMiguel Ojeda by_ref: input.parse()?, 475808c999fSMiguel Ojeda mutability: input.parse()?, 476808c999fSMiguel Ojeda ident: { 477808c999fSMiguel Ojeda if input.peek(Token![self]) { 478808c999fSMiguel Ojeda input.call(Ident::parse_any)? 479808c999fSMiguel Ojeda } else { 480808c999fSMiguel Ojeda input.parse()? 481808c999fSMiguel Ojeda } 482808c999fSMiguel Ojeda }, 483808c999fSMiguel Ojeda subpat: { 484808c999fSMiguel Ojeda if input.peek(Token![@]) { 485808c999fSMiguel Ojeda let at_token: Token![@] = input.parse()?; 486808c999fSMiguel Ojeda let subpat = Pat::parse_single(input)?; 487808c999fSMiguel Ojeda Some((at_token, Box::new(subpat))) 488808c999fSMiguel Ojeda } else { 489808c999fSMiguel Ojeda None 490808c999fSMiguel Ojeda } 491808c999fSMiguel Ojeda }, 492808c999fSMiguel Ojeda }) 493808c999fSMiguel Ojeda } 494808c999fSMiguel Ojeda pat_tuple_struct( input: ParseStream, qself: Option<QSelf>, path: Path, ) -> Result<PatTupleStruct>495808c999fSMiguel Ojeda fn pat_tuple_struct( 496808c999fSMiguel Ojeda input: ParseStream, 497808c999fSMiguel Ojeda qself: Option<QSelf>, 498808c999fSMiguel Ojeda path: Path, 499808c999fSMiguel Ojeda ) -> Result<PatTupleStruct> { 500808c999fSMiguel Ojeda let content; 501808c999fSMiguel Ojeda let paren_token = parenthesized!(content in input); 502808c999fSMiguel Ojeda 503808c999fSMiguel Ojeda let mut elems = Punctuated::new(); 504808c999fSMiguel Ojeda while !content.is_empty() { 505808c999fSMiguel Ojeda let value = Pat::parse_multi_with_leading_vert(&content)?; 506808c999fSMiguel Ojeda elems.push_value(value); 507808c999fSMiguel Ojeda if content.is_empty() { 508808c999fSMiguel Ojeda break; 509808c999fSMiguel Ojeda } 510808c999fSMiguel Ojeda let punct = content.parse()?; 511808c999fSMiguel Ojeda elems.push_punct(punct); 512808c999fSMiguel Ojeda } 513808c999fSMiguel Ojeda 514808c999fSMiguel Ojeda Ok(PatTupleStruct { 515808c999fSMiguel Ojeda attrs: Vec::new(), 516808c999fSMiguel Ojeda qself, 517808c999fSMiguel Ojeda path, 518808c999fSMiguel Ojeda paren_token, 519808c999fSMiguel Ojeda elems, 520808c999fSMiguel Ojeda }) 521808c999fSMiguel Ojeda } 522808c999fSMiguel Ojeda pat_struct(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatStruct>523808c999fSMiguel Ojeda fn pat_struct(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatStruct> { 524808c999fSMiguel Ojeda let content; 525808c999fSMiguel Ojeda let brace_token = braced!(content in input); 526808c999fSMiguel Ojeda 527808c999fSMiguel Ojeda let mut fields = Punctuated::new(); 528808c999fSMiguel Ojeda let mut rest = None; 529808c999fSMiguel Ojeda while !content.is_empty() { 530808c999fSMiguel Ojeda let attrs = content.call(Attribute::parse_outer)?; 531808c999fSMiguel Ojeda if content.peek(Token![..]) { 532808c999fSMiguel Ojeda rest = Some(PatRest { 533808c999fSMiguel Ojeda attrs, 534808c999fSMiguel Ojeda dot2_token: content.parse()?, 535808c999fSMiguel Ojeda }); 536808c999fSMiguel Ojeda break; 537808c999fSMiguel Ojeda } 538808c999fSMiguel Ojeda let mut value = content.call(field_pat)?; 539808c999fSMiguel Ojeda value.attrs = attrs; 540808c999fSMiguel Ojeda fields.push_value(value); 541808c999fSMiguel Ojeda if content.is_empty() { 542808c999fSMiguel Ojeda break; 543808c999fSMiguel Ojeda } 544808c999fSMiguel Ojeda let punct: Token![,] = content.parse()?; 545808c999fSMiguel Ojeda fields.push_punct(punct); 546808c999fSMiguel Ojeda } 547808c999fSMiguel Ojeda 548808c999fSMiguel Ojeda Ok(PatStruct { 549808c999fSMiguel Ojeda attrs: Vec::new(), 550808c999fSMiguel Ojeda qself, 551808c999fSMiguel Ojeda path, 552808c999fSMiguel Ojeda brace_token, 553808c999fSMiguel Ojeda fields, 554808c999fSMiguel Ojeda rest, 555808c999fSMiguel Ojeda }) 556808c999fSMiguel Ojeda } 557808c999fSMiguel Ojeda field_pat(input: ParseStream) -> Result<FieldPat>558808c999fSMiguel Ojeda fn field_pat(input: ParseStream) -> Result<FieldPat> { 559808c999fSMiguel Ojeda let begin = input.fork(); 560808c999fSMiguel Ojeda let boxed: Option<Token![box]> = input.parse()?; 561808c999fSMiguel Ojeda let by_ref: Option<Token![ref]> = input.parse()?; 562808c999fSMiguel Ojeda let mutability: Option<Token![mut]> = input.parse()?; 563808c999fSMiguel Ojeda 564808c999fSMiguel Ojeda let member = if boxed.is_some() || by_ref.is_some() || mutability.is_some() { 565808c999fSMiguel Ojeda input.parse().map(Member::Named) 566808c999fSMiguel Ojeda } else { 567808c999fSMiguel Ojeda input.parse() 568808c999fSMiguel Ojeda }?; 569808c999fSMiguel Ojeda 570808c999fSMiguel Ojeda if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:]) 571808c999fSMiguel Ojeda || !member.is_named() 572808c999fSMiguel Ojeda { 573808c999fSMiguel Ojeda return Ok(FieldPat { 574808c999fSMiguel Ojeda attrs: Vec::new(), 575808c999fSMiguel Ojeda member, 576808c999fSMiguel Ojeda colon_token: Some(input.parse()?), 577808c999fSMiguel Ojeda pat: Box::new(Pat::parse_multi_with_leading_vert(input)?), 578808c999fSMiguel Ojeda }); 579808c999fSMiguel Ojeda } 580808c999fSMiguel Ojeda 581808c999fSMiguel Ojeda let ident = match member { 582808c999fSMiguel Ojeda Member::Named(ident) => ident, 583808c999fSMiguel Ojeda Member::Unnamed(_) => unreachable!(), 584808c999fSMiguel Ojeda }; 585808c999fSMiguel Ojeda 586808c999fSMiguel Ojeda let pat = if boxed.is_some() { 587808c999fSMiguel Ojeda Pat::Verbatim(verbatim::between(&begin, input)) 588808c999fSMiguel Ojeda } else { 589808c999fSMiguel Ojeda Pat::Ident(PatIdent { 590808c999fSMiguel Ojeda attrs: Vec::new(), 591808c999fSMiguel Ojeda by_ref, 592808c999fSMiguel Ojeda mutability, 593808c999fSMiguel Ojeda ident: ident.clone(), 594808c999fSMiguel Ojeda subpat: None, 595808c999fSMiguel Ojeda }) 596808c999fSMiguel Ojeda }; 597808c999fSMiguel Ojeda 598808c999fSMiguel Ojeda Ok(FieldPat { 599808c999fSMiguel Ojeda attrs: Vec::new(), 600808c999fSMiguel Ojeda member: Member::Named(ident), 601808c999fSMiguel Ojeda colon_token: None, 602808c999fSMiguel Ojeda pat: Box::new(pat), 603808c999fSMiguel Ojeda }) 604808c999fSMiguel Ojeda } 605808c999fSMiguel Ojeda pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<Pat>606808c999fSMiguel Ojeda fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<Pat> { 607808c999fSMiguel Ojeda let limits = RangeLimits::parse_obsolete(input)?; 608808c999fSMiguel Ojeda let end = input.call(pat_range_bound)?; 609808c999fSMiguel Ojeda if let (RangeLimits::Closed(_), None) = (&limits, &end) { 610808c999fSMiguel Ojeda return Err(input.error("expected range upper bound")); 611808c999fSMiguel Ojeda } 612808c999fSMiguel Ojeda Ok(Pat::Range(ExprRange { 613808c999fSMiguel Ojeda attrs: Vec::new(), 614808c999fSMiguel Ojeda start: Some(Box::new(Expr::Path(ExprPath { 615808c999fSMiguel Ojeda attrs: Vec::new(), 616808c999fSMiguel Ojeda qself, 617808c999fSMiguel Ojeda path, 618808c999fSMiguel Ojeda }))), 619808c999fSMiguel Ojeda limits, 620808c999fSMiguel Ojeda end: end.map(PatRangeBound::into_expr), 621808c999fSMiguel Ojeda })) 622808c999fSMiguel Ojeda } 623808c999fSMiguel Ojeda pat_range_half_open(input: ParseStream) -> Result<Pat>624808c999fSMiguel Ojeda fn pat_range_half_open(input: ParseStream) -> Result<Pat> { 625808c999fSMiguel Ojeda let limits: RangeLimits = input.parse()?; 626808c999fSMiguel Ojeda let end = input.call(pat_range_bound)?; 627808c999fSMiguel Ojeda if end.is_some() { 628808c999fSMiguel Ojeda Ok(Pat::Range(ExprRange { 629808c999fSMiguel Ojeda attrs: Vec::new(), 630808c999fSMiguel Ojeda start: None, 631808c999fSMiguel Ojeda limits, 632808c999fSMiguel Ojeda end: end.map(PatRangeBound::into_expr), 633808c999fSMiguel Ojeda })) 634808c999fSMiguel Ojeda } else { 635808c999fSMiguel Ojeda match limits { 636808c999fSMiguel Ojeda RangeLimits::HalfOpen(dot2_token) => Ok(Pat::Rest(PatRest { 637808c999fSMiguel Ojeda attrs: Vec::new(), 638808c999fSMiguel Ojeda dot2_token, 639808c999fSMiguel Ojeda })), 640808c999fSMiguel Ojeda RangeLimits::Closed(_) => Err(input.error("expected range upper bound")), 641808c999fSMiguel Ojeda } 642808c999fSMiguel Ojeda } 643808c999fSMiguel Ojeda } 644808c999fSMiguel Ojeda pat_paren_or_tuple(input: ParseStream) -> Result<Pat>645808c999fSMiguel Ojeda fn pat_paren_or_tuple(input: ParseStream) -> Result<Pat> { 646808c999fSMiguel Ojeda let content; 647808c999fSMiguel Ojeda let paren_token = parenthesized!(content in input); 648808c999fSMiguel Ojeda 649808c999fSMiguel Ojeda let mut elems = Punctuated::new(); 650808c999fSMiguel Ojeda while !content.is_empty() { 651808c999fSMiguel Ojeda let value = Pat::parse_multi_with_leading_vert(&content)?; 652808c999fSMiguel Ojeda if content.is_empty() { 653808c999fSMiguel Ojeda if elems.is_empty() && !matches!(value, Pat::Rest(_)) { 654808c999fSMiguel Ojeda return Ok(Pat::Paren(PatParen { 655808c999fSMiguel Ojeda attrs: Vec::new(), 656808c999fSMiguel Ojeda paren_token, 657808c999fSMiguel Ojeda pat: Box::new(value), 658808c999fSMiguel Ojeda })); 659808c999fSMiguel Ojeda } 660808c999fSMiguel Ojeda elems.push_value(value); 661808c999fSMiguel Ojeda break; 662808c999fSMiguel Ojeda } 663808c999fSMiguel Ojeda elems.push_value(value); 664808c999fSMiguel Ojeda let punct = content.parse()?; 665808c999fSMiguel Ojeda elems.push_punct(punct); 666808c999fSMiguel Ojeda } 667808c999fSMiguel Ojeda 668808c999fSMiguel Ojeda Ok(Pat::Tuple(PatTuple { 669808c999fSMiguel Ojeda attrs: Vec::new(), 670808c999fSMiguel Ojeda paren_token, 671808c999fSMiguel Ojeda elems, 672808c999fSMiguel Ojeda })) 673808c999fSMiguel Ojeda } 674808c999fSMiguel Ojeda pat_reference(input: ParseStream) -> Result<PatReference>675808c999fSMiguel Ojeda fn pat_reference(input: ParseStream) -> Result<PatReference> { 676808c999fSMiguel Ojeda Ok(PatReference { 677808c999fSMiguel Ojeda attrs: Vec::new(), 678808c999fSMiguel Ojeda and_token: input.parse()?, 679808c999fSMiguel Ojeda mutability: input.parse()?, 680808c999fSMiguel Ojeda pat: Box::new(Pat::parse_single(input)?), 681808c999fSMiguel Ojeda }) 682808c999fSMiguel Ojeda } 683808c999fSMiguel Ojeda pat_lit_or_range(input: ParseStream) -> Result<Pat>684808c999fSMiguel Ojeda fn pat_lit_or_range(input: ParseStream) -> Result<Pat> { 685808c999fSMiguel Ojeda let start = input.call(pat_range_bound)?.unwrap(); 686808c999fSMiguel Ojeda if input.peek(Token![..]) { 687808c999fSMiguel Ojeda let limits = RangeLimits::parse_obsolete(input)?; 688808c999fSMiguel Ojeda let end = input.call(pat_range_bound)?; 689808c999fSMiguel Ojeda if let (RangeLimits::Closed(_), None) = (&limits, &end) { 690808c999fSMiguel Ojeda return Err(input.error("expected range upper bound")); 691808c999fSMiguel Ojeda } 692808c999fSMiguel Ojeda Ok(Pat::Range(ExprRange { 693808c999fSMiguel Ojeda attrs: Vec::new(), 694808c999fSMiguel Ojeda start: Some(start.into_expr()), 695808c999fSMiguel Ojeda limits, 696808c999fSMiguel Ojeda end: end.map(PatRangeBound::into_expr), 697808c999fSMiguel Ojeda })) 698808c999fSMiguel Ojeda } else { 699808c999fSMiguel Ojeda Ok(start.into_pat()) 700808c999fSMiguel Ojeda } 701808c999fSMiguel Ojeda } 702808c999fSMiguel Ojeda 703808c999fSMiguel Ojeda // Patterns that can appear on either side of a range pattern. 704808c999fSMiguel Ojeda enum PatRangeBound { 705808c999fSMiguel Ojeda Const(ExprConst), 706808c999fSMiguel Ojeda Lit(ExprLit), 707808c999fSMiguel Ojeda Path(ExprPath), 708808c999fSMiguel Ojeda } 709808c999fSMiguel Ojeda 710808c999fSMiguel Ojeda impl PatRangeBound { into_expr(self) -> Box<Expr>711808c999fSMiguel Ojeda fn into_expr(self) -> Box<Expr> { 712808c999fSMiguel Ojeda Box::new(match self { 713808c999fSMiguel Ojeda PatRangeBound::Const(pat) => Expr::Const(pat), 714808c999fSMiguel Ojeda PatRangeBound::Lit(pat) => Expr::Lit(pat), 715808c999fSMiguel Ojeda PatRangeBound::Path(pat) => Expr::Path(pat), 716808c999fSMiguel Ojeda }) 717808c999fSMiguel Ojeda } 718808c999fSMiguel Ojeda into_pat(self) -> Pat719808c999fSMiguel Ojeda fn into_pat(self) -> Pat { 720808c999fSMiguel Ojeda match self { 721808c999fSMiguel Ojeda PatRangeBound::Const(pat) => Pat::Const(pat), 722808c999fSMiguel Ojeda PatRangeBound::Lit(pat) => Pat::Lit(pat), 723808c999fSMiguel Ojeda PatRangeBound::Path(pat) => Pat::Path(pat), 724808c999fSMiguel Ojeda } 725808c999fSMiguel Ojeda } 726808c999fSMiguel Ojeda } 727808c999fSMiguel Ojeda pat_range_bound(input: ParseStream) -> Result<Option<PatRangeBound>>728808c999fSMiguel Ojeda fn pat_range_bound(input: ParseStream) -> Result<Option<PatRangeBound>> { 729808c999fSMiguel Ojeda if input.is_empty() 730808c999fSMiguel Ojeda || input.peek(Token![|]) 731808c999fSMiguel Ojeda || input.peek(Token![=]) 732808c999fSMiguel Ojeda || input.peek(Token![:]) && !input.peek(Token![::]) 733808c999fSMiguel Ojeda || input.peek(Token![,]) 734808c999fSMiguel Ojeda || input.peek(Token![;]) 735808c999fSMiguel Ojeda || input.peek(Token![if]) 736808c999fSMiguel Ojeda { 737808c999fSMiguel Ojeda return Ok(None); 738808c999fSMiguel Ojeda } 739808c999fSMiguel Ojeda 740808c999fSMiguel Ojeda let lookahead = input.lookahead1(); 741808c999fSMiguel Ojeda let expr = if lookahead.peek(Lit) { 742808c999fSMiguel Ojeda PatRangeBound::Lit(input.parse()?) 743808c999fSMiguel Ojeda } else if lookahead.peek(Ident) 744808c999fSMiguel Ojeda || lookahead.peek(Token![::]) 745808c999fSMiguel Ojeda || lookahead.peek(Token![<]) 746808c999fSMiguel Ojeda || lookahead.peek(Token![self]) 747808c999fSMiguel Ojeda || lookahead.peek(Token![Self]) 748808c999fSMiguel Ojeda || lookahead.peek(Token![super]) 749808c999fSMiguel Ojeda || lookahead.peek(Token![crate]) 750808c999fSMiguel Ojeda { 751808c999fSMiguel Ojeda PatRangeBound::Path(input.parse()?) 752808c999fSMiguel Ojeda } else if lookahead.peek(Token![const]) { 753808c999fSMiguel Ojeda PatRangeBound::Const(input.parse()?) 754808c999fSMiguel Ojeda } else { 755808c999fSMiguel Ojeda return Err(lookahead.error()); 756808c999fSMiguel Ojeda }; 757808c999fSMiguel Ojeda 758808c999fSMiguel Ojeda Ok(Some(expr)) 759808c999fSMiguel Ojeda } 760808c999fSMiguel Ojeda pat_slice(input: ParseStream) -> Result<PatSlice>761808c999fSMiguel Ojeda fn pat_slice(input: ParseStream) -> Result<PatSlice> { 762808c999fSMiguel Ojeda let content; 763808c999fSMiguel Ojeda let bracket_token = bracketed!(content in input); 764808c999fSMiguel Ojeda 765808c999fSMiguel Ojeda let mut elems = Punctuated::new(); 766808c999fSMiguel Ojeda while !content.is_empty() { 767808c999fSMiguel Ojeda let value = Pat::parse_multi_with_leading_vert(&content)?; 768808c999fSMiguel Ojeda match value { 769808c999fSMiguel Ojeda Pat::Range(pat) if pat.start.is_none() || pat.end.is_none() => { 770808c999fSMiguel Ojeda let (start, end) = match pat.limits { 771808c999fSMiguel Ojeda RangeLimits::HalfOpen(dot_dot) => (dot_dot.spans[0], dot_dot.spans[1]), 772808c999fSMiguel Ojeda RangeLimits::Closed(dot_dot_eq) => { 773808c999fSMiguel Ojeda (dot_dot_eq.spans[0], dot_dot_eq.spans[2]) 774808c999fSMiguel Ojeda } 775808c999fSMiguel Ojeda }; 776808c999fSMiguel Ojeda let msg = "range pattern is not allowed unparenthesized inside slice pattern"; 777808c999fSMiguel Ojeda return Err(error::new2(start, end, msg)); 778808c999fSMiguel Ojeda } 779808c999fSMiguel Ojeda _ => {} 780808c999fSMiguel Ojeda } 781808c999fSMiguel Ojeda elems.push_value(value); 782808c999fSMiguel Ojeda if content.is_empty() { 783808c999fSMiguel Ojeda break; 784808c999fSMiguel Ojeda } 785808c999fSMiguel Ojeda let punct = content.parse()?; 786808c999fSMiguel Ojeda elems.push_punct(punct); 787808c999fSMiguel Ojeda } 788808c999fSMiguel Ojeda 789808c999fSMiguel Ojeda Ok(PatSlice { 790808c999fSMiguel Ojeda attrs: Vec::new(), 791808c999fSMiguel Ojeda bracket_token, 792808c999fSMiguel Ojeda elems, 793808c999fSMiguel Ojeda }) 794808c999fSMiguel Ojeda } 795808c999fSMiguel Ojeda pat_const(input: ParseStream) -> Result<TokenStream>796808c999fSMiguel Ojeda fn pat_const(input: ParseStream) -> Result<TokenStream> { 797808c999fSMiguel Ojeda let begin = input.fork(); 798808c999fSMiguel Ojeda input.parse::<Token![const]>()?; 799808c999fSMiguel Ojeda 800808c999fSMiguel Ojeda let content; 801808c999fSMiguel Ojeda braced!(content in input); 802808c999fSMiguel Ojeda content.call(Attribute::parse_inner)?; 803808c999fSMiguel Ojeda content.call(Block::parse_within)?; 804808c999fSMiguel Ojeda 805808c999fSMiguel Ojeda Ok(verbatim::between(&begin, input)) 806808c999fSMiguel Ojeda } 807808c999fSMiguel Ojeda } 808808c999fSMiguel Ojeda 809808c999fSMiguel Ojeda #[cfg(feature = "printing")] 810808c999fSMiguel Ojeda mod printing { 811808c999fSMiguel Ojeda use crate::attr::FilterAttrs; 812808c999fSMiguel Ojeda use crate::pat::{ 813808c999fSMiguel Ojeda FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct, 814808c999fSMiguel Ojeda PatTuple, PatTupleStruct, PatType, PatWild, 815808c999fSMiguel Ojeda }; 816808c999fSMiguel Ojeda use crate::path; 817808c999fSMiguel Ojeda use crate::path::printing::PathStyle; 818808c999fSMiguel Ojeda use proc_macro2::TokenStream; 819808c999fSMiguel Ojeda use quote::{ToTokens, TokenStreamExt}; 820808c999fSMiguel Ojeda 821808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 822808c999fSMiguel Ojeda impl ToTokens for PatIdent { to_tokens(&self, tokens: &mut TokenStream)823808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 824808c999fSMiguel Ojeda tokens.append_all(self.attrs.outer()); 825808c999fSMiguel Ojeda self.by_ref.to_tokens(tokens); 826808c999fSMiguel Ojeda self.mutability.to_tokens(tokens); 827808c999fSMiguel Ojeda self.ident.to_tokens(tokens); 828808c999fSMiguel Ojeda if let Some((at_token, subpat)) = &self.subpat { 829808c999fSMiguel Ojeda at_token.to_tokens(tokens); 830808c999fSMiguel Ojeda subpat.to_tokens(tokens); 831808c999fSMiguel Ojeda } 832808c999fSMiguel Ojeda } 833808c999fSMiguel Ojeda } 834808c999fSMiguel Ojeda 835808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 836808c999fSMiguel Ojeda impl ToTokens for PatOr { to_tokens(&self, tokens: &mut TokenStream)837808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 838808c999fSMiguel Ojeda tokens.append_all(self.attrs.outer()); 839808c999fSMiguel Ojeda self.leading_vert.to_tokens(tokens); 840808c999fSMiguel Ojeda self.cases.to_tokens(tokens); 841808c999fSMiguel Ojeda } 842808c999fSMiguel Ojeda } 843808c999fSMiguel Ojeda 844808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 845808c999fSMiguel Ojeda impl ToTokens for PatParen { to_tokens(&self, tokens: &mut TokenStream)846808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 847808c999fSMiguel Ojeda tokens.append_all(self.attrs.outer()); 848808c999fSMiguel Ojeda self.paren_token.surround(tokens, |tokens| { 849808c999fSMiguel Ojeda self.pat.to_tokens(tokens); 850808c999fSMiguel Ojeda }); 851808c999fSMiguel Ojeda } 852808c999fSMiguel Ojeda } 853808c999fSMiguel Ojeda 854808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 855808c999fSMiguel Ojeda impl ToTokens for PatReference { to_tokens(&self, tokens: &mut TokenStream)856808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 857808c999fSMiguel Ojeda tokens.append_all(self.attrs.outer()); 858808c999fSMiguel Ojeda self.and_token.to_tokens(tokens); 859808c999fSMiguel Ojeda self.mutability.to_tokens(tokens); 860808c999fSMiguel Ojeda self.pat.to_tokens(tokens); 861808c999fSMiguel Ojeda } 862808c999fSMiguel Ojeda } 863808c999fSMiguel Ojeda 864808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 865808c999fSMiguel Ojeda impl ToTokens for PatRest { to_tokens(&self, tokens: &mut TokenStream)866808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 867808c999fSMiguel Ojeda tokens.append_all(self.attrs.outer()); 868808c999fSMiguel Ojeda self.dot2_token.to_tokens(tokens); 869808c999fSMiguel Ojeda } 870808c999fSMiguel Ojeda } 871808c999fSMiguel Ojeda 872808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 873808c999fSMiguel Ojeda impl ToTokens for PatSlice { to_tokens(&self, tokens: &mut TokenStream)874808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 875808c999fSMiguel Ojeda tokens.append_all(self.attrs.outer()); 876808c999fSMiguel Ojeda self.bracket_token.surround(tokens, |tokens| { 877808c999fSMiguel Ojeda self.elems.to_tokens(tokens); 878808c999fSMiguel Ojeda }); 879808c999fSMiguel Ojeda } 880808c999fSMiguel Ojeda } 881808c999fSMiguel Ojeda 882808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 883808c999fSMiguel Ojeda impl ToTokens for PatStruct { to_tokens(&self, tokens: &mut TokenStream)884808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 885808c999fSMiguel Ojeda tokens.append_all(self.attrs.outer()); 886808c999fSMiguel Ojeda path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr); 887808c999fSMiguel Ojeda self.brace_token.surround(tokens, |tokens| { 888808c999fSMiguel Ojeda self.fields.to_tokens(tokens); 889808c999fSMiguel Ojeda // NOTE: We need a comma before the dot2 token if it is present. 890808c999fSMiguel Ojeda if !self.fields.empty_or_trailing() && self.rest.is_some() { 891808c999fSMiguel Ojeda <Token![,]>::default().to_tokens(tokens); 892808c999fSMiguel Ojeda } 893808c999fSMiguel Ojeda self.rest.to_tokens(tokens); 894808c999fSMiguel Ojeda }); 895808c999fSMiguel Ojeda } 896808c999fSMiguel Ojeda } 897808c999fSMiguel Ojeda 898808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 899808c999fSMiguel Ojeda impl ToTokens for PatTuple { to_tokens(&self, tokens: &mut TokenStream)900808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 901808c999fSMiguel Ojeda tokens.append_all(self.attrs.outer()); 902808c999fSMiguel Ojeda self.paren_token.surround(tokens, |tokens| { 903808c999fSMiguel Ojeda self.elems.to_tokens(tokens); 904808c999fSMiguel Ojeda // If there is only one element, a trailing comma is needed to 905808c999fSMiguel Ojeda // distinguish PatTuple from PatParen, unless this is `(..)` 906808c999fSMiguel Ojeda // which is a tuple pattern even without comma. 907808c999fSMiguel Ojeda if self.elems.len() == 1 908808c999fSMiguel Ojeda && !self.elems.trailing_punct() 909808c999fSMiguel Ojeda && !matches!(self.elems[0], Pat::Rest { .. }) 910808c999fSMiguel Ojeda { 911808c999fSMiguel Ojeda <Token![,]>::default().to_tokens(tokens); 912808c999fSMiguel Ojeda } 913808c999fSMiguel Ojeda }); 914808c999fSMiguel Ojeda } 915808c999fSMiguel Ojeda } 916808c999fSMiguel Ojeda 917808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 918808c999fSMiguel Ojeda impl ToTokens for PatTupleStruct { to_tokens(&self, tokens: &mut TokenStream)919808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 920808c999fSMiguel Ojeda tokens.append_all(self.attrs.outer()); 921808c999fSMiguel Ojeda path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr); 922808c999fSMiguel Ojeda self.paren_token.surround(tokens, |tokens| { 923808c999fSMiguel Ojeda self.elems.to_tokens(tokens); 924808c999fSMiguel Ojeda }); 925808c999fSMiguel Ojeda } 926808c999fSMiguel Ojeda } 927808c999fSMiguel Ojeda 928808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 929808c999fSMiguel Ojeda impl ToTokens for PatType { to_tokens(&self, tokens: &mut TokenStream)930808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 931808c999fSMiguel Ojeda tokens.append_all(self.attrs.outer()); 932808c999fSMiguel Ojeda self.pat.to_tokens(tokens); 933808c999fSMiguel Ojeda self.colon_token.to_tokens(tokens); 934808c999fSMiguel Ojeda self.ty.to_tokens(tokens); 935808c999fSMiguel Ojeda } 936808c999fSMiguel Ojeda } 937808c999fSMiguel Ojeda 938808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 939808c999fSMiguel Ojeda impl ToTokens for PatWild { to_tokens(&self, tokens: &mut TokenStream)940808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 941808c999fSMiguel Ojeda tokens.append_all(self.attrs.outer()); 942808c999fSMiguel Ojeda self.underscore_token.to_tokens(tokens); 943808c999fSMiguel Ojeda } 944808c999fSMiguel Ojeda } 945808c999fSMiguel Ojeda 946808c999fSMiguel Ojeda #[cfg_attr(docsrs, doc(cfg(feature = "printing")))] 947808c999fSMiguel Ojeda impl ToTokens for FieldPat { to_tokens(&self, tokens: &mut TokenStream)948808c999fSMiguel Ojeda fn to_tokens(&self, tokens: &mut TokenStream) { 949808c999fSMiguel Ojeda tokens.append_all(self.attrs.outer()); 950808c999fSMiguel Ojeda if let Some(colon_token) = &self.colon_token { 951808c999fSMiguel Ojeda self.member.to_tokens(tokens); 952808c999fSMiguel Ojeda colon_token.to_tokens(tokens); 953808c999fSMiguel Ojeda } 954808c999fSMiguel Ojeda self.pat.to_tokens(tokens); 955808c999fSMiguel Ojeda } 956808c999fSMiguel Ojeda } 957808c999fSMiguel Ojeda } 958