【问题标题】:How does compiler infer that Box is borrowing the one which its content borrows?编译器如何推断 Box 正在借用它的内容借用的那个?
【发布时间】:2021-01-05 10:30:23
【问题描述】:
let s: String = String::from("some message");

let b: Box<&String> = Box::<&String>::new(&s);

drop(s);

let another_box = b; // error! b (which borrows s) is used later!

所以,上面的代码看起来很简单。

b 显然是在借用人类意义上的 s

但是,我认为这很神奇: 没有任何生命周期语句,编译器怎么知道呢?

根据 Rust 的标准库, Box的声明如下:

pub struct Box<T, A = Global>(_, _)
    where A: AllocRef, T: ?Sized;

而我认为它的真正含义如下:

pub struct Box<'a, T, A = Global>(_, _)
    where A: AllocRef, T: ?Sized + 'a;

我认为在结构具有通用参数类型的所有情况下,生命周期(或借用)不会自动移动。 还是这样??

【问题讨论】:

    标签: generics rust reference lifetime ownership


    【解决方案1】:

    在这种情况下,生命周期是包装在盒子中的 T 类型的一部分。

    您将&amp;'a String 类型的&amp;s 包装在框中,其中'a 是引用的适当生命周期,由编译器推断。因此b 的类型为Box&lt;&amp;'a String&gt;,因此它包含相同的生命周期参数。盒子本身不需要显式的生命周期参数——它对任意类型都是通用的,并且类型没有理由需要具有静态生命周期。

    这并不特定于 Box。例如,PhantomData 的工作方式相同,尽管 PhantomData 甚至不以任何方式使用其类型参数:

    use std::marker::PhantomData;
    
    fn make_phantom<T>(_: T) -> PhantomData<T> {
        PhantomData
    }
    
    fn main() {
        let s: String = String::from("some message");
        let phantom = make_phantom(&s);
        drop(s);
        let _another_phantom = phantom;
    }
    

    导致相同的错误,即从借用检查器的角度来看,phantom 借用了s,但实际上它不包含对s 的引用。

    (Playground)

    【讨论】:

    • 啊哈!那么,我在问题中的猜测是对的!
    • 它会自动获取其泛型参数(即 &'a String)的生命周期,对吗?
    • 结果类型Box&lt;&amp;String&gt; 有一个生命周期参数,因为它包含一个引用。我不确定您所说的“它会自动获得生命周期……”是什么意思,更多的是所有引用都有生命周期——无论是显式的还是隐式的。
    • 我很困惑,对于所有“struct S”,S 借用了 T 借用的东西。我认为有某种反例
    • @kwonryul 我不这么认为。我在答案中添加了一个示例,以表明此行为并非特定于 Boxes。
    猜你喜欢
    • 2017-05-31
    • 2018-04-04
    • 2020-09-19
    • 1970-01-01
    • 1970-01-01
    • 2019-12-30
    • 2016-05-02
    • 1970-01-01
    • 2015-04-20
    相关资源
    最近更新 更多