# Rust 能自动推断出所有的lifetime吗？

By [Aulee](https://paragraph.com/@aulee) · 2024-01-05

---

答： 不能。

我觉得前面的回答都不能解决[这位题主的疑惑](https://rustcc.cn/article?id=926f8f73-912c-4860-a4e8-979b8d73b4ba) 。我想了一个有点绕的例子，来说明编译器是不能自动推断出generic lifetime的，因为可行的标注方法不只一种（楼上那个`longest`例子从逻辑上看似乎只剩下一种标注方法了，所以不具有足够的说服力）。

如下面定义的函数根据短字符串的长度来截取长字符串，该函数因为没有标注lifetime无法成功编译：

    fn cut_long_according_to_short(l: &str, s: &str) -> &str {
        let len = s.len();
        &l[0..len]    
    }
    

有两种不同的标注方法可以实现成功编译，编译器无法自动推断出该采用哪一个。

第一种比较宽松：

    fn cut_long_according_to_short<'a>(l: &'a str, s: &str) -> &'a str {
        let len = s.len();
        &l[0..len]    
    }
    

第二种比较严格：

    fn cut_long_according_to_short<'a>(l: &'a str, s: &'a str) -> &'a str {
        let len = s.len();
        &l[0..len]    
    }
    

但是两者最终实现的语义是有区别的。后者不仅要求返回引用的lifetime不得超过`l`,而且要求也不得超过`s`。

我们可以验证这二者的区别。例如我们会发现如果采用第一种宽松的标注法，下面的代码是可以成功编译的；反之如果采用第二种严格的标注法，则下面的代码无法编译：

    
    fn main() {
        let result;    
    
        let string1 = String::from("The loooooooong");
        let l = string1.as_str();
    
        {
            let string2 = String::from("The short");
            let s = string2.as_str();
    
            result = cut_long_according_to_short(l, s);
        }
        
        println!("{result}");
        
    }
    

这是由于`string2`的lifetime小于`result`，在`println!`行运行前就被drop掉了（注意`string2`被括号`{}`限定在一个更小的scope内）。这在第一种较宽松的标注中是被允许的，而被第二种严格的标注所禁止。

---

*Originally published on [Aulee](https://paragraph.com/@aulee/rust-lifetime)*
