关于rust:要求相关的错误类型实现Debug特性是一种好习惯吗?

Is it good practice to require associated Error types implement Debug trait?

我遇到了piston2d-graphics条板箱的问题。 当我尝试在从graphics::character::CharacterCache::character方法获得的Result上使用expect()方法时,事实证明我做不到—因为它需要Result的Error类型来实现std::fmt::Debug特性:

1
2
3
4
5
6
7
8
error[E0599]: no method named `expect` found for type `std::result::Result<graphics::character::Character<'_, <G as graphics::Graphics>::Texture>, <C as graphics::character::CharacterCache>::Error>` in the current scope
  --> src/some_file.rs:44:53
   |
44 |             let ch_glyph = glyphs.character(34, ch).expect("Couldn't load character");
   |                                                     ^^^^^^
   |
   = note: the method `expect` exists but the following trait bounds were not satisfied:
           `<C as graphics::character::CharacterCache>::Error : std::fmt::Debug`

ErrorCharacterCache特征的关联(嵌套)类型。 我可以轻松地提交添加需求的PR,然后使用简单的generate宏将其实现添加到所有其他板条箱。 这似乎是合理的,因为expect()和其他相关方法一直在Rust中使用,但是我不 是Rust方式,还是有理由不这样做?

我以实例的形式描述了这个问题,但它与活塞没有任何特定关系,我的问题是关于Rust中的一般模式。 因此标记rust-piston是不相关的,请不要将其添加到问题中。


Is it good practice to require associated Error types implement Debug trait?

是的,如果可能的话。 也许他们忘记了。

解决此问题的方法是使用map_err(),这里是问题的MCVE:

1
2
3
4
5
6
7
8
9
struct Error;

fn foo() -> Result<(), Error> {
    Ok(())
}

fn main() {
    foo().expect("no error");
}
1
2
3
4
5
6
7
8
error[E0599]: no method named `expect` found for type `std::result::Result<(), Error>` in the current scope
 --> src/main.rs:8:11
  |
8 |     foo().expect("no error");
  |           ^^^^^^
  |
  = note: the method `expect` exists but the following trait bounds were not satisfied:
          `Error : std::fmt::Debug`

使用map_err()产生实现Debug的错误,这可能是您自己的自定义错误,在以下示例中,我仅将()作为错误返回:

1
2
3
4
5
6
7
8
9
struct Error;

fn foo() -> Result<(), Error> {
    Ok(())
}

fn main() {
    foo().map_err(|_| ()).expect("no error");
}