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
Send/Sync audit for libcollections #22715
Conversation
r? @pcwalton (rust_highfive has picked a reviewer for you, use r? to override) |
r? @huonw |
@@ -200,6 +200,9 @@ struct RawItems<T> { | |||
tail: *const T, | |||
} | |||
|
|||
unsafe impl<T: Send> Send for RawItems<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.
IIIII'm not sure this is sound. RawItems is basically for draining values out of an allocation, but doesn't actually own its allocation. Sending this seems unsound?
Also RawItems is 100% internal, so I don't think it needs Send/Sync (only exported inside of MoveTraversalImpl, but you impl Send/Sync on that already).
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.
Good catch. I assumed RawItems
is safe since it has Iterator
and DoubleEndedIterator
implementations which take &mut self
. But by closer inspection, the real mutations are all in unsafe
block. MoveTraversalImpl
is also a very good point.
Comment addressed.
6ed9786
to
41315be
Compare
@@ -1529,6 +1529,11 @@ pub struct IterMut<'a, T:'a> { | |||
} | |||
|
|||
#[stable(feature = "rust1", since = "1.0.0")] | |||
unsafe impl<'a, T: Send+'a> Send for IterMut<'a, T> { } | |||
#[stable(feature = "rust1", since = "1.0.0")] | |||
unsafe impl<'a, T: Sync+'a> Sync for IterMut<'a, 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.
Perhaps this could store Unique<T>
instead?
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.
Done and then I tweaked the implementation to match Iter
, which kills pointer all together.
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.
These unsafe impl
blocks can be removed now, right?
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.
Indeed.
41315be
to
38b22dc
Compare
|
||
unsafe { | ||
Some(&mut *self.ptr.offset(tail as isize)) | ||
let elem = self.ring.get_unchecked_mut(tail); | ||
Some(mem::transmute(elem)) |
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.
I think we tend to prefer avoiding transmute
wherever possible, could this be written as Some(&mut *(elem as *mut _))
?
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.
Done.
Can you also add some tests to ensure that we don't regress in these aspects? |
Hmm, seems I've tackled problem the wrong way. Test-driven would be better here. Will rework the patch. |
38b22dc
to
428e795
Compare
An extensive test was added. r? @alexcrichton @huonw |
@@ -568,6 +568,9 @@ pub struct Iter <'a, T: 'a> { | |||
iter: slice::Iter<'a, T>, | |||
} | |||
|
|||
unsafe impl<'a, T: Sync> Sync for Iter<'a, T> {} | |||
unsafe impl<'a, T: Sync> Send for Iter<'a, 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.
Shouldn't these be unnecessary? I would figure that slice::Iter
would implement these as appropriate
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.
Currently it isn't. This can be removed, however, after libcore
is properly Sync
and Send
audited. A FIXME maybe?
Nice test! Sorry for being so pedantic about these, but this feels like an extra level of unsafety I want to be sure we tread carefully with. To me there are a bunch more
Along those lines, some of the structures marked with Does that make sense? |
@edwardw ah it seems you responded as I was responding! Would it be possible to go ahead and "audit" the relevant portions of libcore ahead of time? It should just involve dealing with |
Certainly. That leaves only |
428e795
to
8665138
Compare
So it is symmetric to its `Iter` implementation. Also kills an FIXME.
@@ -740,6 +740,9 @@ pub struct Iter<'a, T: 'a> { | |||
_marker: marker::PhantomData<&'a T>, | |||
} | |||
|
|||
unsafe impl<'a, T: Sync> Sync for Iter<'a, T> {} | |||
unsafe impl<'a, T: Sync> Send for Iter<'a, 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.
T: Sync
=> T: Send
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.
Sync
is correct; Iter<T>
is essentially the same as &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 wow that is subtle, looks like I should read this again.
8665138
to
8119e78
Compare
8119e78
to
296714c
Compare
In the process, also replaces a raw mutable pointers with Unique to spell out the ownership semantics. cc rust-lang#22709
296714c
to
6849006
Compare
In the process, also replaces two raw mutable pointers with `Unique` to spell out the ownership semantics. cc #22709
In the process, also replaces two raw mutable pointers with
Unique
tospell out the ownership semantics.
cc #22709