Support primitives in type info reflection
Tracking issue: rust-lang/rust#146922 `#![feature(type_info)]`
This PR supports {`bool`,`char`,`int`,`uint`,`float`,`str`} primitive types for feature `type_info` reflection.
r? @oli-obk
Unify and deduplicate From<T> float tests
cc rust-lang/rust#141726
Unify the From<bool> tests from f16.rs and f128.rs into a single float_test! in mod.rs.
Use `rand` crate more idiomatically
Small cleanup, found while working on something else.
We were using `rand` un-idiomatically in a couple of places, and it was bugging me...
stabilize `Peekable::next_if_map` (`#![feature(peekable_next_if_map)]`)
# Stabilization report
## Summary
`#![feature(peekable_next_if_map)]` is a variation of `next_if` on peekable iterators that can transform the peeked item. This creates a way to take ownership of the next item in an iterator when some condition holds, but put the item back when the condition doesn't hold. This pattern would otherwise have needed unwraps in many cases.
[Tracking issue](https://github.com/rust-lang/rust/issues/143702)
### What is stabilized
```rust
impl<I: Iterator> Peekable<I> {
pub fn next_if_map<R>(
&mut self,
f: impl FnOnce(I::Item) -> Result<R, I::Item>,
) -> Option<R> {
..
}
pub fn next_if_map_mut<R>(
&mut self,
f: impl FnOnce(&mut I::Item) -> Option<R>,
) -> Option<R> {
..
}
}
```
Example usage adapted from the ACP:
```rust
let mut it = Peekable::new("123".chars());
while let Some(digit) = it.next_if_map(|c| c.to_digit(10).ok_or(c)) {
codepoint = codepoint * 10 + digit;
}
```
or with `next_if_map_mut`:
```rust
let mut it = Peekable::new("123".chars());
while let Some(digit) = iter.next_if_map_mut(|c| c.to_digit(10)) {
line_num = line_num * 10 + digit;
}
```
Note that the major difference here is that `next_if_map_mut` does not get owned items from the iterator, but mutable references. With that api, the closure can return an `Option` which avoids an `ok_or`. This may require cloning or copying the iterator elements, so if that is expensive, the owned version, `next_if_map`, may be preferable.
### Nightly use
At the moment, this feature is barely used in nightly, though I've found multiple good uses for it in my own projects, hence my pushing for stabilization. It makes the kind of patterns used in recursive descent parsing super concise and maybe with its stabilization it will find more use.
### Test coverage
Besides a quite comprehensive doctest, this feature is tested (including panicking in the closure) here:
c880acdd31/library/coretests/tests/iter/adapters/peekable.rs (L275-L359)
## History
- ACP: https://github.com/rust-lang/libs-team/issues/613 accepted with https://github.com/rust-lang/libs-team/issues/613#issuecomment-3049844223
- implementation: https://github.com/rust-lang/rust/pull/143725 with tests, and no issues reported since july.
## Acknowledgments
ACP, implementation and tracking issue for this feature all by @kennytm <3
Implement round-ties-to-even for Duration Debug for consistency with f64
## Summary
This PR proposes a fix for rust-lang/rust#103747 implementing IEEE-754 S4.3 roundTiesToEven for Duration Debug implementation.
## Testing
Added new test in `time.rs` for validating roundTiesToEven behavior in Duration formatting. Reran all debug formatting tests in `time.rs` with `./x test library/coretests --test-args time::debug_formatting`.
This caused several performance regressions because of existing code
which uses `Read::read` and therefore requires full buffer
initialization. This is particularly a problem when the same buffer is
re-used for multiple read calls since this means it needs to be fully
re-initialized each time.
There is still some benefit to landing the API changes, but we will have
to add private APIs so that the existing infrastructure can
track and avoid redundant initialization.
test: update duplicate many_digits test to use f64 instead of f32
Replace the f32 test case with an f64 equivalent to improve coverage for parsing large digit counts in double-precision floating-point conversion. Specifically, this PR updates the `many_digits` test in `library/coretests/tests/num/dec2flt/parse.rs` to test f64 (double-precision) parsing instead of f32 (single-precision).
The test verifies that decimal strings with an excessive number of digits (beyond `Decimal::MAX_DIGITS`) are parsed correctly, ensuring proper truncation of insignificant digits. Previously, the same test was repeated twice (see comment https://github.com/rust-lang/rust/pull/86761#issuecomment-3623334228 by `@Viatorus).`
## Changes
- Replaced the duplicated f32 test case with an equivalent f64 test case.
- Updated the expected bit pattern and input string to a very long decimal with many trailing zeros, testing the limits of f64 precision.
Constify `DropGuard::dismiss` and trait impls
Feature: `drop_guard` (rust-lang/rust#144426), `const_convert` (rust-lang/rust#143773), `const_drop_guard` (no tracking issue yet)
Constifies `DropGuard::dismiss` and trait impls.
I reused `const_convert` (rust-lang/rust#143773) for the `Deref*` impls.
Implement benchmarks for uN::{gather,scatter}_bits
Feature gate: #![feature(uint_gather_scatter_bits)]
Tracking issue: https://github.com/rust-lang/rust/issues/149069
Accepted ACP: https://github.com/rust-lang/libs-team/issues/695#issuecomment-3549284861
For each method, there are three benchmarks, which differ in that the mask (second) argument is one of:
- constant at compile time
- runtime value but invariant for the measured loop
- different for each call
Sample output
```text
num::int_bits::u32::constant::gather_bits 555.82ns/iter +/- 22.41
num::int_bits::u32::constant::scatter_bits 545.45ns/iter +/- 124.26
num::int_bits::u32::invariant::gather_bits 8178.86ns/iter +/- 217.37
num::int_bits::u32::invariant::scatter_bits 7135.95ns/iter +/- 214.51
num::int_bits::u32::variable::gather_bits 10539.29ns/iter +/- 198.90
num::int_bits::u32::variable::scatter_bits 9671.26ns/iter +/- 254.88
```
(and similarly for the other `uN` types)
Additional test for uN::{gather,scatter}_bits
Feature gate: #![feature(uint_gather_scatter_bits)]
Tracking issue: https://github.com/rust-lang/rust/issues/149069
Accepted ACP: https://github.com/rust-lang/libs-team/issues/695#issuecomment-3549284861
Adds an additional runtime test for `uN::gather_bits` and `uN::scatter_bits` in coretests. They are each other's inverses in a sense, so a shared test can test both with relative ease.
I plan to follow up with optimized implementations for these functions.
Remove an outdated test
This... is a weird test.
It has two impls:
- `impl<T> From<Foo<T>> for Box<T>` (commented out, more on that later), and
- `impl<T> Into<Vec<T>> for Foo<T>`
The idea of that test is to show that the first impl doesn't compile, but the second does, thus `TryFrom` should be using `Into` and not `From` (because `Into` is more general, since the `From` impl doesn't compile).
However:
1. The types are different -- `Box` vs `Vec`, which is significant b/c `Box` is fundamental
2. The commented out impl actually compiles! (which wasn't detected b/c it's commented out :\ )
Here is a table for compilation of the impls:
| | `Vec` | `Box` |
|--------|--------------|----------------|
| `From` | since 1.41.0 | never |
| `Into` | always | not since 1.28 |
[godbolt used to test this](https://godbolt.org/z/T38E3jGKa)
Order of events:
1. in `1.28` the `incoherent_fundamental_impls` lint becomes deny by default (this is *not* mentioned in the changelog yay)
2. `1.32` changed absolutely nothing, even though this version is credited in the test
3. the test was added (I'm not exactly sure when) (see https://github.com/rust-lang/rust/pull/56796)
4. in `1.41` coherence was relaxed to allow `From`+`Vec` to compile
To conclude: since `1.41` this test does nothing (and before that it was written in a way which did not detect this change). It looks to me like today (since `1.41`) we *could* bound `TryFrom` impl with `From` (but now it'd be a useless breaking change of course).
Am I missing anything? Is there a useful version of this test that could be written?
Remove initialized-bytes tracking from `BorrowedBuf` and `BorrowedCursor`
As discussed extensively in libs-api, the initialized-bytes tracking primarily benefits calls to `read_buf` that end up initializing the buffer and calling `read`, at the expense of calls to `read_buf` that *don't* need to initialize the buffer. Essentially, this optimizes for the past at the expense of the future. If people observe performance issues using `read_buf` (or something that calls it) with a given `Read` impl, they can fix those performance issues by implementing `read_buf` for that `Read`.
Update the documentation to stop talking about initialized-but-unfilled bytes.
Remove all functions that just deal with those bytes and their tracking, and remove usage of those methods.
Remove `BorrowedCursor::advance` as there's no longer a safe case for advancing within initialized-but-unfilled bytes. Rename `BorrowedCursor::advance_unchecked` to `advance`.
Update tests.
r? ``@Amanieu``
As discussed extensively in libs-api, the initialized-bytes tracking
primarily benefits calls to `read_buf` that end up initializing the
buffer and calling `read`, at the expense of calls to `read_buf` that
*don't* need to initialize the buffer. Essentially, this optimizes for
the past at the expense of the future. If people observe performance
issues using `read_buf` (or something that calls it) with a given `Read`
impl, they can fix those performance issues by implementing `read_buf`
for that `Read`.
Update the documentation to stop talking about initialized-but-unfilled
bytes.
Remove all functions that just deal with those bytes and their tracking,
and remove usage of those methods.
Remove `BorrowedCursor::advance` as there's no longer a safe case for
advancing within initialized-but-unfilled bytes. Rename
`BorrowedCursor::advance_unchecked` to `advance`.
Update tests.
Rename `DropGuard::into_inner` to `DropGuard::dismiss`
Tracking issue: https://github.com/rust-lang/rust/issues/144426
One of the open questions blocking the stabilization of `DropGuard` is what to name the associated method that prevents the destructor from running, and returns the captured value. This method is currently called `into_inner`, but most people (including myself) feel like this would benefit from a method that calls more attention to itself.
This PR proposes naming this method `dismiss`, after the Linux kernel's [`ScopeGuard::dismiss`](https://rust.docs.kernel.org/kernel/types/struct.ScopeGuard.html#method.dismiss). Which crucially does not evoke images of violence or weaponry the way alternatives such as "disarm" or "defuse" do. And personally I enjoy the visual metaphor of "dismissing a guard" (e.g. a person keeping watch over something) - a job well done, they're free to go.
This PR also changes the signature from an static method to an instance method. This also matches the Linux kernel's API, and seems alright since `dismiss` is not nearly as ubiquitous as `into_inner`. This makes it more convenient to use, with a much lower risk of conflicting. Though in the rare case there might be ambiguity, the explicit notation is available as a fallback.
```rust
let x = DropGuard::into_inner(guard); // ← current
let x = guard.dismiss(); // ← proposed
Stabilize `maybe_uninit_write_slice`
Stabilize feature `maybe_uninit_write_slice` (closes https://github.com/rust-lang/rust/issues/79995).
Note that this also const-stabilizes `<[MaybeUninit<_>]>::write_copy_of_slice`. That method depends on `<[_]>::copy_from_slice`, which is already const-stable, and `<[MaybeUninit<_>]>::assume_init_mut` which is now also stable.