如何为创建具有特征生命周期边界的对象的生产者找到通用边界

How to find generic bounds for producer that creates objects with trait-lifetime bounds

我已将我的实际代码缩减为这个最小示例:

trait Producer<P> where P: Something {
    fn produce(&self) -> Box<P>;
}

struct P1 {}

impl Producer<B1> for P1 {
    fn produce(&self) -> Box<B1> {
        Box::new(B1 {})
    }
}

trait Something {}

trait Borrower<'b> {
    type B: std::fmt::Display;
    
    fn borrow(&'b self) -> Self::B;
}

struct B1 {}

impl Something for B1 {}

impl<'b> Borrower<'b> for B1 {
    type B = Borrowing1<'b>;
    
    fn borrow(&'b self) -> Self::B {
        Borrowing1 { _b: &self }
    }
}

struct Borrowing1<'b> {
    _b: &'b B1,
}

impl<'b> std::fmt::Display for Borrowing1<'b> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "Borrowing1")
    }
}

fn perform<'b, P, B>(producer: P) where P: Producer<B>, B: Something + Borrower<'b> + 'static {
    for _ in 0..1 {
        let b = producer.produce();
        let s = b.borrow().to_string();
        eprintln!("{}", s);
    }
}

fn main() {
   let p1 = P1 {};
   perform(p1);
}

我有一个创建 SomethingProducer 类型。而那个东西可以实现Borrower<'b>,它引入了一个生命周期。然后,我想限制函数 perform 来接收生产 Something 且具有 Borrower<'b> 特征的生产者。但是,由于我无法阻止在 perform 中引入生命周期,因此该函数认为所有生成的项目都必须在整个函数执行期间存在。实际上,它们是只是实现 Borrower<'b> 的静态对象。但我很难找到正确的界限。

错误消息反映:

error[E0597]: `*b` does not live long enough
  --> src/main.rs:46:17
   |
43 | fn perform<'b, P, B>(producer: P) where P: Producer<B>, B: Something + Borrower<'b> + 'static {
   |            -- lifetime `'b` defined here
...
46 |         let s = b.borrow().to_string();
   |                 ^---------
   |                 |
   |                 borrowed value does not live long enough
   |                 argument requires that `*b` is borrowed for `'b`
47 |         eprintln!("{}", s);
48 |     }
   |     - `*b` dropped here while still borrowed

也许你可以帮我。

这可以用higher-rank trait bounds解决:

你不必过一辈子才能在这里发挥作用。相反,您需要在调用 borrow() 时定义生命周期。以下应该可以解决问题:

fn perform<P, B>(producer: P)
where
    P: Producer<B>,
    for<'b> B: Something + Borrower<'b> + 'static,
{
    for _ in 0..1 {
        let b = producer.produce();
        let u = b.borrow();
        let s = u.to_string();
        eprintln!("{}", s);
    }
}

Playground

这里很好地解释了更高级别的特征边界: