【问题标题】:Rust lifetime error expected concrete lifetime but found bound lifetimeRust 生命周期错误预期的具体生命周期,但发现绑定生命周期
【发布时间】:2014-09-10 21:49:56
【问题描述】:

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

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

我尝试了很多变体,但无法编译这个东西。我在这里找到了另一个帖子(How to fix: expected concrete lifetime, but found bound lifetime parameter),但似乎是为了解决问题而不是解决问题。我真的不明白为什么问题甚至起源。 &Ref 是通过移动传递的,所以它应该可以正常工作吗?

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

【问题讨论】:

    标签: reference rust lifetime


    【解决方案1】:

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

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

    以及实现:

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

    看到区别了吗?后者没有&lt;'a&gt;&lt;'a&gt; 已在别处指定;它具有相同名称这一事实并不重要:它完全是另一回事。

    从功能上讲,您的 trait 定义表明返回的容器内部将包含来自 r 的引用,但 没有来自 self 的引用。它可以在方法内部使用self,但它可能不会在返回值中存储对它的任何引用。

    但是,您的方法定义使用 'ar 的生命周期和返回的 Containerself 联系起来(即,与对象本身,而不是引用 - @ 中的 ρ₂ 987654333@——这是一个微妙但有时显着的差异),而特征定义没有这种联系。

    可以通过在实现中的方法定义中插入&lt;'a&gt; 来使两者匹配。但请记住,这会使'aContainerB&lt;'a&gt; 重叠; 同一个'a!我们最好给它另一个名字;为方便起见,我将反过来进行更改,在 impl 而不是方法上进行更改(两者都可以):

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

    但是现在你当然有一个问题:返回值是Container&lt;'b&gt; 类型(因为这是ContainerB&lt;'b&gt; 中的字段c),但是你的签名需要Container&lt;'a&gt;(使用引用的东西来自r,而不是来自self)。

    解决它的一种方法是在特征定义和实现中将&amp;self 的生命周期指定为'a;在实现中,这将要求'b 大于或等于'a(因为您已经成功地将生命周期'a 引用到生命周期'b 的对象,并且对象必须比引用长),因此由于子类型('a'b 的子类型)Container&lt;'b&gt; 将被安全地强制转换为 Container&lt;'a&gt;

    如果您不熟悉这些生活问题,则很难考虑它们;但随着时间的推移,它们会变得很自然。

    【讨论】:

    • 另一个修复方法是trait ToC&lt;'a&gt; { fn to_c(&amp;self, r: &amp;'a Ref) -&gt; Container&lt;'a&gt;; }
    • 哦,是的,然后是impl&lt;'a&gt; ToC&lt;'a&gt; for ContainerB&lt;'a&gt;
    • 这当然有很大帮助,并解决了我的一些错误想法(例如终身阴影)!谢谢。这可以 100% 解决这个问题,但我似乎无法将它应用到另一个问题上。我在这里写了这个问题:stackoverflow.com/questions/24853111/…)
    猜你喜欢
    • 1970-01-01
    • 2017-05-03
    • 1970-01-01
    • 2013-07-03
    • 2020-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多