Я использую черты объектов для абстрагирования над ядром базы данных. У меня есть черты Database
и Snapshot
, которые могут быть реализованы для разных механизмов баз данных, но я не могу понять, как вернуть объект черты Snapshot
без использования unsafe.
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
.
Ссылка на детская площадка