#lifetime #associated #static #gat #gal

galemu

为限制于生命周期的泛型关联类型(GAT)提供解决方案(GAL)

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数据结构


用在 degeneric-macros

MIT/Apache

25KB
224

Galemu 最新版本 RustcVersion1.30+

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)
    }
}

你可以查看 模块级文档 以获取完整示例。

无运行时依赖