Enum propagate::Result[][src]

pub enum Result<T, E, S = ErrorTrace> {
    Ok(T),
    Err(E, S),
}
Expand description

A replacement for std::result::Result that supports tracing via the ? operator.

After a propagate::Result has been constructed, it will keep a running “return trace” of the code locations where the ? operator is invoked on it.

Working with propagate::Result

There are a few things to remember when using propagate::Result as a replacement for the std library result.

Creating Errors

Construct an Err variant by providing an error value and a new trace (e.g., using ErrorTrace::new()):

use propagate::ErrorTrace;

fn gives_error() -> propagate::Result<(), &'static str> {
    propagate::Err("Nothing here", ErrorTrace::new())
}

Pattern Matching

The Err variant contains two values: the error and its associated trace. Pattern matching should look like this:

let result: propagate::Result<_, _> = gives_error();
match result {
    propagate::Ok(_) => {}
    propagate::Err(err, trace) => {
        println!("error: {}", err);
        println!("trace: {}", trace);
    }
}

IMPORTANT: Forwarding Errors

When not using try blocks, you must remember to surround result values with Ok(..?) when returning them in a function. The compiler will not force you to do this if the result value’s type is identical to the function’s return type.

// YES: Result surrounded by Ok(..?), so the error trace will include foo()
fn foo() -> propagate::Result<(), &'static str> {
    let result = gives_error();
    propagate::Ok(result?)
}

// NO: Result returned directly, so the error trace will not include bar()
fn bar() -> propagate::Result<(), &'static str> {
    let result = gives_error();
    result
}

When you use try blocks, you do not need the Ok:

#![feature(try_blocks)]
fn foo() -> propagate::Result<(), &'static str> {
    try {
        let result = gives_error();
        result?
    }
}

And the compiler will force you to use ?:

#![feature(try_blocks)]
fn bar() -> propagate::Result<(), &'static str> {
    try {
        let result = gives_error();
        result
    }
}

Coercion Using ?

The ? operator can be used to coerce between result types.

From propagate to propagate

One propagate::Result can be coerced to another if there is an implementation of From between the two error types:

#![feature(try_blocks)]

let result: propagate::Result<(), &str> =
    propagate::Err("str slice", ErrorTrace::new());

// Coerces string slice to String object
let result: propagate::Result<(), String> = try { result? };

From std to propagate

To provide easy interoperability with standard library modules and other crates that return results, any std::result::Result can be coerced to a propagate::Result:

#![feature(try_blocks)]

let result: Result<(), u32> = Err(42);

// Coerces std::result::Result to propagate::Result
let result: propagate::Result<(), u32> = try { result? };

And if there is an implementation of From between the two error types, you can do that coercion at the same time:

#![feature(try_blocks)]

let result: Result<(), &str> = Err("string slice");

// Coerces std::result::Result to propagate::Result
// AND
// Coerces string slice to String object
let result: propagate::Result<(), String> = try { result? };

Variants

Ok(T)

Contains the success value.

Tuple Fields of Ok

0: T
Err(E, S)

Contains the error value and associated error trace.

Tuple Fields of Err

0: E1: S

Implementations

Stuff not from the standard library.

Constructs a new error result from the provided error value.

Examples

Basic usage:

let x: Result<u32, &str> = Result::new_err("Nothing here");

Converts from Result<T, E, S> to std::result::Result<T, E>.

Converts self into a std::result::Result<T, E>, consuming self, and discarding the error trace, if any.

Examples

Basic usage:

let x: Result<u32, &str> = propagate::Ok(2);
assert_eq!(x.to_std(), std::result::Result::Ok(2));

let x: Result<u32, &str> = Result::new_err("Nothing here");
assert_eq!(x.to_std(), std::result::Result::Err("Nothing here"));

Converts from Result<T, E, S> to Option<(E, S)>.

Converts self into an Option<(E, S)>, consuming self, and discarding the success value, if any.

Examples

Basic usage:

let x: Result<u32, &str> = propagate::Ok(2);
assert!(x.err_trace().is_none());

let x: Result<u32, &str> = Result::new_err("Nothing here");
match x.err_trace() {
    Some((err, trace)) => {
        assert_eq!(err, "Nothing here");
        assert_eq!(trace.0.len(), 1);
    }
    None => unreachable!(),
}

