【问题标题】:How do I make a trait that is restricted to types who implement another trait where `&Self` self is a trait's type?如何制作一个仅限于实现另一个特征的类型的特征,其中 `&Self` 自我是特征的类型?
【发布时间】:2021-12-28 17:39:09
【问题描述】:

例如,我希望每个MyTrait 都实现AddAssign<&'a Self>。这是我得到的,在将'a 放在编译器想要的位置之后:

trait MyTrait<'a>: 'a + std::ops::AddAssign<&'a Self> {}

fn func<'a, T: MyTrait<'a>>(a: &mut T, b: T) {
    *a += &b;
}

此代码失败并出现以下错误:

error[E0597]: `b` does not live long enough
 --> src/main.rs:4:11
  |
3 | fn func<'a, T: MyTrait<'a>>(a: &mut T, b: T) {
  |         -- lifetime `'a` defined here
4 |     *a += &b;
  |           ^^
  |           |
  |           borrowed value does not live long enough
  |           requires that `b` is borrowed for `'a`
5 | }
  | - `b` dropped here while still borrowed

For more information about this error, try `rustc --explain E0597`.

我如何告诉编译器&amp;b 将仅用于该总和期间?

【问题讨论】:

  • 要回答您的问题,只需使用b: &amp;'a T 而不是b: T。但是,我认为您可能真正想做的事情(AddAssign 的一个版本,它采用引用而不是值)很遗憾,由于AddAssign 的定义方式,这是不可能的。你会发现,如果你只使用b: &amp;T,一开始它似乎可以工作,但你会遇到这样的问题,即对于非Copy 类型,实际上不可能实现具有任意生命周期的MyTrait&lt;'a&gt;,这首先破坏了使用引用的全部意义。
  • 在我的真实代码中,我不能有b: &amp;'a T,因为我求和的变量是本地的。我特别需要一个解决方案,其中b 可以在a 之前超出范围。由于语法限制,这可能是不可能的,但我不明白这从根本上是不可能的。
  • 这不会是正确的,因为AddAssign 的实现者可以假设加数永远存在;例如,如果允许引用,您可以实现 AddAssign 以将引用推送到内部堆栈,该堆栈在引用无效后将持续存在。我的建议:创建您自己的 AddAssign 版本,使用引用代替。
  • @Coder-256 回答您的问题,“如果我们有foo += &amp;bar,当bar 被删除时foo.vec 会发生什么?”,那么foo 必须在@ 之前被删除987654345@,这从根本上没有错。但是这样的特征实现与我的特征约束不匹配,现在我用@kmdreko 的答案修复了它。在我最初的尝试中,我说引用的对象必须比 MyTrait 对象寿命长,但在接受的答案中没有这样的限制。

标签: rust borrow-checker


【解决方案1】:

您可以使用higher-ranked trait bound 使约束在整个生命周期内通用,因此它不会被限制为使用在特征上定义的约束:

pub trait MyTrait: for<'a> std::ops::AddAssign<&'a Self> {}
                // ^^^^^^^

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多