Jan Lukas Gernert
Jan Lukas Gernert

Reputation: 85

Why is the failure::Fail trait bound not satisfied by my Result type alias?

I'm trying to implement event hooks as demonstrated by "simple event hooks in Rust" while also using the Error + ErrorKind pattern of the failure crate.

This is a stripped down version of my code:

#[macro_use]
extern crate failure;

use failure::{Backtrace, Context, Error, Fail};
use std::fmt;

#[derive(Debug)]
pub struct PortalError {
    inner: Context<PortalErrorKind>,
}

impl Fail for PortalError {
    fn cause(&self) -> Option<&Fail> {
        self.inner.cause()
    }

    fn backtrace(&self) -> Option<&Backtrace> {
        self.inner.backtrace()
    }
}

impl fmt::Display for PortalError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        fmt::Display::fmt(&self.inner, f)
    }
}

#[derive(Copy, Clone, PartialEq, Debug, Fail)]
pub enum PortalErrorKind {
    #[fail(display = "Unknown Error")]
    Unknown,
}

//----------------------------------------------------------

pub type PortalResult<T> = Result<PortalError, T>;
pub trait Portal {
    fn get_something(&self) -> PortalResult<Vec<u32>>;
}

//----------------------------------------------------------

pub trait FeedApi<'a> {
    type T: FeedApi<'a>;

    fn new<P: Portal + 'a>(portal: P) -> Result<Self::T, Error>;
}

//----------------------------------------------------------

pub struct Feedly<'a> {
    portal: Box<Portal + 'a>,
}

impl<'a> FeedApi<'a> for Feedly<'a> {
    type T = Feedly<'a>;

    fn new<P: Portal + 'a>(portal: P) -> Result<Self::T, Error> {
        Ok(Feedly {
            portal: Box::new(portal),
        })
    }
}

impl<'a> Feedly<'a> {
    pub fn demo_function(&self) -> Result<(), Error> {
        let _ = self.portal.get_something().context(PortalErrorKind::Unknown)?;
        Ok(())
    }
}

fn main() {
    println!("Hello, world!");
}
[dependencies]
failure = "0.1.1"

In a method of 'Feedly' I want to use the portal:

self.portal.get_something().context(PortalErrorKind::Unknown)?

But I get the following error:

error[E0599]: no method named `context` found for type `std::result::Result<PortalError, std::vec::Vec<u32>>` in the current scope
  --> src/main.rs:67:45
   |
67 |         let _ = self.portal.get_something().context(PortalErrorKind::Unknown)?;
   |                                             ^^^^^^^
   |
   = note: the method `context` exists but the following trait bounds were not satisfied:
           `std::result::Result<PortalError, std::vec::Vec<u32>> : failure::Fail`
           `&std::result::Result<PortalError, std::vec::Vec<u32>> : failure::Fail`
           `&mut std::result::Result<PortalError, std::vec::Vec<u32>> : failure::Fail`

Looking through the docs the failure::Fail trait has a bound 'static. And the method context has a bound Self: Sized.

I'm not sure which trait is not satisfied here. The boxed Portal is neither Sized nor 'static, but the returned result should be, right?

This is the first time I'm handling boxes and lifetimes in Rust.

Upvotes: 0

Views: 1031

Answers (1)

Shepmaster
Shepmaster

Reputation: 430791

pub type PortalResult<T> = Result<PortalError, T>;

Result has two type parameters: the success type and the error type. You have transposed them; you want:

pub type PortalResult<T> = Result<T, PortalError>;

Upvotes: 2

Related Questions