95. LazyLock::get — Peek at a Lazy Value Without Initializing It
Wanted to know whether a LazyLock has been initialized yet — without causing the initialization by touching it? Rust 1.94 stabilises LazyLock::get and LazyCell::get, which return Option<&T> and leave the closure untouched if it hasn’t fired.
The old pain
Any access that goes through Deref forces the closure to run. So the moment you do *CONFIG — or anything that implicitly derefs — the lazy becomes eager. Before 1.94 there was no way to ask “has this been initialized?” without tripping that wire.
| |
Handy enough, but if you want a metric like “was the config ever read?” you’d have to wrap the whole thing in your own AtomicBool.
The fix: LazyLock::get
Called as an associated function (LazyLock::get(&lock)), it returns Option<&T> without touching the closure. None means the lazy is still pending. Some(&value) means someone already forced it.
| |
Note the call style: LazyLock::get(&CONFIG), not CONFIG.get(). That’s deliberate — method-lookup on the lock itself would go through Deref, which is exactly the thing we’re trying to avoid.
Same story for LazyCell
LazyCell is the single-threaded cousin and gets the same treatment:
| |
Where this shines
Two patterns fall out naturally.
Metrics and diagnostics. You want to log “did we ever load the config?” at shutdown without accidentally loading it just to find out:
| |
Tests. Assert that the lazy init didn’t happen on a code path that shouldn’t need it — a guarantee that was basically impossible to write before.
When to reach for it
Use LazyLock::get / LazyCell::get whenever you need to ask about initialization state without causing it. For everything else, just deref as usual — that’s still the one-liner that Just Works.
Stabilised in Rust 1.94 (March 2026).