为什么在返回`impl Trait`的函数中出现"匹配武器具有不兼容类型"错误?

刘林欣*_*刘林欣 3 rust

trait Counter {
    fn count(&self) -> i32;
}

struct AddCounter {
    a: i32,
    b: i32,
}
impl Counter for AddCounter {
    fn count(&self) -> i32 {
        self.a + self.b
    }
}

struct MulCounter {
    a: i32,
    b: i32,
}
impl Counter for MulCounter {
    fn count(&self) -> i32 {
        self.a * self.b
    }
}

fn get_counter(a: i32, b: i32, op: &str) -> impl Counter {
    match op {
        "+" => AddCounter { a, b },
        "*" => MulCounter { a, b },
        _ => panic!(format!("{}{}", "??????", op)),
    }
}

fn main() {}
Run Code Online (Sandbox Code Playgroud)

我打电话时收到错误get_counter(...):

error[E0308]: match arms have incompatible types
  --> src/main.rs:26:5
   |
26 | /     match op {
27 | |         "+" => AddCounter { a, b },
28 | |         "*" => MulCounter { a, b },
   | |                ------------------- match arm with an incompatible type
29 | |         _ => panic!(format!("{}{}", "??????", op)),
30 | |     }
   | |_____^ expected struct `AddCounter`, found struct `MulCounter`
   |
   = note: expected type `AddCounter`
              found type `MulCounter`
Run Code Online (Sandbox Code Playgroud)

Fre*_*ios 6

impl Trait表示法视为通用类型.你不能写:

fn get_counter<T>(a: i32, b: i32, op: &str) -> T {
    match op {
        "+" => AddCounter { a, b },
        "*" => MulCounter { a, b },
        _ => panic!(format!("{}{}", "??????", op)),
    }
}
Run Code Online (Sandbox Code Playgroud)

因为AddCounter并且MulCounter没有相同的类型:是什么T

您可以使用动态分派而不是静态分派:

fn get_counter(a: i32, b: i32, op: &str) -> Box<dyn Counter> {
    match op {
        "+" => Box::new(AddCounter { a, b }),
        "*" => Box::new(MulCounter { a, b }),
        _ => panic!(format!("{}{}", "??????", op)),
    }
}
Run Code Online (Sandbox Code Playgroud)

进一步说明

当您使用静态分派时,Rust编译器将代码单一化:它为泛型类型的每个值生成一个新函数(有关详细信息,请参阅什么是与C++的上下文的单态化?).每个返回值都是"真实"普通类型.在这种情况下,函数不能返回(例如)String一个路径和i32另一个路径.

动态分派的情况下,它不是返回的"真实"类型而是特征对象:编译器不知道真实类型; 它只关心特征对象可以用作特征实现者.这就是你需要的.