Writing a Rust crate for LMDB, I came across the following problem:
impl<'a> TxnRo<'a> {
/// Get value from database
pub fn get<'b, K, V>(
&'b self,
db: &Db<K, V>,
key: &K,
) -> Result<Option<V::AlignedRef<'b>>, io::Error>
where
K: ?Sized + Storable,
V: ?Sized + Storable,
{
let mut backend = self.backend.lock();
unsafe {
let result = backend.get::<_, K, V>(self.env, db, key)?;
Ok(std::mem::transmute::<
Option<V::AlignedRef<'_>>,
Option<V::AlignedRef<'b>>,
>(result))
}
}
}
Error:
error[E0512]: cannot transmute between types of different sizes, or dependently-sized types
--> src/lib.rs:930:16
|
930 | Ok(std::mem::transmute::<
| ________________^
931 | | Option<V::AlignedRef<'_>>,
932 | | Option<V::AlignedRef<'b>>,
933 | | >(result))
| |_____________^
|
= note: `Option<<V as Storable>::AlignedRef>` does not have a fixed size
For more information about this error, try `rustc --explain E0512`.
However, I would argue that the two types V::AlignedRef<'lt>
and V::AlignedRef<'b>
would always have the same size.
Is this a bug?
Maybe I can workaround it by avoiding the transmutation (by modifying my backend.get
method), but I still think the error is unjustified?
I can indeed work around this problem as follows:
impl TxnBackend {
unsafe fn get_unsafe<'a, E, K, V>(
&mut self,
env: &E,
db: &Db<K, V>,
key: &K,
) -> Result<Option<V::AlignedRef<'a>>, io::Error>
where
E: Env,
K: ?Sized + Storable,
V: ?Sized + Storable,
{
/* … */
}
/* … */
}
impl<'a> TxnRo<'a> {
/// Get value from database
pub fn get<'b, K, V>(
&'b self,
db: &Db<K, V>,
key: &K,
) -> Result<Option<V::AlignedRef<'b>>, io::Error>
where
K: ?Sized + Storable,
V: ?Sized + Storable,
{
let mut backend = self.backend.lock();
unsafe { Ok(backend.get_unsafe::<_, K, V>(self.env, db, key)?) }
}
}
But I still think the compiler error E0512
is not correct in the above case.