Почему при расширении Result для типов сбоев я получаю «метод существует, но не удовлетворены следующие границы признаков»? - PullRequest
0 голосов
/ 13 июня 2019

Я пытаюсь добавить более краткую версию failure ящика .with_context(|e| format!("foo: {}", e)) в мой код. Вот так детская площадка :

use failure::{Context, Fail, ResultExt}; // 0.1.5

/// Extension methods for failure `Result`.
pub trait ResultContext<T, E> {
    /// Wraps the error type in a context type generated by looking at the
    /// error value. This is very similar to `with_context` but much more
    /// concise.
    fn ctx(self, s: &str) -> Result<T, Context<String>>;
}

impl<T, E> ResultContext<T, E> for Result<T, E>
where
    E: Fail,
{
    fn ctx(self, s: &str) -> Result<T, Context<String>> {
        self.map_err(|failure| {
            let context = format!("{}: {}", s, failure);
            failure.context(context)
        })
    }
}

pub fn foo() -> Result<i32, failure::Error> {
    Ok(5i32)
}

pub fn main() -> Result<(), failure::Error> {
    // This works.
    let _ = foo().with_context(|_| "foo".to_string())?;
    // This doesn't.
    foo().ctx("foo")?
}

Я получаю следующую ошибку:

error[E0599]: no method named `ctx` found for type `std::result::Result<i32, failure::error::Error>` in the current scope
  --> src/main.rs:31:11
   |
31 |     foo().ctx("foo")?
   |           ^^^
   |
   = note: the method `ctx` exists but the following trait bounds were not satisfied:
           `std::result::Result<i32, failure::error::Error> : ResultContext<_, _>`
   = help: items from traits can only be used if the trait is implemented and in scope
   = note: the following trait defines an item `ctx`, perhaps you need to implement it:
           candidate #1: `ResultContext`

Я не могу понять, почему. Я более или менее скопировал существующий код with_context.

1 Ответ

1 голос
/ 13 июня 2019

Как говорит компилятор, Result<i32, failure::error::Error> не реализует ResultContext<_, _>. Вы добавили привязку к вашей реализации:

where
    E: Fail,

Но failure::Error не реализует failure::Fail:

use failure; // 0.1.5

fn is_fail<F: failure::Fail>() {}

pub fn main() {
    is_fail::<failure::Error>();
}
error[E0277]: the trait bound `failure::error::Error: std::error::Error` is not satisfied
 --> src/main.rs:6:5
  |
6 |     is_fail::<failure::Error>();
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::error::Error` is not implemented for `failure::error::Error`
  |
  = note: required because of the requirements on the impl of `failure::Fail` for `failure::error::Error`
note: required by `is_fail`
 --> src/main.rs:3:1
  |
3 | fn is_fail<F: failure::Fail>() {}
  | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Вам нужно будет изменить границы или тип.

...