-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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 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
'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.