Lazy type-alias-impl-trait
Previously opaque types were processed by
1. replacing all mentions of them with inference variables
2. memorizing these inference variables in a side-table
3. at the end of typeck, resolve the inference variables in the side table and use the resolved type as the hidden type of the opaque type
This worked okayish for `impl Trait` in return position, but required lots of roundabout type inference hacks and processing.
This PR instead stops this process of replacing opaque types with inference variables, and just keeps the opaque types around.
Whenever an opaque type `O` is compared with another type `T`, we make the comparison succeed and record `T` as the hidden type. If `O` is compared to `U` while there is a recorded hidden type for it, we grab the recorded type (`T`) and compare that against `U`. This makes implementing
* https://github.com/rust-lang/rfcs/pull/2515
much simpler (previous attempts on the inference based scheme were very prone to ICEs and general misbehaviour that was not explainable except by random implementation defined oddities).
r? `@nikomatsakis`
fixes#93411fixes#88236
Make io::Error use 64 bits on targets with 64 bit pointers.
I've wanted this for a long time, but didn't see a good way to do it without having extra allocation. When looking at it yesterday, it was more clear what to do for some reason.
This approach avoids any additional allocations, and reduces the size by half (8 bytes, down from 16). AFAICT it doesn't come additional runtime cost, and the compiler seems to do a better job with code using it.
Additionally, this `io::Error` has a niche (still), so `io::Result<()>` is *also* 64 bits (8 bytes, down from 16), and `io::Result<usize>` (used for lots of io trait functions) is 2x64 bits (16 bytes, down from 24 — this means on x86_64 it can use the nice rax/rdx 2-reg struct return). More generally, it shaves a whole 64 bit integer register off of the size of basically any `io::Result<()>`.
(For clarity: Improving `io::Result` (rather than io::Error) was most of the motivation for this)
On 32 bit (or other non-64bit) targets we still use something equivalent the old repr — I don't think think there's improving it, since one of the fields it stores is a `i32`, so we can't get below that, and it's already about as close as we can get to it.
---
### Isn't Pointer Tagging Dodgy?
The details of the layout, and why its implemented the way it is, are explained in the header comment of library/std/src/io/error/repr_bitpacked.rs. There's probably more details than there need to be, but I didn't trim it down that much, since there's a lot of stuff I did deliberately, that might have not seemed that way.
There's actually only one variant holding a pointer which gets tagged. This one is the (holder for the) user-provided error.
I believe the scheme used to tag it is not UB, and that it preserves pointer provenance (even though often pointer tagging does not) because the tagging operation is just `core::ptr::add`, and untagging is `core::ptr::sub`. The result of both operations lands inside the original allocation, so it would follow the safety contract of `core::ptr::{add,sub}`.
The other pointer this had to encode is not tagged — or rather, the tagged repr is equivalent to untagged (it's tagged with 0b00, and has >=4b alignment, so we can reuse the bottom bits). And the other variants we encode are just integers, which (which can be untagged using bitwise operations without worry — they're integers).
CC `@RalfJung` for the stuff in repr_bitpacked.rs, as my comments are informed by a lot of the UCG work, but it's possible I missed something or got it wrong (even if the implementation is okay, there are parts of the header comment that says things like "We can't do $x" which could be false).
---
### Why So Many Changes?
The repr change was mostly internal, but changed one widely used API: I had to switch how `io::Error::new_const` works.
This required switching `io::Error::new_const` to take the full message data (including the kind) as a `&'static`, rather than just the string. This would have been really tedious, but I made a macro that made it much simpler, but it was a wide change since `io::Error::new_const` is used everywhere.
This included changing files for a lot of targets I don't have easy access to (SGX? Haiku? Windows? Who has heard of these things), so I expect there to be spottiness in CI initially, unless luck is on my side.
Anyway this large only tangentially-related change is all in the first commit (although that commit also pulls the previous repr out into its own file), whereas the packing stuff is all in commit 2.
---
P.S. I haven't looked at all of this since writing it, and will do a pass over it again later, sorry for any obvious typos or w/e. I also definitely repeat myself in comments and such.
(It probably could use more tests too. I did some basic testing, and made it so we `debug_assert!` in cases the decode isn't what we encoded, but I don't know the degree which I can assume libstd's testing of IO would exercise this. That is: it wouldn't be surprising to me if libstds IO testing were minimal, especially around error cases, although I have no idea).
bootstrap: prefer using '--config' over 'RUST_BOOTSTRAP_CONFIG'
Signed-off-by: Muhammad Falak R Wani <falakreyaz@gmail.com>
Closes: #93725
Rleated: #92260
Rerun bootstrap's build script when RUSTC changes
Previously, rustbuild would give strange errors if you tried to reuse the same build directory under two names:
```
$ mkdir tmp && cd tmp
$ ../x.py check
Building rustbuild
Finished dev [unoptimized] target(s) in 35.27s
Checking stage0 std artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
^C
$ cd ..
$ mv tmp/build build
$ ./x.py check
Building rustbuild
Compiling bootstrap v0.0.0 (/home/jnelson/rust-lang/rust/src/bootstrap)
Finished dev [unoptimized] target(s) in 11.18s
failed to execute command: "/home/jnelson/rust-lang/rust/tmp/build/x86_64-unknown-linux-gnu/stage0/bin/rustc" "--target" "x86_64-unknown-linux-gnu" "--print" "target-libdir"
error: No such file or directory (os error 2)
```
This fixes the error. Reusing the same build directory is useful if you want to test path-related things in
bootstrap itself, without having to recompile it each time.
For good measure, this also reruns the build script when PATH changes.
Use shallow clones for submodules managed by rustbuild, not just bootstrap.py
I missed this in https://github.com/rust-lang/rust/pull/89757; it made
`x.py test src/bootstrap` very slow.
Update tracking issue for `const_fn_trait_bound`
It previously pointed to #57563, the conglomerate issue for `const fn` (presumably under the feature gate `const_fn`). This tracking issue doesn't mention anything about `const_fn_trait_bound`(the only occurrence of "trait bound" is for the now-removed `?const Trait` syntax), which can be confusing to people who want to find out more about trait bounds on `const fn`s. This pull request changes the tracking issue to one meant specifically for `const_fn_trait_bound`, #93706, which can help collect information on this feature's stabilization and point users towards `const_trait_impl` if they're looking for const-in-const-contexts trait bounds.
Fixes#93679.
`````@rustbot````` modify labels +A-const-fn +F-const_trait_impl
Linkify sidebar headings for sibling items
Also adjust CSS so this doesn't produce excess padding/margin.
Note: I tried and failed to write a test with browser-UI-test. First I tried to `assert-property: (".block.mod h3 a", {"href": "index.html#macros"})`. But the `href` that gets read out is the fully-quallified URL, starting with `file:///`. That URL will differ depending on what path the test is run from, so that doesn't work.
Next I tried clicking on the appropriate sidebar link, and verifying that the appropriate heading on the next page is highlighted with the right background color. However, that also didn't work: according to browser-UI-test, the targeted heading was plain white. However, running with no-headless, I could see that it actually was yellow. I suspect this is a bug in the older version of Chromium used with browser-UI-test's bundled puppeteer, since it doesn't reproduce on latest Chrome.
Fixes#92957
Demo: https://rustdoc.crud.net/jsha/linkify-sidebar-headings/std/string/trait.ToString.html
r? ``@GuillaumeGomez``
Impl {Add,Sub,Mul,Div,Rem,BitXor,BitOr,BitAnd}Assign<$t> for Wrapping<$t> for rust 1.60.0
Tracking issue #93204
This is about adding basic integer operations to the `Wrapping` type:
```rust
let mut value = Wrapping(2u8);
value += 3u8;
value -= 1u8;
value *= 2u8;
value /= 2u8;
value %= 2u8;
value ^= 255u8;
value |= 123u8;
value &= 2u8;
```
Because this adds stable impls on a stable type, it runs into the following issue if an `#[unstable(...)]` attribute is used:
```
an `#[unstable]` annotation here has no effect
note: see issue #55436 <https://github.com/rust-lang/rust/issues/55436> for more information
```
This means - if I understood this correctly - the new impls have to be stabilized instantly.
Which in turn means, this PR has to kick of an FCP on the tracking issue as well?
This impl is analog to 1c0dc1810d#92356 for the `Saturating` type ``@dtolnay`` ``@Mark-Simulacrum``
Suggest 1-tuple parentheses on exprs without existing parens
A follow-on from #86116, split out from #90677.
This alters the suggestion to add a trailing comma to create a 1-tuple - previously we would only apply this if the relevant expression was parenthesised. We now make the suggestion regardless of parentheses, which reduces the fragility of the check (w.r.t formatting).
e.g.
```rust
let a: Option<(i32,)> = Some(3);
```
gets the below suggestion:
```rust
let a: Option<(i32,)> = Some((3,));
// ^ ^^
```
This change also improves the suggestion in other ways, such as by only making the suggestion if the types would match after the suggestion is applied and making the suggestion a multipart suggestion.
Make the pre-commit script pre-push instead
This should make it substantially less annoying, and hopefully more
people will find it useful. In particular, it will no longer run tidy
each time you run `git commit --amend` or rebase a branch.
This also warns if you have the old script in pre-commit; see the HACK
comment for details.
r? ````@Mark-Simulacrum```` cc ````@caass````
use `fold_list` in `try_super_fold_with` for `SubstsRef`
split out from #93505 as this by itself is responsible for most of the perf improvements there
r? `@michaelwoerister`
Previously, rustbuild would give strange errors if you tried to reuse the same build directory under two names:
```
$ mkdir tmp && cd tmp
$ ../x.py check
Building rustbuild
Finished dev [unoptimized] target(s) in 35.27s
Checking stage0 std artifacts (x86_64-unknown-linux-gnu -> x86_64-unknown-linux-gnu)
^C
$ cd ..
$ mv tmp/build build
$ ./x.py check
Building rustbuild
Compiling bootstrap v0.0.0 (/home/jnelson/rust-lang/rust/src/bootstrap)
Finished dev [unoptimized] target(s) in 11.18s
failed to execute command: "/home/jnelson/rust-lang/rust/tmp/build/x86_64-unknown-linux-gnu/stage0/bin/rustc" "--target" "x86_64-unknown-linux-gnu" "--print" "target-libdir"
error: No such file or directory (os error 2)
```
This fixes the error. Reusing the same build directory is useful if you want to test path-things in
bootstrap itself, without having to recompile it each time.
For good measure, this also reruns the build script when PATH changes.
Fix invalid special casing of the unreachable! macro
This pull-request fix an invalid special casing of the `unreachable!` macro in the same way the `panic!` macro was solved, by adding two new internal only macros `unreachable_2015` and `unreachable_2021` edition dependent and turn `unreachable!` into a built-in macro that do dispatching. This logic is stolen from the `panic!` macro.
~~This pull-request also adds an internal feature `format_args_capture_non_literal` that allows capturing arguments from formatted string that expanded from macros. The original RFC #2795 mentioned this as a future possibility. This feature is [required](https://github.com/rust-lang/rust/issues/92137#issuecomment-1018630522) because of concatenation that needs to be done inside the macro:~~
```rust
$crate::concat!("internal error: entered unreachable code: ", $fmt)
```
**In summary** the new behavior for the `unreachable!` macro with this pr is:
Edition 2021:
```rust
let x = 5;
unreachable!("x is {x}");
```
```
internal error: entered unreachable code: x is 5
```
Edition <= 2018:
```rust
let x = 5;
unreachable!("x is {x}");
```
```
internal error: entered unreachable code: x is {x}
```
Also note that the change in this PR are **insta-stable** and **breaking changes** but this a considered as being a [bug](https://github.com/rust-lang/rust/issues/92137#issuecomment-998441613).
If someone could start a perf run and then a crater run this would be appreciated.
Fixes https://github.com/rust-lang/rust/issues/92137
Rollup of 2 pull requests
Successful merges:
- #90998 (Require const stability attribute on all stable functions that are `const`)
- #93489 (Mark the panic_no_unwind lang item as nounwind)
Failed merges:
r? `@ghost`
`@rustbot` modify labels: rollup
It previously pointed to #57563, the conglomerate issue for
`const fn` (presumably under the feature gate `const_fn`).
`const_fn_trait_bounds` weren't mentioned here, so this commit changes
its tracking issue to a new one.
Mark the panic_no_unwind lang item as nounwind
This has 2 effects:
- It helps LLVM when inlining since it doesn't need to generate landing pads for `panic_no_unwind`.
- It makes it sound for a panic handler to unwind even if `PanicInfo::can_unwind` returns true. This will simply cause another panic once the unwind tries to go past the `panic_no_unwind` lang item. Eventually this will cause a stack overflow, which is safe.
Require const stability attribute on all stable functions that are `const`
This PR requires all stable functions (of all kinds) that are `const fn` to have a `#[rustc_const_stable]` or `#[rustc_const_unstable]` attribute. Stability was previously implied if omitted; a follow-up PR is planned to change the fallback to be unstable.
Optimize `core::str::Chars::count`
I wrote this a while ago after seeing this function as a bottleneck in a profile, but never got around to contributing it. I saw it again, and so here it is. The implementation is fairly complex, but I tried to explain what's happening at both a high level (in the header comment for the file), and in line comments in the impl. Hopefully it's clear enough.
This implementation (`case00_cur_libcore` in the benchmarks below) is somewhat consistently around 4x to 5x faster than the old implementation (`case01_old_libcore` in the benchmarks below), for a wide variety of workloads, without regressing performance on any of the workload sizes I've tried.
I also improved the benchmarks for this code, so that they explicitly check text in different languages and of different sizes (err, the cross product of language x size). The results of the benchmarks are here:
<details>
<summary>Benchmark results</summary>
<pre>
test str::char_count::emoji_huge::case00_cur_libcore ... bench: 20,216 ns/iter (+/- 3,673) = 17931 MB/s
test str::char_count::emoji_huge::case01_old_libcore ... bench: 108,851 ns/iter (+/- 12,777) = 3330 MB/s
test str::char_count::emoji_huge::case02_iter_increment ... bench: 329,502 ns/iter (+/- 4,163) = 1100 MB/s
test str::char_count::emoji_huge::case03_manual_char_len ... bench: 223,333 ns/iter (+/- 14,167) = 1623 MB/s
test str::char_count::emoji_large::case00_cur_libcore ... bench: 293 ns/iter (+/- 6) = 19331 MB/s
test str::char_count::emoji_large::case01_old_libcore ... bench: 1,681 ns/iter (+/- 28) = 3369 MB/s
test str::char_count::emoji_large::case02_iter_increment ... bench: 5,166 ns/iter (+/- 85) = 1096 MB/s
test str::char_count::emoji_large::case03_manual_char_len ... bench: 3,476 ns/iter (+/- 62) = 1629 MB/s
test str::char_count::emoji_medium::case00_cur_libcore ... bench: 48 ns/iter (+/- 0) = 14750 MB/s
test str::char_count::emoji_medium::case01_old_libcore ... bench: 217 ns/iter (+/- 4) = 3262 MB/s
test str::char_count::emoji_medium::case02_iter_increment ... bench: 642 ns/iter (+/- 7) = 1102 MB/s
test str::char_count::emoji_medium::case03_manual_char_len ... bench: 445 ns/iter (+/- 3) = 1591 MB/s
test str::char_count::emoji_small::case00_cur_libcore ... bench: 18 ns/iter (+/- 0) = 3777 MB/s
test str::char_count::emoji_small::case01_old_libcore ... bench: 23 ns/iter (+/- 0) = 2956 MB/s
test str::char_count::emoji_small::case02_iter_increment ... bench: 66 ns/iter (+/- 2) = 1030 MB/s
test str::char_count::emoji_small::case03_manual_char_len ... bench: 29 ns/iter (+/- 1) = 2344 MB/s
test str::char_count::en_huge::case00_cur_libcore ... bench: 25,909 ns/iter (+/- 39,260) = 13299 MB/s
test str::char_count::en_huge::case01_old_libcore ... bench: 102,887 ns/iter (+/- 3,257) = 3349 MB/s
test str::char_count::en_huge::case02_iter_increment ... bench: 166,370 ns/iter (+/- 12,439) = 2071 MB/s
test str::char_count::en_huge::case03_manual_char_len ... bench: 166,332 ns/iter (+/- 4,262) = 2071 MB/s
test str::char_count::en_large::case00_cur_libcore ... bench: 281 ns/iter (+/- 6) = 19160 MB/s
test str::char_count::en_large::case01_old_libcore ... bench: 1,598 ns/iter (+/- 19) = 3369 MB/s
test str::char_count::en_large::case02_iter_increment ... bench: 2,598 ns/iter (+/- 167) = 2072 MB/s
test str::char_count::en_large::case03_manual_char_len ... bench: 2,578 ns/iter (+/- 55) = 2088 MB/s
test str::char_count::en_medium::case00_cur_libcore ... bench: 44 ns/iter (+/- 1) = 15295 MB/s
test str::char_count::en_medium::case01_old_libcore ... bench: 201 ns/iter (+/- 51) = 3348 MB/s
test str::char_count::en_medium::case02_iter_increment ... bench: 322 ns/iter (+/- 40) = 2090 MB/s
test str::char_count::en_medium::case03_manual_char_len ... bench: 319 ns/iter (+/- 5) = 2109 MB/s
test str::char_count::en_small::case00_cur_libcore ... bench: 15 ns/iter (+/- 0) = 2333 MB/s
test str::char_count::en_small::case01_old_libcore ... bench: 14 ns/iter (+/- 0) = 2500 MB/s
test str::char_count::en_small::case02_iter_increment ... bench: 30 ns/iter (+/- 1) = 1166 MB/s
test str::char_count::en_small::case03_manual_char_len ... bench: 30 ns/iter (+/- 1) = 1166 MB/s
test str::char_count::ru_huge::case00_cur_libcore ... bench: 16,439 ns/iter (+/- 3,105) = 19777 MB/s
test str::char_count::ru_huge::case01_old_libcore ... bench: 89,480 ns/iter (+/- 2,555) = 3633 MB/s
test str::char_count::ru_huge::case02_iter_increment ... bench: 217,703 ns/iter (+/- 22,185) = 1493 MB/s
test str::char_count::ru_huge::case03_manual_char_len ... bench: 157,330 ns/iter (+/- 19,188) = 2066 MB/s
test str::char_count::ru_large::case00_cur_libcore ... bench: 243 ns/iter (+/- 6) = 20905 MB/s
test str::char_count::ru_large::case01_old_libcore ... bench: 1,384 ns/iter (+/- 51) = 3670 MB/s
test str::char_count::ru_large::case02_iter_increment ... bench: 3,381 ns/iter (+/- 543) = 1502 MB/s
test str::char_count::ru_large::case03_manual_char_len ... bench: 2,423 ns/iter (+/- 429) = 2096 MB/s
test str::char_count::ru_medium::case00_cur_libcore ... bench: 42 ns/iter (+/- 1) = 15119 MB/s
test str::char_count::ru_medium::case01_old_libcore ... bench: 180 ns/iter (+/- 4) = 3527 MB/s
test str::char_count::ru_medium::case02_iter_increment ... bench: 402 ns/iter (+/- 45) = 1579 MB/s
test str::char_count::ru_medium::case03_manual_char_len ... bench: 280 ns/iter (+/- 29) = 2267 MB/s
test str::char_count::ru_small::case00_cur_libcore ... bench: 12 ns/iter (+/- 0) = 2666 MB/s
test str::char_count::ru_small::case01_old_libcore ... bench: 12 ns/iter (+/- 0) = 2666 MB/s
test str::char_count::ru_small::case02_iter_increment ... bench: 19 ns/iter (+/- 0) = 1684 MB/s
test str::char_count::ru_small::case03_manual_char_len ... bench: 14 ns/iter (+/- 1) = 2285 MB/s
test str::char_count::zh_huge::case00_cur_libcore ... bench: 15,053 ns/iter (+/- 2,640) = 20067 MB/s
test str::char_count::zh_huge::case01_old_libcore ... bench: 82,622 ns/iter (+/- 3,602) = 3656 MB/s
test str::char_count::zh_huge::case02_iter_increment ... bench: 230,456 ns/iter (+/- 7,246) = 1310 MB/s
test str::char_count::zh_huge::case03_manual_char_len ... bench: 220,595 ns/iter (+/- 11,624) = 1369 MB/s
test str::char_count::zh_large::case00_cur_libcore ... bench: 227 ns/iter (+/- 65) = 20792 MB/s
test str::char_count::zh_large::case01_old_libcore ... bench: 1,136 ns/iter (+/- 144) = 4154 MB/s
test str::char_count::zh_large::case02_iter_increment ... bench: 3,147 ns/iter (+/- 253) = 1499 MB/s
test str::char_count::zh_large::case03_manual_char_len ... bench: 2,993 ns/iter (+/- 400) = 1577 MB/s
test str::char_count::zh_medium::case00_cur_libcore ... bench: 36 ns/iter (+/- 5) = 16388 MB/s
test str::char_count::zh_medium::case01_old_libcore ... bench: 142 ns/iter (+/- 18) = 4154 MB/s
test str::char_count::zh_medium::case02_iter_increment ... bench: 379 ns/iter (+/- 37) = 1556 MB/s
test str::char_count::zh_medium::case03_manual_char_len ... bench: 364 ns/iter (+/- 51) = 1620 MB/s
test str::char_count::zh_small::case00_cur_libcore ... bench: 11 ns/iter (+/- 1) = 3000 MB/s
test str::char_count::zh_small::case01_old_libcore ... bench: 11 ns/iter (+/- 1) = 3000 MB/s
test str::char_count::zh_small::case02_iter_increment ... bench: 20 ns/iter (+/- 3) = 1650 MB/s
</pre>
</details>
I also added fairly thorough tests for different sizes and alignments. This completes on my machine in 0.02s, which is surprising given how thorough they are, but it seems to detect bugs in the implementation. (I haven't run the tests on a 32 bit machine yet since before I reworked the code a little though, so... hopefully I'm not about to embarrass myself).
This uses similar SWAR-style techniques to the `is_ascii` impl I contributed in https://github.com/rust-lang/rust/pull/74066, so I'm going to request review from the same person who reviewed that one. That said am not particularly picky, and might not have the correct syntax for requesting a review from someone (so it goes).
r? `@nagisa`
Resolve lifetimes for const generic defaults
We weren't visiting the const generic default argument in `rustc_resolve::late::lifetimes`. This seems to fix the issue, and we deny any non-`'static` lifetimes anyways.
Fixes#93647
Update CPU idle tracking for apple hosts
The previous setup did not properly consider hyperthreads (at least in local
testing), which likely skews CI results as well. The new code is both simpler
and hopefully will produce more accurate results; locally it matches behavior
of the Linux version of this script.
Remove "up here" arrow on item-infos
Use spacing to distinguish what is related to a given heading.
This was originally introduced in #53043, in response to #51387. The arrow is a little distracting, and leads the item-info to not be aligned properly with the text below it.
Demo: https://rustdoc.crud.net/jsha/impl-spacing/std/string/struct.String.html
r? ``@GuillaumeGomez``
Add new target armv7-unknown-linux-uclibceabi (softfloat)
This adds the new target `armv7-unknown-linux-uclibceabi (softfloat)`. It is of course similar to `armv7-unknown-linux-uclibceabihf (hardfloat)` which was just recently added to rust except that it is `softfloat`.
My interest lies in the Broadcom BCM4707/4708/BCM4709 family, notably found in some Netgear and Asus consumer routers. The armv7 Cortex-A9 cpus found in these devices do not have an fpu or NEON support.
With this patch I've been able to bootstrap rustc, std and host tools `(extended = true)` to run on the target device for native compilation, allowing the target to be used as a development platform.
With the recent addition of `armv7-unknown-linux-uclibceabihf (hardfloat)` it looks like many of the edge cases of using the uclibc c-library are getting worked out nicely. I've been able to compile some complex projects. Some patching still needed in some crates, but getting there for sure. I think `armv7-unknown-linux-uclibceabi` is ready to be a tier 3 target.
I use a cross-toolchain from my project to bootstrap rust.
https://github.com/lancethepants/tomatoware
The goal of this project is to create a native development environment with support for various languages.
mips64-openwrt-linux-musl: Add Tier 3 target
Tier 3 tuple for Mips64 OpenWrt toolchain.
This add first-time support for OpenWrt. Future Tier3 targets will be added as I test them.
Signed-off-by: Donald Hoskins <grommish@gmail.com>
Allow unwinding from OOM hooks
This is split off from #88098 and contains just the bare minimum to allow specifying a custom OOM hook with `set_alloc_error_hook` which unwinds instead of aborting.
See #88098 for an actual command-line flag which switches the default OOM behavior to unwind instead of aborting.
Previous perf results show a negligible impact on performance.