特征类型和生命周期问题
Trait type and lifetime issues
我正在尝试编写 Iron 插件中间件,但在尝试定义 typemap
键时我 运行 遇到了问题:
简单类型的最小示例可以正常工作:
pub struct Database;
impl Key for Database {
type Value = isize;
}
但是一旦涉及到生命周期,我就不能编译库了:
pub struct Database<'a> {
pool: &'a Arc<Pool<PostgresConnectionManager>>
}
impl<'a> Key for Database<'a> {
type Value = PooledConnection<'a, PostgresConnectionManager>;
}
这里发生了什么?我收到错误:
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 }
但这对我来说没有意义 - PooledConnection
不能比经理长寿,而 Arc<Pool<...Manager>>
被赋予了生命周期以确保这一点。我在这里错过了什么?
这里是Key
的定义:
pub trait Key: Any {
type Value: Any;
}
也就是说,它扩展了 trait Any
:
pub trait Any: 'static + Reflect {
fn get_type_id(&self) -> TypeId;
}
这意味着任何实现 Key
的类型也必须实现 Any
,并且任何 Value
关联类型实例化也必须实现 Any
。但是,Any
仅针对 'static
类型定义,即不包含非静态引用的类型。
使用生命周期参数进行参数化的类型,例如您的 Database
,通常包含此类引用(实际上,您的类型包含 &'a
字段),因此它们不是 'static
因此他们无法实施 Any
。因此,此类类型无法实现 Key
。这实际上就是你的错误所在,即使这不是很明显:
note: but, the lifetime must be valid for the static lifetime...
无论如何,这个错误的核心原因是 Rust 目前不支持非静态类型的 Any
反射——据我所知,这里的生命周期存在某种健全性问题。所以目前你唯一的选择是重构你的程序,这样你就不需要在 TypeMap
.
中存储非 'static
类型
我正在尝试编写 Iron 插件中间件,但在尝试定义 typemap
键时我 运行 遇到了问题:
简单类型的最小示例可以正常工作:
pub struct Database;
impl Key for Database {
type Value = isize;
}
但是一旦涉及到生命周期,我就不能编译库了:
pub struct Database<'a> {
pool: &'a Arc<Pool<PostgresConnectionManager>>
}
impl<'a> Key for Database<'a> {
type Value = PooledConnection<'a, PostgresConnectionManager>;
}
这里发生了什么?我收到错误:
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 }
但这对我来说没有意义 - PooledConnection
不能比经理长寿,而 Arc<Pool<...Manager>>
被赋予了生命周期以确保这一点。我在这里错过了什么?
这里是Key
的定义:
pub trait Key: Any {
type Value: Any;
}
也就是说,它扩展了 trait Any
:
pub trait Any: 'static + Reflect {
fn get_type_id(&self) -> TypeId;
}
这意味着任何实现 Key
的类型也必须实现 Any
,并且任何 Value
关联类型实例化也必须实现 Any
。但是,Any
仅针对 'static
类型定义,即不包含非静态引用的类型。
使用生命周期参数进行参数化的类型,例如您的 Database
,通常包含此类引用(实际上,您的类型包含 &'a
字段),因此它们不是 'static
因此他们无法实施 Any
。因此,此类类型无法实现 Key
。这实际上就是你的错误所在,即使这不是很明显:
note: but, the lifetime must be valid for the static lifetime...
无论如何,这个错误的核心原因是 Rust 目前不支持非静态类型的 Any
反射——据我所知,这里的生命周期存在某种健全性问题。所以目前你唯一的选择是重构你的程序,这样你就不需要在 TypeMap
.
'static
类型