Rust 错误码 E0277

Rust 错误码 E0277

我遇到的错误

直接使用 Error,没有使用 dyn

1fn run(config: Config) -> Result<(), dyn std::error::Error> {
2    let contents = std::fs::read_to_string(config.file_path).expect(
3    ...
4    Ok(())

官方解释,是你要求返回一个实现了某特质的对象,但是该对象并没有实现该特质。

You tried to use a type which doesn’t implement some trait in a place which expected that trait.

其实编译器给出的报错比较接近:

1error[E0277]: the size for values of type `(dyn std::error::Error + 'static)` cannot be known at compilation time
2   --> src/main.rs:18:27
3    |
418  | fn run(config: Config) -> Result<(), dyn std::error::Error> {
5    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time

它说,dyn std::error::Error 的大小在编译器无法确定,因此我们可以使用 Box 包裹起来。

std::sync::mpsc::Receiver<Job> cannot be shared between threads safely

Receiver 没有实现某些多线程必须的特质,因此报错。

1fn new(id: usize, receiver: mpsc::Receiver<Job>) -> Self 

改成

1fn new(id: usize, receiver: Arc<Mutex<mpsc::Receiver<Job>>>) -> Self 

官方其它举例如下:

 1// 声明一个 Foo 特质,有一个 bar 方法
 2trait Foo {
 3    fn bar(&self);
 4}
 5
 6// 声明一个函数,消费实现了 Foo 特质的对象
 7fn some_func<T: Foo>(foo: T) {
 8    foo.bar();
 9}
10
11fn main() {
12    // 给这个函数传递 i32 类型, 它没有实现 Foo 特质
13    some_func(5i32); // 报错 error: the trait bound `i32 : Foo` is not satisfied
14}

要修复这个问题,你需要对入参做一些检查,例如:

 1trait Foo {
 2    fn bar(&self);
 3}
 4
 5// 为 i32 类型实现特质
 6impl Foo for i32 {
 7    fn bar(&self) {}
 8}
 9
10fn some_func<T: Foo>(foo: T) {
11    foo.bar(); // 现在可以使用了
12}
13
14fn main() {
15    some_func(5i32); // ok!
16}

另一例更常见:

 1fn some_func<T>(foo: T) {
 2    println!("{:?}", foo); // 报错 error: the trait `core::fmt::Debug` is not
 3                           //        implemented for the type `T`
 4}
 5
 6fn main() {
 7    // We now call the method with the i32 type,
 8    // which *does* implement the Debug trait.
 9    some_func(5i32);
10}

尽管 i32 类型实现了 Debug 特质,但是编译器仍然会报错,因为它必须考虑全部情况:万一你没有传递正确的类型呢?

所以,可以做如下限制:

use std::fmt;

// 限制入参,必须实现 Debug 特质
fn some_func<T: fmt::Debug>(foo: T) {
    println!("{:?}", foo);
}

fn main() {
    // Calling the method is still fine, as i32 implements Debug.
    some_func(5i32);

    // This would fail to compile now:
    // struct WithoutDebug;
    // some_func(WithoutDebug);
}