Implement RFC 458: improve Send#22319
Conversation
|
r? @eddyb (rust_highfive has picked a reviewer for you, use r? to override) |
|
This isn't quite ready for merging, since this compiles, but it seems like it shouldn't, since #![feature(core, std_misc)]
use std::thread::Thread;
fn main() {
let bad = || {
let x = 1;
let y = &x;
Thread::scoped(|| {
let z = y;
1 + *z
})
};
println!("{}", bad().join().ok().unwrap());
} |
|
This also does essentially no auditing, just mindlessly adding an additional cc @pythonesque, @aturon. |
|
I take it that after auditing, the expectation is that we'll be able to remove |
|
Could this actually continue to have |
|
Exciting! I'll take a look, and in particular take a look at the unsafety errors. |
I personally think that'd be rather disappointing. We'd be giving up quite a lot of expressiveness (and gaining that expressiveness was sort of the point of the changes to |
|
Re-adding Then again, I do want my safe parallel_map right now! :P |
|
@huonw Looking at your example, I'm not fully convinced it's unsafe. Doesn't the closure last until bad itself goes out of scope? I don't think it has at the point where you use the join guard. I could easily be confused, though (_edit:_ yep, pretty sure I was just confused :P) |
|
@huonw that's true, it doesn't lose anything relative to now. I'm just not happy with it as a permanent solution (though I am fine if we wind up with a different API). Anyway, the problem you encountered is, I think, is the fact that lunch-box. git diff libstd/
diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs
index 3b758c8..f291e83 100644
--- a/src/libstd/thread.rs
+++ b/src/libstd/thread.rs
@@ -255,6 +255,7 @@ impl Builder {
joined: false,
packet: my_packet,
thread: thread,
+ _marker: [],
}
}
@@ -487,6 +488,7 @@ pub struct JoinGuard<'a, T: 'a> {
thread: Thread,
joined: bool,
packet: Packet<T>,
+ _marker: [&'a T; 0], // bind the lifetime `'a`
}
#[stable(feature = "rust1", since = "1.0.0")](As an aside I recently realized that |
|
Also this is a simpler example that exhibited the same problem (no need for closures): #![feature(core, std_misc)]
use std::thread::Thread;
fn main() {
let bad = {
let x = 1;
let y = &x;
Thread::scoped(|| {
let z = y;
1 + *z
})
};
println!("{}", bad.join().ok().unwrap());
} |
|
I added a few comments of places I do not think the |
Oh sorry I should have mentioned that I, too, would love to remove the |
|
well, modulo the need for a marker on |
|
(I'm somewhat indifferent on whether we take that same approach for |
|
Shouldn't Anyway, I'm excited to get sendable references/slices 😍. |
Previously Send was defined as `trait Send: 'static {}`. As detailed in
rust-lang/rfcs#458, the `'static` bound is not
actually necessary for safety, we can use lifetimes to enforce that more
flexibly.
`unsafe` code that was previously relying on `Send` to insert a
`'static` bound now may allow incorrect patterns, and so should be
audited (a quick way to ensure safety immediately and postpone the audit
is to add an explicit `'static` bound to any uses of the `Send` type).
cc rust-lang#22251.
In most places this preserves the current API by adding an explicit `'static` bound. Notably absent are some impls like `unsafe impl<T: Send> Send for Foo<T>` and the `std::thread` module. It is likely that it will be possible to remove these after auditing the code to ensure restricted lifetimes are safe. More progress on rust-lang#22251.
Per RFC 458. Closes rust-lang#22251.
The lifetime was previously, incorrectly unconstrained.
2ee7d9d to
7a14f49
Compare
|
Updated, tests pass. |
Conflicts: src/libstd/sync/task_pool.rs src/libstd/thread.rs src/libtest/lib.rs src/test/bench/shootout-reverse-complement.rs src/test/bench/shootout-spectralnorm.rs
This removes the
'staticbound fromSend, and implementsSendfor&'a T(T: Sync) and&'a mut T(T: Send), as per rust-lang/rfcs#458, and so closes #22251.This is rebased on top of Niko's default object lifetime work.
This makes a parallel for function like
compile, run in parallel, and work with essentially arbitrary iterators, including over references of arrays stored on the stack etc.