为什么返回捕获复制类型的闭合时需要移动关键字?

发布于 2025-01-19 12:56:57 字数 735 浏览 1 评论 0 原文

godbolt

fn foo(c: char) -> impl Fn() -> i32 {
    || bar(c)
}

fn bar(_: char) -> i32 {
    42
}

引发错误的

error[E0597]: `c` does not live long enough
 --> src/lib.rs:2:12
  |
2 |     || bar(c)
  |     --     ^ borrowed value does not live long enough
  |     |
  |     value captured here
3 | }
  |  -
  |  |
  |  `c` dropped here while still borrowed
  |  borrow later used here

我认为原始类型 char> char 默认情况;为什么我需要明确移动 it(移动|| bar(c))以获取编译代码?

godbolt

fn foo(c: char) -> impl Fn() -> i32 {
    || bar(c)
}

fn bar(_: char) -> i32 {
    42
}

Which throws an error

error[E0597]: `c` does not live long enough
 --> src/lib.rs:2:12
  |
2 |     || bar(c)
  |     --     ^ borrowed value does not live long enough
  |     |
  |     value captured here
3 | }
  |  -
  |  |
  |  `c` dropped here while still borrowed
  |  borrow later used here

I thought primitive types like char were copied by default; why do I need to explicitly move it (move || bar(c)) to get the code to compile?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一城柳絮吹成雪 2025-01-26 12:56:57

您是正确的, char copy ,但是当执行副本时,棘手的恰好是

假装复制特质具有一种称为复制的方法,类似于 clone :: clone 。作为编译器所做的示例,您的关闭变为:

|| {
    let c = Copy::copy(&c);
    bar(c)
}

闭合仅通过引用捕获 c ,因为在调用闭合时需要执行副本所需的一切。通过返回关闭,您将试图返回对本地的引用,这是禁止的。

使用移动迫使闭合以按值捕获 c

另请参阅:

You are correct that the char is Copy, but what's tricky is exactly when the copy is performed.

Pretend that the Copy trait had a method called copy, similar to Clone::clone. As an example of what the compiler does, your closure becomes:

|| {
    let c = Copy::copy(&c);
    bar(c)
}

The closure only captures c by reference as that's all it needs to perform the copy when the closure is invoked. By returning the closure, you'd be trying to return the reference to the local, which is forbidden.

Using move forces the closure to capture c by value.

See also:

素染倾城色 2025-01-26 12:56:57

我认为像 char 这样的原始类型是默认复制的;为什么我需要显式移动它 (move || bar(c)) 才能编译代码?

实际上,因为 charCopy 才出现问题:默认情况下,Rust 闭包是“智能”的,因此它们捕获内容的方式如下尽可能不受限制。

这意味着如果他们可以通过引用捕获,他们将通过引用捕获,如果他们不能但可以通过 mut ref 捕获,他们就会这样做,并且只有当他们不能时,他们才会通过值捕获(“移动”)。

在这里,因为 charCopy 它可以通过引用捕获然后复制到被调用者中。因此闭包会执行此操作,并且您必须告诉它按值捕获(使用 move 关键字)。

I thought primitive types like char were copied by default; why do I need to explicitly move it (move || bar(c)) to get the code to compile?

It's actually because char is Copy that the issue occurs: by default, Rust closures are "smart", so the way they capture things is as unrestrictive as possible.

This means if they can capture by reference they will capture by reference, if they can't but can capture by mut ref they'll do that, and only if they can't will they capture by value ("move").

Here, because char is Copy it can be captured by reference then copied into the callee. And so the closure does that, and you have to tell it to capture by value (using the move keyword) instead.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文