From 6d8728bb9411fccf6a7b53dda2a2c2b2adbc89ee Mon Sep 17 00:00:00 2001 From: Colin Kiegel Date: Sun, 20 Dec 2015 10:31:11 +0100 Subject: [PATCH 1/6] refactor FIND_DISPLAY_IMPL --- src/lib.rs | 74 +++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 54 insertions(+), 20 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ac0794a..12e1add 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -113,6 +113,28 @@ //! } //! ``` //! +//! If you need a reference to the error when `Display`ing, you can instead use +//! `display_fn(X, pattern, ..args)`, where `X` sets the name of the reference. +//! +//! ```rust +//! # #[macro_use] extern crate quick_error; +//! # fn main() {} +//! # +//! use std::error::Error; // put methods like `description()` of this trait into scope +//! +//! quick_error! { +//! #[derive(Debug)] +//! pub enum SomeError { +//! Io(err: std::io::Error) { +//! display_fn(X, "{}: {}", X.description(), err) +//! } +//! Utf8(err: std::str::Utf8Error) { +//! display_fn(self_, "{}, valid up to {}", self_.description(), err.valid_up_to()) +//! } +//! } +//! } +//! ``` +//! //! To convert to the type from any other, use one of the three forms of //! `from` clause. //! @@ -181,7 +203,6 @@ //! Empty braces can be omitted as of quick_error 0.1.3. //! - /// Main macro that does all the work #[macro_export] macro_rules! quick_error { @@ -376,9 +397,12 @@ macro_rules! quick_error { match self { $( &$name::$item $( ( $(ref $var),* ) )* => { - quick_error!(FIND_DISPLAY_IMPL - $item self fmt [ $( ( $($var)* ) )* ] - { $($funcs)* }) + let display_fn = quick_error!(FIND_DISPLAY_IMPL + $name::$item + implements { $($funcs)* } + _ => display("{}", ::std::error::Error::description(self))); + + display_fn(self, fmt) } )* } @@ -415,25 +439,33 @@ macro_rules! quick_error { { $($funcs)* }); )* }; - (FIND_DISPLAY_IMPL $item:ident $me:ident $fmt:ident - [ $( ( $($var:ident)* ) )* ] - { display($($exprs:tt)*) $($tail:tt)* } + (FIND_DISPLAY_IMPL $name:ident::$item:ident + implements { display($($exprs:tt)*) $($tail:tt)* } + _ => $($default:tt)* ) => { - write!($fmt, $($exprs)*) + |self_: &$name, f: &mut ::std::fmt::Formatter| { write!(f, $($exprs)*) } }; - (FIND_DISPLAY_IMPL $item:ident $me:ident $fmt:ident - [ $( ( $($var:ident)* ) )* ] - { $t:tt $($tail:tt)* } + (FIND_DISPLAY_IMPL $name:ident::$item:ident + //implements { display_fn(|$me:ident, $fmt:ident| $($body:block)*) $($tail:tt)* } + implements { display_fn($self_:ident, $($exprs:tt)*) $($tail:tt)* } + _ => $($default:tt)* + ) => { + |$self_: &$name, f: &mut ::std::fmt::Formatter| { write!(f, $($exprs)*) } + }; + (FIND_DISPLAY_IMPL $name:ident::$item:ident + implements { $t:tt $($tail:tt)* } + _ => $($default:tt)* ) => { quick_error!(FIND_DISPLAY_IMPL - $item $me $fmt [ $( ( $($var)* ) )* ] - { $($tail)* }) + $name::$item + implements { $($tail)* } + _ => $($default)*) }; - (FIND_DISPLAY_IMPL $item:ident $me:ident $fmt:ident - [ $( ( $($var:ident)* ) )* ] - { } + (FIND_DISPLAY_IMPL $name:ident::$item:ident + implements { } + _ => display($($exprs:tt)*) ) => { - write!($fmt, "{}", ::std::error::Error::description($me)) + |self_: &$name, f: &mut ::std::fmt::Formatter| { write!(f, $($exprs)*) } }; (FIND_DESCRIPTION_IMPL $item:ident $me:ident $fmt:ident [ $( ( $($var:ident)* ) )* ] @@ -535,6 +567,8 @@ macro_rules! quick_error { // skip everything else completely (ERROR_CHECK display($($exprs:tt)*) $($tail:tt)*) => { quick_error!(ERROR_CHECK $($tail)*); }; + (ERROR_CHECK display_fn($($exprs:tt)*) $($tail:tt)*) + => { quick_error!(ERROR_CHECK $($tail)*); }; (ERROR_CHECK description($expr:expr) $($tail:tt)*) => { quick_error!(ERROR_CHECK $($tail)*); }; (ERROR_CHECK cause($expr:expr) $($tail:tt)*) @@ -594,7 +628,7 @@ mod test { /// I/O error with some context IoAt(place: &'static str, err: io::Error) { cause(err) - display("Error at {}: {}", place, err) + display_fn(self_, "{} {}: {}", self_.description(), place, err) description("io error at") from(s: String) -> ("idea", io::Error::new(io::ErrorKind::Other, s)) @@ -633,7 +667,7 @@ mod test { let err: &Error = &IoWrapper::IoAt("file", io::Error::new(io::ErrorKind::NotFound, io1)); assert_eq!(format!("{}", err), - "Error at file: I/O error: some error".to_string()); + "io error at file: I/O error: some error".to_string()); assert_eq!(format!("{:?}", err), "IoAt(\"file\", Error { \ repr: Custom(Custom { kind: NotFound, \ error: Io(Error { repr: Custom(Custom { \ @@ -654,7 +688,7 @@ mod test { #[test] fn io_wrapper_custom_from() { let io1: IoWrapper = From::from("Stringy".to_string()); - assert_eq!(format!("{}", io1), "Error at idea: Stringy".to_string()); + assert_eq!(format!("{}", io1), "io error at idea: Stringy".to_string()); assert_eq!(io1.cause().unwrap().description(), "Stringy"); } From fccd0e9967f886397f6a3b5c8e946e6601c32d5f Mon Sep 17 00:00:00 2001 From: Colin Kiegel Date: Sun, 20 Dec 2015 11:48:36 +0100 Subject: [PATCH 2/6] fix rust coding style --- src/lib.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 12e1add..ccb3fee 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -114,7 +114,7 @@ //! ``` //! //! If you need a reference to the error when `Display`ing, you can instead use -//! `display_fn(X, pattern, ..args)`, where `X` sets the name of the reference. +//! `display_fn(x, pattern, ..args)`, where `x` sets the name of the reference. //! //! ```rust //! # #[macro_use] extern crate quick_error; @@ -126,7 +126,7 @@ //! #[derive(Debug)] //! pub enum SomeError { //! Io(err: std::io::Error) { -//! display_fn(X, "{}: {}", X.description(), err) +//! display_fn(x, "{}: {}", x.description(), err) //! } //! Utf8(err: std::str::Utf8Error) { //! display_fn(self_, "{}, valid up to {}", self_.description(), err.valid_up_to()) From 2cad7c5812ed1ba02caeb2e7d90fc5b9a5ecac6b Mon Sep 17 00:00:00 2001 From: Colin Kiegel Date: Sun, 20 Dec 2015 12:38:20 +0100 Subject: [PATCH 3/6] minor cleanup - conformancy with crate-style --- src/lib.rs | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index ccb3fee..f7cb789 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -398,9 +398,8 @@ macro_rules! quick_error { $( &$name::$item $( ( $(ref $var),* ) )* => { let display_fn = quick_error!(FIND_DISPLAY_IMPL - $name::$item - implements { $($funcs)* } - _ => display("{}", ::std::error::Error::description(self))); + $name $item + { $($funcs)* }); display_fn(self, fmt) } @@ -439,33 +438,30 @@ macro_rules! quick_error { { $($funcs)* }); )* }; - (FIND_DISPLAY_IMPL $name:ident::$item:ident - implements { display($($exprs:tt)*) $($tail:tt)* } - _ => $($default:tt)* + (FIND_DISPLAY_IMPL $name:ident $item:ident + { display($($exprs:tt)*) $($tail:tt)* } ) => { |self_: &$name, f: &mut ::std::fmt::Formatter| { write!(f, $($exprs)*) } }; - (FIND_DISPLAY_IMPL $name:ident::$item:ident + (FIND_DISPLAY_IMPL $name:ident $item:ident //implements { display_fn(|$me:ident, $fmt:ident| $($body:block)*) $($tail:tt)* } - implements { display_fn($self_:ident, $($exprs:tt)*) $($tail:tt)* } - _ => $($default:tt)* + { display_fn($self_:ident, $($exprs:tt)*) $($tail:tt)* } ) => { |$self_: &$name, f: &mut ::std::fmt::Formatter| { write!(f, $($exprs)*) } }; - (FIND_DISPLAY_IMPL $name:ident::$item:ident - implements { $t:tt $($tail:tt)* } - _ => $($default:tt)* + (FIND_DISPLAY_IMPL $name:ident $item:ident + { $t:tt $($tail:tt)* } ) => { quick_error!(FIND_DISPLAY_IMPL - $name::$item - implements { $($tail)* } - _ => $($default)*) + $name $item + { $($tail)* }) }; - (FIND_DISPLAY_IMPL $name:ident::$item:ident - implements { } - _ => display($($exprs:tt)*) + (FIND_DISPLAY_IMPL $name:ident $item:ident + { } ) => { - |self_: &$name, f: &mut ::std::fmt::Formatter| { write!(f, $($exprs)*) } + |self_: &$name, f: &mut ::std::fmt::Formatter| { + write!(f, "{}", ::std::error::Error::description(self_)) + } }; (FIND_DESCRIPTION_IMPL $item:ident $me:ident $fmt:ident [ $( ( $($var:ident)* ) )* ] From 76c819c2fbe8c52d3e27aa1d4afc392988cdbbf5 Mon Sep 17 00:00:00 2001 From: Colin Kiegel Date: Sun, 20 Dec 2015 15:59:08 +0100 Subject: [PATCH 4/6] syntax: display_fn(self) -> ("...", a, b) --- src/lib.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f7cb789..c5f3fdd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -114,7 +114,7 @@ //! ``` //! //! If you need a reference to the error when `Display`ing, you can instead use -//! `display_fn(x, pattern, ..args)`, where `x` sets the name of the reference. +//! `display(x) -> (pattern, ..args)`, where `x` sets the name of the reference. //! //! ```rust //! # #[macro_use] extern crate quick_error; @@ -126,10 +126,10 @@ //! #[derive(Debug)] //! pub enum SomeError { //! Io(err: std::io::Error) { -//! display_fn(x, "{}: {}", x.description(), err) +//! display_fn(x) -> ("{}: {}", x.description(), err) //! } //! Utf8(err: std::str::Utf8Error) { -//! display_fn(self_, "{}, valid up to {}", self_.description(), err.valid_up_to()) +//! display_fn(self_) -> ("{}, valid up to {}", self_.description(), err.valid_up_to()) //! } //! } //! } @@ -439,15 +439,14 @@ macro_rules! quick_error { )* }; (FIND_DISPLAY_IMPL $name:ident $item:ident - { display($($exprs:tt)*) $($tail:tt)* } + { display_fn($self_:ident) -> ($($exprs:tt)*) $($tail:tt)* } ) => { - |self_: &$name, f: &mut ::std::fmt::Formatter| { write!(f, $($exprs)*) } + |$self_: &$name, f: &mut ::std::fmt::Formatter| { write!(f, $($exprs)*) } }; (FIND_DISPLAY_IMPL $name:ident $item:ident - //implements { display_fn(|$me:ident, $fmt:ident| $($body:block)*) $($tail:tt)* } - { display_fn($self_:ident, $($exprs:tt)*) $($tail:tt)* } + { display($($exprs:tt)*) $($tail:tt)* } ) => { - |$self_: &$name, f: &mut ::std::fmt::Formatter| { write!(f, $($exprs)*) } + |_, f: &mut ::std::fmt::Formatter| { write!(f, $($exprs)*) } }; (FIND_DISPLAY_IMPL $name:ident $item:ident { $t:tt $($tail:tt)* } @@ -563,7 +562,7 @@ macro_rules! quick_error { // skip everything else completely (ERROR_CHECK display($($exprs:tt)*) $($tail:tt)*) => { quick_error!(ERROR_CHECK $($tail)*); }; - (ERROR_CHECK display_fn($($exprs:tt)*) $($tail:tt)*) + (ERROR_CHECK display_fn($self_:ident) -> ($($exprs:tt)*) $($tail:tt)*) => { quick_error!(ERROR_CHECK $($tail)*); }; (ERROR_CHECK description($expr:expr) $($tail:tt)*) => { quick_error!(ERROR_CHECK $($tail)*); }; @@ -624,7 +623,7 @@ mod test { /// I/O error with some context IoAt(place: &'static str, err: io::Error) { cause(err) - display_fn(self_, "{} {}: {}", self_.description(), place, err) + display_fn(self_) -> ("{} {}: {}", self_.description(), place, err) description("io error at") from(s: String) -> ("idea", io::Error::new(io::ErrorKind::Other, s)) From be91325fe4a1ca3612ca94aff1c8a8a5a795280e Mon Sep 17 00:00:00 2001 From: Paul Colomiets Date: Sun, 20 Dec 2015 17:48:01 +0200 Subject: [PATCH 5/6] Fix 'display_fn' -> 'display' with some macro-trickery --- src/lib.rs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index c5f3fdd..79d06df 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -126,10 +126,10 @@ //! #[derive(Debug)] //! pub enum SomeError { //! Io(err: std::io::Error) { -//! display_fn(x) -> ("{}: {}", x.description(), err) +//! display(x) -> ("{}: {}", x.description(), err) //! } //! Utf8(err: std::str::Utf8Error) { -//! display_fn(self_) -> ("{}, valid up to {}", self_.description(), err.valid_up_to()) +//! display(self_) -> ("{}, valid up to {}", self_.description(), err.valid_up_to()) //! } //! } //! } @@ -439,14 +439,14 @@ macro_rules! quick_error { )* }; (FIND_DISPLAY_IMPL $name:ident $item:ident - { display_fn($self_:ident) -> ($($exprs:tt)*) $($tail:tt)* } + { display($self_:tt) -> ($($exprs:tt)*) $($tail:tt)* } ) => { - |$self_: &$name, f: &mut ::std::fmt::Formatter| { write!(f, $($exprs)*) } + |quick_error!(IDENT $self_): &$name, f: &mut ::std::fmt::Formatter| { write!(f, $($exprs)*) } }; (FIND_DISPLAY_IMPL $name:ident $item:ident - { display($($exprs:tt)*) $($tail:tt)* } + { display($pattern:expr, $($exprs:tt)*) $($tail:tt)* } ) => { - |_, f: &mut ::std::fmt::Formatter| { write!(f, $($exprs)*) } + |_, f: &mut ::std::fmt::Formatter| { write!(f, $pattern, $($exprs)*) } }; (FIND_DISPLAY_IMPL $name:ident $item:ident { $t:tt $($tail:tt)* } @@ -560,9 +560,9 @@ macro_rules! quick_error { // anything else. // This is to contrast FIND_* clauses which just find stuff they need and // skip everything else completely - (ERROR_CHECK display($($exprs:tt)*) $($tail:tt)*) + (ERROR_CHECK display($self_:tt) -> ($($exprs:tt)*) $($tail:tt)*) => { quick_error!(ERROR_CHECK $($tail)*); }; - (ERROR_CHECK display_fn($self_:ident) -> ($($exprs:tt)*) $($tail:tt)*) + (ERROR_CHECK display($pattern: expr, $($exprs:tt)*) $($tail:tt)*) => { quick_error!(ERROR_CHECK $($tail)*); }; (ERROR_CHECK description($expr:expr) $($tail:tt)*) => { quick_error!(ERROR_CHECK $($tail)*); }; @@ -575,6 +575,8 @@ macro_rules! quick_error { (ERROR_CHECK from($fvar:ident : $ftyp:ty) -> ($($e:expr),*) $($tail:tt)*) => { quick_error!(ERROR_CHECK $($tail)*); }; (ERROR_CHECK) => {}; + // Utility functions + (IDENT $ident: ident) => { $ident } } #[cfg(test)] @@ -623,7 +625,7 @@ mod test { /// I/O error with some context IoAt(place: &'static str, err: io::Error) { cause(err) - display_fn(self_) -> ("{} {}: {}", self_.description(), place, err) + display(self_) -> ("{} {}: {}", self_.description(), place, err) description("io error at") from(s: String) -> ("idea", io::Error::new(io::ErrorKind::Other, s)) From 7a95ea61ded010cf34d13beaf160e4c1005bd747 Mon Sep 17 00:00:00 2001 From: Paul Colomiets Date: Sun, 20 Dec 2015 17:53:51 +0200 Subject: [PATCH 6/6] Fix the case where display is called with bare string (no format arguments) --- src/lib.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/lib.rs b/src/lib.rs index 79d06df..0683b9c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -443,6 +443,11 @@ macro_rules! quick_error { ) => { |quick_error!(IDENT $self_): &$name, f: &mut ::std::fmt::Formatter| { write!(f, $($exprs)*) } }; + (FIND_DISPLAY_IMPL $name:ident $item:ident + { display($pattern:expr) $($tail:tt)* } + ) => { + |_, f: &mut ::std::fmt::Formatter| { write!(f, $pattern) } + }; (FIND_DISPLAY_IMPL $name:ident $item:ident { display($pattern:expr, $($exprs:tt)*) $($tail:tt)* } ) => { @@ -562,6 +567,8 @@ macro_rules! quick_error { // skip everything else completely (ERROR_CHECK display($self_:tt) -> ($($exprs:tt)*) $($tail:tt)*) => { quick_error!(ERROR_CHECK $($tail)*); }; + (ERROR_CHECK display($pattern: expr) $($tail:tt)*) + => { quick_error!(ERROR_CHECK $($tail)*); }; (ERROR_CHECK display($pattern: expr, $($exprs:tt)*) $($tail:tt)*) => { quick_error!(ERROR_CHECK $($tail)*); }; (ERROR_CHECK description($expr:expr) $($tail:tt)*) @@ -633,6 +640,9 @@ mod test { Discard { from(&'static str) } + Singleton { + display("Just a string") + } } } @@ -696,4 +706,10 @@ mod test { assert!(io1.cause().is_none()); } + #[test] + fn io_wrapper_signleton() { + let io1: IoWrapper = IoWrapper::Singleton; + assert_eq!(format!("{}", io1), "Just a string".to_string()); + } + }