Rust:对可能拥有的引用中的借用进行生命周期检查

Rust: lifetime checking of a borrow inside a refernce to a MaybeOwned

我在使用以下代码时遇到问题...

use std::collections::BTreeSet;
use maybe_owned::MaybeOwned;

struct Thing<'a, T> {
    set: BTreeSet<MaybeOwned<'a, T>>
}

impl<'a, T: Ord> Thing<'a, T> {
    fn take(&mut self, x: T){
        let y = self.set.take(&MaybeOwned::Borrowed(&x));
    }
}

给出编译器错误

error[E0597]: `x` does not live long enough
  --> src/main.rs:10:53
   |
8  | impl<'a, T: Ord> Thing<'a, T> {
   |      -- lifetime `'a` defined here
9  |     fn take(&mut self, x: T){
10 |         let y = self.set.take(&MaybeOwned::Borrowed(&x));
   |                 ------------------------------------^^--
   |                 |                                   |
   |                 |                                   borrowed value does not live long enough
   |                 argument requires that `x` is borrowed for `'a`
11 |     }
   |     - `x` dropped here while still borrowed

但是此时显然没有借用 x,因为 MaybeOwned 超出了范围,因此封闭的借用超出了范围。

我如何告诉 Rust 编译器这没问题?

问题在于,虽然临时 MaybeOwned 不会存在那么久,但这并不重要,因为它是隐含的 MaybeOwned<'a, T>。这意味着 x 必须至少与 'a 一样长,但事实并非如此。临时 MaybeOwned 不会活那么久的事实与借用检查器无关。

BTreeSet::take() 的第二个参数是 &Q,其中集合自己的 T 实现了 Borrow<Q>MaybeOwned<'a, T> 没有实现 Borrow<MaybeOwned<'b, T>>,其中 'b: 'a,但是所有 T&T 都实现了 Borrow<T>,这要归功于一揽子实现,所以给出一个参数输入 &MaybeOwned<'_, T>,唯一满足 T: Borrow<Q> 约束的生命周期是 &MaybeOwned<'a, T> —— 因此,临时 MaybeOwned 的生命周期参数被推断为 'a。这是满足特征界限的唯一方法。

谢天谢地,none 这很重要,因为 MaybeOwned<'_, T> 实现了 Borrow<T>,这意味着您只需提供一个 &T:

let y = self.set.take(&x);