scoped threads: pass closure through MaybeUninit to avoid invalid dangling references
The `main` function defined here looks roughly like this, if it were written as a more explicit stand-alone function:
```rust
// Not showing all the `'lifetime` tracking, the point is that
// this closure might live shorter than `thread`.
fn thread(control: ..., closure: impl FnOnce() + 'lifetime) {
closure();
control.signal_done();
// A lot of time can pass here.
}
```
Note that `thread` continues to run even after `signal_done`! Now consider what happens if the `closure` captures a reference of lifetime `'lifetime`:
- The type of `closure` is a struct (the implicit unnameable closure type) with a `&'lifetime mut T` field. References passed to a function are marked with `dereferenceable`, which is LLVM speak for *this reference will remain live for the entire duration of this function*.
- The closure runs, `signal_done` runs. Then -- potentially -- this thread gets scheduled away and the main thread runs, seeing the signal and returning to the user. Now `'lifetime` ends and the memory the reference points to might be deallocated.
- Now we have UB! The reference that as passed to `thread` with the promise of remaining live for the entire duration of the function, actually got deallocated while the function still runs. Oops.
Long-term I think we should be able to use `ManuallyDrop` to fix this without `unsafe`, or maybe a new `MaybeDangling` type. I am working on an RFC for that. But in the mean time it'd be nice to fix this so that Miri with `-Zmiri-retag-fields` (which is needed for "full enforcement" of all the LLVM flags we generate) stops erroring on scoped threads.
Fixes https://github.com/rust-lang/rust/issues/101983
r? `@m-ou-se`
Make tests capture the error printed by a Result return
An error returned by tests previously would get written directly to stderr, instead of to the capture buffer set up by the test harness. This PR makes it write to the capture buffer so that it can be integrated as part of the test output by build tools such as `buck test`, since being able to read the error message returned by a test is pretty critical to debugging why the test failed.
<br>
**Before:**
```rust
// tests/test.rs
#[test]
fn test() -> Result<(), &'static str> {
println!("STDOUT");
eprintln!("STDERR");
Err("RESULT")
}
```
```console
$ cargo build --test test
$ target/debug/deps/test-???????????????? -Z unstable-options --format=json
{ "type": "suite", "event": "started", "test_count": 1 }
{ "type": "test", "event": "started", "name": "test" }
Error: "RESULT"
{ "type": "test", "name": "test", "event": "failed", "stdout": "STDOUT\nSTDERR\n" }
{ "type": "suite", "event": "failed", "passed": 0, "failed": 1, "ignored": 0, "measured": 0, "filtered_out": 0, "exec_time": 0.00040313 }
```
**After:**
```console
$ target/debug/deps/test-???????????????? -Z unstable-options --format=json
{ "type": "suite", "event": "started", "test_count": 1 }
{ "type": "test", "event": "started", "name": "test" }
{ "type": "test", "name": "test", "event": "failed", "stdout": "STDOUT\nSTDERR\nError: \"RESULT\"" }
{ "type": "suite", "event": "failed", "passed": 0, "failed": 1, "ignored": 0, "measured": 0, "filtered_out": 0, "exec_time": 0.000261894 }
```
Rollup of 8 pull requests
Successful merges:
- #101118 (fs::get_mode enable getting the data via fcntl/F_GETFL on major BSD)
- #102072 (Add `ptr::Alignment` type)
- #102799 (rustdoc: remove hover gap in file picker)
- #102820 (Show let-else suggestion on stable.)
- #102829 (rename `ImplItemKind::TyAlias` to `ImplItemKind::Type`)
- #102831 (Don't use unnormalized type in `Ty::fn_sig` call in rustdoc `clean_middle_ty`)
- #102834 (Remove unnecessary `lift`/`lift_to_tcx` calls from rustdoc)
- #102838 (remove cfg(bootstrap) from Miri)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Reduce CString allocations in std as much as possible
Currently, every operation involving paths in `fs` allocates memory to hold the path before sending it through the syscall. This PR instead uses a stack allocation (chosen size is somewhat arbitrary) when the path is short before falling back to heap allocations for long paths.
Benchmarks show that the stack allocation is ~2x faster for short paths:
```
test sys::unix::fd::tests::bench_heap_path_alloc ... bench: 34 ns/iter (+/- 2)
test sys::unix::fd::tests::bench_stack_path_alloc ... bench: 15 ns/iter (+/- 1)
```
For long paths, I couldn't find any measurable difference.
---
I'd be surprised if I was the first to think of this, so I didn't fully flush out the PR. If this change is desirable, I'll make use of `run_with_cstr` across all platforms in every fs method (currently just unix open for testing). I also added an `impl From<FromBytesWithNulError>` which is presumably a no-no (or at least needs to be done in another PR).
---
Also see https://github.com/nix-rust/nix/pull/1655 with a bunch of discussion where I'm doing something similar.
Remove empty core::lazy and std::lazy
PR #98165 with commits 7c360dc117 and c1a2db3372 has moved all of the components of these modules into different places, namely {std,core}::sync and {std,core}::cell. The empty modules remained. As they are unstable, we can simply remove them.
PR #98165 with commits 7c360dc117 and c1a2db3372
has moved all of the components of these modules into different places,
namely {std,core}::sync and {std,core}::cell. The empty
modules remained. As they are unstable, we can simply remove them.
std: use futex in `Once`
Now that we have efficient locks, let's optimize the rest of `sync` as well. This PR adds a futex-based implementation for `Once`, which drastically simplifies the implementation compared to the generic version, which is provided as fallback for platforms without futex (Windows only supports them on newer versions, so it uses the fallback for now).
Instead of storing a linked list of waiters, the new implementation adds another state (`QUEUED`), which is set when there are waiting threads. These now use `futex_wait` on that state and are woken by the running thread when it finishes and notices the `QUEUED` state, thereby avoiding unnecessary calls to `futex_wake_all`.
Avoid repeated re-initialization of the BufReader buffer
Fixes https://github.com/rust-lang/rust/issues/102727
We accidentally removed this in https://github.com/rust-lang/rust/pull/98748. It looks so redundant. But it isn't.
The default `Read::read_buf` will defensively initialize the whole buffer, if any of it is indicated to be uninitialized. In uses where reads from the wrapped `Read` impl completely fill the `BufReader`, `initialized` and `filled` are the same, and this extra member isn't required. But in the reported issue, the `BufReader` wraps a `Read` impl which will _never_ fill the whole buffer. So the default `Read::read_buf` implementation repeatedly re-initializes the extra space in the buffer.
This adds back the extra `initialized` member, which ensures that the default `Read::read_buf` only zero-initialized the buffer once, and I've tried to add a comment which explains this whole situation.
unsafe keyword: trait examples and unsafe_op_in_unsafe_fn update
Having a safe `fn` in an `unsafe trait` vs an `unsafe fn` in a safe `trait` are pretty different situations, but the distinction is subtle and can confuse even seasoned Rust developers. So let's have explicit examples of both. I also removed the existing `unsafe trait` example since it was rather strange.
Also the `unsafe_op_in_unsafe_fn` lint can help disentangle the two sides of `unsafe`, so update the docs to account for that.
Add `AsFd` implementations for stdio lock types on WASI.
This mirrors the implementations on Unix platforms, and also mirrors the existing `AsRawFd` impls.
This is similar to #100892, but is for the `*Lock` types.
Update docs so that deprecated method points to relevant method
The docs for the deprecated 'park_timeout_ms' method suggests that the user 'use park_timeout' method instead (at https://doc.rust-lang.org/std/thread/index.html).
Making a similar change so that the docs for the deprecated `sleep_ms` method suggest that the user `use sleep` method instead.
Add a niche to `Duration`, unix `SystemTime`, and non-apple `Instant`
As the nanoseconds fields is always between `0` and `(NANOS_PER_SEC - 1)` inclusive, use the `rustc_layout_scalar_valid_range` attributes to create a niche in the nanosecond field of `Duration` and `Timespec` (which is used to implement unix `SystemTime` and non-apple unix `Instant`; windows `Instant` is implemented with `Duration` and therefore will also benefit). This change has the benefit of making `Option<T>` the same size as `T` for the previously mentioned types. Also shrinks the nanoseconds field of `Timespec` to a `u32` as nanoseconds do not need the extra range of an `i64`, shrinking `Timespec` by 4 bytes on 32-bit platforms.
r? ```@joshtriplett```
Make `std::os::fd` public.
`std::os::fd` defines types like `OwnedFd` and `RawFd` and is common
between Unix and non-Unix platforms that share a basic file-descriptor
concept. Rust currently uses this internally to simplify its own code,
but it would be useful for external users in the same way, so make it
public.
This means that `OwnedFd` etc. will all appear in three places, for
example on unix platforms:
- `std::os::fd::OwnedFd`
- `std::os::unix::io::OwnedFd`
- `std::os::unix::prelude::OwnedFd`
r? `````@joshtriplett`````
Suggest unwrapping `???<T>` if a method cannot be found on it but is present on `T`.
This suggests various ways to get inside wrapper types if the method cannot be found on the wrapper type, but is present on the wrappee.
For this PR, those wrapper types include `Localkey`, `MaybeUninit`, `RefCell`, `RwLock` and `Mutex`.
Stabilize bench_black_box
This PR stabilize `feature(bench_black_box)`.
```rust
pub fn black_box<T>(dummy: T) -> T;
```
The FCP was completed in https://github.com/rust-lang/rust/issues/64102.
`@rustbot` label +T-libs-api -T-libs
Stabilize `#![feature(mixed_integer_ops)]`
Tracked and FCP completed in #87840.
````@rustbot```` label +T-libs-api +S-waiting-on-review +relnotes
r? rust-lang/t-libs-api
Recover error strings on Unix from_lossy_utf8
Some language settings can result in unreliable UTF-8 being produced.
This can result in failing to emit the error string, panicking instead.
from_lossy_utf8 allows us to assume these strings usually will be fine.
This fixes rust-lang#99535.