Returns true if the result is Ok.

Examples

Basic usage:

let x: Result<i32, &str> = propagate::Ok(-3);
assert_eq!(x.is_ok(), true);

let x: Result<i32, &str> = Result::new_err("Some error message");
assert_eq!(x.is_ok(), false);

Returns true if the result is Err.

Examples

Basic usage:

let x: Result<i32, &str> = propagate::Ok(-3);
assert_eq!(x.is_err(), false);

let x: Result<i32, &str> = Result::new_err("Some error message");
assert_eq!(x.is_err(), true);

Converts from Result<T, E, S> to Option<T>.

Converts self into an Option<T>, consuming self, and discarding the error, if any.

Examples

Basic usage:

let x: Result<u32, &str> = propagate::Ok(2);
assert_eq!(x.ok(), Some(2));

let x: Result<u32, &str> = Result::new_err("Nothing here");
assert_eq!(x.ok(), None);

Converts from Result<T, E, S> to Option<E>.

Converts self into an Option<E>, consuming self, and discarding the success value and error trace, if any.

Examples

Basic usage:

let x: Result<u32, &str> = propagate::Ok(2);
assert_eq!(x.err(), None);

let x: Result<u32, &str> = Result::new_err("Nothing here");
assert_eq!(x.err(), Some("Nothing here"));

Converts from &Result<T, E, S> to Result<&T, &E, &S>.

Produces a new Result, containing a reference into the original, leaving the original in place.

Examples

Basic usage:

let x: Result<u32, &str> = propagate::Ok(2);
assert_eq!(x.as_ref(), propagate::Ok(&2));

let x: Result<u32, &str> = Result::new_err("Error");
assert!(matches!(x.as_ref(), propagate::Err(&"Error", _)));

Converts from &mut Result<T, E, S> to Result<&mut T, &mut E, &mut S>.

Examples

Basic usage:

fn mutate(r: &mut Result<i32, i32>) {
    match r.as_mut() {
        propagate::Ok(v) => *v = 42,
        propagate::Err(e, _) => *e = 0,
    }
}

let mut x: Result<i32, i32> = propagate::Ok(2);
mutate(&mut x);
assert_eq!(x.unwrap(), 42);

let mut x: Result<i32, i32> = Result::new_err(13);
mutate(&mut x);
assert_eq!(x.unwrap_err(), 0);

Maps a Result<T, E> to Result<T, F> by applying a function to a contained Err value, leaving an Ok value untouched.

This function can be used to pass through a successful result while handling an error.

Examples

Basic usage:

fn stringify(x: i32) -> String { format!("error code: {}", x) }

let x: Result<i32, i32> = propagate::Ok(2);
assert_eq!(x.map_err(stringify), propagate::Ok(2));

let x: Result<i32, i32> = Result::new_err(13);
let y: Result<i32, String> = x.map_err(stringify);
assert_eq!(y.err().unwrap(), "error code: 13".to_string());

Returns the contained Ok value or a provided default.

Arguments passed to unwrap_or are eagerly evaluated; if you are passing the result of a function call, it is recommended to use unwrap_or_else, which is lazily evaluated.

Examples

Basic usage:

let default = 2;
let x: Result<u32, &str> = propagate::Ok(9);
assert_eq!(x.unwrap_or(default), 9);

let x: Result<u32, &str> = Result::new_err("error");
assert_eq!(x.unwrap_or(default), default);

Returns the contained Ok value or computes it from a closure.

Examples

Basic usage:

fn count(x: &str) -> usize { x.len() }

let x: Result<usize, &str> = propagate::Ok(2);
assert_eq!(x.unwrap_or_else(count), 2);

let x: Result<usize, &str> = propagate::Err("foo", ErrorTrace::new());
assert_eq!(x.unwrap_or_else(count), 3);

Returns the contained Ok value, consuming the self value.

Panics

Panics if the value is an Err, with a panic message including the passed message, and the content of the Err.

Examples

Basic usage:

let x: Result<u32, &str> = Result::new_err("emergency failure");
x.expect("Testing expect"); // panics with `Testing expect: emergency failure`

Returns the contained Ok value, consuming the self value.

Because this function may panic, its use is generally discouraged. Instead, prefer to use pattern matching and handle the Err case explicitly, or call unwrap_or, unwrap_or_else, or unwrap_or_default.

Panics

Panics if the value is an Err, with a panic message provided by the Err’s value.

Examples

Basic usage:

let x: Result<u32, &str> = propagate::Ok(2);
assert_eq!(x.unwrap(), 2);
let x: Result<u32, &str> = Result::new_err("emergency failure");
x.unwrap(); // panics with `emergency failure`

Returns the contained Err value, consuming the self value.

Panics

Panics if the value is an Ok, with a panic message including the passed message, and the content of the Ok.

Examples

Basic usage:

let x: Result<u32, &str> = propagate::Ok(10);
x.expect_err("Testing expect_err"); // panics with `Testing expect_err: 10`

Returns the contained Err value, consuming the self value.

Panics

Panics if the value is an Ok, with a custom panic message provided by the Ok’s value.

Examples

let x: Result<u32, &str> = propagate::Ok(2);
x.unwrap_err(); // panics with `2`
let x: Result<u32, &str> = Result::new_err("emergency failure");
assert_eq!(x.unwrap_err(), "emergency failure");

Returns the contained Ok value or a default

Consumes the self argument then, if Ok, returns the contained value, otherwise if Err, returns the default value for that type.

Examples

Converts a string to an integer, turning poorly-formed strings into 0 (the default value for integers). parse converts a string to any other type that implements FromStr, returning an Err on error.

let good_year_from_input = "1909";
let bad_year_from_input = "190blarg";
let good_year = good_year_from_input.parse().unwrap_or_default();
let bad_year = bad_year_from_input.parse().unwrap_or_default();

assert_eq!(1909, good_year);
assert_eq!(0, bad_year);

Transposes a Result of an Option into an Option of a Result.

Ok(None) will be mapped to None. Ok(Some(_)) and Err(_, _) will be mapped to Some(Ok(_)) and Some(Err(_, _)).

Examples

#[derive(Debug, Eq, PartialEq)]
struct SomeErr;

let x: Result<Option<i32>, SomeErr> = propagate::Ok(Some(5));
let y: Option<Result<i32, SomeErr>> = Some(propagate::Ok(5));
assert_eq!(x.transpose(), y);

Trait Implementations

Formats the value using the given formatter. Read more

Pushes an entry to the trace when one Result is coerced to another using the ? operator.

🔬 This is a nightly-only experimental API. (try_trait_v2)

Constructs the type from a compatible Residual type. Read more

Starts a new trace when a std::result::Result is coerced to a Result using ?.

🔬 This is a nightly-only experimental API. (try_trait_v2)

Constructs the type from a compatible Residual type. Read more

Feeds this value into the given Hasher. Read more

Feeds a slice of this type into the given Hasher. Read more

This method tests for self and other values to be equal, and is used by ==. Read more

This method tests for !=.

🔬 This is a nightly-only experimental API. (termination_trait_lib)

Is called to get the representation of the value as status code. This status code is returned to the operating system. Read more

Overriding the try operator ? for Result.

Invoking the ? operator invokes Self::branch() under the hood. This function returns a ControlFlow enum which dictates whether the execution will continue forward (i.e., Ok()), or break early (i.e., Err()). The value produced when continuing is the Output, and the value produced when breaking early is called the Residual.

Coercion between residual types is achieved by implementing the FromResidual trait. Result allows coercion from standard library results (std::result::Result) as well as from other Result instances whose inner error types are convertible from one to another.

🔬 This is a nightly-only experimental API. (try_trait_v2)

The type of the value produced by ? when not short-circuiting.

🔬 This is a nightly-only experimental API. (try_trait_v2)

The type of the value passed to FromResidual::from_residual as part of ? when short-circuiting. Read more

🔬 This is a nightly-only experimental API. (try_trait_v2)

Constructs the type from its Output type. Read more

🔬 This is a nightly-only experimental API. (try_trait_v2)

Used in ? to decide whether the operator should produce a value (because this returned ControlFlow::Continue) or propagate a value back to the caller (because this returned ControlFlow::Break). Read more

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Performs the conversion.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.