Stabilize `Seek::stream_position` (feature `seek_convenience`)
Tracking issue: #59359
Unresolved questions from tracking issue:
- "Override `stream_len` for `File`?" → we can do that in the future, this does not block stabilization.
- "Rename to `len` and `position`?" → as noted in the tracking issue, both of these shorter names have problems (`len` is usually a cheap getter, `position` clashes with `Cursor`). I do think the current names are perfectly fine.
- "Rename `stream_position` to `tell`?" → as mentioned in [the comment bringing this up](https://github.com/rust-lang/rust/issues/59359#issuecomment-559541545), `stream_position` is more descriptive. I don't think `tell` would be a good name.
What remains to decide, is whether or not adding these methods is worth it.
Trying to shrink_to greater than capacity should be no-op
Per the discussion in https://github.com/rust-lang/rust/issues/56431, `shrink_to` shouldn't panic if you try to make a vector shrink to a capacity greater than its current capacity.
Make std::future a re-export of core::future
After 1a764a7ef5, there are no `std::future`-specific items (except for `cfg(bootstrap)` items removed in 93eed402ad). So, instead of defining `std` own module, we can re-export the `core::future` directly.
Implement Error for &(impl Error)
Opening this up just to see what it breaks. It's unfortunate that `&(impl Error)` doesn't actually implement `Error`. If this direct approach doesn't work out then I'll try something different, like an `Error::by_ref` method.
**EDIT:** This is a super low-priority experiment so feel free to cancel it for more important crater runs! 🙂
-----
# Stabilization Report
## Why?
We've been working for the last few years to try "fix" the `Error` trait, which is probably one of the most fundamental in the whole standard library. One of its issues is that we commonly expect you to work with abstract errors through `dyn Trait`, but references and smart pointers over `dyn Trait` don't actually implement the `Error` trait. If you have a `&dyn Error` or a `Box<dyn Error>` you simply can't pass it to a method that wants a `impl Error`.
## What does this do?
This stabilizes the following trait impl:
```rust
impl<'a, T: Error + ?Sized + 'static> Error for &'a T;
```
This means that `&dyn Error` will now satisfy a `impl Error` bound.
It doesn't do anything with `Box<dyn Error>` directly. We discussed how we could do `Box<dyn Error>` in the thread here (and elsewhere in the past), but it seems like we need something like lattice-based specialization or a sprinkling of snowflake compiler magic to make that work. Having said that, with this new impl you _can_ now get a `impl Error` from a `Box<dyn Error>` by dereferencing it.
## What breaks?
A crater run revealed a few crates broke with something like the following:
```rust
// where e: &'short &'long dyn Error
err.source()
```
previously we'd auto-deref that `&'short &'long dyn Error` to return a `Option<&'long dyn Error>` from `source`, but now will call directly on `&'short impl Error`, so will return a `Option<&'short dyn Error>`. The fix is to manually deref:
```rust
// where e: &'short &'long dyn Error
(*err).source()
```
In the recent Libs meeting we considered this acceptable breakage.
Remove delay-binding for Win XP and Vista
The minimum supported Windows version is now Windows 7. Windows XP
and Windows Vista are no longer supported; both are already broken, and
require extra steps to use.
This commit removes the delayed-binding support for Windows API
functions that are present on all supported Windows targets. This has
several benefits: Removes needless complexity. Removes a load and
dynamic call on hot paths in mutex acquire / release. This may have
performance benefits.
* "Drop official support for Windows XP"
https://github.com/rust-lang/compiler-team/issues/378
* "Firefox has ended support for Windows XP and Vista"
https://support.mozilla.org/en-US/kb/end-support-windows-xp-and-vista
Inline methods of Path and OsString
These methods are not generic, and therefore aren't candidates for cross-crate inlining without an `#[inline]` attribute.
Document why not use concat! in dbg! macro
Original title: Reduce code generated by `dbg!` macro
The expanded code before/after: <https://rust.godbolt.org/z/hE3j95>.
---
We cannot use `concat!` since `file!` could contains `{` or the expression is a block (`{ .. }`).
Using it will generated malformed format strings.
So let's document this reason why we don't use `concat!` macro at all.
The minimum supported Windows version is now Windows 7. Windows XP
and Windows Vista are no longer supported; both are already broken, and
require extra steps to use.
This commit removes the delayed-binding support for Windows API
functions that are present on all supported Windows targets. This has
several benefits: Removes needless complexity. Removes a load and
dynamic call on hot paths in mutex acquire / release. This may have
performance benefits.
* "Drop official support for Windows XP"
https://github.com/rust-lang/compiler-team/issues/378
* "Firefox has ended support for Windows XP and Vista"
https://support.mozilla.org/en-US/kb/end-support-windows-xp-and-vista
std: Update wasi-libc commit of the wasm32-wasi target
This brings in an implementation of `current_dir` and `set_current_dir`
(emulation in `wasi-libc`) as well as an updated version of finding
relative paths. This also additionally updates clang to the latest
release to build wasi-libc with.
BufWriter: Provide into_raw_parts
If something goes wrong, one might want to unpeel the layers of nested
Writers to perform recovery actions on the underlying writer, or reuse
its resources.
`into_inner` can be used for this when the inner writer is still
working. But when the inner writer is broken, and returning errors,
`into_inner` simply gives you the error from flush, and the same
`Bufwriter` back again.
Here I provide the necessary function, which I have chosen to call
`into_raw_parts`.
I had to do something with `panicked`. Returning it to the caller as
a boolean seemed rather bare. Throwing the buffered data away in this
situation also seems unfriendly: maybe the programmer knows something
about the underlying writer and can recover somehow.
So I went for a custom Error. This may be overkill, but it does have
the nice property that a caller who actually wants to look at the
buffered data, rather than simply extracting the inner writer, will be
told by the type system if they forget to handle the panicked case.
If a caller doesn't need the buffer, it can just be discarded. That
WriterPanicked is a newtype around Vec<u8> means that hopefully the
layouts of the Ok and Err variants can be very similar, with just a
boolean discriminant. So this custom error type should compile down
to nearly no code.
*If this general idea is felt appropriate, I will open a tracking issue, etc.*
Don't use posix_spawn_file_actions_addchdir_np on macOS.
There is a bug on macOS where using `posix_spawn_file_actions_addchdir_np` with a relative executable path will cause `posix_spawnp` to return ENOENT, even though it successfully spawned the process in the given directory.
`posix_spawn_file_actions_addchdir_np` was introduced in macOS 10.15 first released in Oct 2019. I have tested macOS 10.15.7 and 11.0.1.
Example offending program:
```rust
use std::fs;
use std::os::unix::fs::PermissionsExt;
use std::process::*;
fn main() {
fs::create_dir_all("bar").unwrap();
fs::create_dir_all("foo").unwrap();
fs::write("foo/foo.sh", "#!/bin/sh\necho hello ${PWD}\n").unwrap();
let perms = fs::Permissions::from_mode(0o755);
fs::set_permissions("foo/foo.sh", perms).unwrap();
let c = Command::new("../foo/foo.sh").current_dir("bar").spawn();
eprintln!("{:?}", c);
}
```
This prints:
```
Err(Os { code: 2, kind: NotFound, message: "No such file or directory" })
hello /Users/eric/Temp/bar
```
I wanted to open this PR to get some feedback on possible solutions. Alternatives:
* Do nothing.
* Document the bug.
* Try to detect if the executable is a relative path on macOS, and avoid using `posix_spawn_file_actions_addchdir_np` only in that case.
I looked at the [XNU source code](https://opensource.apple.com/source/xnu/xnu-6153.141.1/bsd/kern/kern_exec.c.auto.html), but I didn't see anything obvious that would explain the behavior. The actual chdir succeeds, it is something else further down that fails, but I couldn't see where.
EDIT: I forgot to mention, relative exe paths with `current_dir` in general are discouraged (see #37868). I don't know if #37868 is fixable, since normalizing it would change the semantics for some platforms. Another option is to convert the executable to an absolute path with something like joining the cwd with the new cwd and the executable, but I'm uncertain about that.
Clarify what the effects of a 'logic error' are
This clarifies what a 'logic error' is (which is a term used to describe what happens if you put things in a hash table or btree and then use something like a refcell to break the internal ordering). This tries to be as vague as possible, as we don't really want to promise what happens, except "bad things, but not UB". This was discussed in #80657
This brings in an implementation of `current_dir` and `set_current_dir`
(emulation in `wasi-libc`) as well as an updated version of finding
relative paths. This also additionally updates clang to the latest
release to build wasi-libc with.
Deprecate atomic::spin_loop_hint in favour of hint::spin_loop
For https://github.com/rust-lang/rust/issues/55002
We wanted to leave `atomic::spin_loop_hint` alone when stabilizing `hint::spin_loop` so folks had some time to migrate. This now deprecates `atomic_spin_loop_hint`.
Fix handling of malicious Readers in read_to_end
A malicious `Read` impl could return overly large values from `read`, which would result in the guard's drop impl setting the buffer's length to greater than its capacity! ~~To fix this, the drop impl now uses the safe `truncate` function instead of `set_len` which ensures that this will not happen. The result of calling the function will be nonsensical, but that's fine given the contract violation of the `Read` impl.~~
~~The `Guard` type is also used by `append_to_string` which does not pass untrusted values into the length field, so I've copied the guard type into each function and only modified the one used by `read_to_end`. We could just keep a single one and modify it, but it seems a bit cleaner to keep the guard code close to the functions and related specifically to them.~~
To fix this, we now assert that the returned length is not larger than the buffer passed to the method.
For reference, this bug has been present for ~2.5 years since 1.20: ecbb896b9e.
Closes#80894.
Add a `std::io::read_to_string` function
I recognize that you're usually supposed to open an issue first, but the
implementation is very small so it's okay if this is closed and it was 'wasted
work' :)
-----
The equivalent of `std::fs::read_to_string`, but generalized to all
`Read` impls.
As the documentation on `std::io::read_to_string` says, the advantage of
this function is that it means you don't have to create a variable first
and it provides more type safety since you can only get the buffer out
if there were no errors. If you use `Read::read_to_string`, you have to
remember to check whether the read succeeded because otherwise your
buffer will be empty.
It's friendlier to newcomers and better in most cases to use an explicit
return value instead of an out parameter.
Add missing methods to unix ExitStatusExt
These are the methods corresponding to the remaining exit status examination macros from `wait.h`. `WCOREDUMP` isn't in SuS but is it is very standard. I have not done portability testing to see if this builds everywhere, so I may need to Do Something if it doesn't.
There is also a bugfix and doc improvement to `.signal()`, and an `.into_raw()` accessor.
This would fix#73128 and fix#73129. Please let me know if you like this direction, and if so I will open the tracking issue and so on.
If this MR goes well, I may tackle #73125 next - I have an idea for how to do it.
This is not particularly pretty but the current situation is a mess
and I don't think I'm making it significantly worse.
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
As discussed in #79982.
I think the "new interfaces", ie the new trait and impl, must be
insta-stable. This seems OK because we are, in fact, adding a new
restriction to the stable API.
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
We need to be clear that this never returns WSTOPSIG. That is, if
WIFSTOPPED, the return value is None.
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
A unix wait status can contain, at least, exit statuses, termination
signals, and stop signals.
WTERMSIG is only valid if WIFSIGNALED.
https://pubs.opengroup.org/onlinepubs/9699919799/functions/wait.html
It will not be easy to experience this bug with `Command`, because
that doesn't pass WUNTRACED. But you could make an ExitStatus
containing, say, a WIFSTOPPED, from a call to one of the libc wait
functions.
(In the WIFSTOPPED case, there is WSTOPSIG. But a stop signal is
encoded differently to a termination signal, so WTERMSIG and WSTOPSIG
are by no means the same.)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
use Once instead of Mutex to manage capture resolution
For #78299
This allows us to return borrows of the captured backtrace frames that are tied to a borrow of the Backtrace itself, instead of to some short-lived Mutex guard.
We could alternatively share `&Mutex<Capture>`s and lock on-demand, but then we could potentially forget to call `resolve()` before working with the capture. It also makes it semantically clearer what synchronization is needed on the capture.
cc `@seanchen1991` `@rust-lang/project-error-handling`
Fix safety comment
The size assertion in the comment was inverted compared to the code. After fixing that the implication that `(new_size >= old_size) => new_size != 0` still doesn't hold so explain why `old_size != 0` at this point.
Rustdoc: Fix macros 2.0 and built-in derives being shown at the wrong path
Fixes#74355
- ~~waiting on author + draft PR since my code ought to be cleaned up _w.r.t._ the way I avoid the `.unwrap()`s:~~
- ~~dummy items may avoid the first `?`,~~
- ~~but within the module traversal some tests did fail (hence the second `?`), meaning the crate did not possess the exact path of the containing module (`extern` / `impl` blocks maybe? I'll look into that).~~
r? `@jyn514`
Optimize away some path lookups in the generic `fs::copy` implementation
This also eliminates a use of a `Path` convenience function, in support
of #80741, refactoring `std::path` to focus on pure data structures and
algorithms.
Stabilize slice::strip_prefix and slice::strip_suffix
These two methods are useful. The corresponding methods on `str` are already stable.
I believe that stablising these now would not get in the way of, in the future, extending these to take a richer pattern API a la `str`'s patterns.
Tracking PR: #73413. I also have an outstanding PR to improve the docs for these two functions and the corresponding ones on `str`: #75078
I have tried to follow the [instructions in the dev guide](https://rustc-dev-guide.rust-lang.org/stabilization_guide.html#stabilization-pr). The part to do with `compiler/rustc_feature` did not seem applicable. I assume that's because these are just library features, so there is no corresponding machinery in rustc.
The size assertion in the comment was inverted compared to the code. After fixing that the implication that `(new_size >= old_size) => new_size != 0` still doesn't hold so explain why `old_size != 0` at this point.
This also eliminates a use of a `Path` convenience function, in support
of #80741, refactoring `std::path` to focus on pure data structures and
algorithms.
The heading style for `std::prelude` is to be consistent with the
headings for `std` and `core`: `# The Rust Standard Library` and
`# The Rust Core Library`, respectively.
This allows us to return borrows of the captured backtrace frames
that are tied to a borrow of the Backtrace itself, instead of to
some short-lived Mutex guard.
It also makes it semantically clearer what synchronization is needed
on the capture.
slightly more typed interface to panic implementation
The panic payload is currently being passed around as a `usize`. However, it actually is a pointer, and the involved types are available on all ends of this API, so I propose we use the proper pointer type to avoid some casts. Avoiding int-to-ptr casts also makes this code work with `miri -Zmiri-track-raw-pointers`.
Fix intra-doc links for non-path primitives
This does *not* currently work for associated items that are
auto-implemented by the compiler (e.g. `never::eq`), because they aren't
present in the source code. I plan to fix this in a follow-up PR.
Fixes https://github.com/rust-lang/rust/issues/63351 using the approach mentioned in https://github.com/rust-lang/rust/issues/63351#issuecomment-683352130.
r? `@Manishearth`
cc `@petrochenkov` - this makes `rustc_resolve::Res` public, is that ok? I'd just add an identical type alias in rustdoc if not, which seems a waste.
We hope later to extend `core::str::Pattern` to slices too, perhaps as
part of stabilising that. We want to minimise the amount of type
inference breakage when we do that, so we don't want to stabilise
strip_prefix and strip_suffix taking a simple `&[T]`.
@KodrAus suggested the approach of introducing a new perma-unstable
trait, which reduces this future inference break risk.
I found it necessary to make two impls of this trait, as the unsize
coercion don't apply when hunting for trait implementations.
Since SlicePattern's only method returns a reference, and the whole
trait is just a wrapper for slices, I made the trait type be the
non-reference type [T] or [T;N] rather than the reference. Otherwise
the trait would have a lifetime parameter.
I marked both the no-op conversion functions `#[inline]`. I'm not
sure if that is necessary but it seemed at the very least harmless.
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
Stabilize `core::slice::fill`
Tracking issue https://github.com/rust-lang/rust/issues/70758
Stabilizes the `core::slice::fill` API in Rust 1.50, adding a `memset` doc alias so people coming from C/C++ looking for this operation can find it in the docs. This API hasn't seen any changes since we changed the signature in https://github.com/rust-lang/rust/pull/71165/, and it seems like the right time to propose stabilization. Thanks!
r? `@m-ou-se`
This caught several bugs where people expected `slice` to link to the
primitive, but it linked to the module instead.
This also uses `cfg_attr(bootstrap)` since the ambiguity only occurs
when compiling with stage 1.
Add array search aliases
Missed this in https://github.com/rust-lang/rust/pull/80068. This one will really fix https://github.com/rust-lang/rust/issues/46075.
The last alias especially I'm a little unsure about - maybe fuzzy search should be fixed in rustdoc instead? Happy to make that change although I'd have to figure out how.
r? ``@m-ou-se`` although cc ``@GuillaumeGomez`` for the search issue.
Fix failing build of std on armv5te-unknown-linux-uclibceabi due to missing cmsg_len_zero
I'm getting the following error when trying to build `std` on `armv5te-unknown-linux-uclibceabi`:
```
error[E0425]: cannot find value `cmsg_len_zero` in this scope
--> /home/operutka/.rustup/toolchains/nightly-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/std/src/sys/unix/ext/net/ancillary.rs:376:47
|
376 | let data_len = (*cmsg).cmsg_len - cmsg_len_zero;
| ^^^^^^^^^^^^^ not found in this scope
```
Obviously, this branch:
```rust
cfg_if::cfg_if! {
if #[cfg(any(target_os = "android", all(target_os = "linux", target_env = "gnu")))] {
let cmsg_len_zero = libc::CMSG_LEN(0) as libc::size_t;
} else if #[cfg(any(
target_os = "dragonfly",
target_os = "emscripten",
target_os = "freebsd",
all(target_os = "linux", target_env = "musl",),
target_os = "netbsd",
target_os = "openbsd",
))] {
let cmsg_len_zero = libc::CMSG_LEN(0) as libc::socklen_t;
}
}
```
does not cover the case `all(target_os = "linux", target_env = "uclibc")`.
Mark `-1` as an available niche for file descriptors
Based on discussion from <https://internals.rust-lang.org/t/can-the-standard-library-shrink-option-file/12768>, the file descriptor `-1` is chosen based on the POSIX API designs that use it as a sentinel to report errors. A bigger niche could've been chosen, particularly on Linux, but would not necessarily be portable.
This PR also adds a test case to ensure that the -1 niche (which is kind of hacky and has no obvious test case) works correctly. It requires the "upper" bound, which is actually -1, to be expressed in two's complement.
The equivalent of `std::fs::read_to_string`, but generalized to all
`Read` impls.
As the documentation on `std::io::read_to_string` says, the advantage of
this function is that it means you don't have to create a variable first
and it provides more type safety since you can only get the buffer out
if there were no errors. If you use `Read::read_to_string`, you have to
remember to check whether the read succeeded because otherwise your
buffer will be empty.
It's friendlier to newcomers and better in most cases to use an explicit
return value instead of an out parameter.
Move {f32,f64}::clamp to core.
`clamp` was recently stabilized (tracking issue: https://github.com/rust-lang/rust/issues/44095). But although `Ord::clamp` was added in `core` (because `Ord` is in `core`), the versions for the `f32` and `f64` primitives were added in `std` (together with `floor`, `sin`, etc.), not in `core` (together with `min`, `max`, `from_bits`, etc.).
This change moves them to `core`, such that `clamp` on floats is available in `no_std` programs as well.
Stabilize all stable methods of `Ipv4Addr`, `Ipv6Addr` and `IpAddr` as const
This PR stabilizes all currently stable methods of `Ipv4Addr`, `Ipv6Addr` and `IpAddr` as const.
Tracking issue: #76205
`Ipv4Addr` (`const_ipv4`):
- `octets`
- `is_loopback`
- `is_private`
- `is_link_local`
- `is_multicast`
- `is_broadcast`
- `is_docmentation`
- `to_ipv6_compatible`
- `to_ipv6_mapped`
`Ipv6Addr` (`const_ipv6`):
- `segments`
- `is_unspecified`
- `is_loopback`
- `is_multicast`
- `to_ipv4`
`IpAddr` (`const_ip`):
- `is_unspecified`
- `is_loopback`
- `is_multicast`
## Motivation
The ip methods seem like prime candidates to be made const: their behavior is defined by an external spec, and based solely on the byte contents of an address. These methods have been made unstable const in the beginning of September, after the necessary const integer arithmetic was stabilized.
There is currently a PR open (#78802) to change the internal representation of `IpAddr{4,6}` from `libc` types to a byte array. This does not have any impact on the constness of the methods.
## Implementation
Most of the stabilizations are straightforward, with the exception of `Ipv6Addr::segments`, which uses the unstable feature `const_fn_transmute`. The code could be rewritten to equivalent stable code, but this leads to worse code generation (#75085).
This is why `segments` gets marked with `#[rustc_allow_const_fn_unstable(const_fn_transmute)]`, like the already const-stable `Ipv6Addr::new`, the justification being that a const-stable alternative implementation exists https://github.com/rust-lang/rust/pull/76206#issuecomment-685044184.
## Future posibilities
This PR const-stabilizes all currently stable ip methods, however there are also a number of unstable methods under the `ip` feature (#27709). These methods are already unstable const. There is a PR open (#76098) to stabilize those methods, which could include const-stabilization. However, stabilizing those methods as const is dependent on `Ipv4Addr::octets` and `Ipv6Addr::segments` (covered by this PR).
Add the "async" and "promise" doc aliases to `core::future::Future`
Adds the "async" and "promise" doc aliases to `core::future::Future`. This enables people who search for "async" or "promise" to find `Future`, which is Rust's core primitive for async programming. Thanks!
Stabilize or_insert_with_key
Stabilizes the `or_insert_with_key` feature from https://github.com/rust-lang/rust/issues/71024. This allows inserting key-derived values when a `HashMap`/`BTreeMap` entry is vacant.
The difference between this and `.or_insert_with(|| ... )` is that this provides a reference to the key to the closure after it is moved with `.entry(key_being_moved)`, avoiding the need to copy or clone the key.
Edit formatting in Rust Prelude docs
Use consistent punctuation and capitalization in the list of things re-exported in the prelude.
Also adds a (possibly missing) word.
Refactor and fix `parse_prefix` on Windows
This PR is an extension of #78692 as well as a general refactor of `parse_prefix`:
**Fixes**:
There are two errors in the current implementation of `parse_prefix`:
Firstly, in the current implementation only `\` is recognized as a separator character in device namespace prefixes. This behavior is only correct for verbatim paths; `"\\.\C:/foo"` should be parsed as `"C:"` instead of `"C:/foo"`.
Secondly, the current implementation only handles single separator characters. In non-verbatim paths a series of separator characters should be recognized as a single boundary, e.g. the UNC path `"\\localhost\\\\\\C$\foo"` should be parsed as `"\\localhost\\\\\\C$"` and then `UNC(server: "localhost", share: "C$")`, but currently it is not parsed at all, because it starts being parsed as `\\localhost\` and then has an invalid empty share location.
Paths like `"\\.\C:/foo"` and `"\\localhost\\\\\\C$\foo"` are valid on Windows, they are equivalent to just `"C:\foo"`.
**Refactoring**:
All uses of `&[u8]` within `parse_prefix` are extracted to helper functions and`&OsStr` is used instead. This reduces the number of places unsafe is used:
- `get_first_two_components` is adapted to the more general `parse_next_component` and used in more places
- code for parsing drive prefixes is extracted to `parse_drive`
Add fast futex-based thread parker for Windows.
This adds a fast futex-based thread parker for Windows. It either uses WaitOnAddress+WakeByAddressSingle or NT Keyed Events (NtWaitForKeyedEvent+NtReleaseKeyedEvent), depending on which is available. Together, this makes this thread parker work for Windows XP and up. Before this change, park()/unpark() did not work on Windows XP: it needs condition variables, which only exist since Windows Vista.
---
Unfortunately, NT Keyed Events are an undocumented Windows API. However:
- This API is relatively simple with obvious behaviour, and there are several (unofficial) articles documenting the details. [1]
- parking_lot has been using this API for years (on Windows versions before Windows 8). [2] Many big projects extensively use parking_lot, such as servo and the Rust compiler itself.
- It is the underlying API used by Windows SRW locks and Windows critical sections. [3] [4]
- The source code of the implementations of Wine, ReactOs, and Windows XP are available and match the expected behaviour.
- The main risk with an undocumented API is that it might change in the future. But since we only use it for older versions of Windows, that's not a problem.
- Even if these functions do not block or wake as we expect (which is unlikely, see all previous points), this implementation would still be memory safe. The NT Keyed Events API is only used to sleep/block in the right place.
[1]\: http://www.locklessinc.com/articles/keyed_events/
[2]\: https://github.com/Amanieu/parking_lot/commit/43abbc964e
[3]\: https://docs.microsoft.com/en-us/archive/msdn-magazine/2012/november/windows-with-c-the-evolution-of-synchronization-in-windows-and-c
[4]\: Windows Internals, Part 1, ISBN 9780735671300
---
The choice of fallback API is inspired by parking_lot(_core), but the implementation of this thread parker is different. While parking_lot has no use for a fast path (park() directly returning if unpark() was already called), this implementation has a fast path that returns without even checking which waiting/waking API to use, as the same atomic variable with compatible states is used in all cases.
doc(array,vec): add notes about side effects when empty-initializing
Copying some context from a conversation in the Rust discord:
* Both `vec![T; 0]` and `[T; 0]` are syntactically valid, and produce empty containers of their respective types
* Both *also* have side effects:
```rust
fn side_effect() -> String {
println!("side effect!");
"foo".into()
}
fn main() {
println!("before!");
let x = vec![side_effect(); 0];
let y = [side_effect(); 0];
println!("{:?}, {:?}", x, y);
}
```
produces:
```
before!
side effect!
side effect!
[], []
```
This PR just adds two small notes to each's documentation, warning users that side effects can occur.
I've also submitted a clippy proposal: https://github.com/rust-lang/rust-clippy/issues/6439
Link loop/for keyword
Even though the reference already have all of these, I am just adding related keywords in the see also to let others easily click on the related keyword.
Windows TLS: ManuallyDrop instead of mem::forget
The Windows TLS implementation still used `mem::forget` instead of `ManuallyDrop`, leading to the usual problem of "using" the `Box` when it should not be used any more.
Dogfood `str_split_once()`
Part of https://github.com/rust-lang/rust/issues/74773.
Beyond increased clarity, this fixes some instances of a common confusion with how `splitn(2)` behaves: the first element will always be `Some()`, regardless of the delimiter, and even if the value is empty.
Given this code:
```rust
fn main() {
let val = "...";
let mut iter = val.splitn(2, '=');
println!("Input: {:?}, first: {:?}, second: {:?}", val, iter.next(), iter.next());
}
```
We get:
```
Input: "no_delimiter", first: Some("no_delimiter"), second: None
Input: "k=v", first: Some("k"), second: Some("v")
Input: "=", first: Some(""), second: Some("")
```
Using `str_split_once()` makes more clear what happens when the delimiter is not found.
Make the kernel_copy tests more robust/concurrent.
These tests write to the same filenames in /tmp and in some cases these files don't get cleaned up properly. This caused issues for us when different users run the tests on the same system, e.g.:
```
---- sys::unix::kernel_copy::tests::bench_file_to_file_copy stdout ----
thread 'sys::unix::kernel_copy::tests::bench_file_to_file_copy' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 13, kind: PermissionDenied, message: "Permission denied" }', library/std/src/sys/unix/kernel_copy/tests.rs:71:10
---- sys::unix::kernel_copy::tests::bench_file_to_socket_copy stdout ----
thread 'sys::unix::kernel_copy::tests::bench_file_to_socket_copy' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 13, kind: PermissionDenied, message: "Permission denied" }', library/std/src/sys/unix/kernel_copy/tests.rs💯10
```
Use `std::sys_common::io__test::tmpdir()` to solve this.
CC ``@the8472.``
Improve documentation for `std::{f32,f64}::mul_add`
Makes it more clear that performance improvement is not guaranteed when using FMA, even when the target architecture supports it natively.
Enforce no-move rule of ReentrantMutex using Pin and fix UB in stdio
A `sys_common::ReentrantMutex` may not be moved after initializing it with `.init()`. This was not enforced, but only stated as a requirement in the comments on the unsafe functions. This change enforces this no-moving rule using `Pin`, by changing `&self` to a `Pin` in the `init()` and `lock()` functions.
This uncovered a bug I introduced in #77154: stdio.rs (the only user of ReentrantMutex) called `init()` on its ReentrantMutexes while constructing them in the intializer of `SyncOnceCell::get_or_init`, which would move them afterwards. Interestingly, the ReentrantMutex unit tests already had the same bug, so this invalid usage has been tested on all (CI-tested) platforms for a long time. Apparently this doesn't break badly on any of the major platforms, but it does break the rules.\*
To be able to keep using SyncOnceCell, this adds a `SyncOnceCell::get_or_init_pin` function, which makes it possible to work with pinned values inside a (pinned) SyncOnceCell. Whether this function should be public or not and what its exact behaviour and interface should be if it would be public is something I'd like to leave for a separate issue or PR. In this PR, this function is internal-only and marked with `pub(crate)`.
\* Note: That bug is now included in 1.48, while this patch can only make it to ~~1.49~~ 1.50. We should consider the implications of 1.48 shipping with a wrong usage of `pthread_mutex_t` / `CRITICAL_SECTION` / .. which technically invokes UB according to their specification. The risk is very low, considering the objects are not 'used' (locked) before the move, and the ReentrantMutex unit tests have verified this works fine in practice.
Edit: This has been backported and included in 1.48. And soon 1.49 too.
---
In future changes, I want to push this usage of Pin further inside `sys` instead of only `sys_common`, and apply it to all 'unmovable' objects there (`Mutex`, `Condvar`, `RwLock`). Also, while `sys_common`'s mutexes and condvars are already taken care of by #77147 and #77648, its `RwLock` should still be made movable or get pinned.
Based on discussion from https://internals.rust-lang.org/t/can-the-standard-library-shrink-option-file/12768,
the file descriptor -1 is chosen based on the POSIX API designs that use it as a sentinel to report errors.
A bigger niche could've been chosen, particularly on Linux, but would not necessarily be portable.
This PR also adds a test case to ensure that the -1 niche
(which is kind of hacky and has no obvious test case) works correctly.
It requires the "upper" bound, which is actually -1, to be expressed in two's complement.
implement better availability probing for copy_file_range
Followup to https://github.com/rust-lang/rust/pull/75428#discussion_r469616547
Previously syscall detection was overly pessimistic. Any attempt to copy to an immutable file (EPERM) would disable copy_file_range support for the whole process.
The change tries to copy_file_range on invalid file descriptors which will never run into the immutable file case and thus we can clearly distinguish syscall availability.