-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Tracking Issue for lazy_cell
#109736
Comments
The biggest design question here is the default parameter:
let env = "hello".to_string();
let ok1 = Lazy::new(|| env);
let ok2: Lazy<String, _> = Lazy::new(|| env);
let err: Lazy<String> = Lazy::new(|| env);
// ^ The confusing case. The problem here is that type of `F` isn't inferred,
/// but is taken from the default
|
It is kind of weird to have the Is there a workaround using with raw function pointers maybe? Since the signature is always known, but I'm not sure how things like closure coercions & lifetimes would work here. Or maybe dynamics could work. I haven't thought it totally through (and there might be lifetime trickiness) but at least the std |
Boxing the contents would make it unusable for static values which would render it useless for most use cases. |
Yeah, that is a good point. And Just spitballing here... taking a pub struct TestLazyLock<T> {
cell: OnceLock<T>,
init: Cell<Option<fn() -> T>>,
}
impl<T> TestLazyLock<T> {
const fn new(init: fn() -> T) -> Self {
Self { cell: OnceLock::new(), init: Cell::new(Some(init)) }
}
} |
I don't see how that would be preferable over just having the second type parameter with the |
Yeah, it's not preferable. Just trying to see if there's any way where we could either
To quote @m-ou-se in #74465 (comment)
I think that the form I suggested above with |
I am not super in the know for this, but I don't think there's any particular reason the state couldn't be exposed somehow. The state is known by the OnceCell, and would have to be tracked somehow even with a different underlying implementation. |
I somewhat doubt it would ever be necessary to make such a change (the only edge case is rather contrived), but even then the way to drop the second parameter in a backward-compatible way would be to introduce a new API, deprecate this one, and upgrade everyone with |
If "impl trait" is allowed in let/static/const #63065 then the additional parameter is not an issue anymore. If the Lazy is initialized with a closure, then using "impl trait" in static would actually reduce size of the global variable by one function pointer. |
@NobodyXu I'm not too familar with that feature... would it also allow these type LazyInitFn<T> = impl FnOnce() -> T + Send + ?Sized;
pub struct LazyLock<T> {
cell: OnceLock<T>,
init: Cell<Option<LazyInitFn<T>>>,
}
impl<T> LazyLock<T> {
const fn new(init: LazyInitFn<T>) -> Self { /* ... */ }
} But I haven't seen any examples in the RFC that do this |
Oh you are right, I missed that. According to my understanding, it enables something like this: static F: impl FnOnce() -> u32 = || 1; I was thinking about: static F: Lazy<impl FnOnce() -> u32> = Lazy::new(|| 1); Which might not be covered by the tracking issue I linked. |
Added matklad/once_cell#167 as an unresolved quesrion |
Is there a reason |
I presume to avoid shadowing a |
Makes sense. It does sort of remind me of the discussion on |
Unlike |
Bjorn meant that if whatever the LazyCell derefs to (T) has a I just linked |
This works on nightly, if TAIT is enabled: type F = impl FnOnce() -> ();
static L: LazyLock<(), F> = LazyLock::new(|| ()); |
once_cell supersets lazy_static features and its API is better and "soon" to be stabilized in the standard library: rust-lang/rust#109736
once_cell supersets lazy_static features and its API is better and "soon" to be stabilized in the standard library: rust-lang/rust#109736
The |
No, I don't think that's right - look at it more like a // concretely,
let captured = 10u8;
let cell = LazyCell::new(|| &captured);
fn init_it<'a>(v: &'a (), cell: &'a LazyCell<&'a u8, impl FnOnce() -> &'a u8>) {
&**cell; // call the function and store a `&'a u8` as the value
}
init_it(&(), &cell); // 'a is dead
let v: &u8 = &*a; // and when we access it, we've read it in 'b where not `'a: 'b` In terms of your example, the (edit: oh and I should add that this doesn't create any problems w.r.t. Treed borrows itself afaik - the tagging is all still correct, but breaking the subtyping relationship on the lifetimes does create problems in the verification of borrowck as far as I understand it. someone might know better than me there 😁) edit2: after discussing this on discord we realized that type erasing the function pointer on construction does the trick for "something clever with decoupling the return type of fn init_it<F: FnOnce() -> T>(f: *mut F, out: *mut T) {
*out = (*f)()
}
fn LazyCell::new(f: impl FnOnce() -> T) {
Uninit(f, init_it::<F> as fn(*mut (), *mut ()))
}
fn LazyCell::force() -> &T {
(self.init_fn)(&mut self.f as *mut _ as *mut _, self.cell.as_mut_ptr() as *mut _ as *mut _)
&self.cell
} |
Using lazy_static is now discouraged as unmaintained and once_cell is the recommended replacement. On top of that a similar implementation found in once_cell is being tracked for inclusion under the `lazy_cell` feature gate [0] [0] rust-lang/rust#109736 Change-Id: I21d343a38dbd25bb2d13f239f7fa3a2d7f20323e
For anyone following, this is your notice that #121377 (which will fully stabilize |
@joboet it was mentioned at #121377 (comment) that making the types covariant over |
Open question: - Do we want to wait for LazyLock? rust-lang/rust#109736
I don't understand why making it covariant over |
Open question: - Do we want to wait for LazyLock? rust-lang/rust#109736
Rollup merge of rust-lang#121377 - pitaj:lazy_cell_fn_pointer, r=dtolnay Stabilize `LazyCell` and `LazyLock` Closes rust-lang#109736 This stabilizes the [`LazyLock`](https://doc.rust-lang.org/stable/std/sync/struct.LazyLock.html) and [`LazyCell`](https://doc.rust-lang.org/stable/std/cell/struct.LazyCell.html) types: ```rust 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 }); let lazy: LazyCell<i32> = LazyCell::new(|| { println!("initializing"); 92 }); ``` r? libs-api
We need a |
Using lazy_static is now discouraged as unmaintained and once_cell is the recommended replacement. On top of that a similar implementation found in once_cell is being tracked for inclusion under the `lazy_cell` feature gate [0] [0] rust-lang/rust#109736 Test: m Change-Id: I21d343a38dbd25bb2d13f239f7fa3a2d7f20323e Former-commit-id: 794a952642317f7da1be2ea69e6865c55ea37be6
Using lazy_static is now discouraged as unmaintained and once_cell is the recommended replacement. On top of that a similar implementation found in once_cell is being tracked for inclusion under the `lazy_cell` feature gate [0] [0] rust-lang/rust#109736 Test: m Change-Id: I21d343a38dbd25bb2d13f239f7fa3a2d7f20323e
This is to bypass: error[E0658]: use of unstable library feature 'lazy_cell' --> crates/omnix-init/src/config.rs:1:48 | 1 | use std::{collections::HashMap, path::PathBuf, sync::LazyLock}; | ^^^^^^^^^^^^^^ | = note: see issue #109736 <rust-lang/rust#109736> for more information = help: add `#![feature(lazy_cell)]` to the crate attributes to enable = note: this compiler was built on 2024-05-11; consider upgrading it if it is out of date
…s possible Since 1.80: rust-lang/rust#109736 and rust-lang/rust#98165 Non-Thread-Safe Lazy → std::cell::LazyCell https://doc.rust-lang.org/nightly/std/cell/struct.LazyCell.html Thread-safe SyncLazy → std::sync::LazyLock https://doc.rust-lang.org/nightly/std/sync/struct.LazyLock.html The compiler accepted LazyCell only in minilints. The final use in rslib/src/log.rs couldn't be replaced since get_or_try_init has not yet been standardized: rust-lang/rust#109737
…s possible Since 1.80: rust-lang/rust#109736 and rust-lang/rust#98165 Non-Thread-Safe Lazy → std::cell::LazyCell https://doc.rust-lang.org/nightly/std/cell/struct.LazyCell.html Thread-safe SyncLazy → std::sync::LazyLock https://doc.rust-lang.org/nightly/std/sync/struct.LazyLock.html The compiler accepted LazyCell only in minilints. The final use in rslib/src/log.rs couldn't be replaced since get_or_try_init has not yet been standardized: rust-lang/rust#109737
… possible Since 1.80: rust-lang/rust#109736 and rust-lang/rust#98165 Non-Thread-Safe Lazy → std::cell::LazyCell https://doc.rust-lang.org/nightly/std/cell/struct.LazyCell.html Thread-safe SyncLazy → std::sync::LazyLock https://doc.rust-lang.org/nightly/std/sync/struct.LazyLock.html The compiler accepted LazyCell only in minilints. The final use in rslib/src/log.rs couldn't be replaced since get_or_try_init has not yet been standardized: rust-lang/rust#109737
… possible Since 1.80: rust-lang/rust#109736 and rust-lang/rust#98165 Non-Thread-Safe Lazy → std::cell::LazyCell https://doc.rust-lang.org/nightly/std/cell/struct.LazyCell.html Thread-safe SyncLazy → std::sync::LazyLock https://doc.rust-lang.org/nightly/std/sync/struct.LazyLock.html The compiler accepted LazyCell only in minilints. The final use in rslib/src/log.rs couldn't be replaced since get_or_try_init has not yet been standardized: rust-lang/rust#109737
* Anki: Replace lazy_static with once_cell Unify to once_cell, lazy_static's replacement. The latter in unmaintained. * Anki: Replace once_cell with stabilized LazyCell / LazyLock as far as possible Since 1.80: rust-lang/rust#109736 and rust-lang/rust#98165 Non-Thread-Safe Lazy → std::cell::LazyCell https://doc.rust-lang.org/nightly/std/cell/struct.LazyCell.html Thread-safe SyncLazy → std::sync::LazyLock https://doc.rust-lang.org/nightly/std/sync/struct.LazyLock.html The compiler accepted LazyCell only in minilints. The final use in rslib/src/log.rs couldn't be replaced since get_or_try_init has not yet been standardized: rust-lang/rust#109737 * Declare correct MSRV (dae) Some of our deps require newer Rust versions, so this was misleading. Updating the MSRV also allows us to use .inspect() on Option now
Note:
lazy_cell_consume
is now tracked at #125623This supercedes #74465 after a portion of
once_cell
was stabilized with #105587Feature gate:
#![feature(lazy_cell)]
This is a tracking issue for the
LazyCell
andLazyLock
types, which are designed to support convenient one-time initialization. One of the main goals is to be able to replace thelazy_static
crate, as well asonce_cell::{sync, unsync}::Lazy
.Public API
Steps / History
LazyCell
andLazyLock
#121377Unresolved Questions
Lazy<T, F>
covariant inF
matklad/once_cell#167)F = fn() -> T
in type signature (See Tracking Issue forlazy_cell
#109736 (comment))Footnotes
https://std-dev-guide.rust-lang.org/feature-lifecycle/stabilization.html ↩
The text was updated successfully, but these errors were encountered: