< 返回版块

坚果修补匠 发表于 2021-06-13 10:37

Rust支持Box<dyn trait>实现多态,然而返回Result<Box<dyn trait>>为何会报错啊?下面是实例代码.switch_engine无法通过编译.而switch_engine2却可以.请问是什么原因?如何绕过?

use anyhow::Result
#[automock]
pub trait Engine {
    fn get(&mut self, key: &str) -> Result<Option<String>>;
    fn set(&mut self, key: &str, value: &str) -> Result<()>;
    fn remove(&mut self, key: &str) -> Result<()>;
}

// not work
pub fn switch_engine<T: Into<PathBuf>>(t: EngineType,
                                       path: T) -> Result<Box<dyn Engine>> {
    match t {
        EngineType::Kvs => {
            KvStore::open(path).map(Box::new)
        }
        EngineType::Mock => Ok(Box::new(MockEngine::new())),
        _ => todo!()
    }
}

pub fn switch_engine2<T: Into<PathBuf>>(t: EngineType,
                                       path: T) -> Box<dyn Engine> {
    match t {
        EngineType::Kvs => 
            Box::new(KvStore::open(path)?),
        EngineType::Mock => Box::new(MockEngine::new()),
        _ => todo!()
    }
}
error[E0308]: mismatched types
  --> src\engine.rs:20:13
   |
17 |                                        path: T) -> Result<Box<dyn Engine>> {
   |                                                    ----------------------- expected `std::result::Result<Box<(dyn engine::Engine + 'static)>, anyhow::Error>` because of return type
...
20 |             KvStore::open(path).map(Box::new)
   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn engine::Engine`, found struct `kvstore::KvStore`
   |
   = note: expected enum `std::result::Result<Box<(dyn engine::Engine + 'static)>, _>`
              found enum `std::result::Result<Box<kvstore::KvStore>, _>`

评论区

写评论
作者 坚果修补匠 2021-06-13 12:15

感谢

--
👇
Aya0wind: 你可以这样写

KvStore::open(path).map(|x|Box::new(x) as Box<dyn Exp>)

具体原因嘛,对于Box和Box,即使T实现了Trait,这两个也完全不是一个东西。dyn Trait(或者应该说TraitObject?)需要两个指针大小,装入box一般会实现为栈上两个指针,一个指向堆上的对象,一个指向函数表。而Box则是栈上仅有一个指向堆上对象的指针。

Aya0wind 2021-06-13 10:56

你可以这样写

KvStore::open(path).map(|x|Box::new(x) as Box<dyn Exp>)

具体原因嘛,对于Box和Box,即使T实现了Trait,这两个也完全不是一个东西。dyn Trait(或者应该说TraitObject?)需要两个指针大小,装入box一般会实现为栈上两个指针,一个指向堆上的对象,一个指向函数表。而Box则是栈上仅有一个指向堆上对象的指针。

1 共 2 条评论, 1 页