Summary

向标准库添加对延迟初始化值的支持,从而有效地取代了流行的 lazy_static crate。

use std::sync::Lazy;

// `BACKTRACE` implements `Deref<Target = Option<String>>` and is initialized
// on the first access
static BACKTRACE: Lazy<Option<String>> = Lazy::new(|| {
    std::env::var("RUST_BACKTRACE").ok()
});

Motivation

使用惰性初始化值无处不在,整个生态系统都使用lazy_static和 lazycell crate。尽管 lazy_static 的一些流行可以归因于当前 Rust 中持续评估的局限性,但在很多情况下,即使是完美的 const fn 也无法取代惰性值。同时,在 Rust 中使用惰性值并不容易:

  1. 实现它们需要适度棘手的不安全代码。在 crates.io 的实现中发现了多个健全性漏洞。
  2. C++ 和 Java 为静态值提供语言级延迟初始化,而 Rust 需要显式代码来处理运行时初始化。
  3. Rust 借用规则在实现惰性字段时需要一种特殊的模式。

lazy_static是使用宏实现的,以解决以前的语言限制。从那时起,各种语言改进使得在静态范围内创建运行时初始化(惰性)对象成为可能,无需宏即可实现相同的目标。

我们可以为一个常用的棘手的不安全概念提供一个规范的 API,所以我们可能应该拥有它!

  1. std::cell::OnceCell

    相当于Cell,只是相比于Cell来说,他只能初始化一次

  2. std::sync::OnceLock

    线程安全版本的OnceCell,用来代替once_cell crate的OnceCell,还有lazy_static等crate

此外这个RFC还提供了LazyCell、 LazyLock (用来代替lazy_static!),这两个目前还没稳定。

OnceCell的基本用法