[][src]Struct terminator::Terminator

pub struct Terminator { /* fields omitted */ }

A type that lets you output your error as Display for fn main() -> Result<(), Error>

Trait Implementations

impl<T: Into<Box<dyn Error>>> From<T> for Terminator[src]

This impl block is what does all of the work. Rust has some rules regarding what traits can be implemented for what. Initially the this was what was written:

use std::error::Error;
impl<T: Error> From<T> for Terminator {

However, we run into issues of cohesion and specialization. There exists an impl defined in stdlib of this form:

impl<T> From<T> for T {

Which impl then should Rust use? While we know it's more specialized rustc does not. On top of this we are violating coherence meaning that we have more than one impl for each given type. What's a programmer to do then in this case? We want to be able to say I want to restrict this to types that implement std::error::Error. Well the good news is that we can with Into and some Box magic.

This is the actual impl that does all our magic:

use std::error::Error;
impl<T: Into<Box<dyn Error>>> From<T> for Terminator {

We are not asking for any given T that impls std::error::Error! We are asking only the ones that can turn into a Box<dyn Error>. Since we are then turning into another type we're not actually breaking cohesion. Dynamic dispatch allows us to do what we originally wanted with only some overhead. With this impl ? now works for any type that can turn into Box<dyn Error> which should be all error types that implement std::error::Error.

Why do we care so much about std::error::Error? The neat thing is that besides restricting ourselves to only types that are errors, we also get a type that implements Display since that is one of std::error::Error's trait bounds. What is a little less known is that if you implement Display for a type, you implicitly get ToString. It's kind of like how if you implement From you automatically get Into. As a result calling to_string() on this error type gives us what it would look like if it was display, so during our conversion we just call .into().to_string() on the input to From and store the value to then be dumped to stdout. Then all we have after this is a simple Debug implementation for Terminator that just dumps that string out as if it was Display!

impl Debug for Terminator[src]

A manually implemented implementation of Debug that writes the error out to stderr as if it was Display

Auto Trait Implementations

Blanket Implementations

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T> From<T> for T[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> Any for T where
    T: 'static + ?Sized
[src]