gpt4 book ai didi

rust - 对自定义 FnBox 代码的轻微调整会阻止它编译

转载 作者:行者123 更新时间:2023-11-29 07:46:28 27 4
gpt4 key购买 nike

以下代码在 nightly 1.7.0 上编译时没有警告:

trait FnBox {
fn call_box(self: Box<Self>);
}

impl <F: FnOnce()> FnBox for F {
fn call_box(self: Box<F>) {
(*self)()
}
}

fn main() {}

但是当我进行这个轻微的修改时,我认为这意味着完全相同的事情,我得到了关于 FnOnce 未调整大小且不可移动的错误。

trait FnBox {
fn call_box(self: Box<Self>);
}

impl FnBox for FnOnce() {
fn call_box(self: Box<FnOnce()>) {
(*self)();
}
}

fn main() {}

错误信息:

error[E0161]: cannot move a value of type dyn std::ops::FnOnce(): the size of dyn std::ops::FnOnce() cannot be statically determined
--> src/main.rs:7:9
|
7 | (*self)();
| ^^^^^^^

这两个例子有什么区别,为什么第一个没有问题?

最佳答案

其实差别很大。在第一段代码中:

impl<F: FnOnce()> FnBox for F {
fn call_box(self: Box<F>) {
(*self)()
}
}

声明对于任何类型 F实现FnOnce我们实现FnBox . F是一个具体的类型,并且在每个调用站点call_box()方法将被单态化。 F的具体类型每个调用点的大小及其大小都是编译器已知的,因此此定义没有问题。

然而,在第二段代码中:

impl FnBox for FnOnce() {
fn call_box(self: Box<FnOnce()>) {
(*self)();
}
}

声明裸特征对象类型实现FnBox .然而,这个实现是不可靠的:while Box<FnOnce()>是适合变量和函数参数的正确大小类型,FnOnce()本身不是 - 它是一个裸特征对象类型并且它是未调整大小的,也就是说,编译器不知道它的大小。这对您可以使用此类型执行的操作施加了一些限制,其中一个主要限制是您不能按值使用此类型的值。但是,这正是这段代码中发生的事情:您尝试取消引用 Box<FnOnce()>得到FnOnce() .

以前按值self方法意味着特征是 not object-safe ,因为 FnOnce::call_once按值消耗实现实例,它不是对象安全的。但是,按值selfRFC 817 以来,方法不会使特征对象不安全得到实现。按值self但是,根据上述推理,仍然不能在特征对象上调用方法。

关于rust - 对自定义 FnBox 代码的轻微调整会阻止它编译,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34898330/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com