Repository: winnow-rs/winnow (Rust)

Issue:
Add a non-consuming combinator that returns `()`
### Please complete the following tasks

- [X] I have searched the [discussions](https://github.com/winnow-rs/winnow/discussions)
- [X] I have searched the [open](https://github.com/winnow-rs/winnow/issues) and [rejected](https://github.com/winnow-rs/winnow/issues?q=is%3Aissue+label%3AS-wont-fix+is%3Aclosed) issues

### winnow version

0.5.30

### Describe your use case

`success` only handles the equivalent of `Parser::value` but there is also `Parser::void`, `Parser::default_value` (#398).

### Describe the solution you'd like

[`chumsky::primitive::empty`](https://docs.rs/chumsky/latest/chumsky/primitive/fn.empty.html) would be nice

The main question is in naming
- `empty`: conveys what is done for parsing
- `success` reads nicely for longer `alt`s
- `void` ... too focused on the output and not the grammar

### Alternatives, if applicable

_No response_

### Additional Context

Split out of #82


Discussion:
#### Provide a few name references：
- noop or no_op: representing 'no operation,' meaning it does not produce any effect when executed.
- pass
- skip
- do_nothing



Patch:
diff --git a/examples/json/parser_dispatch.rs b/examples/json/parser_dispatch.rs
index 8f7eaf999..bc54d4319 100644
--- a/examples/json/parser_dispatch.rs
+++ b/examples/json/parser_dispatch.rs
@@ -5,9 +5,9 @@ use winnow::prelude::*;
 use winnow::{
     ascii::float,
     combinator::cut_err,
+    combinator::empty,
     combinator::fail,
     combinator::peek,
-    combinator::success,
     combinator::{alt, dispatch},
     combinator::{delimited, preceded, separated_pair, terminated},
     combinator::{fold_repeat, separated},
@@ -115,14 +115,14 @@ fn character<'i, E: ParserError<Stream<'i>>>(input: &mut Stream<'i>) -> PResult<
     let c = none_of('\"').parse_next(input)?;
     if c == '\\' {
         dispatch!(any;
-          '"' => success('"'),
-          '\\' => success('\\'),
-          '/'  => success('/'),
-          'b' => success('\x08'),
-          'f' => success('\x0C'),
-          'n' => success('\n'),
-          'r' => success('\r'),
-          't' => success('\t'),
+          '"' => empty.value('"'),
+          '\\' => empty.value('\\'),
+          '/'  => empty.value('/'),
+          'b' => empty.value('\x08'),
+          'f' => empty.value('\x0C'),
+          'n' => empty.value('\n'),
+          'r' => empty.value('\r'),
+          't' => empty.value('\t'),
           'u' => unicode_escape,
           _ => fail,
         )
diff --git a/src/_tutorial/chapter_3.rs b/src/_tutorial/chapter_3.rs
index e3f86b501..2ad012461 100644
--- a/src/_tutorial/chapter_3.rs
+++ b/src/_tutorial/chapter_3.rs
@@ -293,7 +293,7 @@
 //! # }
 //! ```
 //!
-//! > **Note:** [`success`] and [`fail`] are parsers that might be useful in the `else` case.
+//! > **Note:** [`empty`] and [`fail`] are parsers that might be useful in the `else` case.
 //!
 //! Sometimes a giant if/else-if ladder can be slow and you'd rather have a `match` statement for
 //! branches of your parser that have unique prefixes. In this case, you can use the
@@ -364,11 +364,11 @@ use super::chapter_6;
 use crate::combinator;
 use crate::combinator::alt;
 use crate::combinator::dispatch;
+use crate::combinator::empty;
 use crate::combinator::fail;
 use crate::combinator::opt;
 use crate::combinator::peek;
 use crate::combinator::preceded;
-use crate::combinator::success;
 use crate::stream::Stream;
 
 pub use super::chapter_2 as previous;
diff --git a/src/combinator/core.rs b/src/combinator/core.rs
index 4f7642613..efd77580f 100644
--- a/src/combinator/core.rs
+++ b/src/combinator/core.rs
@@ -434,11 +434,16 @@ enum State<E> {
     Incomplete(Needed),
 }
 
-/// Always succeeds with given value without consuming any input.
+/// Succeed, consuming no input
 ///
 /// For example, it can be used as the last alternative in `alt` to
 /// specify the default case.
 ///
+/// Useful with:
+/// - [`Parser::value`]
+/// - [`Parser::default_value`]
+/// - [`Parser::map`]
+///
 /// **Note:** This never advances the [`Stream`]
 ///
 /// # Example
@@ -447,16 +452,13 @@ enum State<E> {
 /// # use winnow::{error::ErrMode, error::ErrorKind, error::InputError};
 /// # use winnow::prelude::*;
 /// use winnow::combinator::alt;
-/// use winnow::combinator::success;
-///
-/// let mut parser = success::<_,_,InputError<_>>(10);
-/// assert_eq!(parser.parse_peek("xyz"), Ok(("xyz", 10)));
+/// use winnow::combinator::empty;
 ///
 /// fn sign(input: &str) -> IResult<&str, isize> {
 ///     alt((
 ///         '-'.value(-1),
 ///         '+'.value(1),
-///         success::<_,_,InputError<_>>(1)
+///         empty.value(1)
 ///     )).parse_peek(input)
 /// }
 /// assert_eq!(sign("+10"), Ok(("10", 1)));
@@ -464,7 +466,13 @@ enum State<E> {
 /// assert_eq!(sign("10"), Ok(("10", 1)));
 /// ```
 #[doc(alias = "value")]
-#[doc(alias = "empty")]
+#[doc(alias = "success")]
+pub fn empty<I: Stream, E: ParserError<I>>(_input: &mut I) -> PResult<(), E> {
+    Ok(())
+}
+
+/// Deprecated, replaced with [`empty`] + [`Parser::value`]
+#[deprecated(since = "0.5.35", note = "Replaced with empty.value(...)`")]
 pub fn success<I: Stream, O: Clone, E: ParserError<I>>(val: O) -> impl Parser<I, O, E> {
     trace("success", move |_input: &mut I| Ok(val.clone()))
 }
diff --git a/src/macros/dispatch.rs b/src/macros/dispatch.rs
index 9305fd70c..b763d4ba4 100644
--- a/src/macros/dispatch.rs
+++ b/src/macros/dispatch.rs
@@ -14,7 +14,7 @@
 /// # use winnow::token::any;
 /// # use winnow::combinator::peek;
 /// # use winnow::combinator::preceded;
-/// # use winnow::combinator::success;
+/// # use winnow::combinator::empty;
 /// # use winnow::combinator::fail;
 ///
 /// fn escaped(input: &mut &str) -> PResult<char> {
@@ -23,13 +23,13 @@
 ///
 /// fn escape_seq_char(input: &mut &str) -> PResult<char> {
 ///     dispatch! {any;
-///         'b' => success('\u{8}'),
-///         'f' => success('\u{c}'),
-///         'n' => success('\n'),
-///         'r' => success('\r'),
-///         't' => success('\t'),
-///         '\\' => success('\\'),
-///         '"' => success('"'),
+///         'b' => empty.value('\u{8}'),
+///         'f' => empty.value('\u{c}'),
+///         'n' => empty.value('\n'),
+///         'r' => empty.value('\r'),
+///         't' => empty.value('\t'),
+///         '\\' => empty.value('\\'),
+///         '"' => empty.value('"'),
 ///         _ => fail::<_, char, _>,
 ///     }
 ///     .parse_next(input)
diff --git a/src/macros/seq.rs b/src/macros/seq.rs
index bb1cd25f6..e104391f8 100644
--- a/src/macros/seq.rs
+++ b/src/macros/seq.rs
@@ -6,7 +6,7 @@
 /// # use winnow::prelude::*;
 /// # use winnow::ascii::{alphanumeric1, dec_uint, space0};
 /// # use winnow::combinator::delimited;
-/// # use winnow::combinator::success;
+/// # use winnow::combinator::empty;
 /// # use winnow::error::ContextError;
 /// use winnow::combinator::seq;
 ///
@@ -22,7 +22,7 @@
 /// // Parse into structs / tuple-structs
 /// fn field(input: &mut &[u8]) -> PResult<Field> {
 ///     seq!{Field {
-///         namespace: success(5),
+///         namespace: empty.value(5),
 ///         name: alphanumeric1.map(|s: &[u8]| s.to_owned()),
 ///         // `_` fields are ignored when building the struct
 ///         _: (space0, b':', space0),
diff --git a/src/parser.rs b/src/parser.rs
index 796ce029b..55d7aba98 100644
--- a/src/parser.rs
+++ b/src/parser.rs
@@ -11,12 +11,12 @@ use crate::stream::{AsChar, Compare, Location, ParseSlice, Stream, StreamIsParti
 /// ```rust
 /// use winnow::prelude::*;
 ///
-/// fn success(input: &mut &str) -> PResult<()> {
+/// fn empty(input: &mut &str) -> PResult<()> {
 ///     let output = ();
 ///     Ok(output)
 /// }
 ///
-/// let (input, output) = success.parse_peek("Hello").unwrap();
+/// let (input, output) = empty.parse_peek("Hello").unwrap();
 /// assert_eq!(input, "Hello");  // We didn't consume any input
 /// ```
 ///
@@ -24,14 +24,14 @@ use crate::stream::{AsChar, Compare, Location, ParseSlice, Stream, StreamIsParti
 /// ```rust
 /// use winnow::prelude::*;
 ///
-/// fn success<O: Clone>(output: O) -> impl FnMut(&mut &str) -> PResult<O> {
+/// fn empty<O: Clone>(output: O) -> impl FnMut(&mut &str) -> PResult<O> {
 ///     move |input: &mut &str| {
 ///         let output = output.clone();
 ///         Ok(output)
 ///     }
 /// }
 ///
-/// let (input, output) = success("World").parse_peek("Hello").unwrap();
+/// let (input, output) = empty("World").parse_peek("Hello").unwrap();
 /// assert_eq!(input, "Hello");  // We didn't consume any input
 /// assert_eq!(output, "World");
 /// ```


Test patch:
diff --git a/src/macros/test.rs b/src/macros/test.rs
index faf917f23..17601bc38 100644
--- a/src/macros/test.rs
+++ b/src/macros/test.rs
@@ -1,8 +1,8 @@
 use crate::ascii::dec_uint;
 use crate::combinator::dispatch;
+use crate::combinator::empty;
 use crate::combinator::fail;
 use crate::combinator::seq;
-use crate::combinator::success;
 use crate::error::ErrMode;
 use crate::error::ErrorKind;
 use crate::error::ParserError;
@@ -13,13 +13,13 @@ use crate::token::any;
 fn dispatch_basics() {
     fn escape_seq_char(input: &mut &str) -> PResult<char> {
         dispatch! {any;
-            'b' => success('\u{8}'),
-            'f' => success('\u{c}'),
-            'n' => success('\n'),
-            'r' => success('\r'),
-            't' => success('\t'),
-            '\\' => success('\\'),
-            '"' => success('"'),
+            'b' => empty.value('\u{8}'),
+            'f' => empty.value('\u{c}'),
+            'n' => empty.value('\n'),
+            'r' => empty.value('\r'),
+            't' => empty.value('\t'),
+            '\\' => empty.value('\\'),
+            '"' => empty.value('"'),
             _ => fail::<_, char, _>,
         }
         .parse_next(input)
@@ -135,7 +135,7 @@ fn seq_struct_trailing_comma_elided() {
                 x: dec_uint,
                 _: ',',
                 y: dec_uint,
-                _: success(()),
+                _: empty,
             }
         }
         .parse_next(input)
@@ -180,7 +180,7 @@ fn seq_struct_no_trailing_comma_elided() {
                 x: dec_uint,
                 _: ',',
                 y: dec_uint,
-                _: success(())
+                _: empty
             }
         }
         .parse_next(input)
@@ -235,7 +235,7 @@ fn seq_tuple_struct_trailing_comma_elided() {
                 dec_uint,
                 _: ',',
                 dec_uint,
-                _: success(()),
+                _: empty,
             )
         }
         .parse_next(input)
@@ -274,7 +274,7 @@ fn seq_tuple_struct_no_trailing_comma_elided() {
                 dec_uint,
                 _: ',',
                 dec_uint,
-                _: success(())
+                _: empty
             )
         }
         .parse_next(input)
@@ -323,7 +323,7 @@ fn seq_tuple_trailing_comma_elided() {
                 dec_uint,
                 _: ',',
                 dec_uint,
-                _: success(()),
+                _: empty,
             )
         }
         .parse_next(input)
@@ -356,7 +356,7 @@ fn seq_tuple_no_trailing_comma_elided() {
                 dec_uint,
                 _: ',',
                 dec_uint,
-                _: success(())
+                _: empty
             )
         }
         .parse_next(input)