Skip to content
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

Lazy mutable API extension #193

Merged
merged 23 commits into from Sep 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
14cd81e
Implemented try_insert_mut
danielSanchezQ Sep 1, 2022
7a19949
Implemented get_mut_or_init and get_mut_or_try_init
danielSanchezQ Sep 1, 2022
d353abd
Implemented mut api for sync::OnceCell
danielSanchezQ Sep 1, 2022
a7db7ad
Add OnceCell extension mut API tests to it.rs
danielSanchezQ Sep 1, 2022
ef1d848
Add changelog notes
danielSanchezQ Sep 1, 2022
fcdf154
Implement force_mut and get_mut for unsync::Lazy
danielSanchezQ Sep 1, 2022
5c75c22
Added force_mut and get_mut tests to it.rs
danielSanchezQ Sep 1, 2022
e4f38c1
Added sync::Lazy version of `force_mut` and `get_mut`
danielSanchezQ Sep 1, 2022
2b0da3e
Added changelog notes
danielSanchezQ Sep 1, 2022
eef42a7
Modify cargo version
danielSanchezQ Sep 1, 2022
59ea68e
Added try_insert_mut for sync::OnceCell
danielSanchezQ Sep 1, 2022
61346b3
Use &mut for get_mut_unchecked
danielSanchezQ Sep 1, 2022
f8d5f76
Implemented get_mut_unchecked to imp_std
danielSanchezQ Sep 1, 2022
e68da06
Fix tests
danielSanchezQ Sep 1, 2022
2ff6d0e
Fix get_mut_unchecked, used get instead of get_mut
danielSanchezQ Sep 1, 2022
8b19199
Remove get_mut_unchecked
danielSanchezQ Sep 2, 2022
180305a
Remove oncecell mut extensions
danielSanchezQ Sep 2, 2022
8f6ca60
Remove oncecell mut extensions tests
danielSanchezQ Sep 2, 2022
a9fb2d3
Remove changelog oncecell notes
danielSanchezQ Sep 2, 2022
d3e28a5
Formatting tests missing line
danielSanchezQ Sep 2, 2022
cca53a4
Use force_mut return mut ref in test
danielSanchezQ Sep 2, 2022
02f8b9f
Fix unnecesary mut
danielSanchezQ Sep 2, 2022
ceff838
Update CHANGELOG.md
matklad Sep 2, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Expand Up @@ -4,6 +4,13 @@

-

## 1.14.0

- Add extension to `unsync` and `sync` `Lazy` mut API:
- `force_mut`
- `get_mut`


## 1.13.1

- Make implementation compliant with [strict provenance](https://github.com/rust-lang/rust/issues/95228).
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "once_cell"
version = "1.13.1"
version = "1.14.0"
authors = ["Aleksey Kladov <aleksey.kladov@gmail.com>"]
license = "MIT OR Apache-2.0"
edition = "2018"
Expand Down
70 changes: 70 additions & 0 deletions src/lib.rs
Expand Up @@ -742,6 +742,25 @@ pub mod unsync {
})
}

/// Forces the evaluation of this lazy value and returns a mutable reference to
/// the result.
///
/// This is equivalent to the `DerefMut` impl, but is explicit.
///
/// # Example
/// ```
/// use once_cell::unsync::Lazy;
///
/// let mut lazy = Lazy::new(|| 92);
///
/// assert_eq!(Lazy::force_mut(&mut lazy), &92);
/// assert_eq!(*lazy, 92);
/// ```
pub fn force_mut(this: &mut Lazy<T, F>) -> &mut T {
Self::force(this);
Self::get_mut(this).unwrap_or_else(|| unreachable!())
}

/// Gets the reference to the result of this lazy value if
/// it was initialized, otherwise returns `None`.
///
Expand All @@ -758,6 +777,23 @@ pub mod unsync {
pub fn get(this: &Lazy<T, F>) -> Option<&T> {
this.cell.get()
}

/// Gets the mutable reference to the result of this lazy value if
/// it was initialized, otherwise returns `None`.
///
/// # Example
/// ```
/// use once_cell::unsync::Lazy;
///
/// let mut lazy = Lazy::new(|| 92);
///
/// assert_eq!(Lazy::get_mut(&mut lazy), None);
/// assert_eq!(*lazy, 92);
/// assert_eq!(Lazy::get_mut(&mut lazy), Some(&mut 92));
/// ```
pub fn get_mut(this: &mut Lazy<T, F>) -> Option<&mut T> {
this.cell.get_mut()
}
}

impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
Expand Down Expand Up @@ -1232,6 +1268,23 @@ pub mod sync {
})
}

/// Forces the evaluation of this lazy value and
/// returns a mutable reference to the result. This is equivalent
/// to the `Deref` impl, but is explicit.
///
/// # Example
/// ```
/// use once_cell::sync::Lazy;
///
/// let mut lazy = Lazy::new(|| 92);
///
/// assert_eq!(Lazy::force_mut(&mut lazy), &mut 92);
/// ```
pub fn force_mut(this: &mut Lazy<T, F>) -> &mut T {
Self::force(this);
Self::get_mut(this).unwrap_or_else(|| unreachable!())
}

/// Gets the reference to the result of this lazy value if
/// it was initialized, otherwise returns `None`.
///
Expand All @@ -1248,6 +1301,23 @@ pub mod sync {
pub fn get(this: &Lazy<T, F>) -> Option<&T> {
this.cell.get()
}

/// Gets the reference to the result of this lazy value if
/// it was initialized, otherwise returns `None`.
///
/// # Example
/// ```
/// use once_cell::sync::Lazy;
///
/// let mut lazy = Lazy::new(|| 92);
///
/// assert_eq!(Lazy::get_mut(&mut lazy), None);
/// assert_eq!(&*lazy, &92);
/// assert_eq!(Lazy::get_mut(&mut lazy), Some(&mut 92));
/// ```
pub fn get_mut(this: &mut Lazy<T, F>) -> Option<&mut T> {
this.cell.get_mut()
}
}

impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
Expand Down
35 changes: 35 additions & 0 deletions tests/it.rs
Expand Up @@ -137,6 +137,41 @@ mod unsync {
assert_eq!(called.get(), 1);
}

#[test]
fn lazy_force_mut() {
let called = Cell::new(0);
let mut x = Lazy::new(|| {
called.set(called.get() + 1);
92
});
assert_eq!(called.get(), 0);
let v = Lazy::force_mut(&mut x);
assert_eq!(called.get(), 1);

*v /= 2;
assert_eq!(*x, 46);
assert_eq!(called.get(), 1);
}

#[test]
fn lazy_get_mut() {
let called = Cell::new(0);
let mut x: Lazy<u32, _> = Lazy::new(|| {
called.set(called.get() + 1);
92
});

assert_eq!(called.get(), 0);
assert_eq!(*x, 92);

let mut_ref: &mut u32 = Lazy::get_mut(&mut x).unwrap();
assert_eq!(called.get(), 1);

*mut_ref /= 2;
assert_eq!(*x, 46);
assert_eq!(called.get(), 1);
}

#[test]
fn lazy_default() {
static CALLED: AtomicUsize = AtomicUsize::new(0);
Expand Down