Repository: dtolnay/syn
Pull request #811 (2020-05-20 21:37:43)

Disallow leading vert in most places
See https://github.com/rust-lang/rust/blob/8858a435f3eef655df3e4fb6bec15d33e44a374e/src/test/ui/or-patterns/remove-leading-vert.stderr.

@taiki-e


Patch:
diff --git a/src/expr.rs b/src/expr.rs
index 101b8430..1828ae84 100644
--- a/src/expr.rs
+++ b/src/expr.rs
@@ -2009,7 +2009,7 @@ pub(crate) mod parsing {
         Ok(ExprLet {
             attrs: Vec::new(),
             let_token: input.parse()?,
-            pat: pat::parsing::pat_or(input)?,
+            pat: pat::parsing::multi_pat_with_leading_vert(input)?,
             eq_token: input.parse()?,
             expr: Box::new(input.call(expr_no_struct)?),
         })
@@ -2060,7 +2060,7 @@ pub(crate) mod parsing {
             let label: Option<Label> = input.parse()?;
             let for_token: Token![for] = input.parse()?;
 
-            let pat = pat::parsing::pat_or(input)?;
+            let pat = pat::parsing::multi_pat_with_leading_vert(input)?;
 
             let in_token: Token![in] = input.parse()?;
             let expr: Expr = input.call(expr_no_struct)?;
@@ -2576,7 +2576,7 @@ pub(crate) mod parsing {
             let requires_comma;
             Ok(Arm {
                 attrs: input.call(Attribute::parse_outer)?,
-                pat: pat::parsing::pat_or(input)?,
+                pat: pat::parsing::multi_pat_with_leading_vert(input)?,
                 guard: {
                     if input.peek(Token![if]) {
                         let if_token: Token![if] = input.parse()?;
diff --git a/src/item.rs b/src/item.rs
index a821b85d..986ddc89 100644
--- a/src/item.rs
+++ b/src/item.rs
@@ -1671,7 +1671,7 @@ pub mod parsing {
 
         Ok(PatType {
             attrs: Vec::new(),
-            pat: Box::new(pat::parsing::pat_or(input)?),
+            pat: Box::new(pat::parsing::multi_pat(input)?),
             colon_token: input.parse()?,
             ty: Box::new(match input.parse::<Option<Token![...]>>()? {
                 Some(dot3) => Type::Verbatim(variadic_to_tokens(&dot3)),
diff --git a/src/pat.rs b/src/pat.rs
index 64d0775d..b1128ff7 100644
--- a/src/pat.rs
+++ b/src/pat.rs
@@ -596,7 +596,7 @@ pub mod parsing {
                 attrs,
                 member,
                 colon_token: input.parse()?,
-                pat: Box::new(pat_or(input)?),
+                pat: Box::new(multi_pat(input)?),
             });
         }
 
@@ -675,7 +675,7 @@ pub mod parsing {
 
         let mut elems = Punctuated::new();
         while !content.is_empty() {
-            let value = pat_or(&content)?;
+            let value = multi_pat(&content)?;
             elems.push_value(value);
             if content.is_empty() {
                 break;
@@ -771,7 +771,7 @@ pub mod parsing {
 
         let mut elems = Punctuated::new();
         while !content.is_empty() {
-            let value = pat_or(&content)?;
+            let value = multi_pat(&content)?;
             elems.push_value(value);
             if content.is_empty() {
                 break;
@@ -787,8 +787,16 @@ pub mod parsing {
         })
     }
 
-    pub fn pat_or(input: ParseStream) -> Result<Pat> {
+    pub fn multi_pat(input: ParseStream) -> Result<Pat> {
+        multi_pat_impl(input, None)
+    }
+
+    pub fn multi_pat_with_leading_vert(input: ParseStream) -> Result<Pat> {
         let leading_vert: Option<Token![|]> = input.parse()?;
+        multi_pat_impl(input, leading_vert)
+    }
+
+    fn multi_pat_impl(input: ParseStream, leading_vert: Option<Token![|]>) -> Result<Pat> {
         let mut pat: Pat = input.parse()?;
         if leading_vert.is_some()
             || input.peek(Token![|]) && !input.peek(Token![||]) && !input.peek(Token![|=])
diff --git a/src/stmt.rs b/src/stmt.rs
index f7fdbd2d..a3765d58 100644
--- a/src/stmt.rs
+++ b/src/stmt.rs
@@ -219,7 +219,7 @@ pub mod parsing {
             attrs,
             let_token: input.parse()?,
             pat: {
-                let mut pat: Pat = pat::parsing::pat_or(input)?;
+                let mut pat: Pat = pat::parsing::multi_pat_with_leading_vert(input)?;
                 if input.peek(Token![:]) {
                     let colon_token: Token![:] = input.parse()?;
                     let ty: Type = input.parse()?;


Test patch:
diff --git a/tests/test_pat.rs b/tests/test_pat.rs
index 8cba735f..73388dd7 100644
--- a/tests/test_pat.rs
+++ b/tests/test_pat.rs
@@ -1,5 +1,5 @@
 use quote::quote;
-use syn::Pat;
+use syn::{Item, Pat, Stmt};
 
 #[test]
 fn test_pat_ident() {
@@ -16,3 +16,23 @@ fn test_pat_path() {
         value => panic!("expected PatPath, got {:?}", value),
     }
 }
+
+#[test]
+fn test_leading_vert() {
+    // https://github.com/rust-lang/rust/blob/1.43.0/src/test/ui/or-patterns/remove-leading-vert.rs
+
+    syn::parse_str::<Item>("fn f() {}").unwrap();
+    syn::parse_str::<Item>("fn fun1(| A: E) {}").unwrap_err();
+    syn::parse_str::<Item>("fn fun2(|| A: E) {}").unwrap_err();
+
+    syn::parse_str::<Stmt>("let | () = ();").unwrap();
+    syn::parse_str::<Stmt>("let (| A): E;").unwrap_err();
+    syn::parse_str::<Stmt>("let (|| A): (E);").unwrap_err();
+    syn::parse_str::<Stmt>("let (| A,): (E,);").unwrap_err();
+    syn::parse_str::<Stmt>("let [| A]: [E; 1];").unwrap_err();
+    syn::parse_str::<Stmt>("let [|| A]: [E; 1];").unwrap_err();
+    syn::parse_str::<Stmt>("let TS(| A): TS;").unwrap_err();
+    syn::parse_str::<Stmt>("let TS(|| A): TS;").unwrap_err();
+    syn::parse_str::<Stmt>("let NS { f: | A }: NS;").unwrap_err();
+    syn::parse_str::<Stmt>("let NS { f: || A }: NS;").unwrap_err();
+}