aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author魏曹先生 <1992414357@qq.com>2026-06-22 23:59:31 +0800
committer魏曹先生 <1992414357@qq.com>2026-06-22 23:59:31 +0800
commit443ffe86485519a218997955335cde142733f88f (patch)
treeef331749338c8653ac8a241bfd1cf83cd0683468
parent31b5abfc96013309530025b751293c7de916dcf3 (diff)
Make route! macro auto-convert error types
`route!()` now calls `Groupped::to_chain()` on the error branch, removing the need for callers to pre-convert with `.to_chain()` or `.to_render()`.
-rw-r--r--CHANGELOG.md10
-rw-r--r--examples/example-argument-parse/src/main.rs2
-rw-r--r--examples/example-custom-pickable/src/main.rs2
-rw-r--r--examples/full-todolist/src/main.rs4
-rw-r--r--mingling/src/example_docs.rs4
-rw-r--r--mingling_macros/src/lib.rs15
6 files changed, 24 insertions, 13 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5384b45..b9b7bd7 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -278,6 +278,16 @@ use mingling::{res::ResExitCode, res::ResREPL};
Removed the per-type inherent method generation from both `groupped.rs` and `pack.rs` in `mingling_macros`.
+4. **\[macros\]** Changed the `route!()` macro's error branch from `return e` to `return ::mingling::Groupped::to_chain(e)`, so that the error type no longer needs to be pre-converted to `ChainProcess` via `.to_chain()` or `.to_render()`. The macro now accepts any type implementing `Groupped` in the error position and automatically converts it.
+
+```rust
+// Before
+let value = route!(prev.pick_or_route((), Error::default().to_chain()).unpack());
+
+// After
+let value = route!(prev.pick_or_route((), Error::default()).unpack());
+```
+
### Release 0.1.9 (2026-05-29)
#### Fixes:
diff --git a/examples/example-argument-parse/src/main.rs b/examples/example-argument-parse/src/main.rs
index 316e52f..4929b7c 100644
--- a/examples/example-argument-parse/src/main.rs
+++ b/examples/example-argument-parse/src/main.rs
@@ -59,7 +59,7 @@ fn handle_strict_transfer_parse(args: EntryStrictTransfer) -> Next {
.pick::<bool>(["--dir", "-D"])
.pick_or::<usize>("--size", 1024 * 1024_usize)
// Finally parse the positional argument; if not found, route to `ErrorNoNameProvided`
- .pick_or_route::<String, _>((), ErrorNoNameProvided::default().to_chain())
+ .pick_or_route::<String, _>((), ErrorNoNameProvided::default())
.after(|str| str.trim().replace(' ', ""))
.unpack()
}
diff --git a/examples/example-custom-pickable/src/main.rs b/examples/example-custom-pickable/src/main.rs
index a2aa662..015cc62 100644
--- a/examples/example-custom-pickable/src/main.rs
+++ b/examples/example-custom-pickable/src/main.rs
@@ -46,7 +46,7 @@ pack!(ErrorParseAddressFailed = ());
#[chain]
fn handle_connect(prev: EntryConnect) -> Next {
let connect: Address =
- route! { prev.pick_or_route((), ErrorParseAddressFailed::default().to_chain()).unpack() };
+ route! { prev.pick_or_route((), ErrorParseAddressFailed::default()).unpack() };
connect.to_chain()
}
diff --git a/examples/full-todolist/src/main.rs b/examples/full-todolist/src/main.rs
index fdac1c7..7f958d4 100644
--- a/examples/full-todolist/src/main.rs
+++ b/examples/full-todolist/src/main.rs
@@ -79,7 +79,7 @@ fn main() {
fn handle_add(args: EntryAdd) -> Next {
let task: String = route! {
args
- .pick_or_route((), ErrorNoTaskDescriptionProvided::new(()).to_render())
+ .pick_or_route((), ErrorNoTaskDescriptionProvided::new(()))
.unpack()
};
StateAddTodo::new(task).to_chain()
@@ -119,7 +119,7 @@ fn handle_list(_args: EntryList, todolist: &mut LazyRes<ResTodoList>) -> Next {
#[chain]
fn handle_complete(args: EntryComplete) -> Next {
let index: i32 = route! {
- args.pick_or_route((), ErrorNoIndexProvided::new(()).to_render()).unpack()
+ args.pick_or_route((), ErrorNoIndexProvided::new(())).unpack()
};
StateCompleteTodo::new(index).to_chain()
}
diff --git a/mingling/src/example_docs.rs b/mingling/src/example_docs.rs
index f77d9f6..caa12ae 100644
--- a/mingling/src/example_docs.rs
+++ b/mingling/src/example_docs.rs
@@ -79,7 +79,7 @@
/// .pick::<bool>(["--dir", "-D"])
/// .pick_or::<usize>("--size", 1024 * 1024_usize)
/// // Finally parse the positional argument; if not found, route to `ErrorNoNameProvided`
-/// .pick_or_route::<String, _>((), ErrorNoNameProvided::default().to_chain())
+/// .pick_or_route::<String, _>((), ErrorNoNameProvided::default())
/// .after(|str| str.trim().replace(' ', ""))
/// .unpack()
/// }
@@ -670,7 +670,7 @@ pub mod example_completion {}
/// #[chain]
/// fn handle_connect(prev: EntryConnect) -> Next {
/// let connect: Address =
-/// route! { prev.pick_or_route((), ErrorParseAddressFailed::default().to_chain()).unpack() };
+/// route! { prev.pick_or_route((), ErrorParseAddressFailed::default()).unpack() };
/// connect.to_chain()
/// }
///
diff --git a/mingling_macros/src/lib.rs b/mingling_macros/src/lib.rs
index 204d59c..3b33f09 100644
--- a/mingling_macros/src/lib.rs
+++ b/mingling_macros/src/lib.rs
@@ -405,12 +405,13 @@ pub fn pack_err(input: TokenStream) -> TokenStream {
/// ```rust,ignore
/// match expr {
/// Ok(r) => r,
-/// Err(e) => return e,
+/// Err(e) => return ::mingling::Groupped::to_chain(e),
/// }
/// ```
///
-/// It is useful inside chain functions where you have a `Result<ChainProcess<G>, ChainProcess<G>>`
-/// and want to propagate the error case as an early return.
+/// It is useful inside chain functions where you have a `Result<SomeType, SomeType>`
+/// where both types implement `Groupped` and want to propagate the error case
+/// as an early return via `Groupped::to_chain()`.
///
/// # Example
///
@@ -419,9 +420,9 @@ pub fn pack_err(input: TokenStream) -> TokenStream {
///
/// #[chain]
/// fn process(prev: SomeEntry) -> ChainProcess<ThisProgram> {
-/// let value = route!(try_something().ok_or(ErrorEntry::new("failed".into()).to_render()));
-/// // value is the Ok(ChainProcess) from try_something()
-/// value
+/// let value = route!(current_dir().map_err(|e| ErrorEntry::new(e.to_string_lossy().to_string())));
+/// // value is the PathBuf from current_dir()
+/// value.to_chain()
/// }
/// ```
#[cfg(feature = "extra_macros")]
@@ -431,7 +432,7 @@ pub fn route(input: TokenStream) -> TokenStream {
let expanded = quote! {
match #expr {
Ok(r) => r,
- Err(e) => return e,
+ Err(e) => return ::mingling::Groupped::to_chain(e),
}
};
TokenStream::from(expanded)