-
Notifications
You must be signed in to change notification settings - Fork 13.4k
Implement RFC 458: improve Send #22319
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
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
'static
bound fromSend
, and implementsSend
for&'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.