This implements support for applying PGO to the rustc compilation step (not
standard library or any tooling, including rustdoc). Expanding PGO to more tools
is not terribly difficult but will involve more work and greater CI time
commitment.
For the same reason of avoiding greater time commitment, this currently avoids
implementing for platforms outside of x86_64-unknown-linux-gnu, though in
practice it should be quite simple to extend over time to more platforms. The
initial implementation is intentionally minimal here to avoid too much work
investment before we start seeing wins for a subset of Rust users.
The choice of workloads to profile here is somewhat arbitrary, but the general
rationale was to aim for a small set that largely avoided time regressions on
perf.rust-lang.org's full suite of crates. The set chosen is libcore, cargo (and
its dependencies), and a few ad-hoc stress tests from perf.rlo. The stress tests
are arguably the most controversial, but they benefit those cases (avoiding
regressions) and do not really remove wins from other benchmarks.
The primary next step after this PR lands is to implement support for PGO in
LLVM. It is unclear whether we can afford a full LLVM rebuild in CI, though, so
the approach taken there may need to be more staggered. rustc-only PGO seems
well affordable on linux at least, giving us up to 20% wall time wins on some
crates for 15 minutes of extra CI time (1 hour up from 45 minutes).
The PGO data is uploaded to allow others to reuse it if attempting to reproduce
the CI build or potentially, in the future, on other platforms where an
off-by-one strategy is used for dist builds at minimal performance cost.
`replace_prefix` is currently implemented as a method but has no real relation
to the struct it is implemented on. Turn it into a closure and move it into the
only method from which it is called.
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 :))
Rename `overlapping_patterns` lint
As discussed in https://github.com/rust-lang/rust/issues/65477. I also tweaked a few things along the way.
r? `@varkor`
`@rustbot` modify labels: +A-exhaustiveness-checking
Reserve necessary space for params in generics_of
Always reserve space for the exact number of generic parameters we need in generics_of. As far as I can see, the default is 0/4 elements based on has_self, and the vector grows on after that.
Acknowledge that `[CONST; N]` is stable
When `const_in_array_repeat_expressions` (RFC 2203) got unstably implemented as part of https://github.com/rust-lang/rust/pull/61749, accidentally, the special case of repeating a *constant* got stabilized immediately. That is why the following code works on stable:
```rust
const EMPTY: Vec<i32> = Vec::new();
pub const fn bar() -> [Vec<i32>; 2] {
[EMPTY; 2]
}
fn main() {
let x = bar();
}
```
In contrast, if we had written `[expr; 2]` for some expression that is not *literally* a constant but could be evaluated at compile-time (e.g. `(EMPTY,).0`), this would have failed.
We could take back this stabilization as it was clearly accidental. However, I propose we instead just officially accept this and stabilize a small subset of RFC 2203, while leaving the more complex case of general expressions that could be evaluated at compile-time unstable. Making that case work well is pretty much blocked on inline `const` expressions (to avoid relying too much on [implicit promotion](https://github.com/rust-lang/const-eval/blob/master/promotion.md)), so it could take a bit until it comes to full fruition. `[CONST; N]` is an uncontroversial subset of this feature that has no semantic ambiguities, does not rely on promotion, and basically provides the full expressive power of RFC 2203 but without the convenience (people have to define constants to repeat them, possibly using associated consts if generics are involved).
Well, I said "no semantic ambiguities", that is only almost true... the one point I am not sure about is `[CONST; 0]`. There are two possible behaviors here: either this is equivalent to `let x = CONST; [x; 0]`, or it is a NOP (if we argue that the constant is never actually instantiated). The difference between the two is that if `CONST` has a destructor, it should run in the former case (but currently doesn't, due to https://github.com/rust-lang/rust/issues/74836); but should not run if it is considered a NOP. For regular `[x; 0]` there seems to be consensus on running drop (there isn't really an alternative); any opinions for the `CONST` special case? Should this instantiate the const only to immediately run its destructors? That seems somewhat silly to me. After all, the `let`-expansion does *not* work in general, for `N > 1`.
Cc `@rust-lang/lang` `@rust-lang/wg-const-eval`
Cc https://github.com/rust-lang/rust/issues/49147
Ran the tidy check
Following the diagnostic guide better
Diagnostic generation is now relegated to its own function in the diagnostics module.
Added tests
Fixed the ui test
Fix pretty printing an AST representing `&(mut ident)`
The PR fixes a misguiding help diagnostic in the parser that I reported in #80186. I discovered that the parsers recovery and reporting logic was correct but the pretty printer produced wrong code for the example. (Details in https://github.com/rust-lang/rust/issues/80186#issuecomment-748498676)
Example:
```rust
#![allow(unused_variables)]
fn main() {
let mut &x = &0;
}
```
The AST fragment
`PatKind::Ref(PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ..), Mutability::Not)`
was printed to be `&mut ident`. But this wouldn't round trip through parsing again, because then it would be:
`PatKind::Ref(PatKind::Ident(BindingMode::ByValue(Mutability::Not), ..), Mutability::Mut)`
Now the pretty-printer prints `&(mut ident)`. Reparsing that code results in the AST fragment
`PatKind::Ref(PatKind::Paren(PatKind::Ident(BindingMode::ByValue(Mutability::Mut), ..)), Mutability::Not)`
which I think should behave like the original pattern.
Old diagnostic:
```
error: `mut` must be attached to each individual binding
--> src/main.rs:3:9
|
3 | let mut &x = &0;
| ^^^^^^ help: add `mut` to each binding: `&mut x`
|
= note: `mut` may be followed by `variable` and `variable @ pattern`
```
New diagnostic:
```
error: `mut` must be attached to each individual binding
--> src/main.rs:3:9
|
3 | let mut &x = &0;
| ^^^^^^ help: add `mut` to each binding: `&(mut x)`
|
= note: `mut` may be followed by `variable` and `variable @ pattern`
```
Fixes#80186
Minor cleanups in LateResolver
- Avoid calculating hash twice
- Avoid creating a closure in every iteration of a loop
- Reserve space for path in advance
- Some readability changes