为什么对const进行静态引用会返回对临时变量的引用?

时间:2019-03-29 18:14:51

标签: rust lifetime borrow-checker

在Rust中,我有以下代码:

pub trait Test: Sized {
    const CONST: Self;
    fn static_ref() -> &'static Self {
        &Self::CONST
    }
}

我的期望是,由于const'static,所以我应该能够引用它也是'static。但是,编译器给出以下错误:

error[E0515]: cannot return reference to temporary value
   --> file.rs:9:9
    |
  9 |         &Self::CONST
    |         ^-----------
    |         ||
    |         |temporary value created here
    |         returns a reference to data owned by the current function

这里如何引入临时变量?

此外,似乎在某些情况下引用常量确实有效。这是一个简短的具体示例,其Test的实现略有不同

pub trait Test: Sized {
    fn static_ref() -> &'static Self;
}

struct X;

impl Test for X {
    fn static_ref() -> &'static Self {
        &X
    }
}

2 个答案:

答案 0 :(得分:7)

Rust中的常量是一个编译时常量,而不是带有内存位置的实际变量。 Rust编译器可以在任何使用常量的地方替换其实际的 value 。如果使用这样一个值的地址,那么您将获得一个临时地址。

Rust也具有静态变量的概念。这些变量实际上具有与整个程序持续时间一致的内存位置,并且引用静态变量的确会导致引用的生存期为'static

另请参阅:

答案 1 :(得分:3)

定义特征时,该定义必须对所有可能的实现有意义。

如果没有发生故障的示例,则可能无法立即解决问题。因此,假设您具有这样的类型:

struct MyStruct;
impl MyStruct {
    const fn new() -> Self {
        MyStruct
    }
}

您试图实现以下特征:

impl Test for MyStruct {
    const CONST: Self = MyStruct::new();
}

这将不起作用,因为static_ref的实现现在看起来像这样:

fn static_ref() -> &'static Self {
    // &Self::CONST
    &MyStruct::new()
}

它正在函数内部创建一个值并尝试返回它。此值为不是静态的,因此'static的生存期无效。


但是,只需稍微跳一下,您就可以使某些事情生效:

pub trait Test: Sized + 'static {
    // This is now a reference instead of a value:
    const CONST: &'static Self;
    fn static_ref() -> &'static Self {
        Self::CONST
    }
}

struct MyStruct;
impl MyStruct {
    const fn new() -> Self {
        MyStruct
    }
}

impl Test for MyStruct {
    const CONST: &'static Self = &MyStruct::new();
}

之所以可行,是因为CONST已经是'static引用,因此该函数可以返回它。所有可能的实现都必须能够获得对'static的{​​{1}}引用才能实现特征,因此,不再需要引用某些局部值。