4 个版本
使用旧的 Rust 2015
0.2.3 | 2019年10月11日 |
---|---|
0.2.2 | 2018年11月6日 |
0.2.1 | 2018年11月5日 |
0.2.0 | 2018年11月5日 |
#679 在 数据结构
25KB
224 行
Galemu
galemu 是一个库,使绕过尚未拥有泛型关联类型(GAT)相对于生命周期(GAL)变得简单
在当前的 Rust 中,由于 Rust 中没有泛型关联类型(GAT),抽象某些类型可能会变得很复杂。通常只需要有关生命周期的 GAT,而这个 crate 提供了一些辅助工具来解决这个问题。
示例问题
例如,你想抽象一个可以打开事务并且这个事务可以提交的(数据库)连接。一旦 Rust 有 GAT,你将编写以下代码(字符串化简化,例如不返回结果,添加方法等)
trait GenericConnection {
type Transaction<'conn>: GenericTransaction;
// the lifetime could have been omitted
fn create_transaction<'s>(&'s self) -> Self::Transaction<'s>;
}
trait GenericTransaction {
fn commit(self);
}
然后你可以为任何 GenericTransaction
实现任何 Transaction<'a>
。
但今天你只能有以下这些
trait GenericConnection {
type Transaction: GenericTransaction;
// the lifetime could have been omitted
fn create_transaction(&self) -> Self::Transaction;
}
trait GenericTransaction {
fn commit(self);
}
但如果你想为 Transaction<'conn>
实现它,这是不可能的,因为 'conn
需要绑定到 create_transaction
函数的生命周期。
问题解决方案
这个 crate 的想法是将生命周期提升到一个已知的包装类型,结果如下
use galemu::{Bound, BoundExt};
trait GenericConnection {
type Transaction: GenericTransaction;
// the lifetime could have been omitted
fn create_transaction<'s>(&'s self) -> Bound<'s, Self::Transaction>;
}
trait GenericTransaction: for<'a> BoundExt<'a> {
// on nightly use the "arbitrary self type" feature
fn commit(me: Bound<'s, Self>);
}
实现时,你会使用以下内容
use galemu::{create_gal_wrapper_type};
create_gal_wrapper_type!{
/// Wraps `Transaction` erasing it's lifetime.
///
/// This can only be used through a `Bound<'a, TransactionWrapper>` instance,
/// as only then it is possible to access the wrapped type with the correct lifetime.
struct TransactionWrapper(Transaction<'a>);
}
impl GenericConnection for Connection {
type Transaction = TransactionWrapper;
fn create_transaction(&mut self) -> Bound<Self::Transaction> {
let trans = self.transaction();
TransactionWrapper::new(trans)
}
}
你可以查看 模块级文档 以获取完整示例。