Skip to content
This repository was archived by the owner on Aug 16, 2021. It is now read-only.

Commit 7caf213

Browse files
committed
Allow skipping the Msg variant
While the `Msg` variant may be a useful option for some users, many will prefer to stick to more descriptive error types, and won't want this variant present. This allows a `skip_msg_variant` flag to be passed to `error_chain!`, which will cause no `Msg` variant to be present in the generated code. I've also refactored the body of `impl_error_chain_processing` to not care about the number of arguments other than the final branch, so more cases can be added in the future without having to touch as many places as I did. Fixes #200.
1 parent 9989177 commit 7caf213

File tree

2 files changed

+105
-44
lines changed

2 files changed

+105
-44
lines changed

src/error_chain.rs

Lines changed: 84 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,68 @@ macro_rules! impl_error_chain_processed {
3333
#[allow(unused)]
3434
pub type $result_name<T> = ::std::result::Result<T, $error_name>;
3535
};
36-
// Without `Result` wrapper.
36+
37+
// With `Msg` variant.
38+
(
39+
types {
40+
$error_name:ident, $error_kind_name:ident, $($types:tt)*
41+
}
42+
links $links:tt
43+
foreign_links $foreign_links:tt
44+
errors { $($errors:tt)* }
45+
) => {
46+
impl_error_chain_processed! {
47+
types {
48+
$error_name, $error_kind_name, $($types)*
49+
}
50+
skip_msg_variant
51+
links $links
52+
foreign_links $foreign_links
53+
errors {
54+
/// A convenient variant for String.
55+
Msg(s: String) {
56+
description(&s)
57+
display("{}", s)
58+
}
59+
60+
$($errors)*
61+
}
62+
}
63+
64+
impl<'a> From<&'a str> for $error_kind_name {
65+
fn from(s: &'a str) -> Self {
66+
$error_kind_name::Msg(s.into())
67+
}
68+
}
69+
70+
impl From<String> for $error_kind_name {
71+
fn from(s: String) -> Self {
72+
$error_kind_name::Msg(s)
73+
}
74+
}
75+
76+
impl<'a> From<&'a str> for $error_name {
77+
fn from(s: &'a str) -> Self {
78+
Self::from_kind(s.into())
79+
}
80+
}
81+
82+
impl From<String> for $error_name {
83+
fn from(s: String) -> Self {
84+
Self::from_kind(s.into())
85+
}
86+
}
87+
};
88+
89+
// Without `Result` wrapper or `Msg` variant.
3790
(
3891
types {
3992
$error_name:ident, $error_kind_name:ident,
4093
$result_ext_name:ident;
4194
}
4295

96+
skip_msg_variant
97+
4398
links {
4499
$( $link_variant:ident ( $link_error_path:path, $link_kind_path:path )
45100
$( #[$meta_links:meta] )*; ) *
@@ -227,18 +282,6 @@ macro_rules! impl_error_chain_processed {
227282
}
228283
}
229284

230-
impl<'a> From<&'a str> for $error_name {
231-
fn from(s: &'a str) -> Self {
232-
$error_name::from_kind(s.into())
233-
}
234-
}
235-
236-
impl From<String> for $error_name {
237-
fn from(s: String) -> Self {
238-
$error_name::from_kind(s.into())
239-
}
240-
}
241-
242285
impl ::std::ops::Deref for $error_name {
243286
type Target = $error_kind_name;
244287

@@ -255,13 +298,6 @@ macro_rules! impl_error_chain_processed {
255298
/// The kind of an error.
256299
#[derive(Debug)]
257300
pub enum $error_kind_name {
258-
259-
/// A convenient variant for String.
260-
Msg(s: String) {
261-
description(&s)
262-
display("{}", s)
263-
}
264-
265301
$(
266302
$(#[$meta_links])*
267303
$link_variant(e: $link_kind_path) {
@@ -291,18 +327,6 @@ macro_rules! impl_error_chain_processed {
291327
}
292328
) *
293329

294-
impl<'a> From<&'a str> for $error_kind_name {
295-
fn from(s: &'a str) -> Self {
296-
$error_kind_name::Msg(s.to_string())
297-
}
298-
}
299-
300-
impl From<String> for $error_kind_name {
301-
fn from(s: String) -> Self {
302-
$error_kind_name::Msg(s)
303-
}
304-
}
305-
306330
impl From<$error_name> for $error_kind_name {
307331
fn from(e: $error_name) -> Self {
308332
e.0
@@ -352,48 +376,64 @@ macro_rules! impl_error_chain_processed {
352376
#[macro_export]
353377
macro_rules! error_chain_processing {
354378
(
355-
({}, $b:tt, $c:tt, $d:tt)
379+
({}, $($rest:tt)*)
356380
types $content:tt
357381
$( $tail:tt )*
358382
) => {
359383
error_chain_processing! {
360-
($content, $b, $c, $d)
384+
($content, $($rest)*)
361385
$($tail)*
362386
}
363387
};
388+
364389
(
365-
($a:tt, {}, $c:tt, $d:tt)
390+
($a:tt, {}, $($rest:tt)*)
366391
links $content:tt
367392
$( $tail:tt )*
368393
) => {
369394
error_chain_processing! {
370-
($a, $content, $c, $d)
395+
($a, $content, $($rest)*)
371396
$($tail)*
372397
}
373398
};
399+
374400
(
375-
($a:tt, $b:tt, {}, $d:tt)
401+
($a:tt, $b:tt, {}, $($rest:tt)*)
376402
foreign_links $content:tt
377403
$( $tail:tt )*
378404
) => {
379405
error_chain_processing! {
380-
($a, $b, $content, $d)
406+
($a, $b, $content, $($rest)*)
381407
$($tail)*
382408
}
383409
};
410+
384411
(
385-
($a:tt, $b:tt, $c:tt, {})
412+
($a:tt, $b:tt, $c:tt, {}, $($rest:tt)*)
386413
errors $content:tt
387414
$( $tail:tt )*
388415
) => {
389416
error_chain_processing! {
390-
($a, $b, $c, $content)
417+
($a, $b, $c, $content, $($rest)*)
418+
$($tail)*
419+
}
420+
};
421+
422+
(
423+
($a:tt, $b:tt, $c:tt, $d:tt, {}, $($rest:tt)*)
424+
skip_msg_variant
425+
$( $tail:tt )*
426+
) => {
427+
error_chain_processing! {
428+
($a, $b, $c, $d, {skip_msg_variant}, $($rest)*)
391429
$($tail)*
392430
}
393431
};
394-
( ($a:tt, $b:tt, $c:tt, $d:tt) ) => {
432+
433+
( ($a:tt, $b:tt, $c:tt, $d:tt, {$($e:tt)*},) ) => {
395434
impl_error_chain_processed! {
396435
types $a
436+
$($e)*
397437
links $b
398438
foreign_links $c
399439
errors $d
@@ -404,10 +444,10 @@ macro_rules! error_chain_processing {
404444
/// Macro for generating error types and traits. See crate level documentation for details.
405445
#[macro_export]
406446
macro_rules! error_chain {
407-
( $( $block_name:ident { $( $block_content:tt )* } )* ) => {
447+
( $($args:tt)* ) => {
408448
error_chain_processing! {
409-
({}, {}, {}, {})
410-
$($block_name { $( $block_content )* })*
449+
({}, {}, {}, {}, {},)
450+
$($args)*
411451
}
412452
};
413453
}

tests/tests.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -641,3 +641,24 @@ fn trailing_comma_in_errors_impl() {
641641
}
642642
};
643643
}
644+
645+
#[test]
646+
fn skipping_msg_variant() {
647+
error_chain! {
648+
skip_msg_variant
649+
650+
errors {
651+
MyMsg(s: String) {
652+
description(&s)
653+
display("{}", s)
654+
}
655+
}
656+
}
657+
658+
let x = Error::from_kind(ErrorKind::MyMsg("some string".into()));
659+
// This would fail to compile if we generate a `Msg` variant
660+
match *x.kind() {
661+
ErrorKind::MyMsg(_) => {}
662+
ErrorKind::__Nonexhaustive {} => {}
663+
}
664+
}

0 commit comments

Comments
 (0)