首页 > 解决方案 > 通过本地生命周期来满足特征

问题描述

我有一个通用函数创建一个本地对象并采用一个特征来指定如何处理该对象。trait 获取对象的引用并在其生命周期内保存它(以避免一次又一次地将它传递给每个函数调用)。它在

fn do_stuff<'a, T>()
  where T : BigBorrower<'a>
{
  let borrowee = Borrowed{ data : 1 };
  {
    let _borrowee = T::new(&borrowee);
  }
}

这是函数调用。因为必须在函数声明中指定 trait 的生命周期,它使编译器认为生命周期延长了 _borrowee 的生命周期。

https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=a445fb4ab7befefbadd3bdb8fb43c86a

   |
24 | fn do_stuff<'a, T>()
   |             -- lifetime `'a` defined here
...
29 |     let _borrowee = T::new(&borrowee);
   |                     -------^^^^^^^^^-
   |                     |      |
   |                     |      borrowed value does not live long enough
   |                     argument requires that `borrowee` is borrowed for `'a`
30 |   }
31 | }
   | - `borrowee` dropped here while still borrowed

标签: rustlifetime

解决方案


您刚刚遇到了生命周期和编译器的问题之一。一旦你意识到它为什么会发生,这就是有道理的。

您的方法调用'a为您提供的泛型类型强制执行生命周期。这意味着,除其他外,需要尊重这一生命周期,并且所有对象都必须活得那么久。实际上,当您这样做时,生命周期就是函数调用的生命周期。

通过传递T::new()对局部变量的引用,您将强制编译器选择一个劣于的生命周期'a(因为它不会超过函数调用),因此,您违背了自己的要求。

通常,您解决此问题的方法是将您do_stuff<'a, T>分成两部分,就像在这个游乐场样本中一样。这使得编译器可以接受生命周期检查,因为该引用的预期寿命保证比被调用函数的预期寿命长。

请注意,我new在 trait 和 implementations 中将您的方法重命名为borrow,因为它更接近它的本质。


推荐阅读