简体   繁体   English

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

[英]Why does taking a static reference to a const return a reference to a temporary variable?

In Rust I have the following code:在 Rust 中,我有以下代码:

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

My expectation is that since const is 'static , then I should be able to take a reference to it that is also 'static .我的期望是,由于const'static ,那么我应该能够引用它也是'static However, the compiler gives the following error:但是,编译器给出以下错误:

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

How is a temporary variable being introduced here?这里如何引入临时变量?

Additionally, it seems that there are some cases where taking a reference to a constant does work.此外,似乎在某些情况下引用常量确实有效。 Here is a short concrete example with a slightly different implementation of Test这是一个简短的具体示例,其中 Test 的实现略有不同

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

struct X;

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

A constant in Rust is a compile-time constant, not an actual variable with a memory location. Rust中的常量是编译时常量,而不是具有内存位置的实际变量。 The Rust compiler can substitute the actual value of the constant whereever it is used. Rust编译器可以替换使用它的常量的实际 If you take the address of such a value, you get the address of a temporary. 如果您获取此类值的地址,则会获得临时地址。

Rust also has the concept of a static variable . Rust还具有静态变量的概念。 These variables actually have memory locations that are consistent for the whole program duration, and taking a reference to a static variable indeed results in a reference with 'static lifetime. 这些变量实际上具有与整个程序持续时间一致的存储器位置,并且对静态变量的引用确实导致具有'static寿命'static的引用。

See also: 也可以看看:

When you define a trait, the definition must make sense for all possible implementations. 定义特征时,定义必须适用于所有可能的实现。

The problem may not be immediately clear without an example of where it fails. 如果没有失败的例子,问题可能不会立即得到解决。 So suppose you had a type like this: 所以假设你有这样的类型:

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

And you attempted to implement the trait like this: 你试图像这样实现这个特征:

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

This won't work because the implementation of static_ref will now look like this: 这不起作用,因为static_ref的实现现在看起来像这样:

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

It's creating a value inside the function and trying to return it. 它在函数内部创建一个值并尝试返回它。 This value is not static, so the 'static lifetime is invalid. 该值不是静态的,因此'static生命周期无效。


However, with a little re-jigging, you can make something work: 然而,通过一些重新跳汰,你可以做一些工作:

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();
}

This works because CONST is already a 'static reference, so the function can just return it. 这是有效的,因为CONST已经是一个'static引用,所以函数可以返回它。 All possible implementations would have to be able to obtain a 'static reference to Self to implement the trait, so there is no longer an issue with referencing some arbitrary local value. 所有可能的实现都必须能够获得对Self 'static引用以实现特征,因此引用某些任意本地值不再存在问题。

The mechanism at work here is static promotion.这里的工作机制是静态提升。 See RFC 1414RFC 1414

Here's a quote:这是一个报价:

Inside a function body's block:在函数体的块内:

  • If a shared reference to a constexpr rvalue is taken.如果采用对 constexpr 右值的共享引用。 (&) (&)
  • And the constexpr does not contain a UnsafeCell { ... } constructor.而且 constexpr 不包含 UnsafeCell { ... } 构造函数。
  • And the constexpr does not contain a const fn call returning a type containing a UnsafeCell.并且 constexpr 不包含返回包含 UnsafeCell 的类型的 const fn 调用。
  • Then instead of translating the value into a stack slot, translate it into a static memory location and give the resulting reference a 'static lifetime.然后,不是将值转换为堆栈槽,而是将其转换为静态内存位置,并为结果引用提供“静态生命周期”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM