生命周期省略
为了使常见的模式更符合人体工程学,Rust 允许在函数签名中省略生命周期。
生命周期位置是指在一个类型中可以写入生命周期的任何地方。
&'a T&'a mut TT<'a>
生命周期位置可以作为“输入”或“输出”出现:
- 对于
fn定义、fn类型以及 TraitFn、FnMut和FnOnce,输入是指形式参数的类型,而输出是指结果类型。所以fn foo(s: &str) -> (&str, &str)在输入位置有一个生命周期,在输出位置有两个生命周期。请注意,fn方法定义的输入位置不包括方法的impl头中出现的生命周期(对于默认方法,也不包括 trait 头中出现的生命周期) - 对于
impl头,所有类型都是输入。所以impl Trait<&T> for Struct<&T>在输入位置上省略了两个生命周期,而impl Struct<&T>则省略了一个
省略规则如下:
- 在输入位置的每一个被省略的生命周期都成为一个独立的生命周期参数
- 如果正好有一个输入生命周期的位置(无论是否被省略),该生命周期将被分配给所有被省略的输出生命周期
- 如果有多个输入生命周期位置,但其中一个是
&self或&mut self,那么self的生命周期将被分配给所有被省略的输出生命周期 - 否则,省略一个输出生命周期是一个错误
示例:
fn print(s: &str); // elidedfn print<'a>(s: &'a str); // expandedfn debug(lvl: usize, s: &str); // elidedfn debug<'a>(lvl: usize, s: &'a str); // expandedfn substr(s: &str, until: usize) -> &str; // elidedfn substr<'a>(s: &'a str, until: usize) -> &'a str; // expandedfn get_str() -> &str; // ILLEGALfn frob(s: &str, t: &str) -> &str; // ILLEGALfn get_mut(&mut self) -> &mut T; // elidedfn get_mut<'a>(&'a mut self) -> &'a mut T; // expandedfn args<T: ToCStr>(&mut self, args: &[T]) -> &mut Command // elidedfn args<'a, 'b, T: ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expandedfn new(buf: &mut [u8]) -> BufWriter; // elidedfn new(buf: &mut [u8]) -> BufWriter<'_>; // elided (with `rust_2018_idioms`)fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded
