Rust 生命周期错误预期具体生命周期,但发现绑定生命周期 [英] Rust lifetime error expected concrete lifetime but found bound lifetime

查看:45
本文介绍了Rust 生命周期错误预期具体生命周期,但发现绑定生命周期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在处理结构的生命周期参数时遇到问题.我不是 100% 确定如何描述问题,但我创建了一个显示编译时错误的小案例.

I am having an issue working with lifetime parameters for structs. I am not 100% sure how to describe the problem, but I created a trivial case that shows my compile time error.

struct Ref;

struct Container<'a> {
  r : &'a Ref
}

struct ContainerB<'a> {
  c : Container<'a>
}

trait ToC {
  fn to_c<'a>(&self, r : &'a Ref) -> Container<'a>;
}

impl<'a> ToC for ContainerB<'a> {
  fn to_c(&self, r : &'a Ref) -> Container<'a> {
    self.c
  }
}

我遇到的错误是

test.rs:16:3: 18:4 error: method `to_c` has an incompatible type for trait: expected concrete lifetime, but found bound lifetime parameter 'a
test.rs:16   fn to_c(&self, r : &'a Ref) -> Container<'a> {
test.rs:17     self.c
test.rs:18   }
test.rs:16:48: 18:4 note: expected concrete lifetime is the lifetime 'a as defined on the block at 16:47
test.rs:16   fn to_c(&self, r : &'a Ref) -> Container<'a> {
test.rs:17     self.c
test.rs:18   }
error: aborting due to previous error

我尝试了很多变体,但无法编译这个东西.我在这里找到了另一篇文章(如何修复:预期的具体生命周期,但发现绑定生命周期参数)但似乎绕过了问题而不是解决它.我真的不明白为什么这个问题甚至起源.&Ref 是通过移动传递的,所以它应该可以正常工作吗?

I have tried many variations and just can't get this thing to compile. I found another post here (How to fix: expected concrete lifetime, but found bound lifetime parameter) but is appears to get around the problem instead of solving it. I can't really see why the problem even originates. The &Ref is being passed along via moves so it should just work right?

有什么想法吗?感谢大家的帮助.

Any ideas? Thanks for all the help.

推荐答案

让我们比较一下这两个定义.一、trait方法:

Let’s compare the two definitions. First, the trait method:

fn to_c<'a>(&self, r: &'a Ref) -> Container<'a>;

和实现:

fn to_c(&self, r: &'a Ref) -> Container<'a>;

看到区别了吗?后者没有 <'a>.<'a> 已在别处指定;它具有相同的名称这一事实并不重要:它是完全不同的东西.

See the difference? The latter doesn’t have <'a>. <'a> has been specified elsewhere; the fact that it has the same name does not matter: it is a different thing entirely.

在功能上,您的特征定义表示返回的容器将在其中引用来自 r 的内容,但 没有来自 self 的内容.它可以在方法内部使用 self,但它不能在返回值中存储对其的任何引用.

Functionally, your trait definition says that the returned container will have a reference inside it to something from r, but nothing from self. It may use self inside the method, but it may not store any references to it in the returned value.

然而,您的方法定义使用了一个 'a,它将 r 和返回的 Container 的生命周期与 self 联系起来(即对象本身,而不是引用——&'ρ₁ T<'ρ₂> 中的 ρ₂——这是一个微妙但有时显着的差异),而特征定义没有这种联系.

Your method definition, however, is using a 'a that ties the lifetimes of r and the returned Container to self (that is, to the object itself, not the reference—the ρ₂ in &'ρ₁ T<'ρ₂>—it’s a subtle but sometimes significant difference), whereas the trait definition had no such connection.

可以通过在实现中的方法定义中插入<'a>来使两者匹配.但请记住,这是从 ContainerB<'a>; 遮蔽了 'a;它不是同一个'a!我们最好再给它起个名字;为方便起见,我将进行相反的更改,在 impl 而不是方法上更改它(两者都可以):

The two can be made to match by inserting the <'a> in the method definition in the implementation. But bear in mind that that is shadowing the 'a from ContainerB<'a>; it is not the same 'a! We’re better to give it another name; for convenience, I’ll make the change the other way round, changing it on the impl instead of the method (either would do):

impl<'b> ToC for ContainerB<'b> {
    fn to_c<'a>(&self, r: &'a Ref) -> Container<'a> {
        self.c
    }
}

但现在你当然有一个问题:返回值的类型是 Container<'b>(因为这就是 ContainerB<'b> 是),但您的签名需要 Container<'a>(使用来自 r 的引用,而不是来自 self代码>).

But now of course you have a problem: the return value is of type Container<'b> (because that’s what the field c in a ContainerB<'b> is), but your signature demands Container<'a> (something using a reference from r, not from self).

修复它的一种方法是在特征定义和实现中将 &self 的生命周期指定为 'a ;在实现中,这将要求 'b 大于或等于 'a(因为您已经成功地引用了生命周期 'a 到具有生命周期 'b 的对象,并且该对象必须比引用存活时间长)等由于子类型('a'b) Container<'b> 将被安全地强制转换为 Container<'a>.

One way which would fix it is specifying the lifetime of &self as 'a in both the trait definition and the implementation; in the implementation, this would then demand that 'b was greater than or equal to 'a (by virtue of the fact that you have successfully taken a reference with lifetime 'a to an object with lifetime 'b, and the object must outlive the reference) and so due to the subtyping ('a is a subtype of 'b) Container<'b> would be safely coerced to Container<'a>.

当你不熟悉它们时,这些一生的事情是很难想到的;但随着时间的推移,它们变得很自然.

These sorts of lifetime matters are difficult to think about when you’re not familiar with them; but in time they become quite natural.

这篇关于Rust 生命周期错误预期具体生命周期,但发现绑定生命周期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