7 个版本

0.1.5 2022 年 12 月 1 日
0.1.4 2022 年 12 月 1 日
0.1.3 2022 年 8 月 10 日
0.0.0 2022 年 8 月 5 日

#1141Rust 模式

BlueOak-1.0.0 OR Apache-2.0

23KB
271

因此,你有一个很好的 async fn,并且你想要将返回的未来存储在结构体中。不需要装箱或动态调度:你静态地知道类型。你只需要...

name-it

#[name_it(Test)]
async fn add(x: i32, y: i32) -> i32 {
    do_something_very_async().await;
    x + y
}

let foo: Test = add(2, 3);
assert_eq!(block_on(foo), 5);

函数属性(包括文档注释)被保留。创建的类型将与函数本身的可见性相同,大小、对齐以及 SendSync 与原始未来相同。

MSRV 是 1.61。据我所知,它无法在旧版本的 Rust 上运行。

安全性

我不认为这会有不安全的地方。Miri 喜欢它,我与其他人讨论过,所有不安全的部分都不是特别严重。

Miri 不再喜欢它了,见 这个构建运行

该问题已在 UCG 仓库中报告以供讨论: https://github.com/rust-lang/unsafe-code-guidelines/issues/380

为了解决一些特定的问题

  1. 将任何类型转换为 MaybeUninit<u8> 数组,并将其转换回来目前被认为是安全的。

  2. 生成的类型的对齐被保留。

  3. 生成的类型在析构函数中从不解引用使用,也从不移动到析构函数中。

  4. 生成的类型的生命周期与每个输入的生命周期绑定,因此不可能发生 use-after-free。

尽管如此,我无法完全确定它是否安全。如果您发现任何安全性问题,请提交问题。

限制

绝对

  1. 它不能直接应用于方法或关联函数。您可以移动方法的主体到一个自由函数,并将方法作为一个薄包装器。

  2. 它不支持具有 类型 泛型的函数。这是由于在 const 上下文中使用泛型的限制造成的。

(可能) 可解

  1. 它目前还不支持显式 生命周期 泛型。它没有根本问题,只是需要在宏中实现(需要帮助)!

  2. 所有参数都必须是简单标识符(因此不允许像这样 (x, y): (i32, i32) 的结构)。再次强调,这应该是可行的,只是尚未实现。

  3. 尽管底层技巧可以在大多数 impl Trait 类型上工作,但这个crate只为 async fn 实现了它。不清楚如何使宏适用于任何特质。

那么关于 stackfuture 呢?

微软的 stackfuture 实际上采取了类似的方法来解决此问题。主要区别

  1. name-it 会自动推断类型大小、对齐和自动特质。 stackfuture 具有固定对齐,手动指定大小,并且始终是 Send + !Sync

  2. stackfuture 不使用宏,因此对工具更友好,并支持泛型。它还可以直接用于方法,包括特质方法。

  3. stackfuture 使用动态分派。 name-it 完全是静态的,没有动态函数调用。

许可证

蓝橡树模型许可证 1.0.0 是一种宽泛的非版权许可证。如果你对罕见的许可证感到不安,你可以使用 Apache 2.0。

文件 tests/futures-* 来自于 futures-rs 项目。

依赖关系

~1.5MB
~35K SLoC