3 个不稳定版本

0.1.3 2022年8月10日
0.1.0 2022年8月8日
0.0.0 2022年8月5日

#17 in #visibility


name-it 中使用

BlueOak-1.0.0

10KB
219

所以,你有一个很好的 async fn,并想将返回的 future 存储在结构体中。不需要装箱或动态分发:你静态地知道类型。你只需要...

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

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

MSRV 是 1.61。据我所知,使其在旧版 Rust 版本上工作是不可能的。

安全性

我不明白为什么会不安全。Miri 很喜欢它,我与其他人讨论过,所有不安全的部分都不特别恶劣。

Miri 现在不喜欢它了,请参阅 这个构建运行

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

为了解决一些特定的担忧

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

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

  3. 生成的类型永远不会在析构函数中未锁定使用,也永远不会在析构函数中移动。

  4. 生成的类型的生命周期与每个输入的生命周期绑定,因此不可能发生使用后释放。

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

限制

绝对

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

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

(可能) 可解

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

  2. 所有参数必须是简单标识符(因此,像 (x, y): (i32, i32) 这样的格式是不允许的)。再次强调,这应该可以实现,只是目前还没有实现。

  3. 虽然底层技巧可以在大多数 impl Trait 类型上工作,但这个包只为 async fn 实现了它。不清楚如何使宏对任何特质都有效。

那么 stackfuture 呢?

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

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

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

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

许可证

Blue Oak Model License 1.0.0 是一种宽容的、非版权许可。如果您不喜欢罕见的许可,您可以使用 Apache 2.0。

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

依赖关系

~1.5MB
~36K SLoC