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