Skip to content

Commit 3cddc8b

Browse files
committed
More inference-friendly API for lazy
The signature for new was ``` fn new<F>(f: F) -> Lazy<T, F> ``` Notably, with `F` unconstrained, `T` can be literally anything, and just `let _ = Lazy::new(|| 92)` would not typecheck. This historiacally was a necessity -- `new` is a `const` function, it couldn't have any bounds. Today though, we can move `new` under the `F: FnOnce() -> T` bound, which gives the compiler enough data to infer the type of T from closure.
1 parent 33b55ac commit 3cddc8b

File tree

4 files changed

+14
-7
lines changed

4 files changed

+14
-7
lines changed

library/core/src/cell/lazy.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub struct LazyCell<T, F = fn() -> T> {
3131
init: Cell<Option<F>>,
3232
}
3333

34-
impl<T, F> LazyCell<T, F> {
34+
impl<T, F: FnOnce() -> T> LazyCell<T, F> {
3535
/// Creates a new lazy value with the given initializing function.
3636
///
3737
/// # Examples
@@ -51,9 +51,7 @@ impl<T, F> LazyCell<T, F> {
5151
pub const fn new(init: F) -> LazyCell<T, F> {
5252
LazyCell { cell: OnceCell::new(), init: Cell::new(Some(init)) }
5353
}
54-
}
5554

56-
impl<T, F: FnOnce() -> T> LazyCell<T, F> {
5755
/// Forces the evaluation of this lazy value and returns a reference to
5856
/// the result.
5957
///

library/core/tests/lazy.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,12 @@ fn lazy_new() {
106106
assert_eq!(called.get(), 1);
107107
}
108108

109+
// Check that we can infer `T` from closure's type.
110+
#[test]
111+
fn lazy_type_inference() {
112+
let _ = LazyCell::new(|| ());
113+
}
114+
109115
#[test]
110116
fn aliasing_in_get() {
111117
let x = OnceCell::new();

library/std/src/sync/lazy_lock.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,14 @@ pub struct LazyLock<T, F = fn() -> T> {
4444
cell: OnceLock<T>,
4545
init: Cell<Option<F>>,
4646
}
47-
48-
impl<T, F> LazyLock<T, F> {
47+
impl<T, F: FnOnce() -> T> LazyLock<T, F> {
4948
/// Creates a new lazy value with the given initializing
5049
/// function.
5150
#[unstable(feature = "once_cell", issue = "74465")]
5251
pub const fn new(f: F) -> LazyLock<T, F> {
5352
LazyLock { cell: OnceLock::new(), init: Cell::new(Some(f)) }
5453
}
55-
}
5654

57-
impl<T, F: FnOnce() -> T> LazyLock<T, F> {
5855
/// Forces the evaluation of this lazy value and
5956
/// returns a reference to result. This is equivalent
6057
/// to the `Deref` impl, but is explicit.

library/std/src/sync/lazy_lock/tests.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,12 @@ fn sync_lazy_poisoning() {
136136
}
137137
}
138138

139+
// Check that we can infer `T` from closure's type.
140+
#[test]
141+
fn lazy_type_inference() {
142+
let _ = LazyCell::new(|| ());
143+
}
144+
139145
#[test]
140146
fn is_sync_send() {
141147
fn assert_traits<T: Send + Sync>() {}

0 commit comments

Comments
 (0)