Repository: Geal/nom
Pull request #998 (2019-07-17 21:42:45)

Fix meta variable misuse
Rust issue: https://github.com/rust-lang/rust/issues/61053
Rust PR: https://github.com/rust-lang/rust/pull/62008

Reproduce by compiling with a stage2 (or stage1) compiler at the PR given above (set the meta_variable_misuse lint to deny if it's not). The output would look like (only first errors are kept):
```
error: unknown macro variable `submac2`
   --> src/combinator/macros.rs:660:41
    |
660 |     $crate::combinator::verify($f, |&o| $submac2!(o, $($args)*))($i)
    |                                         ^^^^^^^^
    |
    = note: #[deny(meta_variable_misuse)] on by default

error: meta-variable repeats with different Kleene operator
   --> src/branch/mod.rs:215:75
    |
199 |   ($it:tt, $self:expr, $input:ident, $res:expr, $all_done:expr, $head:ident $($id:ident)+) => ({
    |                                                                                         - expected repetition
...
215 |     succ!($it, permutation_trait_inner!($self, $input, $res, $all_done, $($id)*));
    |                                                                           ^^^ - conflicting repetition

error: unknown macro variable `args`
   --> src/sequence/macros.rs:471:43
    |
471 |   (( $(args:tt)* )) => ( compile_error!($($args)*) );
    |                                           ^^^^^

error: meta-variable repeats with different Kleene operator
   --> src/whitespace.rs:147:67
    |
144 |   ($i:expr, $separator:path, $submac1:ident!( $($args1:tt)* ), $($rest:tt)+) => ({
    |                                                                           - expected repetition
...
147 |     match tuple_sep!($i, $separator, (), $submac1!($($args1)*), $($rest)*) {
    |                                                                   ^^^^^ - conflicting repetition
```



Patch:
diff --git a/doc/custom_input_types.md b/doc/custom_input_types.md
index 1c6f725..aadf25b 100644
--- a/doc/custom_input_types.md
+++ b/doc/custom_input_types.md
@@ -10,21 +10,20 @@ that can carry line and column information, or to parse
 
 ## Implementing a custom type
 
-Let's assume we have an input type we'll call `MyInput`. The goal is to define
-nom parsers with this signature: `MyInput -> IResult<MyInput, Output>`.
-To employ it in a `named!` parser, you can write it like this:
+Let's assume we have an input type we'll call `MyInput`. `MyInput` is a sequence of `MyItem` type.
+The goal is to define nom parsers with this signature: `MyInput -> IResult<MyInput, Output>`.
 
 ```rust
-named!(parser<MyInput, Output>, tag!("test"));
+fn parser(i: MyInput) -> IResult<MyInput, Output> {
+    tag("test")(i)
+}
 ```
 
-Here are the traits we have to implement:
-
+Here are the traits we have to implement for `MyInput`:
 
 | trait | usage |
 |---|---|
 | [AsBytes](https://docs.rs/nom/latest/nom/trait.AsBytes.html) | casts the input type to a byte slice |
-| [AsChar](https://docs.rs/nom/latest/nom/trait.AsChar.html) | transforms common types to a char for basic token parsing |
 | [Compare](https://docs.rs/nom/latest/nom/trait.Compare.html) | character comparison operations |
 | [ExtendInto](https://docs.rs/nom/latest/nom/trait.ExtendInto.html) |abstracts something which can extend an Extend |
 | [FindSubstring](https://docs.rs/nom/latest/nom/trait.FindSubstring.html) | look for a substring in self |
@@ -36,3 +35,9 @@ Here are the traits we have to implement:
 | [Offset](https://docs.rs/nom/latest/nom/trait.Offset.html) | calculate the offset between slices |
 | [ParseTo](https://docs.rs/nom/latest/nom/trait.ParseTo.html) | used to integrate `&str`'s parse() method |
 | [Slice](https://docs.rs/nom/latest/nom/trait.Slice.html) | slicing operations using ranges |
+
+Here are the traits we have to implement for `MyItem`:
+
+| trait | usage |
+|---|---|
+| [AsChar](https://docs.rs/nom/latest/nom/trait.AsChar.html) | transforms common types to a char for basic token parsing |
diff --git a/src/branch/mod.rs b/src/branch/mod.rs
index 2c19a65..babb5f2 100644
--- a/src/branch/mod.rs
+++ b/src/branch/mod.rs
@@ -212,7 +212,7 @@ macro_rules! permutation_trait_inner(
         }
       };
     }
-    succ!($it, permutation_trait_inner!($self, $input, $res, $all_done, $($id)*));
+    succ!($it, permutation_trait_inner!($self, $input, $res, $all_done, $($id)+));
   });
   ($it:tt, $self:expr, $input:ident, $res:expr, $all_done:expr, $head:ident) => ({
     if $res.$it.is_none() {
diff --git a/src/combinator/macros.rs b/src/combinator/macros.rs
index aa164e2..de105f6 100644
--- a/src/combinator/macros.rs
+++ b/src/combinator/macros.rs
@@ -79,12 +79,12 @@
 /// # use nom::{named, tag};
 /// named!(my_function<&[u8], &[u8]>, tag!("abcd"));
 /// ```
-/// This one will have &[u8] as input type, &[u8] as output type:
+/// This one will have `&[u8]` as input type, `&[u8]` as output type:
 /// ```
 /// # use nom::{named, tag};
 /// named!(my_function, tag!("abcd"));
 /// ```
-/// Will use &[u8] as output type:
+/// Will use `&[u8]` as output type:
 /// ```
 /// # use nom::{named, tag};
 /// named!(my_function<&[u8]>, tag!("abcd"));
@@ -134,7 +134,7 @@ macro_rules! named (
 /// Makes a function from a parser combination with arguments.
 ///
 /// ```ignore
-/// //takes `&[u8]` as input
+/// //takes [`&[u8]`] as input
 /// named_args!(tagged(open_tag: &[u8], close_tag: &[u8])<&str>,
 ///   delimited!(tag!(open_tag), map_res!(take!(4), str::from_utf8), tag!(close_tag))
 /// );
@@ -657,7 +657,7 @@ macro_rules! verify (
     $crate::combinator::verify($f, $g)($i)
   );
   ($i:expr, $f:expr, $submac:ident!( $($args:tt)* )) => (
-    $crate::combinator::verify($f, |&o| $submac2!(o, $($args)*))($i)
+    $crate::combinator::verify($f, |&o| $submac!(o, $($args)*))($i)
   );
 );
 
diff --git a/src/multi/mod.rs b/src/multi/mod.rs
index 269fc44..93b3e4c 100644
--- a/src/multi/mod.rs
+++ b/src/multi/mod.rs
@@ -409,6 +409,10 @@ where
     let mut input = i.clone();
     let mut count: usize = 0;
 
+    if n == 0 {
+        return Ok((i, vec!()))
+    }
+
     loop {
       let _i = input.clone();
       match f(_i) {
diff --git a/src/sequence/macros.rs b/src/sequence/macros.rs
index edcbc59..a5a3351 100644
--- a/src/sequence/macros.rs
+++ b/src/sequence/macros.rs
@@ -468,7 +468,7 @@ macro_rules! do_parse (
 #[doc(hidden)]
 #[macro_export]
 macro_rules! nom_compile_error (
-  (( $(args:tt)* )) => ( compile_error!($($args)*) );
+  (( $($args:tt)* )) => ( compile_error!($($args)*) );
 );
 
 #[cfg(test)]
diff --git a/src/whitespace.rs b/src/whitespace.rs
index 9f1d1c7..9ed3f55 100644
--- a/src/whitespace.rs
+++ b/src/whitespace.rs
@@ -144,7 +144,7 @@ macro_rules! delimited_sep (
   ($i:expr, $separator:path, $submac1:ident!( $($args1:tt)* ), $($rest:tt)+) => ({
     use $crate::lib::std::result::Result::*;
 
-    match tuple_sep!($i, $separator, (), $submac1!($($args1)*), $($rest)*) {
+    match tuple_sep!($i, $separator, (), $submac1!($($args1)*), $($rest)+) {
       Err(e) => Err(e),
       Ok((remaining, (_,o,_))) => {
         Ok((remaining, o))
@@ -152,7 +152,7 @@ macro_rules! delimited_sep (
     }
   });
   ($i:expr, $separator:path, $f:expr, $($rest:tt)+) => (
-    delimited_sep!($i, $separator, call!($f), $($rest)*);
+    delimited_sep!($i, $separator, call!($f), $($rest)+);
   );
 );
 
@@ -162,7 +162,7 @@ macro_rules! separated_pair_sep (
   ($i:expr, $separator:path, $submac1:ident!( $($args1:tt)* ), $($rest:tt)+) => ({
     use $crate::lib::std::result::Result::*;
 
-    match tuple_sep!($i, $separator, (), $submac1!($($args1)*), $($rest)*) {
+    match tuple_sep!($i, $separator, (), $submac1!($($args1)*), $($rest)+) {
       Err(e) => Err(e),
       Ok((remaining, (o1,_,o2))) => {
         Ok((remaining, (o1,o2)))
@@ -170,7 +170,7 @@ macro_rules! separated_pair_sep (
     }
   });
   ($i:expr, $separator:path, $f:expr, $($rest:tt)+) => (
-    separated_pair_sep!($i, $separator, call!($f), $($rest)*);
+    separated_pair_sep!($i, $separator, call!($f), $($rest)+);
   );
 );
 
@@ -508,7 +508,7 @@ macro_rules! alt_sep (
       match sep!($i, $separator, $subrule!( $($args)* )) {
         Ok((i,o))               => Ok((i,$gen(o))),
         Err(Err::Error(_))      => {
-          alt_sep!(__impl $i, $separator, $($rest)*)
+          alt_sep!(__impl $i, $separator, $($rest)+)
         },
         Err(e)            => Err(e),
       }


Test patch:
diff --git a/tests/issues.rs b/tests/issues.rs
index a7bf516..094b47c 100644
--- a/tests/issues.rs
+++ b/tests/issues.rs
@@ -290,3 +290,11 @@ fn issue_942() {
   }
   assert_eq!(parser::<()>("aaa"), Ok(("", 3)));
 }
+
+#[test]
+fn issue_many_m_n_with_zeros() {
+    use nom::multi::many_m_n;
+    use nom::character::complete::char;
+    let parser = many_m_n::<_, _, (), _>(0, 0, char('a'));
+    assert_eq!(parser("aaa"), Ok(("aaa", vec!())));
+}