gpt4 book ai didi

rust - 闭包签名的强制/强制评估

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

这是我想做的一个人为的例子:

use std::boxed::Box;

#[derive(Debug)]
pub struct Foo<'a>(pub &'a str);

pub trait IntoBox {
fn into_box<'a>(self) -> Box<Fn(Foo) -> String>;
}

impl<B> IntoBox for B where B: Fn(Foo) -> String + 'static {
fn into_box(self) -> Box<Fn(Foo) -> String> { Box::new(self) }
}

fn direct_into_box<B: Fn(Foo) -> String + 'static>(b: B) -> Box<Fn(Foo) -> String> {
Box::new(b)
}

fn main() {
// Doesn't work
let x = IntoBox::into_box(|i| format!("{:?}", i) );

// Works
let y = IntoBox::into_box(|i: Foo| format!("{:?}", i) );

// Also works
let z = direct_into_box(|i| format!("{:?}", i) );
}

如何让我的 trait impl 对闭包进行与我的 direct_into_box 相同的评估?我原以为 direct_into_box 和我的 trait impl 会以相同的方式运行。

x 上的错误:

error[E0271]: type mismatch resolving `for<'r> <[closure@<anon>:20:31: 20:53] as std::ops::FnOnce<(Foo<'r>,)>>::Output == std::string::String`
--> <anon>:20:13
|
20 | let x = IntoBox::into_box(|i| format!("{:?}", i) );
| ^^^^^^^^^^^^^^^^^ expected bound lifetime parameter , found concrete lifetime
|
= note: concrete lifetime that was found is lifetime '_#29r
= note: required because of the requirements on the impl of `IntoBox` for `[closure@<anon>:20:31: 20:53]`
= note: required by `IntoBox::into_box`

error[E0281]: type mismatch: the type `[closure@<anon>:20:31: 20:53]` implements the trait `std::ops::Fn<(_,)>`, but the trait `for<'r> std::ops::Fn<(Foo<'r>,)>` is required (expected concrete lifetime, found bound lifetime parameter )
--> <anon>:20:13
|
20 | let x = IntoBox::into_box(|i| format!("{:?}", i) );
| ^^^^^^^^^^^^^^^^^
|
= note: required because of the requirements on the impl of `IntoBox` for `[closure@<anon>:20:31: 20:53]`
= note: required by `IntoBox::into_box`

最佳答案

听起来像 an inference bug in the compiler .似乎发生的是编译器实现了 Fn(Foo<'x>) 一个特定的生命周期'x 而不是 Fn(Foo<'a>) 任何一生'a 关闭。

让我们看看是否可以通过手动定义结构来重现错误(这需要夜间编译器),以便我们更好地理解发生了什么。首先,让我们以正确的方式定义结构:

#![feature(fn_traits)]
#![feature(unboxed_closures)]

// Foo and IntoBox unchanged

struct Func;

impl<'a> FnOnce<(Foo<'a>,)> for Func {
type Output = String;

extern "rust-call" fn call_once(self, args: (Foo<'a>,)) -> String {
self.call(args)
}
}

impl<'a> FnMut<(Foo<'a>,)> for Func {
extern "rust-call" fn call_mut(&mut self, args: (Foo<'a>,)) -> String {
self.call(args)
}
}

impl<'a> Fn<(Foo<'a>,)> for Func {
extern "rust-call" fn call(&self, (i,): (Foo<'a>,)) -> String {
format!("{:?}", i)
}
}

fn main() {
let x = IntoBox::into_box(Func);
}

Func struct 可以很好地编译并且表现得就像您原来的闭包一样。

现在,让我们打破它:

impl FnOnce<(Foo<'static>,)> for Func {
type Output = String;

extern "rust-call" fn call_once(self, args: (Foo<'static>,)) -> String {
self.call(args)
}
}

impl FnMut<(Foo<'static>,)> for Func {
extern "rust-call" fn call_mut(&mut self, args: (Foo<'static>,)) -> String {
self.call(args)
}
}

impl Fn<(Foo<'static>,)> for Func {
extern "rust-call" fn call(&self, (i,): (Foo<'static>,)) -> String {
format!("{:?}", i)
}
}

我在这里所做的是删除了 <'a>在每个 impl ,因此 impl 在一生中不再通用,我已经替换了 Foo<'a>Foo<'static> .这意味着现在,只有当“闭包”的参数是 Foo<'static> 时才会实现这些特征。 .

编译失败,出现以下错误:

error[E0271]: type mismatch resolving `for<'r> <Func as std::ops::FnOnce<(Foo<'r>,)>>::Output == std::string::String`
--> <anon>:51:13
|
51 | let x = IntoBox::into_box(Func);
| ^^^^^^^^^^^^^^^^^ expected bound lifetime parameter , found concrete lifetime
|
= note: concrete lifetime that was found is the static lifetime
= note: required because of the requirements on the impl of `IntoBox` for `Func`
= note: required by `IntoBox::into_box`

error[E0277]: the trait bound `for<'r> Func: std::ops::Fn<(Foo<'r>,)>` is not satisfied
--> <anon>:51:13
|
51 | let x = IntoBox::into_box(Func);
| ^^^^^^^^^^^^^^^^^ the trait `for<'r> std::ops::Fn<(Foo<'r>,)>` is not implemented for `Func`
|
= help: the following implementations were found:
= help: <Func as std::ops::Fn<(Foo<'static>,)>>
= note: required because of the requirements on the impl of `IntoBox` for `Func`
= note: required by `IntoBox::into_box`

第一个错误是相同的,但不是像 '_#29r 这样的内部名称,编译器提到了静态生命周期,因为这就是我在这里使用的。我怀疑编译器对你的代码中没有编译的闭包所做的事情与我的第二组 impl 相似,只是不是 'static。 ,这是我们无法在 Rust 中命名的其他具体生命周期。第二个错误不同,但意思几乎相同。

关于rust - 闭包签名的强制/强制评估,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40535543/

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