gpt4 book ai didi

rust - HRTB 的奇怪行为

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

I have this code :

use std::fmt::Debug;

struct S<A>
where
for<'a> A: Debug + 'a,
{
f: Box<Fn(A) -> i32>,
}

impl<A> S<A>
where
for<'a> A: Debug + 'a,
{
fn call(&self, a: A) {
println!("Return {:?}", (self.f)(a));
}
}

fn create<A>(f: Box<Fn(A) -> i32>) -> S<A>
where
for<'a> A: Debug + 'a,
{
S::<A> { f }
}

fn helper() {
let x = create::<&i32>(Box::new(|x: &i32| *x * 2));
let arg = 333;
x.call(&arg);
}

fn main() {
let x = helper();
}

编译失败:

error[E0310]: the parameter type `A` may not live long enough

code 2 ,我改变了Fn(A) -> i32Fn(&A) -> i32 ,代码有效。

...
f: Box<Fn(&A) -> i32>,
...

AFn 的参数特征,它是一个具有 Higher-Rank lifetime 的类型.它不应该受到结构 S<A> 的生命周期的影响。 .

但是为什么代码1编译不出来呢?
我如何解决借用或非借用类型 A

最佳答案

没有简单的方法来制作helper在当前的 Rust 中工作,即使你删除了所有的 for<'a> A: Debug + 'a,边界(这只会进一步限制 A 可以是什么类型,而您希望允许更多)。

这很简单,我可以做你的例子:

struct S<A> {
f: Box<Fn(A) -> i32>,
}

impl<A> S<A> {
fn call(&self, a: A) {
println!("Return {:?}", (self.f)(a));
}
}

fn create<A>(f: Box<Fn(A) -> i32>) -> S<A> {
S { f }
}

fn helper() {
let x = create(Box::new(|x: &i32| *x * 2));
let arg = 333;
x.call(&arg);
}

fn main() {
helper();
}

它不起作用的原因是 A “来自外部”,Rust 无法推断出您想要 for<'a> S<&'a A> , 连这种类型都谈不上。
请注意,如果 let arg = 333;放在let x上面,此示例确实编译(因为它推断出对 arg 的引用特别是,而不是 for<'a>)。

你今天能得到的最接近的是在具有生命周期参数的特征上的关联类型,例如:

// Emulating `type Type<'a>` by moving `'a` to the trait.
trait Apply<'a> {
type Type;
}
struct Plain<T>(std::marker::PhantomData<T>);
impl<'a, T> Apply<'a> for Plain<T> {
type Type = T;
}
struct Ref<T: ?Sized>(std::marker::PhantomData<T>);
impl<'a, T: ?Sized + 'a> Apply<'a> for Ref<T> {
type Type = &'a T;
}

struct S<A: for<'a> Apply<'a>> {
f: Box<for<'a> Fn(<A as Apply<'a>>::Type) -> i32>,
}

impl<A: for<'a> Apply<'a>> S<A> {
fn call<'a>(&self, a: <A as Apply<'a>>::Type) {
println!("Return {:?}", (self.f)(a));
}
}

fn create<A: for<'a> Apply<'a>>(
f: Box<for<'a> Fn(<A as Apply<'a>>::Type) -> i32>,
) -> S<A> {
S { f }
}

fn helper() {
let x = create::<Ref<i32>>(Box::new(|x: &i32| *x * 2));
let arg = 333;
x.call(&arg);
}

fn main() {
helper();
}

然而,事实证明这个编码命中了https://github.com/rust-lang/rust/issues/52812 ,所以它目前实际上不可用(而且我不知道有什么解决方法)。

关于rust - HRTB 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52464694/

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