gpt4 book ai didi

rust - `Box` ed 类型的方法调用解析

转载 作者:行者123 更新时间:2023-11-29 08:12:21 28 4
gpt4 key购买 nike

Rust playground :

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

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

fn main() {
let job: Box<FnOnce()> = Box::new(|| {});
// versions that compile
// let job = Box::new(|| {});
// let job: Box<FnBox> = Box::new(|| {});
job.call_box();
}

job.call_box();不编译:

error[E0599]: no method named `call_box` found for type `std::boxed::Box<std::ops::FnOnce()>` in the current scope
--> src/main.rs:16:9
|
16 | job.call_box();
| ^^^^^^^^
|
= note: job is a function, perhaps you wish to call it
= note: the method `call_box` exists but the following trait bounds were not satisfied:
`std::ops::FnOnce() : FnBox`
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `call_box`, perhaps you need to implement it:
candidate #1: `FnBox`

为什么编译器看不到到 FnBox 的转换这里?

我想当我使用 let job = Box::new(|| {}); 时结果是 Box<closure>类型。编译器设法解析 job.call_box() ,即 Box<closure> -> Box<FnOnce()> -> Box<FnBox> (因为 FnBox 是为 FnOnce() 实现的,而不是为 closure 实现的)。为什么不只是 Box<FnOnce()> -> Box<FnBox>工作?

最佳答案

Author's note: Since Rust 1.35, an adapter trait like FnBox is not required to call boxed FnOnce closures; read to the end to see why.

FnBox FnOnce() 实现.

FnOnce()有两个含义:作为特征和作为类型。在 Box<FnOnce()> ,它是一个(动态的,未调整大小的)类型。 Since Rust 1.27, the type can be written more explicitly as dyn FnOnce() .对于这个答案的其余部分,我将使用 dyn为了弄清楚我什么时候在谈论特征,什么时候在谈论动态类型。

impl你写的没有实现 FnBox对于类型 dyn FnOnce() ,因为 generic parameters have an implicit Sized bound .如果我们按照该问题答案的建议添加 + ?SizedF , 编译器确实给出了一个稍微有用的错误信息:

impl<F: FnOnce() + ?Sized> FnBox for F {
fn call_box(self: Box<F>) {
(*self)()
}
}
error[E0161]: cannot move a value of type F: the size of F cannot be statically determined
--> src/main.rs:7:9
|
7 | (*self)()
| ^^^^^^^

哪个确实明确指出了Sized的地方需要 ness。

在 1.35 之前的 Rust 版本中,没有办法修复这个错误; FnOnce() 的特征对象只是没用。然而,今天Box<dyn FnOnce()>工具 FnOnce() , 所以你可以像普通闭包一样调用它,而不用 * :

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

另见

关于rust - `Box` ed 类型的方法调用解析,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48598903/

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