Rust impl Trait 作为函数返回类型

Jak*_*ter 5 rust

我有以下功能,其中Command有一个特征

pub fn parse_arguments(matches: ArgMatches) -> Result<impl Command, &'static str>
Run Code Online (Sandbox Code Playgroud)

在函数体内,我想根据参数返回 Command 的不同实现,例如

match args.subcommand() {
    ("init", Some(args)) => {
        Ok(Init::new(args))
    }
    ("btc", Some(args)) => {
        Ok(ImportBtc::new(args))
    },
    ("grin", Some(args)) => {
        Ok(ImportGrin::new(args))
    },
    _ => Err ("Invalid subcommand supplied")
}
Run Code Online (Sandbox Code Playgroud)

编译将失败并出现错误:

expected struct `commands::cmd_types::Init`, found struct `commands::cmd_types::ImportBtc`
Run Code Online (Sandbox Code Playgroud)

返回线也类似ImportGrin

我是否误解了impl Trait工作原理?

Dan*_*all 8

不幸的是,这并不完全impl Trait是这样。impl Trait作为返回类型意味着“此函数将返回实现此特征的单个类型”,而您试图返回实现此特征的多个类型。这对于编译器来说很困难,因为它需要知道返回的类型有多大,并且不同的类型有不同的大小。

一些选项:

  1. 将返回值装箱,因为 aBox始终具有相同的大小
  2. 定义每个enum返回类型都有一个变体的 ,将返回值包装在 中enum,并实现 的特征enum
  3. 使用https://crates.io/crates/auto_enums来自动创建 2 中描述的枚举。

  • 我不确定我是否会将任何描述为或多或少地惯用——它们有不同的权衡。装箱将需要堆分配,并增加运行时 vtable 查找开销。使用枚举可能会浪费堆栈空间(例如,如果变体具有不同的大小),并在运行时添加匹配查找。但我同意,无论哪种方式,保留“impl Trait”返回类型都是一件好事! (2认同)