-
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
Implement rfc 1789: Conversions from &mut T
to &Cell<T>
#50494
Conversation
(rust_highfive has picked a reviewer for you, use r? to override) |
This comment has been minimized.
This comment has been minimized.
src/libcore/cell.rs
Outdated
@@ -235,7 +236,7 @@ use ptr; | |||
/// | |||
/// See the [module-level documentation](index.html) for more. | |||
#[stable(feature = "rust1", since = "1.0.0")] | |||
pub struct Cell<T> { | |||
pub struct Cell<T: ?Sized> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this be #[repr(transparent)]
, or at least #[repr(C)]
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should definitely be repr(transparent)
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks. Fixed.
Ping from triage @joshtriplett! This PR needs your review. |
This looks plausible to me, but I'd feel more comfortable if a second reviewer looked at it. |
src/libcore/cell.rs
Outdated
@@ -235,7 +236,8 @@ use ptr; | |||
/// | |||
/// See the [module-level documentation](index.html) for more. | |||
#[stable(feature = "rust1", since = "1.0.0")] | |||
pub struct Cell<T> { | |||
#[repr(transparent)] | |||
pub struct Cell<T: ?Sized> { | |||
value: UnsafeCell<T>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@eddyb is UnsafeCell
itself already effectively repr(transparent)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be explicitly marked as such.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that #[repr(transparent)]
means the same thing as #[repr(C)]
except it also guarantees you can pass it by value and get the same call ABI as its only non-ZST field. If we don't want to make the call ABI transparency guarantee, we should use only #[repr(C)]
. Although, transparency would be nice. So maybe we should have a proper decision on it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, in terms of implementation details, within the libcore/libstd you can "just" assume that anything newtype-shaped already has the memory layout and call ABI of the inner type. So this PR by itself needs no annotations, and adding annotations should be considered as sort of insta-stable "guarantees".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It should be explicitly marked as such.
Should that be a separate PR or happen here?
Just trying to make sure it doesn't get forgotten.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc @rust-lang/lang @rust-lang/libs Whose responsibility is it, for the addition of insta-stable #[repr]
attributes like these ones?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For what it’s worth we’re about to stabilize the attribute itself: #43036
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The attribute is stable. #51395 adds #[repr(transparent)]
to UnsafeCell
and Cell
. (It’s waiting on checkboxes from team members.)
☔ The latest upstream changes (presumably #50629) made this pull request unmergeable. Please resolve the merge conflicts. |
@F001 You need to rebase to get rid of the merge commit. |
cc @rust-lang/libs . Is there anyone else can help to do the review? Thanks! |
cc @rust-lang/libs |
src/libcore/cell.rs
Outdated
@@ -521,6 +567,20 @@ impl<T: Default> Cell<T> { | |||
#[unstable(feature = "coerce_unsized", issue = "27732")] | |||
impl<T: CoerceUnsized<U>, U> CoerceUnsized<Cell<U>> for Cell<T> {} | |||
|
|||
#[unstable(feature = "as_cell", issue="43038")] | |||
impl<T, I> Index<I> for Cell<[T]> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Trait implementations are insta-stable, so this needs a review (and I think an FCP?) from @rust-lang/libs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or perhaps it's effectively unstable because it's not possible to construct a Cell<[T]>
safely without this change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure it is, make a &Cell<[T; N]>
and unsize it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@rfcbot fcp merge
Due to the new trait impl let's FCP for merge
src/libcore/cell.rs
Outdated
/// ``` | ||
#[inline] | ||
#[unstable(feature = "as_cell", issue="43038")] | ||
pub fn get_with<U, F>(&self, f: F) -> U |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Was this in the RFC? As-is I think this isn't sound unfortunately :(
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As I mentioned in the description of this pull request (at the top of the thread), I am not quite confident on this method. Could you please help to point out how to fix it, or remove it completely?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately as-is this can't be safely written, but I think you can coerce &Cell<[i32]>
to &[Cell<i32>]
to get the length, right?
src/libcore/cell.rs
Outdated
#[unstable(feature = "as_cell", issue="43038")] | ||
pub fn get_with<U, F>(&self, f: F) -> U | ||
where | ||
F: Fn(&T) -> U, U: 'static |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
-
FnOnce
should be used in a situation like this. -
U: 'static
doesn't do anything useful here,U
can't hold the reference toT
anyway in Rust, becauseF
gets no guarantee as to how long that anonymous lifetime is. -
I'll make a separate comment on the PR about the unsoundness so it doesn't get lost
To expand on what @alexcrichton said, let cell = Cell::new(Some(String::from("foo")));
cell.get_with(|s| {
let s = s.as_ref().unwrap();
cell.set(None);
let s2 = String::from("bar");
println!("{}", s); // crash or print "bar" or garbage
println!("{}", s2); // keep `s2` alive
}); If there was, you could even make it give out Sadly, we're not ready to support anything like this yet (cc @nikomatsakis @RalfJung). |
This comment has been minimized.
This comment has been minimized.
src/libcore/cell.rs
Outdated
/// ``` | ||
#[inline] | ||
#[unstable(feature = "as_cell", issue="43038")] | ||
pub fn from_mut<'a>(t: &'a mut T) -> &'a Cell<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
get_mut
relies on lifetime elision while this doesn't - they should be more uniform IMO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
src/libcore/cell.rs
Outdated
impl<T, I> Index<I> for Cell<[T]> | ||
where | ||
I: SliceIndex<[Cell<T>]> | ||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, something potentially of note: it should be possible to implement Deref<Target=[Cell<T>]>
on Cell<[T]>
(instead of Index
), to allow e.g. calling .len()
directly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! IMHO it is a great improvement. I think it is sound AFAIK.
This comment has been minimized.
This comment has been minimized.
I have no idea why linkchecker failed. It seems irrelevant to my last commit. |
src/libcore/cell.rs
Outdated
/// let cell_slice: &Cell<[i32]> = Cell::from_mut(slice); | ||
/// assert_eq!(cell_slice.len(), 3); | ||
/// let slice_cell : &[Cell<i32>] = &cell_slice[..]; | ||
/// assert_eq!(slice_cell.len(), 3); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please leave some empty lines in this example just like the get_mut
example does.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
src/libcore/cell.rs
Outdated
/// let slice: &mut [i32] = &mut [1,2,3]; | ||
/// let cell_slice: &Cell<[i32]> = Cell::from_mut(slice); | ||
/// assert_eq!(cell_slice.len(), 3); | ||
/// let slice_cell : &[Cell<i32>] = &cell_slice[..]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: extraneous space before :
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
src/libcore/cell.rs
Outdated
/// ``` | ||
/// #![feature(as_cell)] | ||
/// use std::cell::Cell; | ||
/// let slice: &mut [i32] = &mut [1,2,3]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: missing spaces after ,
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed.
This comment has been minimized.
This comment has been minimized.
If it's an unstable-only method, I'd suggest |
This comment has been minimized.
This comment has been minimized.
@alexcrichton I have replaced the "Deref" by "Index". Could you please help to do the review? |
@F001 I believe the objection was not about a trait v.s. another trait but having a trait impl that becomes stable as soon as this PR lands, rather an inherent method that is |
This comment has been minimized.
This comment has been minimized.
📌 Commit 489101c has been approved by |
Implement rfc 1789: Conversions from `&mut T` to `&Cell<T>` I'm surprised that RFC 1789 has not been implemented for several months. Tracking issue: #43038 Please note: when I was writing tests for `&Cell<[i32]>`, I found it is not easy to get the length of the contained slice. So I designed a `get_with` method which might be useful for similar cases. This method is not designed in the RFC, and it certainly needs to be reviewed by core team. I think it has some connections with `Cell::update` #50186 , which is also in design phase.
☀️ Test successful - status-appveyor, status-travis |
Version 1.29.0 (2018-09-13) ========================== Compiler -------- - [Bumped minimum LLVM version to 5.0.][51899] - [Added `powerpc64le-unknown-linux-musl` target.][51619] - [Added `aarch64-unknown-hermit` and `x86_64-unknown-hermit` targets.][52861] Libraries --------- - [`Once::call_once` now no longer requires `Once` to be `'static`.][52239] - [`BuildHasherDefault` now implements `PartialEq` and `Eq`.][52402] - [`Box<CStr>`, `Box<OsStr>`, and `Box<Path>` now implement `Clone`.][51912] - [Implemented `PartialEq<&str>` for `OsString` and `PartialEq<OsString>` for `&str`.][51178] - [`Cell<T>` now allows `T` to be unsized.][50494] - [`SocketAddr` is now stable on Redox.][52656] Stabilized APIs --------------- - [`Arc::downcast`] - [`Iterator::flatten`] - [`Rc::downcast`] Cargo ----- - [Cargo can silently fix some bad lockfiles ][cargo/5831] You can use `--locked` to disable this behaviour. - [`cargo-install` will now allow you to cross compile an install using `--target`][cargo/5614] - [Added the `cargo-fix` subcommand to automatically move project code from 2015 edition to 2018.][cargo/5723] Misc ---- - [`rustdoc` now has the `--cap-lints` option which demotes all lints above the specified level to that level.][52354] For example `--cap-lints warn` will demote `deny` and `forbid` lints to `warn`. - [`rustc` and `rustdoc` will now have the exit code of `1` if compilation fails, and `101` if there is a panic.][52197] - [A preview of clippy has been made available through rustup.][51122] You can install the preview with `rustup component add clippy-preview` Compatibility Notes ------------------- - [`str::{slice_unchecked, slice_unchecked_mut}` are now deprecated.][51807] Use `str::get_unchecked(begin..end)` instead. - [`std::env::home_dir` is now deprecated for its unintuitive behaviour.][51656] Consider using the `home_dir` function from https://crates.io/crates/dirs instead. - [`rustc` will no longer silently ignore invalid data in target spec.][52330] [52861]: rust-lang/rust#52861 [52656]: rust-lang/rust#52656 [52239]: rust-lang/rust#52239 [52330]: rust-lang/rust#52330 [52354]: rust-lang/rust#52354 [52402]: rust-lang/rust#52402 [52103]: rust-lang/rust#52103 [52197]: rust-lang/rust#52197 [51807]: rust-lang/rust#51807 [51899]: rust-lang/rust#51899 [51912]: rust-lang/rust#51912 [51511]: rust-lang/rust#51511 [51619]: rust-lang/rust#51619 [51656]: rust-lang/rust#51656 [51178]: rust-lang/rust#51178 [51122]: rust-lang/rust#51122 [50494]: rust-lang/rust#50494 [cargo/5614]: rust-lang/cargo#5614 [cargo/5723]: rust-lang/cargo#5723 [cargo/5831]: rust-lang/cargo#5831 [`Arc::downcast`]: https://doc.rust-lang.org/std/sync/struct.Arc.html#method.downcast [`Iterator::flatten`]: https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.flatten [`Rc::downcast`]: https://doc.rust-lang.org/std/rc/struct.Rc.html#method.downcast
I'm surprised that RFC 1789 has not been implemented for several months. Tracking issue: #43038
Please note: when I was writing tests for
&Cell<[i32]>
, I found it is not easy to get the length of the contained slice. So I designed aget_with
method which might be useful for similar cases. This method is not designed in the RFC, and it certainly needs to be reviewed by core team. I think it has some connections withCell::update
#50186 , which is also in design phase.