Reputation: 34145
I'm trying to write an Iron plugin middleware, but I'm running into an issue when trying to define a typemap
key:
The minimal example with simple type works without issues:
pub struct Database;
impl Key for Database {
type Value = isize;
}
But as soon as lifetime is involved, I cannot compile the library:
pub struct Database<'a> {
pool: &'a Arc<Pool<PostgresConnectionManager>>
}
impl<'a> Key for Database<'a> {
type Value = PooledConnection<'a, PostgresConnectionManager>;
}
What's happening here? I get the errors:
src/lib.rs:33:1: 35:2 note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 33:0...
src/lib.rs:33 impl<'a> Key for Database<'a> {
src/lib.rs:34 type Value = PooledConnection<'a, PostgresConnectionManager>;
src/lib.rs:35 }
src/lib.rs:33:1: 35:2 note: ...so that trait type parameters matches those specified on the impl (expected `typemap::Key`, found `typemap::Key`)
src/lib.rs:33 impl<'a> Key for Database<'a> {
src/lib.rs:34 type Value = PooledConnection<'a, PostgresConnectionManager>;
src/lib.rs:35 }
note: but, the lifetime must be valid for the static lifetime...
src/lib.rs:33:1: 35:2 note: ...so that the type `r2d2::PooledConnection<'_, r2d2_postgres::PostgresConnectionManager>` will meet its required lifetime bounds
src/lib.rs:33 impl<'a> Key for Database<'a> {
src/lib.rs:34 type Value = PooledConnection<'a, PostgresConnectionManager>;
src/lib.rs:35 }
But that doesn't make sense to me - the PooledConnection
cannot outlive the manager and the Arc<Pool<...Manager>>
is given that lifetime to ensure this. What am I missing here?
Upvotes: 1
Views: 365
Reputation: 127751
Here is the definition of Key
:
pub trait Key: Any {
type Value: Any;
}
That is, it extends trait Any
:
pub trait Any: 'static + Reflect {
fn get_type_id(&self) -> TypeId;
}
This means that any type which implements Key
must also implement Any
, and any Value
associated type instantiation must also implement Any
. However, Any
is only defined for types which are 'static
, that is, which do not contain non-static references.
Types which are parameterized with lifetime parameters, like your Database
, usually do contain such references (and indeed, your type contains &'a
field), so they are not 'static
and so they cannot implement Any
. Therefore such types can't implement Key
. And this is in fact what your error is about, even if this is not really obvious:
note: but, the lifetime must be valid for the static lifetime...
Anyway, the core reason of this error is that Rust currently does not support reflection with Any
for non-static types - as far as I remember, there were some kind of soundness issues around lifetimes here. So currently your only option is to refactor your program so you won't need to store non-'static
types in TypeMap
.
Upvotes: 3