Rust 当其中一个字符串文本超出范围时,为什么要编译这段带有字符串文本的代码?

Rust 当其中一个字符串文本超出范围时,为什么要编译这段带有字符串文本的代码?,rust,scope,lifetime,Rust,Scope,Lifetime,一开始我遇到了这个问题,有点困惑。所以我决定通过编写一个小示例来尝试一下。() fn main(){ 让b=“你好”; 让mut d=“未分配”; { 让a=“嗨”; 设c=寿命(&a和&b); d=&c; } //我的困惑发生在这里,我期待一个编译时错误 //因为“c”的生存期与前一块中的“a”相同 //据我所知,但这一切都很好 println!(“{}”,d); } fn寿命(测试:&'a str,测试2:&'b str)->&'a str{ println!(“{},{}”,test,te

一开始我遇到了这个问题,有点困惑。所以我决定通过编写一个小示例来尝试一下。()

fn main(){
让b=“你好”;
让mut d=“未分配”;
{
让a=“嗨”;
设c=寿命(&a和&b);
d=&c;
}
//我的困惑发生在这里,我期待一个编译时错误
//因为“c”的生存期与前一块中的“a”相同
//据我所知,但这一切都很好
println!(“{}”,d);
}
fn寿命(测试:&'a str,测试2:&'b str)->&'a str{
println!(“{},{}”,test,test2);
返回“生命周期返回值”;
}
据我所知,
lifety
函数将lifety
'a
绑定到返回的参考值。 所以通常我会期望行
println!(“{}”,d)
在编译时中断,引用生存期
'a
的错误超出范围,我错了

我理解错了什么? 这段代码为什么要编译


我看到了,这基本上让我更加困惑,因为他们在某种程度上说出了我最初期望的结果。

在了解了上述评论中指出的情况后,我写了这个小片段(类似于问题)

struct马铃薯(i32);
fn不工作(){
设b=马铃薯(1);
让d;
{
设a=马铃薯(2);
设c=lifetime2(&b,&a);
d=c;
}
//编译时错误!借用值的有效期不够长。
println!(“{}”,d.0);
}
fn寿命2(测试:&'a土豆,测试2:&'b土豆)->&'a土豆{
返回和马铃薯(测试0);
}
现在给出了实际的预期编译时错误


它发现在我最初的问题中,寿命被推断为
'static
,这是
str
引用的最高公共寿命。

在代码一侧绘制这些值的寿命可能有用。从这里,您将看到
a
绑定的值在到达
println时仍然有效。请参阅一个更复杂的示例,该示例涉及生命周期协变和逆变。我的理解是,生命周期用于将编译器关于对象生命周期的知识扩展到词法范围之外。您不会为对象指定生存期。您只是告诉compler返回的字符串引用的有效期至少与
b
一样长,这是正确的,因为字符串文本是静态的,并且在整个程序期间是有效的。然后,您将结果分配到
d
,并且
d
本身将一直持续到
main
的末尾。请注意,当返回对字符串文本的引用时,正确的生存期是
'static
。现在这更有意义了,我没有意识到反向协方差根据更长的生存期推断生存期。正如@E_net4removesmeta-commentation所说,它实际上回答了我的部分问题。有趣的是,当我试图通过更改
let mut d=“Unassigned”来消除警告时,我会让它打开,以防有人对这个特殊情况有更精确的解释到<代码>让d,我得到一个类似于您所期望的编译器错误。(我无法解释原因。)
struct Potato(i32);

fn doesnt_work() {
    let b = Potato(1);
    let d;
    {
        let a = Potato(2);
        let c = lifetime2(&b, &a);
        d = c;
    }

    // Compile-time error ! Borrowed value does not live long enough.
    println!("{}", d.0);
}

fn lifetime2<'a, 'b>(test: &'a Potato, test2: &'b Potato) -> &'a Potato {
    return &Potato(test.0);
}