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.
Add `impl Div<NonZeroU{0}> for u{0}` which cannot panic
Dividing an unsigned int by a `NonZeroUxx` requires a user to write (for example, in [this SO question](https://stackoverflow.com/questions/64855738/how-to-inform-the-optimizer-that-nonzerou32get-will-never-return-zero)):
```
pub fn safe_div(x: u32, y: std::num::NonZeroU32) -> u32 {
x / y.get()
}
```
which generates a panicking-checked-div [assembly](https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(fontScale:14,j:1,lang:rust,selection:(endColumn:2,endLineNumber:6,positionColumn:2,positionLineNumber:6,selectionStartColumn:2,selectionStartLineNumber:6,startColumn:2,startLineNumber:6),source:%27pub+fn+div(x:+u32,+y:+u32)+-%3E+u32+%7B%0A++++x+/+y%0A%7D%0Apub+fn+safe_div(x:+u32,+y:+std::num::NonZeroU32)+-%3E+u32+%7B%0A++++x+/+y.get()+//+an+unchecked+division+expected%0A%7D%27),l:%275%27,n:%270%27,o:%27Rust+source+%231%27,t:%270%27)),k:50,l:%274%27,n:%270%27,o:%27%27,s:0,t:%270%27),(g:!((h:compiler,i:(compiler:r1470,filters:(b:%270%27,binary:%271%27,commentOnly:%270%27,demangle:%270%27,directives:%270%27,execute:%271%27,intel:%270%27,libraryCode:%271%27,trim:%271%27),fontScale:14,j:1,lang:rust,libs:!(),options:%27-O%27,selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1),l:%275%27,n:%270%27,o:%27rustc+1.47.0+(Editor+%231,+Compiler+%231)+Rust%27,t:%270%27)),k:50,l:%274%27,n:%270%27,o:%27%27,s:0,t:%270%27)),l:%272%27,n:%270%27,o:%27%27,t:%270%27)),version:4).
Avoiding the `panic` currently requires `unsafe` code.
This PR adds an `impl Div<NonZeroU{0}> for u{0}` (and `impl Rem<NonZeroU{0}> for u{0}`) which calls the `unchecked_div` (and `unchecked_rem`) intrinsic without any additional checks,
making the following code compile:
```
pub fn safe_div(x: u32, y: std::num::NonZeroU32) -> u32 {
x / y
}
pub fn safe_rem(x: u32, y: std::num::NonZeroU32) -> u32 {
x % y
}
```
The doc is set to match the regular div impl [docs](https://doc.rust-lang.org/beta/src/core/ops/arith.rs.html#460).
I've marked these as stable because (as I understand it) trait impls are automatically stable. I'm happy to change it to unstable if needed.
Following `@dtolnay` template from a similar issue:
this adds the following **stable** impls, which rely on dividing unsigned integers by nonzero integers being well defined and previously would have involved unsafe code to encode that knowledge:
```
impl Div<NonZeroU8> for u8 {
type Output = u8;
}
impl Rem<NonZeroU8> for u8 {
type Output = u8;
}
```
and equivalent for u16, u32, u64, u128, usize, but **not** for i8, i16, i32, i64, i128, isize (since -1/MIN is undefined).
r? `@dtolnay`
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>
BTreeMap: clean up access to MaybeUninit arrays
Stop exposing and using immutable access to `MaybeUninit` slices when we need and have exclusive access to the tree.
r? `@Mark-Simulacrum`
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`
BTreeMap: relax the explicit borrow rule to make code shorter and safer
Expressions like `.reborrow_mut().into_len_mut()` are annoyingly long, and kind of dangerous for the reason `reborrow_mut()` is unsafe. By relaxing the single rule, we no longer have to make an exception for functions with a `borrow` name and functions like `as_leaf_mut`. This is largely restoring the declaration style of the btree::node API about a year ago, but with more explanation and consistency.
r? `@Mark-Simulacrum`
Deprecate atomic compare_and_swap method
Finish implementing [RFC 1443](https://github.com/rust-lang/rfcs/blob/master/text/1443-extended-compare-and-swap.md) (https://github.com/rust-lang/rfcs/pull/1443).
It was decided to deprecate `compare_and_swap` [back in Rust 1.12 already](https://github.com/rust-lang/rust/issues/31767#issuecomment-215903038). I can't find any info about that decision being reverted. My understanding is just that it has been forgotten. If there has been a decision on keeping `compare_and_swap` then it's hard to find, and even if this PR does not go through it can act as a place where people can find out about the decision being reverted.
Atomic operations are hard to understand, very hard. And it does not help that there are multiple similar methods to do compare and swap with. They are so similar that for a reader it might be hard to understand the difference. This PR aims to make that simpler by finally deprecating `compare_and_swap` which is essentially just a more limited version of `compare_exchange`. The documentation is also updated (according to the RFC text) to explain the differences a bit better.
Even if we decide to not deprecate `compare_and_swap`. I still think the documentation for the atomic operations should be improved to better describe their differences and similarities. And the documentation can be written nicer than the PR currently proposes, but I wanted to start somewhere. Most of it is just copied from the RFC.
The documentation for `compare_exchange` and `compare_exchange_weak` indeed describe how they work! The problem is that they are more complex and harder to understand than `compare_and_swap`. So for someone who does not fully grasp this they might fall back to using `compare_and_swap`. Making the documentation outline the similarities and differences might build a bridge for people so they can cross over to the more powerful and sometimes more efficient operations.
The conversions I do to avoid the `std` internal deprecation errors are very straight forward `compare_and_swap -> compare_exchange` changes where the orderings are just using the mapping in the new documentation. Only in one place did I use `compare_exchange_weak`. This can probably be improved further. But the goal here was not for those operations to be perfect. Just to not get worse and to allow the deprecation to happen.
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.
Added [T; N]::zip()
This is my first PR to rust so I hope I have done everything right, or at least close :)
---
This is PR adds the array method `[T; N]::zip()` which, in my mind, is a natural extension to #75212.
My implementation of `zip()` is mostly just a modified copy-paste of `map()`. Should I keep the comments? Also am I right in assuming there should be no way for the `for`-loop to panic, thus no need for the dropguard seen in the `map()`-function?
The doc comment is in a similar way a slightly modified copy paste of [`Iterator::zip()`](https://doc.rust-lang.org/beta/std/iter/trait.Iterator.html#method.zip)
`@jplatte` mentioned in [#75490](https://github.com/rust-lang/rust/pull/75490#issuecomment-677790758) `zip_with()`,
> zip and zip_with seem like they would be useful :)
is this something I should add (assuming there is interest for this PR at all :))
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.
Fix memory leak in test "mem::uninit_write_slice_cloned_no_drop"
This fixes#80116. I replaced the `Rc` based method I was using with a type that panics when dropped.
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.
Fix overflow when converting ZST Vec to VecDeque
```rust
let v = vec![(); 100];
let queue = VecDeque::from(v);
println!("{:?}", queue);
```
This code will currently panic with a capacity overflow.
This PR resolves this issue and makes the code run fine.
Resolves#78532
Integer types have a `count_ones` method that end up calling
`intrinsics::ctpop`.
On some architectures, that intrinsic is translated as a corresponding
CPU instruction know as "popcount" or "popcnt".
This PR makes it so that searching for those names in rustdoc shows those methods.
CC https://blog.rust-lang.org/2020/11/19/Rust-1.48.html#adding-search-aliases
MaybeUninit::copy/clone_from_slice
This PR adds 2 new methods to MaybeUninit under the feature of `maybe_uninit_write_slice`: `copy_from_slice` and `clone_from_slice`.
These are useful for initializing uninitialized buffers (such as the one returned by `Vec::spare_capacity_mut` for example) with initialized data.
The methods behave similarly to the methods on slices, but the destination is uninitialized and they return the destination slice as an initialized slice.
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`
Do not inline finish_grow
Fixes#78471.
Looking at libgkrust.a in Firefox, the sizes for the `gkrust.*.o` file is:
- 18584816 (text) 582418 (data) with unmodified master
- 17937659 (text) 582554 (data) with #72227 reverted
- 17968228 (text) 582858 (data) with `#[inline(never)]` on `grow_amortized` and `grow_exact`, but that has some performance consequences
- 17927760 (text) 582322 (data) with this change
So in terms of size, at least in the case of Firefox, this patch more than undoes the regression. I don't think it should affect performance, but we'll see.
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
BTreeMap: clarify comments and panics around choose_parent_kv
Fixes a lie in recent code: `unreachable!("empty non-root node")` should shout "empty internal node", but it might as well be good and keep quiet
r? `@Mark-Simulacrum`
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.
std::iter: document iteration over `&T` and `&mut T`
A colleague of mine is new to Rust, and mentioned that it was “slightly
confusing” to figure out what `&mut` does in iterating over `&mut foo`:
```rust
for value in &mut self.my_vec {
// ...
}
```
My colleague had read the `std::iter` docs and not found the answer
there. There is a brief section at the top about “the three forms of
iteration”, which mentions `iter_mut`, but it doesn’t cover the purpose
of `&mut coll` for a collection `coll`. This patch adds an explanatory
section to the docs. I opted to create a new section so that it can
appear after the note that `impl<I: Iterator> IntoIterator for I`, and
it’s nice for the existing “three forms of iteration” to appear near the
top.
Test Plan:
Ran `./x.py doc library/core`, and the result looked good, including
links. Manually copy-pasted the two doctests into the playground and ran
them.
wchargin-branch: doc-iter-by-reference
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.
Clarify that String::split_at takes a byte index.
To someone skimming through the `String` docs and only reads the first line, the person could interpret "index" to be "char index". Later on in the docs it clarifies, but by adding "byte" it removes that ambiguity.
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.
Add some core::cmp::Ordering helpers
...to allow easier equal-to-or-greater-than and less-than-or-equal-to
comparisons.
Prior to Rust 1.42 a greater-than-or-equal-to comparison might be written
either as a match block, or a traditional conditional check like this:
```rust
if cmp == Ordering::Equal || cmp == Ordering::Greater {
// Do something
}
```
Which requires two instances of `cmp`. Don't forget that while `cmp` here
is very short, it could be something much longer in real use cases.
From Rust 1.42 a nicer alternative is possible:
```rust
if matches!(cmp, Ordering::Equal | Ordering::Greater) {
// Do something
}
```
The commit adds another alternative which may be even better in some cases:
```rust
if cmp.is_equal_or_greater() {
// Do something
}
```
The earlier examples could be cleaner than they are if the variants of
`Ordering` are imported such that `Equal`, `Greater` and `Less` can be
referred to directly, but not everyone will want to do that.
The new solution can shorten lines, help avoid logic mistakes, and avoids
having to import `Ordering` / `Ordering::*`.
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.
...to allow easier greater-than-or-equal-to and less-than-or-equal-to
comparisons, and variant checking without needing to import the enum,
similar to `Option::is_none()` / `Option::is_some()`, in situations where
you are dealing with an `Ordering` value. (Simple `PartialOrd` / `Ord`
based evaluation may not be suitable for all situations).
Prior to Rust 1.42 a greater-than-or-equal-to comparison might be written
either as a match block, or a traditional conditional check like this:
```rust
if cmp == Ordering::Equal || cmp == Ordering::Greater {
// Do something
}
```
Which requires two instances of `cmp`. Don't forget that while `cmp` here
is very short, it could be something much longer in real use cases.
From Rust 1.42 a nicer alternative is possible:
```rust
if matches!(cmp, Ordering::Equal | Ordering::Greater) {
// Do something
}
```
The commit adds another alternative which may be even better in some cases:
```rust
if cmp.is_ge() {
// Do something
}
```
The earlier examples could be cleaner than they are if the variants of
`Ordering` are imported such that `Equal`, `Greater` and `Less` can be
referred to directly, but not everyone will want to do that.
The new solution can shorten lines, help avoid logic mistakes, and avoids
having to import `Ordering` / `Ordering::*`.
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.
Constier maybe uninit
I was playing around trying to make `[T; N]::zip()` in #79451 be `const fn`. One of the things I bumped into was `MaybeUninit::assume_init`. Is there any reason for the intrinsic `assert_inhabited<T>()` and therefore `MaybeUninit::assume_init` not being `const`?
---
I have as best as I could tried to follow the instruction in [library/core/src/intrinsics.rs](https://github.com/rust-lang/rust/blob/master/library/core/src/intrinsics.rs#L11). I have no idea what I am doing but it seems to compile after some slight changes after the copy paste. Is this anywhere near how this should be done?
Also any ideas for name of the feature gate? I guess `const_maybe_assume_init` is quite misleading since I have added some more methods. Should I add test? If so what should be tested?
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.
Rollup of 12 pull requests
Successful merges:
- #79732 (minor stylistic clippy cleanups)
- #79750 (Fix trimming of lint docs)
- #79777 (Remove `first_merge` from liveness debug logs)
- #79795 (Privatize some of libcore unicode_internals)
- #79803 (Update xsv to prevent random CI failures)
- #79810 (Account for gaps in def path table during decoding)
- #79818 (Fixes to Rust coverage)
- #79824 (Strip prefix instead of replacing it with empty string)
- #79826 (Simplify visit_{foreign,trait}_item)
- #79844 (Move RWUTable to a separate module)
- #79861 (Update LLVM submodule)
- #79862 (Remove tab-lock and replace it with ctrl+up/down arrows to switch between search result tabs)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
Privatize some of libcore unicode_internals
My understanding is that these API are perma unstable, so it doesn't
make sense to pollute docs & IDE completion[1] with them.
[1]: https://github.com/rust-analyzer/rust-analyzer/issues/6738
ext/ucred: Support PID in peer creds on macOS
This is a follow-up to https://github.com/rust-lang/rust/pull/75148 (RFC: https://github.com/rust-lang/rust/issues/42839).
The original PR used `getpeereid` on macOS and the BSDs, since they don't (generally) support the `SO_PEERCRED` mechanism that Linux supplies.
This PR splits the macOS/iOS implementation of `peer_cred()` from that of the BSDs, since macOS supplies the `LOCAL_PEERPID` sockopt as a source of the missing PID. It also adds a `cfg`-gated tests that ensures that platforms with support for PIDs in `UCred` have the expected data.
Use is_write_vectored to optimize the write_vectored implementation for BufWriter
In case when the underlying writer does not have an efficient implementation `write_vectored`, the present implementation of
`write_vectored` for `BufWriter` may still forward vectored writes directly to the writer depending on the total length of the data. This misses the advantage of buffering, as the actually written slice may be small.
Provide an alternative code path for the non-vectored case, where the slices passed to `BufWriter` are coalesced in the buffer before being flushed to the underlying writer with plain `write` calls. The buffer is only bypassed if an individual slice's length is at least as large as the buffer.
Remove a FIXME comment referring to #72919 as the issue has been closed with an explanation provided.
The code in io::stdio before this change misused the ReentrantMutexes,
by calling init() on them and moving them afterwards. Now that
ReentrantMutex requires Pin for init(), this mistake is no longer easy
to make.
We also change the specialization of `SpecFromIterNested::from_iter` for
`TrustedLen` to use `Vec::with_capacity` when the iterator has a proper size
hint, instead of `Vec::new`, avoiding calls to `grow_*` and thus
`finish_grow` in some fully inlinable cases, which would regress with
this change.
Fixes#78471.
Fix SGX CI, take 3
Broken in #79038
r? `@Mark-Simulacrum`
I actually ran `./x.py test --target x86_64-fortanix-unknown-sgx` on the commit before submitting it this time.
Fix incorrect io::Take's limit resulting from io::copy specialization
The specialization introduced in #75272 fails to update `io::Take` wrappers after performing the copy syscalls which bypass those wrappers. The buffer flushing before the copy does update them correctly, but the bytes copied after the initial flush weren't subtracted.
The fix is to subtract the bytes copied from each `Take` in the chain of wrappers, even when an error occurs during the syscall loop. To do so the `CopyResult` enum now has to carry the bytes copied so far in the error case.
Provide IntoInnerError::into_parts
Hi. This is an updated version of the IntoInnerError bits of my previous portmanteau MR #78689. Thanks to `@jyn514` and `@m-ou-se` for helpful comments there.
I have made this insta-stable since it seems like it will probably be uncontroversial, but that is definitely something that someone from the libs API team should be aware of and explicitly consider.
I included a tangentially-related commit providing documentation of the buffer full behaviiour of `&mut [u8] as Write`; the behaviour I am documenting is relied on by the doctest for `into_parts`.
In particular, IntoIneerError only currently provides .error() which
returns a reference, not an owned value. This is not helpful and
means that a caller of BufWriter::into_inner cannot acquire an owned
io::Error which seems quite wrong.
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
disable a ptr equality test on Miri
This test relies on deduplication of constants. I do not think that this is a *guarantee* that Rust currently makes, and indeed Miri does not deduplicate constants the same way that rustc does, leading to different behavior in this test.
For now, I propose we simply disable this test in Miri.
Use more std:: instead of core:: in docs for consistency
``@rustbot`` label T-doc
Some cleanup work to use `std::` instead of `core::` in docs as much as possible. This helps with terminology and consistency, especially for newcomers from other languages that have often heard of `std` to describe the standard library but not of `core`.
Edit: I also added more intra doc links when I saw the opportunity.
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.
unix: Extend UnixStream and UnixDatagram to send and receive file descriptors
Add the functions `recv_vectored_fds` and `send_vectored_fds` to `UnixDatagram` and `UnixStream`. With this functions `UnixDatagram` and `UnixStream` can send and receive file descriptors, by using `recvmsg` and `sendmsg` system call.
std::io: Use sendfile for UnixStream
`UnixStream` was forgotten in #75272 .
Benchmark yields the following results.
Before:
`running 1 test
test sys::unix::kernel_copy::tests::bench_file_to_uds_copy ... bench: 54,399 ns/iter (+/- 6,817) = 2409 MB/s`
After:
`running 1 test
test sys::unix::kernel_copy::tests::bench_file_to_uds_copy ... bench: 18,627 ns/iter (+/- 6,007) = 7036 MB/s`
Avoid panic_bounds_check in fmt::write.
Writing any fmt::Arguments would trigger the inclusion of usize formatting and padding code in the resulting binary, because indexing used in fmt::write would generate code using panic_bounds_check, which prints the index and length.
These bounds checks are not necessary, as fmt::Arguments never contains any out-of-bounds indexes.
This change replaces them with unsafe get_unchecked, to reduce the amount of generated code, which is especially important for embedded targets.
---
Demonstration of the size of and the symbols in a 'hello world' no_std binary:
<details>
<summary>Source code</summary>
```rust
#![feature(lang_items)]
#![feature(start)]
#![no_std]
use core::fmt;
use core::fmt::Write;
#[link(name = "c")]
extern "C" {
#[allow(improper_ctypes)]
fn write(fd: i32, s: &str) -> isize;
fn exit(code: i32) -> !;
}
struct Stdout;
impl fmt::Write for Stdout {
fn write_str(&mut self, s: &str) -> fmt::Result {
unsafe { write(1, s) };
Ok(())
}
}
#[start]
fn main(_argc: isize, _argv: *const *const u8) -> isize {
let _ = writeln!(Stdout, "Hello World");
0
}
#[lang = "eh_personality"]
fn eh_personality() {}
#[panic_handler]
fn panic(_: &core::panic::PanicInfo) -> ! {
unsafe { exit(1) };
}
```
</details>
Before:
```
text data bss dec hex filename
6059 736 8 6803 1a93 before
```
```
0000000000001e00 T <T as core::any::Any>::type_id
0000000000003dd0 D core::fmt::num::DEC_DIGITS_LUT
0000000000001ce0 T core::fmt::num:👿:<impl core::fmt::Display for u64>::fmt
0000000000001ce0 T core::fmt::num:👿:<impl core::fmt::Display for usize>::fmt
0000000000001370 T core::fmt::write
0000000000001b30 t core::fmt::Formatter::pad_integral::write_prefix
0000000000001660 T core::fmt::Formatter::pad_integral
0000000000001350 T core::ops::function::FnOnce::call_once
0000000000001b80 t core::ptr::drop_in_place
0000000000001120 t core::ptr::drop_in_place
0000000000001c50 t core::iter::adapters::zip::Zip<A,B>::new
0000000000001c90 t core::iter::adapters::zip::Zip<A,B>::new
0000000000001b90 T core::panicking::panic_bounds_check
0000000000001c10 T core::panicking::panic_fmt
0000000000001130 t <&mut W as core::fmt::Write>::write_char
0000000000001200 t <&mut W as core::fmt::Write>::write_fmt
0000000000001250 t <&mut W as core::fmt::Write>::write_str
```
After:
```
text data bss dec hex filename
3068 600 8 3676 e5c after
```
```
0000000000001360 T core::fmt::write
0000000000001340 T core::ops::function::FnOnce::call_once
0000000000001120 t core::ptr::drop_in_place
0000000000001620 t core::iter::adapters::zip::Zip<A,B>::new
0000000000001660 t core::iter::adapters::zip::Zip<A,B>::new
0000000000001130 t <&mut W as core::fmt::Write>::write_char
0000000000001200 t <&mut W as core::fmt::Write>::write_fmt
0000000000001250 t <&mut W as core::fmt::Write>::write_str
```
Update tests to remove old numeric constants
Part of #68490.
Care has been taken to leave the old consts where appropriate, for testing backcompat regressions, module shadowing, etc. The intrinsics docs were accidentally referring to some methods on f64 as std::f64, which I changed due to being contrary with how we normally disambiguate the shadow module from the primitive. In one other place I changed std::u8 to std::ops since it was just testing path handling in macros.
For places which have legitimate uses of the old consts, deprecated attributes have been optimistically inserted. Although currently unnecessary, they exist to emphasize to any future deprecation effort the necessity of these specific symbols and prevent them from being accidentally removed.
Part of #68490.
Care has been taken to leave the old consts where appropriate, for testing backcompat regressions, module shadowing, etc. The intrinsics docs were accidentally referring to some methods on f64 as std::f64, which I changed due to being contrary with how we normally disambiguate the shadow module from the primitive. In one other place I changed std::u8 to std::ops since it was just testing path handling in macros.
For places which have legitimate uses of the old consts, deprecated attributes have been optimistically inserted. Although currently unnecessary, they exist to emphasize to any future deprecation effort the necessity of these specific symbols and prevent them from being accidentally removed.
BTreeMap: try to enhance various comments
All in internal documentation, propagating the "key-value pair" notation from public documentation.
r? ``@Mark-Simulacrum``
Require allocator to be static for boxed `Pin`-API
Allocators has to retain their validity until the instance and all of its clones are dropped. When pinning a value, it must live forever, thus, the allocator requires a `'static` lifetime for pinning a value. [Example from reddit](https://www.reddit.com/r/rust/comments/jymzdw/the_story_continues_vec_now_supports_custom/gd7qak2?utm_source=share&utm_medium=web2x&context=3):
```rust
let alloc = MyAlloc(/* ... */);
let pinned = Box::pin_in(42, alloc);
mem::forget(pinned); // Now `value` must live forever
// Otherwise `Pin`'s invariants are violated, storage invalidated
// before Drop was called.
// borrow of `memory` can end here, there is no value keeping it.
drop(alloc); // Oh, value doesn't live forever.
```