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

Introduce a new type MoveCell<T> in std::cell #1659

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions text/0000-movecell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
- Feature Name: movecell
- Start Date: 2016-06-27
- RFC PR: (leave this empty)
- Rust Issue: (leave this empty)

# Summary
[summary]: #summary

Introduce a new type `MoveCell<T>` in `std::cell`.

# Motivation
[motivation]: #motivation

The type `Cell<T>` is only usable with `Copy` types to be able to safely
implement its `get` and `set` methods. To implement interior mutability
for non-`Copy` types, the type `RefCell<T>` must be used but it comes with
runtime overhead with its reference counting.

This new type `MoveCell<T>` aims to cover the use case where the user just needs
to store a non-`Copy` value elsewhere, through a single operation `replace`
which replaces the cell value and returns the older one.

# Detailed design
[design]: #detailed-design

The core of this new cell just consists of two methods:

```rust
pub struct MoveCell<T>(UnsafeCell<T>);

impl<T> MoveCell<T> {
pub fn new(value: T) -> Self {
MoveCell(UnsafeCell::new(value))
}

pub fn replace(&self, value: T) -> T {
mem::replace(unsafe { &mut *self.0.get() }, value)
}
}
```

We could in the future add various convenience functions,
based on real-world usage:

```rust
impl<T> MoveCell<T> {
/// A `set` method that just drops the value returned by `replace`.
pub fn set(&self, value: T) {
drop(self.replace(value));
}
}

impl<T: Default> MoveCell<T> {
/// A `take` method replacing by the `Default` value for `T`. This coincides
/// with `Option::take::<T>` for `Option<T>` cells.
pub fn take(&self) -> T {
self.replace(T::default())
}
}
```

# Drawbacks
[drawbacks]: #drawbacks

There are no drawbacks.

# Alternatives
[alternatives]: #alternatives

@Amanieu [proposed](https://github.com/rust-lang/rfcs/pull/1651) that the
`Cell<T>` type be extended instead.

# Unresolved questions
[unresolved]: #unresolved-questions

Should convenience methods be included from start? Or should they wait users
to first use that new cell type?