Rollup of 10 pull requests
Successful merges:
- #119305 (Add `AsyncFn` family of traits)
- #119389 (Provide more context on recursive `impl` evaluation overflow)
- #119895 (Remove `track_errors` entirely)
- #120230 (Assert that a single scope is passed to `for_scope`)
- #120278 (Remove --fatal-warnings on wasm targets)
- #120292 (coverage: Dismantle `Instrumentor` and flatten span refinement)
- #120315 (On E0308 involving `dyn Trait`, mention trait objects)
- #120317 (pattern_analysis: Let `ctor_sub_tys` return any Iterator they want)
- #120318 (pattern_analysis: Reuse most of the `DeconstructedPat` `Debug` impl)
- #120325 (rustc_data_structures: use either instead of itertools)
r? `@ghost`
`@rustbot` modify labels: rollup
rustc_data_structures: use either instead of itertools
`itertools::Either` is a re-export from `either`, so we might as well use the source.
This flattens the compiler build tree a little, but I don't really expect it to make much difference overall.
pattern_analysis: Reuse most of the `DeconstructedPat` `Debug` impl
The `DeconstructedPat: Debug` is best-effort because we'd need `tcx` to get things like field names etc. Since rust-analyzer has a similar constraint, this PR moves most the impl to be shared between the two. While I was at it I also fixed a nit in the `IntRange: Debug` impl.
r? `@compiler-errors`
pattern_analysis: Let `ctor_sub_tys` return any Iterator they want
I noticed that we always `.cloned()` and allocate the output of `TypeCx::ctor_sub_tys` now, so there was no need to force it to return a slice. `ExactSizeIterator` is not super important but saves some manual counting.
r? `@compiler-errors`
On E0308 involving `dyn Trait`, mention trait objects
When encountering a type mismatch error involving `dyn Trait`, mention the existence of boxed trait objects if the other type involved implements `Trait`.
Fix#102629.
coverage: Dismantle `Instrumentor` and flatten span refinement
This is a combination of two refactorings that are unrelated, but would otherwise have a merge conflict.
No functional changes, other than a small tweak to debug logging as part of rearranging some functions.
Ignoring whitespace is highly recommended, since most of the modified lines have just been reindented.
---
The first change is to dismantle `Instrumentor` into ordinary functions.
This is one of those cases where encapsulating several values into a struct ultimately hurts more than it helps. With everything stored as local variables in one main function, and passed explicitly into helper functions, it's easier to see what is used where, and make changes as necessary.
---
The second change is to flatten the functions for extracting/refining coverage spans.
Consolidating this code into flatter functions reduces the amount of pointer-chasing required to read and modify it.
Remove --fatal-warnings on wasm targets
These were added with good intentions, but a recent change in LLVM 18 emits a warning while examining .rmeta sections in .rlib files. Since this flag is a nice-to-have and users can update their LLVM linker independently of rustc's LLVM version, we can just omit the flag.
See [this comment on wasm targets' uses of `--fatal-warnings`](https://github.com/llvm/llvm-project/pull/78658#issuecomment-1906651390).
Remove `track_errors` entirely
follow up to https://github.com/rust-lang/rust/pull/119869
r? `@matthewjasper`
There are some diagnostic changes adding new diagnostics or not emitting some anymore. We can improve upon that in follow-up work imo.
Provide more context on recursive `impl` evaluation overflow
When an associated type `Self::Assoc` is part of a `where` clause, we end up unable to evaluate the requirement and emit a E0275.
We now point at the associated type if specified in the `impl`. If so, we also suggest using that type instead of `Self::Assoc`. Otherwise, we explain that these are not allowed.
```
error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
--> $DIR/impl-wf-cycle-1.rs:15:1
|
LL | / impl<T: Grault> Grault for (T,)
LL | |
LL | | where
LL | | Self::A: Baz,
LL | | Self::B: Fiz,
| |_________________^
LL | {
LL | type A = ();
| ------ associated type `<(T,) as Grault>::A` is specified here
|
note: required for `(T,)` to implement `Grault`
--> $DIR/impl-wf-cycle-1.rs:15:17
|
LL | impl<T: Grault> Grault for (T,)
| ^^^^^^ ^^^^
...
LL | Self::A: Baz,
| --- unsatisfied trait bound introduced here
= note: 1 redundant requirement hidden
= note: required for `(T,)` to implement `Grault`
help: associated type for the current `impl` cannot be restricted in `where` clauses, remove this bound
|
LL - Self::A: Baz,
|
```
```
error[E0275]: overflow evaluating the requirement `<T as B>::Type == <T as B>::Type`
--> $DIR/impl-wf-cycle-3.rs:7:1
|
LL | / impl<T> B for T
LL | | where
LL | | T: A<Self::Type>,
| |_____________________^
LL | {
LL | type Type = bool;
| --------- associated type `<T as B>::Type` is specified here
|
note: required for `T` to implement `B`
--> $DIR/impl-wf-cycle-3.rs:7:9
|
LL | impl<T> B for T
| ^ ^
LL | where
LL | T: A<Self::Type>,
| ------------- unsatisfied trait bound introduced here
help: replace the associated type with the type specified in this `impl`
|
LL | T: A<bool>,
| ~~~~
```
```
error[E0275]: overflow evaluating the requirement `<T as Filter>::ToMatch == <T as Filter>::ToMatch`
--> $DIR/impl-wf-cycle-4.rs:5:1
|
LL | / impl<T> Filter for T
LL | | where
LL | | T: Fn(Self::ToMatch),
| |_________________________^
|
note: required for `T` to implement `Filter`
--> $DIR/impl-wf-cycle-4.rs:5:9
|
LL | impl<T> Filter for T
| ^^^^^^ ^
LL | where
LL | T: Fn(Self::ToMatch),
| ----------------- unsatisfied trait bound introduced here
note: associated types for the current `impl` cannot be restricted in `where` clauses
--> $DIR/impl-wf-cycle-4.rs:7:11
|
LL | T: Fn(Self::ToMatch),
| ^^^^^^^^^^^^^
```
Fix#116925
Add `AsyncFn` family of traits
I'm proposing to add a new family of `async`hronous `Fn`-like traits to the standard library for experimentation purposes.
## Why do we need new traits?
On the user side, it is useful to be able to express `AsyncFn` trait bounds natively via the parenthesized sugar syntax, i.e. `x: impl AsyncFn(&str) -> String` when experimenting with async-closure code.
This also does not preclude `AsyncFn` becoming something else like a trait alias if a more fundamental desugaring (which can take many[^1] different[^2] forms) comes around. I think we should be able to play around with `AsyncFn` well before that, though.
I'm also not proposing stabilization of these trait names any time soon (we may even want to instead express them via new syntax, like `async Fn() -> ..`), but I also don't think we need to introduce an obtuse bikeshedding name, since `AsyncFn` just makes sense.
## The lending problem: why not add a more fundamental primitive of `LendingFn`/`LendingFnMut`?
Firstly, for `async` closures to be as flexible as possible, they must be allowed to return futures which borrow from the async closure's captures. This can be done by introducing `LendingFn`/`LendingFnMut` traits, or (equivalently) by adding a new generic associated type to `FnMut` which allows the return type to capture lifetimes from the `&mut self` argument of the trait. This was proposed in one of [Niko's blog posts](https://smallcultfollowing.com/babysteps/blog/2023/05/09/giving-lending-and-async-closures/).
Upon further experimentation, for the purposes of closure type- and borrow-checking, I've come to the conclusion that it's significantly harder to teach the compiler how to handle *general* lending closures which may borrow from their captures. This is, because unlike `Fn`/`FnMut`, the `LendingFn`/`LendingFnMut` traits don't form a simple "inheritance" hierarchy whose top trait is `FnOnce`.
```mermaid
flowchart LR
Fn
FnMut
FnOnce
LendingFn
LendingFnMut
Fn -- isa --> FnMut
FnMut -- isa --> FnOnce
LendingFn -- isa --> LendingFnMut
Fn -- isa --> LendingFn
FnMut -- isa --> LendingFnMut
```
For example:
```
fn main() {
let s = String::from("hello, world");
let f = move || &s;
let x = f(); // This borrows `f` for some lifetime `'1` and returns `&'1 String`.
```
That trait hierarchy means that in general for "lending" closures, like `f` above, there's not really a meaningful return type for `<typeof(f) as FnOnce>::Output` -- it can't return `&'static str`, for example.
### Special-casing this problem:
By splitting out these traits manually, and making sure that each trait has its own associated future type, we side-step the issue of having to answer the questions of a general `LendingFn`/`LendingFnMut` implementation, since the compiler knows how to generate built-in implementations for first-class constructs like async closures, including the required future types for the (by-move) `AsyncFnOnce` and (by-ref) `AsyncFnMut`/`AsyncFn` trait implementations.
[^1]: For example, with trait transformers, we may eventually be able to write: `trait AsyncFn = async Fn;`
[^2]: For example, via the introduction of a more fundamental "`LendingFn`" trait, plus a [special desugaring with augmented trait aliases](https://rust-lang.zulipchat.com/#narrow/stream/213817-t-lang/topic/Lending.20closures.20and.20Fn*.28.29.20-.3E.20impl.20Trait/near/408471480).
Modify GenericArg and Term structs to use strict provenance rules
This is the first PR to solve issue #119217 . In this PR, I have modified the GenericArg struct to use the `NonNull` struct as the pointer instead of `NonZeroUsize`. The change were tested by running `./x test compiler/rustc_middle`.
Resolves https://github.com/rust-lang/rust/issues/119217
r? `@WaffleLapkin`
Replacement of #114390: Add new intrinsic `is_var_statically_known` and optimize pow for powers of two
This adds a new intrinsic `is_val_statically_known` that lowers to [``@llvm.is.constant.*`](https://llvm.org/docs/LangRef.html#llvm-is-constant-intrinsic).` It also applies the intrinsic in the int_pow methods to recognize and optimize the idiom `2isize.pow(x)`. See #114390 for more discussion.
While I have extended the scope of the power of two optimization from #114390, I haven't added any new uses for the intrinsic. That can be done in later pull requests.
Note: When testing or using the library, be sure to use `--stage 1` or higher. Otherwise, the intrinsic will be a noop and the doctests will be skipped. If you are trying out edits, you may be interested in [`--keep-stage 0`](https://rustc-dev-guide.rust-lang.org/building/suggested.html#faster-builds-with---keep-stage).
Fixes#47234Resolves#114390
`@Centri3`
Remove all ConstPropNonsense
We track all locals and projections on them ourselves within the const propagator and only use the InterpCx to actually do some low level operations or read from constants (via `OpTy` we get for said constants).
This helps moving the const prop lint out from the normal pipeline and running it just based on borrowck information. This in turn allows us to make progress on https://github.com/rust-lang/rust/pull/108730#issuecomment-1875557745
there are various follow up cleanups that can be done after this PR (e.g. not matching on Rvalue twice and doing binop checks twice), but lets try landing this one first.
r? `@RalfJung`
When encountering a type mismatch error involving `dyn Trait`, mention
the existence of boxed trait objects if the other type involved
implements `Trait`.
Partially addresses #102629.
Add mw to review rotation and add some owner assignments
I've also added a `debuginfo` group and fixed the ownership assignment for the `incremental` group. I hope I got the syntax right.
r? ``@davidtwco``
privacy: Refactor top-level visiting in `TypePrivacyVisitor`
Full hierarchical visiting (`nested_filter::All`) is not necessary, visiting all item-likes in isolation is enough.
Tracking current item is not necessary, just keeping the current `mod` item is enough.
`visit_generic_arg` should behave like its default version, including checking types of const arguments.
Some comments, including FIXMEs, are also added.
Noticed while reading code to review https://github.com/rust-lang/rust/pull/113671.
r? ``@oli-obk``
Remove no-system-llvm
We currently have a bunch of codegen tests that use no-system-llvm -- however, all of those tests also pass with system LLVM 16.
I've opted to remove `no-system-llvm` entirely, as there's basically no valid use case for it anymore:
* The only thing this option could have legitimately been used for (testing the target feature support that requires an LLVM patch) doesn't use it, and the need for this will go away with LLVM 18 anyway.
* In cases where the test depends on optimizations/fixes from newer LLVM versions, `min-llvm-version` should be used instead.
* In case it depends on optimization/fixes from newer LLVM versions that have been backported into our fork, `min-system-llvm-version` (with the major version larger than the one in our fork) should be used instead.
r? `````@cuviper`````
coverage: Don't instrument `#[automatically_derived]` functions
This PR makes the coverage instrumentor detect and skip functions that have [`#[automatically_derived]`](https://doc.rust-lang.org/reference/attributes/derive.html#the-automatically_derived-attribute) on their enclosing impl block.
Most notably, this means that methods generated by built-in derives (e.g. `Clone`, `Debug`, `PartialEq`) are now ignored by coverage instrumentation, and won't appear as executed or not-executed in coverage reports.
This is a noticeable change in user-visible behaviour, but overall I think it's a net improvement. For example, we've had a few user requests for this sort of change (e.g. #105055, https://github.com/rust-lang/rust/issues/84605#issuecomment-1902069040), and I believe it's the behaviour that most users will expect/prefer by default.
It's possible to imagine situations where users would want to instrument these derived implementations, but I think it's OK to treat that as an opportunity to consider adding more fine-grained option flags to control the details of coverage instrumentation, while leaving this new behaviour as the default.
(Also note that while `-Cinstrument-coverage` is a stable feature, the exact details of coverage instrumentation are allowed to change. So we *can* make this change; the main question is whether we *should*.)
Fixes#105055.
Add a new `wasm32-wasi-preview2` target
This is the initial implementation of the MCP https://github.com/rust-lang/compiler-team/issues/694 creating a new tier 3 target `wasm32-wasi-preview2`. That MCP has been seconded and will most likely be approved in a little over a week from now. For more information on the need for this target, please read the [MCP](https://github.com/rust-lang/compiler-team/issues/694).
There is one aspect of this PR that will become insta-stable once these changes reach a stable compiler:
* A new `target_family` named `wasi` is introduced. This target family incorporates all wasi targets including `wasm32-wasi` and its derivative `wasm32-wasi-preview1-threads`. The difference between `target_family = wasi` and `target_os = wasi` will become much clearer when `wasm32-wasi` is renamed to `wasm32-wasi-preview1` and the `target_os` becomes `wasm32-wasi-preview1`. You can read about this target rename in [this MCP](https://github.com/rust-lang/compiler-team/issues/695) which has also been seconded and will hopefully be officially approved soon.
Additional technical details include:
* Both `std::sys::wasi_preview2` and `std::os::wasi_preview2` have been created and mostly use `#[path]` annotations on their submodules to reach into the existing `wasi` (soon to be `wasi_preview1`) modules. Over time the differences between `wasi_preview1` and `wasi_preview2` will grow and most like all `#[path]` based module aliases will fall away.
* Building `wasi-preview2` relies on a [`wasi-sdk`](https://github.com/WebAssembly/wasi-sdk) in the same way that `wasi-preview1` does (one must include a `wasi-root` path in the `Config.toml` pointing to sysroot included in the wasi-sdk). The target should build against [wasi-sdk v21](https://github.com/WebAssembly/wasi-sdk/releases/tag/wasi-sdk-21) without modifications. However, the wasi-sdk itself is growing [preview2 support](https://github.com/WebAssembly/wasi-sdk/pull/370) so this might shift rapidly. We will be following along quickly to make sure that building the target remains possible as the wasi-sdk changes.
* This requires a [patch to libc](https://github.com/rylev/rust-libc/tree/wasm32-wasi-preview2) that we'll need to land in conjunction with this change. Until that patch lands the target won't actually build.
coverage: Never emit improperly-ordered coverage regions
If we emit a coverage region that is improperly ordered (end < start), `llvm-cov` will fail with `coveragemap_error::malformed`, which is inconvenient for users and also very hard to debug.
Ideally we would fix the root causes of these situations, but they tend to occur in very obscure edge-case scenarios (often involving nested macros), and we don't always have a good MCVE to work from. So it makes sense to also have a catch-all check that will prevent improperly-ordered regions from ever being emitted.
---
This is mainly aimed at resolving #119453. We don't have a specific way to reproduce it, which is why I haven't been able to add a test case in this PR. But based on the information provided in that issue, this change seems likely to avoid the error in `llvm-cov`.
`````@rustbot````` label +A-code-coverage
Add `NonZero*::count_ones`
This PR adds the following APIs to the standard library:
```rust
impl NonZero* {
pub const fn count_ones(self) -> NonZeroU32;
}
```
This is potentially interesting, given that `count_ones` can't ever return 0.
r? libs-api
Return a finite number of AllocIds per ConstAllocation in Miri
Before this, every evaluation of a const slice would produce a new AllocId. So in Miri, this program used to have unbounded memory use:
```rust
fn main() {
loop {
helper();
}
}
fn helper() {
"ouch";
}
```
Every trip around the loop creates a new AllocId which we need to keep track of a base address for. And the provenance GC can never clean up that AllocId -> u64 mapping, because the AllocId is for a const allocation which will never be deallocated.
So this PR moves the logic of producing an AllocId for a ConstAllocation to the Machine trait, and the implementation that Miri provides will only produce 16 AllocIds for each allocation. The cache is also keyed on the Instance that the const is evaluated in, so that equal consts evaluated in two functions will have disjoint base addresses.
r? RalfJung
Update cargo
10 commits in 1ae631085f01c1a72d05df1ec81f3759a8360042..7bb7b539558dc88bea44cee4168b6269bf8177b0
2024-01-17 17:26:41 +0000 to 2024-01-20 00:15:32 +0000
- feat: inherit jobserver from env for all kinds of runner (rust-lang/cargo#12776)
- Fix static_mut_ref warning. (rust-lang/cargo#13329)
- fix(trim-paths): remap common prefix only (rust-lang/cargo#13210)
- fix(cargo-rustdoc): use same path by output format logic everywhere (rust-lang/cargo#13325)
- chore: Make MSRV=N-2 the workspace default (rust-lang/cargo#13324)
- Fix precise-prerelease tracking link. (rust-lang/cargo#13320)
- test(pkgid): keep package ID format in sync (rust-lang/cargo#13322)
- Improve GitHub Actions CI config (rust-lang/cargo#13317)
- Go back to passing an empty `values()` when no features are declared (rust-lang/cargo#13316)
- fix(`--package`): accept `?` if it's a valid pkgid spec (rust-lang/cargo#13315)
r? ghost
Rollup of 9 pull requests
Successful merges:
- #112806 (Small code improvements in `collect_intra_doc_links.rs`)
- #119766 (Split tait and impl trait in assoc items logic)
- #120139 (Do not normalize closure signature when building `FnOnce` shim)
- #120160 (Manually implement derived `NonZero` traits.)
- #120171 (Fix assume and assert in jump threading)
- #120183 (Add `#[coverage(off)]` to closures introduced by `#[test]` and `#[bench]`)
- #120195 (add several resolution test cases)
- #120259 (Split Diagnostics for Uncommon Codepoints: Add List to Display Characters Involved)
- #120261 (Provide structured suggestion to use trait objects in some cases of `if` arm type divergence)
r? `@ghost`
`@rustbot` modify labels: rollup
Provide structured suggestion to use trait objects in some cases of `if` arm type divergence
```
error[E0308]: `if` and `else` have incompatible types
--> $DIR/suggest-box-on-divergent-if-else-arms.rs:15:9
|
LL | let _ = if true {
| _____________-
LL | | Struct
| | ------ expected because of this
LL | | } else {
LL | | foo()
| | ^^^^^ expected `Struct`, found `Box<dyn Trait>`
LL | | };
| |_____- `if` and `else` have incompatible types
|
= note: expected struct `Struct`
found struct `Box<dyn Trait>`
help: `Struct` implements `Trait` so you can box it to coerce to the trait object `Box<dyn Trait>`
|
LL | Box::new(Struct)
| +++++++++ +
error[E0308]: `if` and `else` have incompatible types
--> $DIR/suggest-box-on-divergent-if-else-arms.rs:20:9
|
LL | let _ = if true {
| _____________-
LL | | foo()
| | ----- expected because of this
LL | | } else {
LL | | Struct
| | ^^^^^^ expected `Box<dyn Trait>`, found `Struct`
LL | | };
| |_____- `if` and `else` have incompatible types
|
= note: expected struct `Box<dyn Trait>`
found struct `Struct`
= note: for more on the distinction between the stack and the heap, read https://doc.rust-lang.org/book/ch15-01-box.html, https://doc.rust-lang.org/rust-by-example/std/box.html, and https://doc.rust-lang.org/std/boxed/index.html
help: store this in the heap by calling `Box::new`
|
LL | Box::new(Struct)
| +++++++++ +
error[E0308]: `if` and `else` have incompatible types
--> $DIR/suggest-box-on-divergent-if-else-arms.rs:25:9
|
LL | fn bar() -> impl Trait {
| ---------- the found opaque type
...
LL | let _ = if true {
| _____________-
LL | | Struct
| | ------ expected because of this
LL | | } else {
LL | | bar()
| | ^^^^^ expected `Struct`, found opaque type
LL | | };
| |_____- `if` and `else` have incompatible types
|
= note: expected struct `Struct`
found opaque type `impl Trait`
help: `Struct` implements `Trait` so you can box both arms and coerce to the trait object `Box<dyn Trait>`
|
LL ~ Box::new(Struct) as Box<dyn Trait>
LL | } else {
LL ~ Box::new(bar())
|
error[E0308]: `if` and `else` have incompatible types
--> $DIR/suggest-box-on-divergent-if-else-arms.rs:30:9
|
LL | fn bar() -> impl Trait {
| ---------- the expected opaque type
...
LL | let _ = if true {
| _____________-
LL | | bar()
| | ----- expected because of this
LL | | } else {
LL | | Struct
| | ^^^^^^ expected opaque type, found `Struct`
LL | | };
| |_____- `if` and `else` have incompatible types
|
= note: expected opaque type `impl Trait`
found struct `Struct`
help: `Struct` implements `Trait` so you can box both arms and coerce to the trait object `Box<dyn Trait>`
|
LL ~ Box::new(bar()) as Box<dyn Trait>
LL | } else {
LL ~ Box::new(Struct)
|
```
Partially address #102629.
Split Diagnostics for Uncommon Codepoints: Add List to Display Characters Involved
This Pull Request adds a list of the uncommon codepoints involved in the `uncommon_codepoints` lint, as outlined as a first step in #120228.
Example rendered diagnostic:
```
error: identifier contains an uncommon Unicode codepoint: 'µ'
--> $DIR/lint-uncommon-codepoints.rs:3:7
|
LL | const µ: f64 = 0.000001;
| ^
|
note: the lint level is defined here
--> $DIR/lint-uncommon-codepoints.rs:1:9
|
LL | #![deny(uncommon_codepoints)]
| ^^^^^^^^^^^^^^^^^^^
```
(Retrying #120258.)
Add `#[coverage(off)]` to closures introduced by `#[test]` and `#[bench]`
These closures are an internal implementation detail of the `#[test]` and `#[bench]` attribute macros, so from a user perspective there is no reason to instrument them for coverage.
Skipping them makes coverage reports slightly cleaner, and will also allow other changes to span processing during coverage instrumentation, without having to worry about how they affect the `#[test]` macro.
The `#[coverage(off)]` attribute has no effect when `-Cinstrument-coverage` is not used.
Fixes#120046.
---
Note that this PR has no effect on the user-written function that has the `#[test]` attribute attached to it. That function will still be instrumented as normal.
Manually implement derived `NonZero` traits.
Step 3 as mentioned in https://github.com/rust-lang/rust/pull/100428#pullrequestreview-1767139731.
Manually implement the traits that would cause “borrow of layout constrained field with interior mutability” errors when switching to `NonZero<T>`.
r? ```@dtolnay```
Do not normalize closure signature when building `FnOnce` shim
It is not necessary to normalize the closure signature when building an `FnOnce` shim for an `Fn`/`FnMut` closure. That closure shim is just calling `FnMut::call_mut(&mut self)` anyways.
It's also somewhat sketchy that we were ever doing this to begin with, since we're normalizing with a `ParamEnv::reveal_all()` param-env, which is definitely not right with possibly polymorphic substs.
This cuts out a tiny bit of unnecessary work in `Instance::resolve` and simplifies the signature because now we can unconditionally return an `Instance`.