生命周期省略

为了使常见模式更符合人体工程学,Rust 允许在函数签名中_省略_生命周期。

_生命周期位置_是可以在类型中编写生命周期的任何地方

&'a T
&'a mut T
T<'a>

生命周期位置可以表现为“输入”或“输出”

  • 对于 fn 定义、fn 类型以及特征 FnFnMutFnOnce,输入指的是形式参数的类型,而输出指的是结果类型。因此 fn foo(s: &str) -> (&str, &str) 在输入位置省略了一个生命周期,在输出位置省略了两个生命周期。请注意,fn 方法定义的输入位置不包括出现在方法的 impl 标头中的生命周期(也不包括出现在特征标头中的生命周期,对于默认方法)。

  • 对于 impl 标头,所有类型都是输入。因此 impl Trait<&T> for Struct<&T> 在输入位置省略了两个生命周期,而 impl Struct<&T> 省略了一个。

省略规则如下

  • 输入位置中的每个省略的生命周期都将成为一个不同的生命周期参数。

  • 如果只有一个输入生命周期位置(省略或未省略),则该生命周期将分配给_所有_省略的输出生命周期。

  • 如果有多个输入生命周期位置,但其中一个是 &self&mut self,则 self 的生命周期将分配给_所有_省略的输出生命周期。

  • 否则,省略输出生命周期将是错误的。

示例

fn print(s: &str);                                      // elided
fn print<'a>(s: &'a str);                               // expanded

fn debug(lvl: usize, s: &str);                          // elided
fn debug<'a>(lvl: usize, s: &'a str);                   // expanded

fn substr(s: &str, until: usize) -> &str;               // elided
fn substr<'a>(s: &'a str, until: usize) -> &'a str;     // expanded

fn get_str() -> &str;                                   // ILLEGAL

fn frob(s: &str, t: &str) -> &str;                      // ILLEGAL

fn get_mut(&mut self) -> &mut T;                        // elided
fn get_mut<'a>(&'a mut self) -> &'a mut T;              // expanded

fn args<T: ToCStr>(&mut self, args: &[T]) -> &mut Command                  // elided
fn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded

fn new(buf: &mut [u8]) -> BufWriter;                    // elided
fn new(buf: &mut [u8]) -> BufWriter<'_>;                // elided (with `rust_2018_idioms`)
fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a>          // expanded