Skip to content

Commit 91cc872

Browse files
authored
Rollup merge of rust-lang#49727 - stjepang:cell-update, r=SimonSapin
Add Cell::update This commit adds a new method `Cell::update`, which applies a function to the value inside the cell. Previously discussed in: rust-lang/rfcs#2171 ### Motivation Updating `Cell`s is currently a bit verbose. Here are several real examples (taken from rustc and crossbeam): ```rust self.print_fuel.set(self.print_fuel.get() + 1); self.diverges.set(self.diverges.get() | Diverges::Always); let guard_count = self.guard_count.get(); self.guard_count.set(guard_count.checked_add(1).unwrap()); if guard_count == 0 { // ... } ``` With the addition of the new method `Cell::update`, this code can be simplified to: ```rust self.print_fuel.update(|x| x + 1); self.diverges.update(|x| x | Diverges::Always); if self.guard_count.update(|x| x.checked_add(1).unwrap()) == 1 { // ... } ``` ### Unresolved questions 1. Should we return the old value instead of the new value (like in `fetch_add` and `fetch_update`)? 2. Should the return type simply be `()`? 3. Naming: `update` vs `modify` vs `mutate` etc. cc @SimonSapin
2 parents cefdd6d + 29e9de8 commit 91cc872

File tree

3 files changed

+39
-0
lines changed

3 files changed

+39
-0
lines changed

src/libcore/cell.rs

+27
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,33 @@ impl<T:Copy> Cell<T> {
256256
pub fn get(&self) -> T {
257257
unsafe{ *self.value.get() }
258258
}
259+
260+
/// Updates the contained value using a function and returns the new value.
261+
///
262+
/// # Examples
263+
///
264+
/// ```
265+
/// #![feature(cell_update)]
266+
///
267+
/// use std::cell::Cell;
268+
///
269+
/// let c = Cell::new(5);
270+
/// let new = c.update(|x| x + 1);
271+
///
272+
/// assert_eq!(new, 6);
273+
/// assert_eq!(c.get(), 6);
274+
/// ```
275+
#[inline]
276+
#[unstable(feature = "cell_update", issue = "50186")]
277+
pub fn update<F>(&self, f: F) -> T
278+
where
279+
F: FnOnce(T) -> T,
280+
{
281+
let old = self.get();
282+
let new = f(old);
283+
self.set(new);
284+
new
285+
}
259286
}
260287

261288
#[stable(feature = "rust1", since = "1.0.0")]

src/libcore/tests/cell.rs

+11
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,17 @@ fn smoketest_cell() {
2626
assert!(y.get() == (30, 40));
2727
}
2828

29+
#[test]
30+
fn cell_update() {
31+
let x = Cell::new(10);
32+
33+
assert_eq!(x.update(|x| x + 5), 15);
34+
assert_eq!(x.get(), 15);
35+
36+
assert_eq!(x.update(|x| x / 3), 5);
37+
assert_eq!(x.get(), 5);
38+
}
39+
2940
#[test]
3041
fn cell_has_sensible_show() {
3142
let x = Cell::new("foo bar");

src/libcore/tests/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
#![feature(ascii_ctype)]
1212
#![feature(box_syntax)]
13+
#![feature(cell_update)]
1314
#![feature(core_float)]
1415
#![feature(core_private_bignum)]
1516
#![feature(core_private_diy_float)]

0 commit comments

Comments
 (0)