| Age | Commit message (Collapse) | Author | Lines |
|
|
|
Simplify 'product' factorial example
This simplifies the [`factorial(n: 32)`](https://doc.rust-lang.org/std/iter/trait.Iterator.html#examples-46) implementation as example for the `Iterator::product()` function.
It currently uses unnecessary additional complexity.
Although very minimal, I do not want to include it in some other irrelevant PR.
|
|
Add core::iter::once_with()
Functions `iter::once()` and `iter::repeat()` construct iterators from values. The latter has the lazy variant `iter::repeat_with()`, but the former doesn't. This PR therefore adds `iter::once_with()`.
Another way to think of `iter::once_with()` is that it's a function that converts `FnOnce() -> T` into `Iterator<Item = T>`.
If this seems like a reasonable addition, I'll open a tracking issue and update the `#[feature(...)]` attributes.
|
|
|
|
|
|
|
|
|
|
Stabilize core::convert::identity
r? @SimonSapin
fixes https://github.com/rust-lang/rust/issues/53500
This is waiting for FCP to complete but in the interim it would be good to review.
|
|
|
|
|
|
|
|
Rollup of 4 pull requests
Successful merges:
- #57004 (Make `TokenStream` less recursive.)
- #57102 (NLL: Add union justifications to conflicting borrows.)
- #57337 (rustc: Place wasm linker args first instead of last)
- #57549 (Add #[must_use] message to Iterator and Future)
Failed merges:
r? @ghost
|
|
Add #[must_use] message to Iterator and Future
~~Iterator's message is based on current iterator adaptor's #[must_use] message (added in #15561) and https://github.com/rust-lang/rust/pull/56677/files#r241236020~~
Future's message is the same as those used in [futures-rs](https://github.com/rust-lang-nursery/futures-rs/search?q=must_use&unscoped_q=must_use) and [tokio](https://github.com/tokio-rs/tokio/search?q=must_use&unscoped_q=must_use).
r? @Centril
|
|
|
|
Stabilize `transpose_result` in 1.33
fixes https://github.com/rust-lang/rust/issues/47338.
FCP completed: https://github.com/rust-lang/rust/issues/47338#issuecomment-453762236
r? @alexreg
|
|
Rollup of 16 pull requests
Successful merges:
- #57351 (Don't actually create a full MIR stack frame when not needed)
- #57353 (Optimise floating point `is_finite` (2x) and `is_infinite` (1.6x).)
- #57412 (Improve the wording)
- #57436 (save-analysis: use a fallback when access levels couldn't be computed)
- #57453 (lldb_batchmode.py: try `import _thread` for Python 3)
- #57454 (Some cleanups for core::fmt)
- #57461 (Change `String` to `&'static str` in `ParseResult::Failure`.)
- #57473 (std: Render large exit codes as hex on Windows)
- #57474 (save-analysis: Get path def from parent in case there's no def for the path itself.)
- #57494 (Speed up item_bodies for large match statements involving regions)
- #57496 (re-do docs for core::cmp)
- #57508 (rustdoc: Allow inlining of reexported crates and crate items)
- #57547 (Use `ptr::eq` where applicable)
- #57557 (resolve: Mark extern crate items as used in more cases)
- #57560 (hygiene: Do not treat `Self` ctor as a local variable)
- #57564 (Update the const fn tracking issue to the new metabug)
Failed merges:
r? @ghost
|
|
|
|
|
|
|
|
re-do docs for core::cmp
Fixes #32934
|
|
Some cleanups for core::fmt
|
|
Optimise floating point `is_finite` (2x) and `is_infinite` (1.6x).
These can both rely on IEEE754 semantics to be made faster, by folding
away the sign with an abs (left private for now), and then comparing
to infinity, letting the NaN semantics of a direct float comparison
handle NaN input properly.
The `abs` bit-fiddling is simple (a single and), and so these new
forms compile down to a few instructions, without branches, e.g. for
f32:
```asm
is_infinite:
andps xmm0, xmmword ptr [rip + .LCPI2_0] ; 0x7FFF_FFFF
ucomiss xmm0, dword ptr [rip + .LCPI2_1] ; 0x7F80_0000
setae al
ret
is_finite:
andps xmm0, xmmword ptr [rip + .LCPI1_0] ; 0x7FFF_FFFF
movss xmm1, dword ptr [rip + .LCPI1_1] ; 0x7F80_0000
ucomiss xmm1, xmm0
seta al
ret
```
When used in loops/repeatedly, they get even better: the memory
operations (loading the mask 0x7FFFFFFF for abs, and infinity
0x7F80_0000) are likely to be hoisted out of the individual calls, to
be shared, and the `seta`/`setae` are likely to be collapsed into
conditional jumps or moves (or similar).
The old `is_infinite` did two comparisons, and the old `is_finite` did
three (with a branch), and both of them had to check the flags after
every one of those comparison. These functions have had that old
implementation since they were added in
https://github.com/rust-lang/rust/commit/6284190ef9918e05cb9147a2a81100ddcb06fea8
7 years ago.
Benchmark (`abs` is the new form, `std` is the old):
```
test f32_is_finite_abs ... bench: 55 ns/iter (+/- 10)
test f32_is_finite_std ... bench: 118 ns/iter (+/- 5)
test f32_is_infinite_abs ... bench: 53 ns/iter (+/- 1)
test f32_is_infinite_std ... bench: 84 ns/iter (+/- 6)
test f64_is_finite_abs ... bench: 52 ns/iter (+/- 12)
test f64_is_finite_std ... bench: 128 ns/iter (+/- 25)
test f64_is_infinite_abs ... bench: 54 ns/iter (+/- 5)
test f64_is_infinite_std ... bench: 93 ns/iter (+/- 23)
```
```rust
#![feature(test)]
extern crate test;
use std::{f32, f64};
use test::Bencher;
const VALUES_F32: &[f32] = &[0.910, 0.135, 0.735, -0.874, 0.518, 0.150, -0.527, -0.418, 0.449, -0.158, -0.064, -0.144, -0.948, -0.103, 0.225, -0.104, -0.795, 0.435, 0.860, 0.027, 0.625, -0.848, -0.454, 0.359, -0.930, 0.067, 0.642, 0.976, -0.682, -0.035, 0.750, 0.005, -0.825, 0.731, -0.850, -0.740, -0.118, -0.972, 0.888, -0.958, 0.086, 0.237, -0.580, 0.488, 0.028, -0.552, 0.302, 0.058, -0.229, -0.166, -0.248, -0.430, 0.789, -0.122, 0.120, -0.934, -0.911, -0.976, 0.882, -0.410, 0.311, -0.611, -0.758, 0.786, -0.711, 0.378, 0.803, -0.068, 0.932, 0.483, 0.085, 0.247, -0.128, -0.839, -0.737, -0.605, 0.637, -0.230, -0.502, 0.231, -0.694, -0.400, -0.441, 0.142, 0.174, 0.681, -0.763, -0.608, 0.848, -0.550, 0.883, -0.212, 0.876, 0.186, -0.909, 0.401, -0.533, -0.961, 0.539, -0.298, -0.448, 0.223, -0.307, -0.594, 0.629, -0.534, 0.959, 0.349, -0.926, -0.523, -0.895, -0.157, -0.074, -0.060, 0.513, -0.647, -0.649, 0.428, 0.401, 0.391, 0.426, 0.700, 0.880, -0.101, 0.862, 0.493, 0.819, -0.597];
#[bench]
fn f32_is_infinite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().any(|x| x.is_infinite()));
}
#[bench]
fn f32_is_infinite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().any(|x| x.abs()== f32::INFINITY));
}
#[bench]
fn f32_is_finite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().all(|x| x.is_finite()));
}
#[bench]
fn f32_is_finite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().all(|x| x.abs() < f32::INFINITY));
}
const VALUES_F64: &[f64] = &[0.910, 0.135, 0.735, -0.874, 0.518, 0.150, -0.527, -0.418, 0.449, -0.158, -0.064, -0.144, -0.948, -0.103, 0.225, -0.104, -0.795, 0.435, 0.860, 0.027, 0.625, -0.848, -0.454, 0.359, -0.930, 0.067, 0.642, 0.976, -0.682, -0.035, 0.750, 0.005, -0.825, 0.731, -0.850, -0.740, -0.118, -0.972, 0.888, -0.958, 0.086, 0.237, -0.580, 0.488, 0.028, -0.552, 0.302, 0.058, -0.229, -0.166, -0.248, -0.430, 0.789, -0.122, 0.120, -0.934, -0.911, -0.976, 0.882, -0.410, 0.311, -0.611, -0.758, 0.786, -0.711, 0.378, 0.803, -0.068, 0.932, 0.483, 0.085, 0.247, -0.128, -0.839, -0.737, -0.605, 0.637, -0.230, -0.502, 0.231, -0.694, -0.400, -0.441, 0.142, 0.174, 0.681, -0.763, -0.608, 0.848, -0.550, 0.883, -0.212, 0.876, 0.186, -0.909, 0.401, -0.533, -0.961, 0.539, -0.298, -0.448, 0.223, -0.307, -0.594, 0.629, -0.534, 0.959, 0.349, -0.926, -0.523, -0.895, -0.157, -0.074, -0.060, 0.513, -0.647, -0.649, 0.428, 0.401, 0.391, 0.426, 0.700, 0.880, -0.101, 0.862, 0.493, 0.819, -0.597];
#[bench]
fn f64_is_infinite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().any(|x| x.is_infinite()));
}
#[bench]
fn f64_is_infinite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().any(|x| x.abs() == f64::INFINITY));
}
#[bench]
fn f64_is_finite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().all(|x| x.is_finite()));
}
#[bench]
fn f64_is_finite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().all(|x| x.abs() < f64::INFINITY));
}
```
|
|
|
|
|
|
|
|
|
|
|
|
|
|
name old ns/iter new ns/iter diff ns/iter diff % speedup
fmt::write_str_macro1 13,927 12,489 -1,438 -10.33% x 1.12
fmt::write_str_macro2 24,633 23,418 -1,215 -4.93% x 1.05
fmt::write_str_macro_debug 234,633 233,092 -1,541 -0.66% x 1.01
fmt::write_str_ref 5,819 5,823 4 0.07% x 1.00
fmt::write_str_value 6,012 5,828 -184 -3.06% x 1.03
fmt::write_vec_macro1 18,550 17,143 -1,407 -7.58% x 1.08
fmt::write_vec_macro2 30,369 28,920 -1,449 -4.77% x 1.05
fmt::write_vec_macro_debug 244,338 244,901 563 0.23% x 1.00
fmt::write_vec_ref 5,952 5,885 -67 -1.13% x 1.01
fmt::write_vec_value 5,944 5,894 -50 -0.84% x 1.01
|
|
note that FromStr does not work for borrowed types
Fixes #47757
|
|
Add link destination for `read-ownership`
Resolves #56610.
|
|
Const-stabilize `const_int_ops` + `const_ip`
r? @oli-obk
## Note for relnotes: This PR includes https://github.com/rust-lang/rust/pull/57105.
I've added T-lang since this affects intrinsics and the operational semantics of Rust's `const fn` fragment.
## Stable APIs proposed for constification
+ `const_int_ops`:
+ `count_ones`
+ `count_zeros`
+ `leading_zeros`
+ `trailing_zeros`
+ `swap_bytes`
+ `from_be`
+ `from_le`
+ `to_be`
+ `to_le`
+ `const_ip`
+ `Ipv4Addr::new`
## Unstable APIs constified
+ `const_int_conversion`:
+ `reverse_bits`
|
|
Fixes #32934
|
|
|
|
Fixes #47757
|
|
|
|
Reborrow Pin<P> using &mut in `Pin::set`
Fixes https://github.com/rust-lang/rust/issues/57339.
This makes it possible to call `.set` multiple times without
using `.as_mut()` first to reborrow the pointer.
r? @withoutboats
cc @rust-lang/libs
|
|
|
|
check missing docs for reexported macros as well
Fixes #56334.
|
|
|
|
|
|
|
|
This makes it possible to call `.set` multiple times without
using `.as_mut()` first to reborrow the pointer.
|
|
Fixes #57306
|
|
Add duration constants
Add constants `SECOND`, `MILLISECOND`, `MICROSECOND`, and `NANOSECOND` to `core::time`.
This will make working with durations more ergonomic. Compare:
```rust
// Convenient, but deprecated function.
thread::sleep_ms(2000);
// The current canonical way to sleep for two seconds.
thread::sleep(Duration::from_secs(2));
// Sleeping using one of the new constants.
thread::sleep(2 * SECOND);
```
|
|
These can both rely on IEEE754 semantics to be made faster, by folding
away the sign with an abs (left private for now), and then comparing
to infinity, letting the NaN semantics of a direct float comparison
handle NaN input properly.
The `abs` bit-fiddling is simple (a single and), and so these new
forms compile down to a few instructions, without branches, e.g. for
f32:
```asm
is_infinite:
andps xmm0, xmmword ptr [rip + .LCPI2_0] ; 0x7FFF_FFFF
ucomiss xmm0, dword ptr [rip + .LCPI2_1] ; 0x7F80_0000
setae al
ret
is_finite:
andps xmm0, xmmword ptr [rip + .LCPI1_0] ; 0x7FFF_FFFF
movss xmm1, dword ptr [rip + .LCPI1_1] ; 0x7F80_0000
ucomiss xmm1, xmm0
seta al
ret
```
When used in loops/repeatedly, they get even better: the memory
operations (loading the mask 0x7FFFFFFF for abs, and infinity
0x7F80_0000) are likely to be hoisted out of the individual calls, to
be shared, and the `seta`/`setae` are likely to be collapsed into
conditional jumps or moves (or similar).
The old `is_infinite` did two comparisons, and the old `is_finite` did
three (with a branch), and both of them had to check the flags after
every one of those comparison. These functions have had that old
implementation since they were added in
https://github.com/rust-lang/rust/commit/6284190ef9918e05cb9147a2a81100ddcb06fea8
7 years ago.
Benchmark (`abs` is the new form, `std` is the old):
```
test f32_is_finite_abs ... bench: 55 ns/iter (+/- 10)
test f32_is_finite_std ... bench: 118 ns/iter (+/- 5)
test f32_is_infinite_abs ... bench: 53 ns/iter (+/- 1)
test f32_is_infinite_std ... bench: 84 ns/iter (+/- 6)
test f64_is_finite_abs ... bench: 52 ns/iter (+/- 12)
test f64_is_finite_std ... bench: 128 ns/iter (+/- 25)
test f64_is_infinite_abs ... bench: 54 ns/iter (+/- 5)
test f64_is_infinite_std ... bench: 93 ns/iter (+/- 23)
```
```rust
#![feature(test)]
extern crate test;
use std::{f32, f64};
use test::Bencher;
const VALUES_F32: &[f32] = &[0.910, 0.135, 0.735, -0.874, 0.518, 0.150, -0.527, -0.418, 0.449, -0.158, -0.064, -0.144, -0.948, -0.103, 0.225, -0.104, -0.795, 0.435, 0.860, 0.027, 0.625, -0.848, -0.454, 0.359, -0.930, 0.067, 0.642, 0.976, -0.682, -0.035, 0.750, 0.005, -0.825, 0.731, -0.850, -0.740, -0.118, -0.972, 0.888, -0.958, 0.086, 0.237, -0.580, 0.488, 0.028, -0.552, 0.302, 0.058, -0.229, -0.166, -0.248, -0.430, 0.789, -0.122, 0.120, -0.934, -0.911, -0.976, 0.882, -0.410, 0.311, -0.611, -0.758, 0.786, -0.711, 0.378, 0.803, -0.068, 0.932, 0.483, 0.085, 0.247, -0.128, -0.839, -0.737, -0.605, 0.637, -0.230, -0.502, 0.231, -0.694, -0.400, -0.441, 0.142, 0.174, 0.681, -0.763, -0.608, 0.848, -0.550, 0.883, -0.212, 0.876, 0.186, -0.909, 0.401, -0.533, -0.961, 0.539, -0.298, -0.448, 0.223, -0.307, -0.594, 0.629, -0.534, 0.959, 0.349, -0.926, -0.523, -0.895, -0.157, -0.074, -0.060, 0.513, -0.647, -0.649, 0.428, 0.401, 0.391, 0.426, 0.700, 0.880, -0.101, 0.862, 0.493, 0.819, -0.597];
#[bench]
fn f32_is_infinite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().any(|x| x.is_infinite()));
}
#[bench]
fn f32_is_infinite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().any(|x| x.abs()== f32::INFINITY));
}
#[bench]
fn f32_is_finite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().all(|x| x.is_finite()));
}
#[bench]
fn f32_is_finite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F32).iter().all(|x| x.abs() < f32::INFINITY));
}
const VALUES_F64: &[f64] = &[0.910, 0.135, 0.735, -0.874, 0.518, 0.150, -0.527, -0.418, 0.449, -0.158, -0.064, -0.144, -0.948, -0.103, 0.225, -0.104, -0.795, 0.435, 0.860, 0.027, 0.625, -0.848, -0.454, 0.359, -0.930, 0.067, 0.642, 0.976, -0.682, -0.035, 0.750, 0.005, -0.825, 0.731, -0.850, -0.740, -0.118, -0.972, 0.888, -0.958, 0.086, 0.237, -0.580, 0.488, 0.028, -0.552, 0.302, 0.058, -0.229, -0.166, -0.248, -0.430, 0.789, -0.122, 0.120, -0.934, -0.911, -0.976, 0.882, -0.410, 0.311, -0.611, -0.758, 0.786, -0.711, 0.378, 0.803, -0.068, 0.932, 0.483, 0.085, 0.247, -0.128, -0.839, -0.737, -0.605, 0.637, -0.230, -0.502, 0.231, -0.694, -0.400, -0.441, 0.142, 0.174, 0.681, -0.763, -0.608, 0.848, -0.550, 0.883, -0.212, 0.876, 0.186, -0.909, 0.401, -0.533, -0.961, 0.539, -0.298, -0.448, 0.223, -0.307, -0.594, 0.629, -0.534, 0.959, 0.349, -0.926, -0.523, -0.895, -0.157, -0.074, -0.060, 0.513, -0.647, -0.649, 0.428, 0.401, 0.391, 0.426, 0.700, 0.880, -0.101, 0.862, 0.493, 0.819, -0.597];
#[bench]
fn f64_is_infinite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().any(|x| x.is_infinite()));
}
#[bench]
fn f64_is_infinite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().any(|x| x.abs() == f64::INFINITY));
}
#[bench]
fn f64_is_finite_std(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().all(|x| x.is_finite()));
}
#[bench]
fn f64_is_finite_abs(b: &mut Bencher) {
b.iter(|| test::black_box(VALUES_F64).iter().all(|x| x.abs() < f64::INFINITY));
}
```
|
|
|
|
|
|
|
|
|