从函数返回装箱的特征对象

时间:2019-07-05 13:52:16

标签: rust lifetime

我正在使用trait对象通过数据库引擎进行抽象。我有DatabaseSnapshot特质可以为不同的数据库引擎实现,但是我不知道如何在不使用不安全的情况下返回Snapshot特质对象。

use std::marker::PhantomData;
use std::mem;
use std::sync::Arc;

pub trait Database: Send + Sync + 'static {
    fn snapshot(&self) -> Box<dyn Snapshot>;
}

trait Snapshot: 'static {
    fn foo(&self);
}

struct DB {}

struct DBSnapshot<'a> {
    _lifetime: PhantomData<&'a ()>,
}

impl DB {
    fn snapshot(&self) -> DBSnapshot {
        DBSnapshot {
            _lifetime: PhantomData,
        }
    }
}

struct DBWrapper {
    db: Arc<DB>,
}

impl Database for DBWrapper {
    fn snapshot(&self) -> Box<dyn Snapshot> {
        Box::new(DBWrapperSnapshot {
            snapshot: self.db.snapshot(),
            // Will work with `transmute`
            // snapshot: unsafe { mem::transmute(self.db.snapshot()) },
            db: Arc::clone(&self.db),
        })
    }
}

struct DBWrapperSnapshot {
    snapshot: DBSnapshot<'static>,
    db: Arc<DB>,
}

impl Snapshot for DBWrapperSnapshot {
    fn foo(&self) {}
}

在不安全的情况下,我得到了错误:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter in function call due to conflicting requirements
  --> src/main.rs:32:35
   |
32 |                 snapshot: self.db.snapshot(),
   |                                   ^^^^^^^^
   |
note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the method body at 30:9...
  --> src/main.rs:30:9
   |
30 | /         fn snapshot(&self) -> Box<dyn Snapshot> {
31 | |             Box::new(DBWrapperSnapshot {
32 | |                 snapshot: self.db.snapshot(),
33 | |                 // Will work with `transmute`
...  |
36 | |             })
37 | |         }
   | |_________^
note: ...so that reference does not outlive borrowed content
  --> src/main.rs:32:27
   |
32 |                 snapshot: self.db.snapshot(),
   |                           ^^^^^^^
   = note: but, the lifetime must be valid for the static lifetime...
   = note: ...so that the expression is assignable:
           expected DBSnapshot<'static>
              found DBSnapshot<'_>

错误是完全合理的,但是是否可以避免在此处使用transmute?因为我想确保snapshot中的DBWrapperSnapshot字段不会超出对self.db的引用。 链接到playground

0 个答案:

没有答案