Crate throw [−] [src]
Throw!
Throw is a new experimental rust error handling library, meant to assist and build on existing error handling systems.
Throw exports two structs, throw::ErrorPoint
and throw::Error
. throw::Error
stores a
single original_error
variable which it is created from, and then a list of ErrorPoint
s
which starts out with the original point of creation with throw!()
, and is added to every
time you propagate the error upwards with up!()
.
Throw does not replace existing error handling systems. The throw::Error
type has a type
parameter E
which represents an internal error type stored. throw::Error
just warps your
error type and stores ErrorPoints alongside it.
Throw helps you better keep track of your errors. Instead of seeing a generic "No such file or directory" message, you get a stack trace of functions which propagated the error as well.
Instead of:
IO Error: failed to lookup address information: Name or service not known
Get:
Error: IO Error: failed to lookup address information: Name or service not known
at 79:17 in zaldinar::startup (src/startup.rs)
at 104:4 in zaldinar::startup (src/startup.rs)
at 28:17 in zaldinar_irclib (/home/daboross/Projects/Rust/zaldinar/zaldinar-irclib/src/lib.rs)
Using throw!
The main way you use throw is through two macros, throw!()
and up!()
. throw!()
is used
when you have a regular (non-throw) result coming from some library function that you want to
propagate upwards in case of an error. up!()
is used when you have an error which was
created using throw!()
in a sub-function which you want to add an error point to and
propagate upwards.
Here's an example of throw in action:
#[macro_use] extern crate throw; use std::io::prelude::*; use std::io; use std::fs::File; fn read_log() -> Result<String, throw::Error<io::Error>> { let mut file = throw!(File::open("some_file.log")); let mut buf = String::new(); throw!(file.read_to_string(&mut buf)); Ok((buf)) } fn do_things() -> Result<(), throw::Error<io::Error>> { let log_contents = up!(read_log()); println!("Log contents: {}", log_contents); Ok(()) } fn main() { let result = do_things(); if let Err(e) = result { panic!("{}", e); } }
This simple program behaves exactly as if Result<_, io::Error>
directly when it functions
correctly. When the program encounters is when throw really shines. This will result in an
error message:
Error: No such file or directory (os error 2)
at 16:23 in main (src/main.rs)
at 9:19 in main (src/main.rs)
These stack traces are stored inside throw::Error, and are recorded automatically when
throw!()
or up!()
returns an Err value.
In each at
line, the 16:23
represents line_num:column_num
, the main
represents the
module path (for example my_program::sub_module
), and src/main.rs
represents the path of
the file in which throw!()
was used in.
Throwing directly from a function is also supported, using throw_new!()
:
fn possibly_fails() -> Result<(), throw::Error<&'static str>> { if true { // throw_new!() will always return directly throw_new!("oops"); } Ok(()) } fn main() { possibly_fails().unwrap() }
called `Result::unwrap()` on an `Err` value: Error: "oops"
at 6:8 in main (src/main.rs)
throw_new!()
differs from throw!()
in that it takes a parameter directly to pass to a
throw::Error
, rather than a Result<>
to match on. throw_new!()
will always return
directly from the function.
Macros
throw! | |
throw_new! | |
up! |
Structs
Error |
Represents an error. Stores an original error of type E, and any number of ErrorPoints at which the error was propagated. |
ErrorPoint |
Represents a location at which an error was thrown via throw!() |
Type Definitions
Result |
Result alias for a result containing a throw::Error. |