特质类型和生命周期问题

时间:2015-05-13 15:41:52

标签: rust lifetime

我正在尝试编写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>>会给予生命周期以确保这一点。我在这里缺少什么?

documentation for Pool

1 个答案:

答案 0 :(得分:3)

以下是Key的定义:

pub trait Key: Any {
    type Value: Any;
}

也就是说,它扩展了特质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对非静态类型的反射 - 据我记得,这里有一些健全性问题。因此,目前您唯一的选择是重构您的计划,这样您就不需要在'static中存储非TypeMap类型。