为什么没有相同签名的生锈闭合具有相同的类型?
per
为什么生锈的封闭方式与不同类型相同的签名?这是理论上的限制还是编译器的限制?
在Haskell中,他们受到了同样的对待。
Per this answer, Rust treats async blocks and closures with the same return type as different types.
Why does Rust treat closures with the same signature as different types? Is this a theoretical limitation or a limitation of the compiler?
In Haskell they are treated the same.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
Afaik,Haskell将它们分配在堆上。这等同于rust中的
box< dyn fn()>
。既然您将它们包装,则您知道大小将始终是2*USIZE
(数据指针和VTable指针)。默认情况下,生锈不会封闭。相反,每个闭合都会获得一个带有所有捕获变量的新的,不愿透露姓名的结构。例如,以下内容:
转化为类似的东西(并非完全但没关系):
这更有效,从本质上讲,闭合成本为零,但是我们必须付的价格是,不同的封闭方式在内存中具有不同的布局。因此,即使它们具有相同的签名,它们也不相等,因此您无法返回其中一个。
此外,即使它们恰好具有相同的布局,您仍然无法返回不同的封闭类型,因为闭合是静态派遣的。而不是依靠VTable来查找闭合代码,而只是直接称其为称为封闭代码。同样,这使它们的成本为零,这对Rust很重要,但意味着您不知道如果它们不同样的封闭,该代码就会调用什么代码。
有一个特殊情况:封闭,捕获什么都不能转换为功能指针。这就像没有数据指针的VTable一样,因为我们知道它们没有数据:
AFAIK, Haskell allocates them on the heap. This is equivalent to
Box<dyn Fn()>
in Rust. Since you box them, you know the size will always be2*usize
(a data pointer and a vtable pointer).By default Rust does not box closures. Rather, each closure gets a new, unnameable struct with all captured variables. For example, the following:
Translates into something like (not exactly but it doesn't matter):
This is more efficient, and essentially makes the closure zero cost, but the price we have to pay is that different closures have different layouts in memory. Because of that they are not equal even if they have the same signature, so you cannot return one of them.
Moreover, even if they happen to have the same layout you still cannot return different closure types, because closures are dispatched statically. Instead of relying on a vtable to find the closure code we just call it directly. Again, this makes them zero cost which is important for Rust but means you cannot know what code to call if they are not the same closure.
There is one special case: closures that capture nothing can be converted to function pointers. This is like just a vtable without the data pointer, because we know they don't have data: