pat.rs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957
  1. // SPDX-License-Identifier: Apache-2.0 OR MIT
  2. use crate::attr::Attribute;
  3. use crate::expr::Member;
  4. use crate::ident::Ident;
  5. use crate::path::{Path, QSelf};
  6. use crate::punctuated::Punctuated;
  7. use crate::token;
  8. use crate::ty::Type;
  9. use proc_macro2::TokenStream;
  10. pub use crate::expr::{
  11. ExprConst as PatConst, ExprLit as PatLit, ExprMacro as PatMacro, ExprPath as PatPath,
  12. ExprRange as PatRange,
  13. };
  14. ast_enum_of_structs! {
  15. /// A pattern in a local binding, function signature, match expression, or
  16. /// various other places.
  17. ///
  18. /// # Syntax tree enum
  19. ///
  20. /// This type is a [syntax tree enum].
  21. ///
  22. /// [syntax tree enum]: crate::expr::Expr#syntax-tree-enums
  23. #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
  24. #[non_exhaustive]
  25. pub enum Pat {
  26. /// A const block: `const { ... }`.
  27. Const(PatConst),
  28. /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
  29. Ident(PatIdent),
  30. /// A literal pattern: `0`.
  31. Lit(PatLit),
  32. /// A macro in pattern position.
  33. Macro(PatMacro),
  34. /// A pattern that matches any one of a set of cases.
  35. Or(PatOr),
  36. /// A parenthesized pattern: `(A | B)`.
  37. Paren(PatParen),
  38. /// A path pattern like `Color::Red`, optionally qualified with a
  39. /// self-type.
  40. ///
  41. /// Unqualified path patterns can legally refer to variants, structs,
  42. /// constants or associated constants. Qualified path patterns like
  43. /// `<A>::B::C` and `<A as Trait>::B::C` can only legally refer to
  44. /// associated constants.
  45. Path(PatPath),
  46. /// A range pattern: `1..=2`.
  47. Range(PatRange),
  48. /// A reference pattern: `&mut var`.
  49. Reference(PatReference),
  50. /// The dots in a tuple or slice pattern: `[0, 1, ..]`.
  51. Rest(PatRest),
  52. /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`.
  53. Slice(PatSlice),
  54. /// A struct or struct variant pattern: `Variant { x, y, .. }`.
  55. Struct(PatStruct),
  56. /// A tuple pattern: `(a, b)`.
  57. Tuple(PatTuple),
  58. /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
  59. TupleStruct(PatTupleStruct),
  60. /// A type ascription pattern: `foo: f64`.
  61. Type(PatType),
  62. /// Tokens in pattern position not interpreted by Syn.
  63. Verbatim(TokenStream),
  64. /// A pattern that matches any value: `_`.
  65. Wild(PatWild),
  66. // For testing exhaustiveness in downstream code, use the following idiom:
  67. //
  68. // match pat {
  69. // #![cfg_attr(test, deny(non_exhaustive_omitted_patterns))]
  70. //
  71. // Pat::Box(pat) => {...}
  72. // Pat::Ident(pat) => {...}
  73. // ...
  74. // Pat::Wild(pat) => {...}
  75. //
  76. // _ => { /* some sane fallback */ }
  77. // }
  78. //
  79. // This way we fail your tests but don't break your library when adding
  80. // a variant. You will be notified by a test failure when a variant is
  81. // added, so that you can add code to handle it, but your library will
  82. // continue to compile and work for downstream users in the interim.
  83. }
  84. }
  85. ast_struct! {
  86. /// A pattern that binds a new variable: `ref mut binding @ SUBPATTERN`.
  87. ///
  88. /// It may also be a unit struct or struct variant (e.g. `None`), or a
  89. /// constant; these cannot be distinguished syntactically.
  90. #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
  91. pub struct PatIdent {
  92. pub attrs: Vec<Attribute>,
  93. pub by_ref: Option<Token![ref]>,
  94. pub mutability: Option<Token![mut]>,
  95. pub ident: Ident,
  96. pub subpat: Option<(Token![@], Box<Pat>)>,
  97. }
  98. }
  99. ast_struct! {
  100. /// A pattern that matches any one of a set of cases.
  101. #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
  102. pub struct PatOr {
  103. pub attrs: Vec<Attribute>,
  104. pub leading_vert: Option<Token![|]>,
  105. pub cases: Punctuated<Pat, Token![|]>,
  106. }
  107. }
  108. ast_struct! {
  109. /// A parenthesized pattern: `(A | B)`.
  110. #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
  111. pub struct PatParen {
  112. pub attrs: Vec<Attribute>,
  113. pub paren_token: token::Paren,
  114. pub pat: Box<Pat>,
  115. }
  116. }
  117. ast_struct! {
  118. /// A reference pattern: `&mut var`.
  119. #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
  120. pub struct PatReference {
  121. pub attrs: Vec<Attribute>,
  122. pub and_token: Token![&],
  123. pub mutability: Option<Token![mut]>,
  124. pub pat: Box<Pat>,
  125. }
  126. }
  127. ast_struct! {
  128. /// The dots in a tuple or slice pattern: `[0, 1, ..]`.
  129. #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
  130. pub struct PatRest {
  131. pub attrs: Vec<Attribute>,
  132. pub dot2_token: Token![..],
  133. }
  134. }
  135. ast_struct! {
  136. /// A dynamically sized slice pattern: `[a, b, ref i @ .., y, z]`.
  137. #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
  138. pub struct PatSlice {
  139. pub attrs: Vec<Attribute>,
  140. pub bracket_token: token::Bracket,
  141. pub elems: Punctuated<Pat, Token![,]>,
  142. }
  143. }
  144. ast_struct! {
  145. /// A struct or struct variant pattern: `Variant { x, y, .. }`.
  146. #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
  147. pub struct PatStruct {
  148. pub attrs: Vec<Attribute>,
  149. pub qself: Option<QSelf>,
  150. pub path: Path,
  151. pub brace_token: token::Brace,
  152. pub fields: Punctuated<FieldPat, Token![,]>,
  153. pub rest: Option<PatRest>,
  154. }
  155. }
  156. ast_struct! {
  157. /// A tuple pattern: `(a, b)`.
  158. #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
  159. pub struct PatTuple {
  160. pub attrs: Vec<Attribute>,
  161. pub paren_token: token::Paren,
  162. pub elems: Punctuated<Pat, Token![,]>,
  163. }
  164. }
  165. ast_struct! {
  166. /// A tuple struct or tuple variant pattern: `Variant(x, y, .., z)`.
  167. #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
  168. pub struct PatTupleStruct {
  169. pub attrs: Vec<Attribute>,
  170. pub qself: Option<QSelf>,
  171. pub path: Path,
  172. pub paren_token: token::Paren,
  173. pub elems: Punctuated<Pat, Token![,]>,
  174. }
  175. }
  176. ast_struct! {
  177. /// A type ascription pattern: `foo: f64`.
  178. #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
  179. pub struct PatType {
  180. pub attrs: Vec<Attribute>,
  181. pub pat: Box<Pat>,
  182. pub colon_token: Token![:],
  183. pub ty: Box<Type>,
  184. }
  185. }
  186. ast_struct! {
  187. /// A pattern that matches any value: `_`.
  188. #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
  189. pub struct PatWild {
  190. pub attrs: Vec<Attribute>,
  191. pub underscore_token: Token![_],
  192. }
  193. }
  194. ast_struct! {
  195. /// A single field in a struct pattern.
  196. ///
  197. /// Patterns like the fields of Foo `{ x, ref y, ref mut z }` are treated
  198. /// the same as `x: x, y: ref y, z: ref mut z` but there is no colon token.
  199. #[cfg_attr(docsrs, doc(cfg(feature = "full")))]
  200. pub struct FieldPat {
  201. pub attrs: Vec<Attribute>,
  202. pub member: Member,
  203. pub colon_token: Option<Token![:]>,
  204. pub pat: Box<Pat>,
  205. }
  206. }
  207. #[cfg(feature = "parsing")]
  208. pub(crate) mod parsing {
  209. use crate::attr::Attribute;
  210. use crate::error::{self, Result};
  211. use crate::expr::{
  212. Expr, ExprConst, ExprLit, ExprMacro, ExprPath, ExprRange, Member, RangeLimits,
  213. };
  214. use crate::ext::IdentExt as _;
  215. use crate::ident::Ident;
  216. use crate::lit::Lit;
  217. use crate::mac::{self, Macro};
  218. use crate::parse::{Parse, ParseBuffer, ParseStream};
  219. use crate::pat::{
  220. FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct,
  221. PatTuple, PatTupleStruct, PatType, PatWild,
  222. };
  223. use crate::path::{self, Path, QSelf};
  224. use crate::punctuated::Punctuated;
  225. use crate::stmt::Block;
  226. use crate::token;
  227. use crate::verbatim;
  228. use proc_macro2::TokenStream;
  229. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  230. impl Pat {
  231. /// Parse a pattern that does _not_ involve `|` at the top level.
  232. ///
  233. /// This parser matches the behavior of the `$:pat_param` macro_rules
  234. /// matcher, and on editions prior to Rust 2021, the behavior of
  235. /// `$:pat`.
  236. ///
  237. /// In Rust syntax, some examples of where this syntax would occur are
  238. /// in the argument pattern of functions and closures. Patterns using
  239. /// `|` are not allowed to occur in these positions.
  240. ///
  241. /// ```compile_fail
  242. /// fn f(Some(_) | None: Option<T>) {
  243. /// let _ = |Some(_) | None: Option<T>| {};
  244. /// // ^^^^^^^^^^^^^^^^^^^^^^^^^??? :(
  245. /// }
  246. /// ```
  247. ///
  248. /// ```console
  249. /// error: top-level or-patterns are not allowed in function parameters
  250. /// --> src/main.rs:1:6
  251. /// |
  252. /// 1 | fn f(Some(_) | None: Option<T>) {
  253. /// | ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Some(_) | None)`
  254. /// ```
  255. pub fn parse_single(input: ParseStream) -> Result<Self> {
  256. let begin = input.fork();
  257. let lookahead = input.lookahead1();
  258. if lookahead.peek(Ident)
  259. && (input.peek2(Token![::])
  260. || input.peek2(Token![!])
  261. || input.peek2(token::Brace)
  262. || input.peek2(token::Paren)
  263. || input.peek2(Token![..]))
  264. || input.peek(Token![self]) && input.peek2(Token![::])
  265. || lookahead.peek(Token![::])
  266. || lookahead.peek(Token![<])
  267. || input.peek(Token![Self])
  268. || input.peek(Token![super])
  269. || input.peek(Token![crate])
  270. {
  271. pat_path_or_macro_or_struct_or_range(input)
  272. } else if lookahead.peek(Token![_]) {
  273. input.call(pat_wild).map(Pat::Wild)
  274. } else if input.peek(Token![box]) {
  275. pat_box(begin, input)
  276. } else if input.peek(Token![-]) || lookahead.peek(Lit) || lookahead.peek(Token![const])
  277. {
  278. pat_lit_or_range(input)
  279. } else if lookahead.peek(Token![ref])
  280. || lookahead.peek(Token![mut])
  281. || input.peek(Token![self])
  282. || input.peek(Ident)
  283. {
  284. input.call(pat_ident).map(Pat::Ident)
  285. } else if lookahead.peek(Token![&]) {
  286. input.call(pat_reference).map(Pat::Reference)
  287. } else if lookahead.peek(token::Paren) {
  288. input.call(pat_paren_or_tuple)
  289. } else if lookahead.peek(token::Bracket) {
  290. input.call(pat_slice).map(Pat::Slice)
  291. } else if lookahead.peek(Token![..]) && !input.peek(Token![...]) {
  292. pat_range_half_open(input)
  293. } else if lookahead.peek(Token![const]) {
  294. input.call(pat_const).map(Pat::Verbatim)
  295. } else {
  296. Err(lookahead.error())
  297. }
  298. }
  299. /// Parse a pattern, possibly involving `|`, but not a leading `|`.
  300. pub fn parse_multi(input: ParseStream) -> Result<Self> {
  301. multi_pat_impl(input, None)
  302. }
  303. /// Parse a pattern, possibly involving `|`, possibly including a
  304. /// leading `|`.
  305. ///
  306. /// This parser matches the behavior of the Rust 2021 edition's `$:pat`
  307. /// macro_rules matcher.
  308. ///
  309. /// In Rust syntax, an example of where this syntax would occur is in
  310. /// the pattern of a `match` arm, where the language permits an optional
  311. /// leading `|`, although it is not idiomatic to write one there in
  312. /// handwritten code.
  313. ///
  314. /// ```
  315. /// # let wat = None;
  316. /// match wat {
  317. /// | None | Some(false) => {}
  318. /// | Some(true) => {}
  319. /// }
  320. /// ```
  321. ///
  322. /// The compiler accepts it only to facilitate some situations in
  323. /// macro-generated code where a macro author might need to write:
  324. ///
  325. /// ```
  326. /// # macro_rules! doc {
  327. /// # ($value:expr, ($($conditions1:pat),*), ($($conditions2:pat),*), $then:expr) => {
  328. /// match $value {
  329. /// $(| $conditions1)* $(| $conditions2)* => $then
  330. /// }
  331. /// # };
  332. /// # }
  333. /// #
  334. /// # doc!(true, (true), (false), {});
  335. /// # doc!(true, (), (true, false), {});
  336. /// # doc!(true, (true, false), (), {});
  337. /// ```
  338. ///
  339. /// Expressing the same thing correctly in the case that either one (but
  340. /// not both) of `$conditions1` and `$conditions2` might be empty,
  341. /// without leading `|`, is complex.
  342. ///
  343. /// Use [`Pat::parse_multi`] instead if you are not intending to support
  344. /// macro-generated macro input.
  345. pub fn parse_multi_with_leading_vert(input: ParseStream) -> Result<Self> {
  346. let leading_vert: Option<Token![|]> = input.parse()?;
  347. multi_pat_impl(input, leading_vert)
  348. }
  349. }
  350. #[cfg_attr(docsrs, doc(cfg(feature = "parsing")))]
  351. impl Parse for PatType {
  352. fn parse(input: ParseStream) -> Result<Self> {
  353. Ok(PatType {
  354. attrs: Vec::new(),
  355. pat: Box::new(Pat::parse_single(input)?),
  356. colon_token: input.parse()?,
  357. ty: input.parse()?,
  358. })
  359. }
  360. }
  361. fn multi_pat_impl(input: ParseStream, leading_vert: Option<Token![|]>) -> Result<Pat> {
  362. let mut pat = Pat::parse_single(input)?;
  363. if leading_vert.is_some()
  364. || input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=])
  365. {
  366. let mut cases = Punctuated::new();
  367. cases.push_value(pat);
  368. while input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=]) {
  369. let punct = input.parse()?;
  370. cases.push_punct(punct);
  371. let pat = Pat::parse_single(input)?;
  372. cases.push_value(pat);
  373. }
  374. pat = Pat::Or(PatOr {
  375. attrs: Vec::new(),
  376. leading_vert,
  377. cases,
  378. });
  379. }
  380. Ok(pat)
  381. }
  382. fn pat_path_or_macro_or_struct_or_range(input: ParseStream) -> Result<Pat> {
  383. let expr_style = true;
  384. let (qself, path) = path::parsing::qpath(input, expr_style)?;
  385. if qself.is_none()
  386. && input.peek(Token![!])
  387. && !input.peek(Token![!=])
  388. && path.is_mod_style()
  389. {
  390. let bang_token: Token![!] = input.parse()?;
  391. let (delimiter, tokens) = mac::parse_delimiter(input)?;
  392. return Ok(Pat::Macro(ExprMacro {
  393. attrs: Vec::new(),
  394. mac: Macro {
  395. path,
  396. bang_token,
  397. delimiter,
  398. tokens,
  399. },
  400. }));
  401. }
  402. if input.peek(token::Brace) {
  403. pat_struct(input, qself, path).map(Pat::Struct)
  404. } else if input.peek(token::Paren) {
  405. pat_tuple_struct(input, qself, path).map(Pat::TupleStruct)
  406. } else if input.peek(Token![..]) {
  407. pat_range(input, qself, path)
  408. } else {
  409. Ok(Pat::Path(ExprPath {
  410. attrs: Vec::new(),
  411. qself,
  412. path,
  413. }))
  414. }
  415. }
  416. fn pat_wild(input: ParseStream) -> Result<PatWild> {
  417. Ok(PatWild {
  418. attrs: Vec::new(),
  419. underscore_token: input.parse()?,
  420. })
  421. }
  422. fn pat_box(begin: ParseBuffer, input: ParseStream) -> Result<Pat> {
  423. input.parse::<Token![box]>()?;
  424. Pat::parse_single(input)?;
  425. Ok(Pat::Verbatim(verbatim::between(&begin, input)))
  426. }
  427. fn pat_ident(input: ParseStream) -> Result<PatIdent> {
  428. Ok(PatIdent {
  429. attrs: Vec::new(),
  430. by_ref: input.parse()?,
  431. mutability: input.parse()?,
  432. ident: {
  433. if input.peek(Token![self]) {
  434. input.call(Ident::parse_any)?
  435. } else {
  436. input.parse()?
  437. }
  438. },
  439. subpat: {
  440. if input.peek(Token![@]) {
  441. let at_token: Token![@] = input.parse()?;
  442. let subpat = Pat::parse_single(input)?;
  443. Some((at_token, Box::new(subpat)))
  444. } else {
  445. None
  446. }
  447. },
  448. })
  449. }
  450. fn pat_tuple_struct(
  451. input: ParseStream,
  452. qself: Option<QSelf>,
  453. path: Path,
  454. ) -> Result<PatTupleStruct> {
  455. let content;
  456. let paren_token = parenthesized!(content in input);
  457. let mut elems = Punctuated::new();
  458. while !content.is_empty() {
  459. let value = Pat::parse_multi_with_leading_vert(&content)?;
  460. elems.push_value(value);
  461. if content.is_empty() {
  462. break;
  463. }
  464. let punct = content.parse()?;
  465. elems.push_punct(punct);
  466. }
  467. Ok(PatTupleStruct {
  468. attrs: Vec::new(),
  469. qself,
  470. path,
  471. paren_token,
  472. elems,
  473. })
  474. }
  475. fn pat_struct(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<PatStruct> {
  476. let content;
  477. let brace_token = braced!(content in input);
  478. let mut fields = Punctuated::new();
  479. let mut rest = None;
  480. while !content.is_empty() {
  481. let attrs = content.call(Attribute::parse_outer)?;
  482. if content.peek(Token![..]) {
  483. rest = Some(PatRest {
  484. attrs,
  485. dot2_token: content.parse()?,
  486. });
  487. break;
  488. }
  489. let mut value = content.call(field_pat)?;
  490. value.attrs = attrs;
  491. fields.push_value(value);
  492. if content.is_empty() {
  493. break;
  494. }
  495. let punct: Token![,] = content.parse()?;
  496. fields.push_punct(punct);
  497. }
  498. Ok(PatStruct {
  499. attrs: Vec::new(),
  500. qself,
  501. path,
  502. brace_token,
  503. fields,
  504. rest,
  505. })
  506. }
  507. fn field_pat(input: ParseStream) -> Result<FieldPat> {
  508. let begin = input.fork();
  509. let boxed: Option<Token![box]> = input.parse()?;
  510. let by_ref: Option<Token![ref]> = input.parse()?;
  511. let mutability: Option<Token![mut]> = input.parse()?;
  512. let member = if boxed.is_some() || by_ref.is_some() || mutability.is_some() {
  513. input.parse().map(Member::Named)
  514. } else {
  515. input.parse()
  516. }?;
  517. if boxed.is_none() && by_ref.is_none() && mutability.is_none() && input.peek(Token![:])
  518. || !member.is_named()
  519. {
  520. return Ok(FieldPat {
  521. attrs: Vec::new(),
  522. member,
  523. colon_token: Some(input.parse()?),
  524. pat: Box::new(Pat::parse_multi_with_leading_vert(input)?),
  525. });
  526. }
  527. let ident = match member {
  528. Member::Named(ident) => ident,
  529. Member::Unnamed(_) => unreachable!(),
  530. };
  531. let pat = if boxed.is_some() {
  532. Pat::Verbatim(verbatim::between(&begin, input))
  533. } else {
  534. Pat::Ident(PatIdent {
  535. attrs: Vec::new(),
  536. by_ref,
  537. mutability,
  538. ident: ident.clone(),
  539. subpat: None,
  540. })
  541. };
  542. Ok(FieldPat {
  543. attrs: Vec::new(),
  544. member: Member::Named(ident),
  545. colon_token: None,
  546. pat: Box::new(pat),
  547. })
  548. }
  549. fn pat_range(input: ParseStream, qself: Option<QSelf>, path: Path) -> Result<Pat> {
  550. let limits = RangeLimits::parse_obsolete(input)?;
  551. let end = input.call(pat_range_bound)?;
  552. if let (RangeLimits::Closed(_), None) = (&limits, &end) {
  553. return Err(input.error("expected range upper bound"));
  554. }
  555. Ok(Pat::Range(ExprRange {
  556. attrs: Vec::new(),
  557. start: Some(Box::new(Expr::Path(ExprPath {
  558. attrs: Vec::new(),
  559. qself,
  560. path,
  561. }))),
  562. limits,
  563. end: end.map(PatRangeBound::into_expr),
  564. }))
  565. }
  566. fn pat_range_half_open(input: ParseStream) -> Result<Pat> {
  567. let limits: RangeLimits = input.parse()?;
  568. let end = input.call(pat_range_bound)?;
  569. if end.is_some() {
  570. Ok(Pat::Range(ExprRange {
  571. attrs: Vec::new(),
  572. start: None,
  573. limits,
  574. end: end.map(PatRangeBound::into_expr),
  575. }))
  576. } else {
  577. match limits {
  578. RangeLimits::HalfOpen(dot2_token) => Ok(Pat::Rest(PatRest {
  579. attrs: Vec::new(),
  580. dot2_token,
  581. })),
  582. RangeLimits::Closed(_) => Err(input.error("expected range upper bound")),
  583. }
  584. }
  585. }
  586. fn pat_paren_or_tuple(input: ParseStream) -> Result<Pat> {
  587. let content;
  588. let paren_token = parenthesized!(content in input);
  589. let mut elems = Punctuated::new();
  590. while !content.is_empty() {
  591. let value = Pat::parse_multi_with_leading_vert(&content)?;
  592. if content.is_empty() {
  593. if elems.is_empty() && !matches!(value, Pat::Rest(_)) {
  594. return Ok(Pat::Paren(PatParen {
  595. attrs: Vec::new(),
  596. paren_token,
  597. pat: Box::new(value),
  598. }));
  599. }
  600. elems.push_value(value);
  601. break;
  602. }
  603. elems.push_value(value);
  604. let punct = content.parse()?;
  605. elems.push_punct(punct);
  606. }
  607. Ok(Pat::Tuple(PatTuple {
  608. attrs: Vec::new(),
  609. paren_token,
  610. elems,
  611. }))
  612. }
  613. fn pat_reference(input: ParseStream) -> Result<PatReference> {
  614. Ok(PatReference {
  615. attrs: Vec::new(),
  616. and_token: input.parse()?,
  617. mutability: input.parse()?,
  618. pat: Box::new(Pat::parse_single(input)?),
  619. })
  620. }
  621. fn pat_lit_or_range(input: ParseStream) -> Result<Pat> {
  622. let start = input.call(pat_range_bound)?.unwrap();
  623. if input.peek(Token![..]) {
  624. let limits = RangeLimits::parse_obsolete(input)?;
  625. let end = input.call(pat_range_bound)?;
  626. if let (RangeLimits::Closed(_), None) = (&limits, &end) {
  627. return Err(input.error("expected range upper bound"));
  628. }
  629. Ok(Pat::Range(ExprRange {
  630. attrs: Vec::new(),
  631. start: Some(start.into_expr()),
  632. limits,
  633. end: end.map(PatRangeBound::into_expr),
  634. }))
  635. } else {
  636. Ok(start.into_pat())
  637. }
  638. }
  639. // Patterns that can appear on either side of a range pattern.
  640. enum PatRangeBound {
  641. Const(ExprConst),
  642. Lit(ExprLit),
  643. Path(ExprPath),
  644. }
  645. impl PatRangeBound {
  646. fn into_expr(self) -> Box<Expr> {
  647. Box::new(match self {
  648. PatRangeBound::Const(pat) => Expr::Const(pat),
  649. PatRangeBound::Lit(pat) => Expr::Lit(pat),
  650. PatRangeBound::Path(pat) => Expr::Path(pat),
  651. })
  652. }
  653. fn into_pat(self) -> Pat {
  654. match self {
  655. PatRangeBound::Const(pat) => Pat::Const(pat),
  656. PatRangeBound::Lit(pat) => Pat::Lit(pat),
  657. PatRangeBound::Path(pat) => Pat::Path(pat),
  658. }
  659. }
  660. }
  661. fn pat_range_bound(input: ParseStream) -> Result<Option<PatRangeBound>> {
  662. if input.is_empty()
  663. || input.peek(Token![|])
  664. || input.peek(Token![=])
  665. || input.peek(Token![:]) && !input.peek(Token![::])
  666. || input.peek(Token![,])
  667. || input.peek(Token![;])
  668. || input.peek(Token![if])
  669. {
  670. return Ok(None);
  671. }
  672. let lookahead = input.lookahead1();
  673. let expr = if lookahead.peek(Lit) {
  674. PatRangeBound::Lit(input.parse()?)
  675. } else if lookahead.peek(Ident)
  676. || lookahead.peek(Token![::])
  677. || lookahead.peek(Token![<])
  678. || lookahead.peek(Token![self])
  679. || lookahead.peek(Token![Self])
  680. || lookahead.peek(Token![super])
  681. || lookahead.peek(Token![crate])
  682. {
  683. PatRangeBound::Path(input.parse()?)
  684. } else if lookahead.peek(Token![const]) {
  685. PatRangeBound::Const(input.parse()?)
  686. } else {
  687. return Err(lookahead.error());
  688. };
  689. Ok(Some(expr))
  690. }
  691. fn pat_slice(input: ParseStream) -> Result<PatSlice> {
  692. let content;
  693. let bracket_token = bracketed!(content in input);
  694. let mut elems = Punctuated::new();
  695. while !content.is_empty() {
  696. let value = Pat::parse_multi_with_leading_vert(&content)?;
  697. match value {
  698. Pat::Range(pat) if pat.start.is_none() || pat.end.is_none() => {
  699. let (start, end) = match pat.limits {
  700. RangeLimits::HalfOpen(dot_dot) => (dot_dot.spans[0], dot_dot.spans[1]),
  701. RangeLimits::Closed(dot_dot_eq) => {
  702. (dot_dot_eq.spans[0], dot_dot_eq.spans[2])
  703. }
  704. };
  705. let msg = "range pattern is not allowed unparenthesized inside slice pattern";
  706. return Err(error::new2(start, end, msg));
  707. }
  708. _ => {}
  709. }
  710. elems.push_value(value);
  711. if content.is_empty() {
  712. break;
  713. }
  714. let punct = content.parse()?;
  715. elems.push_punct(punct);
  716. }
  717. Ok(PatSlice {
  718. attrs: Vec::new(),
  719. bracket_token,
  720. elems,
  721. })
  722. }
  723. fn pat_const(input: ParseStream) -> Result<TokenStream> {
  724. let begin = input.fork();
  725. input.parse::<Token![const]>()?;
  726. let content;
  727. braced!(content in input);
  728. content.call(Attribute::parse_inner)?;
  729. content.call(Block::parse_within)?;
  730. Ok(verbatim::between(&begin, input))
  731. }
  732. }
  733. #[cfg(feature = "printing")]
  734. mod printing {
  735. use crate::attr::FilterAttrs;
  736. use crate::pat::{
  737. FieldPat, Pat, PatIdent, PatOr, PatParen, PatReference, PatRest, PatSlice, PatStruct,
  738. PatTuple, PatTupleStruct, PatType, PatWild,
  739. };
  740. use crate::path;
  741. use crate::path::printing::PathStyle;
  742. use proc_macro2::TokenStream;
  743. use quote::{ToTokens, TokenStreamExt};
  744. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  745. impl ToTokens for PatIdent {
  746. fn to_tokens(&self, tokens: &mut TokenStream) {
  747. tokens.append_all(self.attrs.outer());
  748. self.by_ref.to_tokens(tokens);
  749. self.mutability.to_tokens(tokens);
  750. self.ident.to_tokens(tokens);
  751. if let Some((at_token, subpat)) = &self.subpat {
  752. at_token.to_tokens(tokens);
  753. subpat.to_tokens(tokens);
  754. }
  755. }
  756. }
  757. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  758. impl ToTokens for PatOr {
  759. fn to_tokens(&self, tokens: &mut TokenStream) {
  760. tokens.append_all(self.attrs.outer());
  761. self.leading_vert.to_tokens(tokens);
  762. self.cases.to_tokens(tokens);
  763. }
  764. }
  765. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  766. impl ToTokens for PatParen {
  767. fn to_tokens(&self, tokens: &mut TokenStream) {
  768. tokens.append_all(self.attrs.outer());
  769. self.paren_token.surround(tokens, |tokens| {
  770. self.pat.to_tokens(tokens);
  771. });
  772. }
  773. }
  774. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  775. impl ToTokens for PatReference {
  776. fn to_tokens(&self, tokens: &mut TokenStream) {
  777. tokens.append_all(self.attrs.outer());
  778. self.and_token.to_tokens(tokens);
  779. self.mutability.to_tokens(tokens);
  780. self.pat.to_tokens(tokens);
  781. }
  782. }
  783. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  784. impl ToTokens for PatRest {
  785. fn to_tokens(&self, tokens: &mut TokenStream) {
  786. tokens.append_all(self.attrs.outer());
  787. self.dot2_token.to_tokens(tokens);
  788. }
  789. }
  790. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  791. impl ToTokens for PatSlice {
  792. fn to_tokens(&self, tokens: &mut TokenStream) {
  793. tokens.append_all(self.attrs.outer());
  794. self.bracket_token.surround(tokens, |tokens| {
  795. self.elems.to_tokens(tokens);
  796. });
  797. }
  798. }
  799. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  800. impl ToTokens for PatStruct {
  801. fn to_tokens(&self, tokens: &mut TokenStream) {
  802. tokens.append_all(self.attrs.outer());
  803. path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
  804. self.brace_token.surround(tokens, |tokens| {
  805. self.fields.to_tokens(tokens);
  806. // NOTE: We need a comma before the dot2 token if it is present.
  807. if !self.fields.empty_or_trailing() && self.rest.is_some() {
  808. <Token![,]>::default().to_tokens(tokens);
  809. }
  810. self.rest.to_tokens(tokens);
  811. });
  812. }
  813. }
  814. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  815. impl ToTokens for PatTuple {
  816. fn to_tokens(&self, tokens: &mut TokenStream) {
  817. tokens.append_all(self.attrs.outer());
  818. self.paren_token.surround(tokens, |tokens| {
  819. self.elems.to_tokens(tokens);
  820. // If there is only one element, a trailing comma is needed to
  821. // distinguish PatTuple from PatParen, unless this is `(..)`
  822. // which is a tuple pattern even without comma.
  823. if self.elems.len() == 1
  824. && !self.elems.trailing_punct()
  825. && !matches!(self.elems[0], Pat::Rest { .. })
  826. {
  827. <Token![,]>::default().to_tokens(tokens);
  828. }
  829. });
  830. }
  831. }
  832. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  833. impl ToTokens for PatTupleStruct {
  834. fn to_tokens(&self, tokens: &mut TokenStream) {
  835. tokens.append_all(self.attrs.outer());
  836. path::printing::print_qpath(tokens, &self.qself, &self.path, PathStyle::Expr);
  837. self.paren_token.surround(tokens, |tokens| {
  838. self.elems.to_tokens(tokens);
  839. });
  840. }
  841. }
  842. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  843. impl ToTokens for PatType {
  844. fn to_tokens(&self, tokens: &mut TokenStream) {
  845. tokens.append_all(self.attrs.outer());
  846. self.pat.to_tokens(tokens);
  847. self.colon_token.to_tokens(tokens);
  848. self.ty.to_tokens(tokens);
  849. }
  850. }
  851. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  852. impl ToTokens for PatWild {
  853. fn to_tokens(&self, tokens: &mut TokenStream) {
  854. tokens.append_all(self.attrs.outer());
  855. self.underscore_token.to_tokens(tokens);
  856. }
  857. }
  858. #[cfg_attr(docsrs, doc(cfg(feature = "printing")))]
  859. impl ToTokens for FieldPat {
  860. fn to_tokens(&self, tokens: &mut TokenStream) {
  861. tokens.append_all(self.attrs.outer());
  862. if let Some(colon_token) = &self.colon_token {
  863. self.member.to_tokens(tokens);
  864. colon_token.to_tokens(tokens);
  865. }
  866. self.pat.to_tokens(tokens);
  867. }
  868. }
  869. }