Rust 生命周期错误预期具体生命周期,但发现绑定生命周期 [英] Rust lifetime error expected concrete lifetime but found bound lifetime
问题描述
我在处理结构的生命周期参数时遇到问题.我不是 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屋!