Stabilize LazyCell and LazyLock - #121377
Conversation
730d4df to
bf11b8b
Compare
Removes the once_cell dependency, instead using std::sync::OnceLock and a minimal polyfill for std::sync::LazyLock, which may be stabilized soon (see rust-lang/rust#121377). This should not require a bump in MSRV, as OnceLock was stabilized in 1.70, which this crate is using.
It is not fully clear to me which issues this sidesteps. Can you add some clarifications of what is and isn't allowed after this PR, and what a possible upgrade path looks like to a future where LazyCell/LazyLock don't unnecessarily store a function pointer in memory? |
Unresolved Questions
Summary: With the unstable default type parameter, specifying the second type parameter is an error. The only way to get a // LazyLock<String, {closure}>
let foo = LazyLock::new(|| "foo".to_string());
// LazyLock<String, fn() -> String>
let bar: LazyLock<String> = LazyLock::new(|| "bar".to_string());
// LazyLock<String, fn() -> String>
static STAT: LazyLock<String> = LazyLock::new(|| "stat".to_string());Some future possibilities that would allow avoiding the function pointer: // Just "opaque type inference in statics"
pub static LazyLock<T, F = fn() -> T> { ... }
// lint the missing type parameter
static FOO: LazyLock<String> = ...;
// recommend setting it to infer the closure type
static FOO: LazyLock<String, _> = ...;
// "Opaque type inference in statics" and "type parameter default infer"
pub struct LazyLock<T, F = _> { ... }
static FOO: LazyLock<String> = ...;
// "`impl Trait` in statics" and "type parameter default `impl Trait`"
pub struct LazyLock<T, F = impl FnOnce() -> T> { ... }
static FOO: LazyLock<String> = ...;
Summary: Because the unstable type parameter can't be specified explicitly, it's impossible to set it to a type which can cause those variance issues. The only remotely possible way would be type inference in a local variable, but I can't think of a way that could cause issues, if it's possible at all. There are only two possible futures here:
@rustbot ready |
|
cc @danielhenrymantilla who did a lot of the variance work for |
|
@m-ou-se is the response in #121377 (comment) sufficient to get this nominated again? |
This comment has been minimized.
This comment has been minimized.
a0c614d to
dc75ed4
Compare
|
We discussed this in a libs-api meeting and decided for a full stabilization of these types as they are right now, including stabilizing the The reason for also stabilizing Regarding the variance of |
|
Great news! I will soon modify this PR to fully stabilize, rather than leaving |
dc75ed4 to
b4a6715
Compare
|
|
|
@danielhenrymantilla yeah that's what I would think, similar to how |
|
I filed an issue for that: #125615 |
|
Actually people have already discussed replacing |
|
I tried this code: use std::sync::LazyLock;
use std::collections::HashMap;
static HASHMAP: LazyLock<HashMap<i32, String>> = LazyLock::new(|| {
println!("initializing");
let mut m = HashMap::new();
m.insert(13, "Spica".to_string());
m.insert(74, "Hoyten".to_string());
m
});
fn main() {
println!("{:?}", &HASHMAP);
HASHMAP.get(&74);
println!("{:?}", &HASHMAP);
}And got this output: Is this the expected behaviour? Is it illegal to attempt to print a |
|
@DoubleHyphen these Lazy types have explicit |
|
@DoubleHyphen what makes you think that anything illegal happened? |
Terse version: I was expecting printing the Verbose version: As I saw this thread, I was immediately reminded of Graydon Hoare's famous article, things rust shipped without. One of those things was
which at first glance seemed at odds with this here feature. But then I thought “Wait. The clue is in the name. Those variables ought to be initialised before their first use, not before Now when it comes to lazy iterators, their uninitialised state is not observable; as soon as one tries to do anything with them, they are immediately initialised. I had expected the same to be true of Maybe clear documentation will fix this issue, or at least assuage it. But for now, in its absence, there is no clear way to use a I'm not convinced that |
I am confused by the question, since your example already does that: you just deref it. Your own code does that when calling I don't quite understand the problem here. Anyway a merged PR is a bad place for discussion, please open an issue describing the expected and actual behavior, or otherwise clarifying what you are missing in the current API surface. |
|
It's too bad we have to go through a function pointer and not directly through the ZST, is there no way to somehow make inference or EDIT: This was already discussed above |
Closes #109736
This stabilizes the
LazyLockandLazyCelltypes:r? libs-api