Peephole optimize `x == false` and `x != true`
This adds peephole optimizations to make `x == false`, `false == x`, `x != true`, and `true != x` get optimized to `!x` in the `instcombine` MIR pass. That pass currently handles `x == true` -> `x` already.
Reland - Report coverage `0` of dead blocks
Fixes: #84018
With `-Z instrument-coverage`, coverage reporting of dead blocks
(for example, blocks dropped because a conditional branch is dropped,
based on const evaluation) is now supported.
Note, this PR relands an earlier, reverted PR that failed when compiling
generators. The prior issues with generators has been resolved and a new
test was added to prevent future regressions.
Check out the resulting changes to test coverage of dead blocks in the
test coverage reports in this PR.
r? `@tmandry`
fyi: `@wesleywiser`
Remove unused feature gates
The first commit removes a usage of a feature gate, but I don't expect it to be controversial as the feature gate was only used to workaround a limitation of rust in the past. (closures never being `Clone`)
The second commit uses `#[allow_internal_unstable]` to avoid leaking the `trusted_step` feature gate usage from inside the index newtype macro. It didn't work for the `min_specialization` feature gate though.
The third commit removes (almost) all feature gates from the compiler that weren't used anyway.
rustc: Allow safe #[target_feature] on wasm
This commit updates the compiler's handling of the `#[target_feature]`
attribute when applied to functions on WebAssembly-based targets. The
compiler in general requires that any functions with `#[target_feature]`
are marked as `unsafe` as well, but this commit relaxes the restriction
for WebAssembly targets where the attribute can be applied to safe
functions as well.
The reason this is done is that the motivation for this feature of the
compiler is not applicable for WebAssembly targets. In general the
`#[target_feature]` attribute is used to enhance target CPU features
enabled beyond the basic level for the rest of the compilation. If done
improperly this means that your program could execute an instruction
that the CPU you happen to be running on does not understand. This is
considered undefined behavior where it is unknown what will happen (e.g.
it's not a deterministic `SIGILL`).
For WebAssembly, however, the target is different. It is not possible
for a running WebAssembly program to execute an instruction that the
engine does not understand. If this were the case then the program would
not have validated in the first place and would not run at all. Even if
this were allowed in some hypothetical future where engines have some
form of runtime feature detection (which they do not right now) any
implementation of such a feature would generate a trap if a module
attempts to execute an instruction the module does not understand. This
deterministic trap behavior would still not fall into the category of
undefined behavior because the trap is deterministic.
For these reasons the `#[target_feature]` attribute is now allowed on
safe functions, but only for WebAssembly targets. This notably enables
the wasm-SIMD intrinsics proposed for stabilization in #74372 to be
marked as safe generally instead of today where they're all `unsafe` due
to the historical implementation of `#[target_feature]` in the compiler.
Fixes: #84018
With `-Z instrument-coverage`, coverage reporting of dead blocks
(for example, blocks dropped because a conditional branch is dropped,
based on const evaluation) is now supported.
Note, this PR relands an earlier, reverted PR that failed when compiling
generators. The prior issues with generators has been resolved and a new
test was added to prevent future regressions.
Check out the resulting changes to test coverage of dead blocks in the
test coverage reports in this PR.
Reduce the amount of untracked state in TyCtxt
Access to untracked global state may generate instances of #84970.
The GlobalCtxt contains the lowered HIR, the resolver outputs and interners.
By wrapping the resolver inside a query, we make sure those accesses are properly tracked.
As a no_hash query, all dependent queries essentially become `eval_always`,
what they should have been from the beginning.
Make `Step` trait safe to implement
This PR makes a few modifications to the `Step` trait that I believe better position it for stabilization in the short term. In particular,
1. `unsafe trait TrustedStep` is introduced, indicating that the implementation of `Step` for a given type upholds all stated invariants (which have remained unchanged). This is gated behind a new `trusted_step` feature, as stabilization is realistically blocked on min_specialization.
2. The `Step` trait is internally specialized on the `TrustedStep` trait, which avoids a serious performance regression.
3. `TrustedLen` is implemented for `T: TrustedStep` as the latter's invariants subsume the former's.
4. The `Step` trait is no longer `unsafe`, as the invariants must not be relied upon by unsafe code (unless the type implements `TrustedStep`).
5. `TrustedStep` is implemented for all types that implement `Step` in the standard library and compiler.
6. The `step_trait_ext` feature is merged into the `step_trait` feature. I was unable to find any reasoning for the features being split; the `_unchecked` methods need not necessarily be stabilized at the same time, but I think it is useful to have them under the same feature flag.
All existing implementations of `Step` will be broken, as it is not possible to `unsafe impl` a safe trait. Given this trait only exists on nightly, I feel this breakage is acceptable. The blanket `impl<T: Step> TrustedLen for T` will likely cause some minor breakage, but this should be covered by the equivalent impl for `TrustedStep`.
Hopefully these changes are sufficient to place `Step` in decent position for stabilization, which would allow user-defined types to be used with `a..b` syntax.
A bit more polish on const eval errors
This PR adds a bit more polish to the const eval errors:
- a slight improvement to the PME messages from #85633: I mentioned there that the erroneous item's paths were dependent on the environment, and could be displayed fully qualified or not. This can obscure the items when they come from a dependency. This PR uses the pretty-printing code ensuring the items' paths are not trimmed.
- whenever there are generics involved in an item where const evaluation errors out, the error message now displays the instance and its const arguments, so that we can see which instantiated item and compile-time values lead to the error.
So we get this slight improvement for our beloved `stdarch` example, on nightly:
```
error[E0080]: evaluation of constant value failed
--> ./stdarch/crates/core_arch/src/macros.rs:8:9
|
8 | assert!(IMM >= MIN && IMM <= MAX, "IMM value not in expected range");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'IMM value not in expected range', /rustc/9111b8ae9793f18179a1336417618fc07a9cac85/library/core/src/../../stdarch/crates/core_arch/src/macros.rs:8:9
|
```
to this PR's:
```
error[E0080]: evaluation of `core::core_arch::macros::ValidateConstImm::<51_i32, 0_i32, 15_i32>::VALID` failed
--> ./stdarch/crates/core_arch/src/macros.rs:8:9
|
8 | assert!(IMM >= MIN && IMM <= MAX, "IMM value not in expected range");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'IMM value not in expected range', ./stdarch/crates/core_arch/src/macros.rs:8:9
|
```
with this PR.
Of course this is an idea from Oli, so maybe r? `@oli-obk` if they have the time.
This commit updates the compiler's handling of the `#[target_feature]`
attribute when applied to functions on WebAssembly-based targets. The
compiler in general requires that any functions with `#[target_feature]`
are marked as `unsafe` as well, but this commit relaxes the restriction
for WebAssembly targets where the attribute can be applied to safe
functions as well.
The reason this is done is that the motivation for this feature of the
compiler is not applicable for WebAssembly targets. In general the
`#[target_feature]` attribute is used to enhance target CPU features
enabled beyond the basic level for the rest of the compilation. If done
improperly this means that your program could execute an instruction
that the CPU you happen to be running on does not understand. This is
considered undefined behavior where it is unknown what will happen (e.g.
it's not a deterministic `SIGILL`).
For WebAssembly, however, the target is different. It is not possible
for a running WebAssembly program to execute an instruction that the
engine does not understand. If this were the case then the program would
not have validated in the first place and would not run at all. Even if
this were allowed in some hypothetical future where engines have some
form of runtime feature detection (which they do not right now) any
implementation of such a feature would generate a trap if a module
attempts to execute an instruction the module does not understand. This
deterministic trap behavior would still not fall into the category of
undefined behavior because the trap is deterministic.
For these reasons the `#[target_feature]` attribute is now allowed on
safe functions, but only for WebAssembly targets. This notably enables
the wasm-SIMD intrinsics proposed for stabilization in #74372 to be
marked as safe generally instead of today where they're all `unsafe` due
to the historical implementation of `#[target_feature]` in the compiler.
const-eval: disallow unwinding across functions that `!fn_can_unwind()`
Following https://github.com/rust-lang/miri/pull/1776#discussion_r633074343, so r? `@RalfJung`
This PR turns `unwind` in `StackPopCleanup::Goto` into a new enum `StackPopUnwind`, with a `NotAllowed` variant to indicate that unwinding is not allowed. This variant is chosen based on `rustc_middle::ty::layout::fn_can_unwind()` in `eval_fn_call()` when pushing the frame. A check is added in `unwind_to_block()` to report UB if unwinding happens across a `StackPopUnwind::NotAllowed` frame.
Tested with Miri `HEAD` with [minor changes](https://github.com/rust-lang/miri/compare/HEAD..9cf3c7f0d86325a586fbcbf2acdc9232b861f1d8) and the rust-lang/miri#1776 branch with [these changes](d866c1c52f..626638fbfe).
Post-monomorphization errors traces MVP
This PR works towards better diagnostics for the errors encountered in #85155 and similar.
We can encounter post-monomorphization errors (PMEs) when collecting mono items. The current diagnostics are confusing for these cases when they happen in a dependency (but are acceptable when they happen in the local crate).
These kinds of errors will be more likely now that `stdarch` uses const generics for its intrinsics' immediate arguments, and validates these const arguments with a mechanism that triggers such PMEs.
(Not to mention that the errors happen during codegen, so only when building code that actually uses these code paths. Check builds don't trigger them, neither does unused code)
So in this PR, we detect these kinds of errors during the mono item graph walk: if any error happens while collecting a node or its neighbors, we print a diagnostic about the current collection step, so that the user has at least some context of which erroneous code and dependency triggered the error.
The diagnostics for issue #85155 now have this note showing the source of the erroneous const argument:
```
note: the above error was encountered while instantiating `fn std::arch::x86_64::_mm_blend_ps::<51_i32>`
--> issue-85155.rs:11:24
|
11 | let _blended = _mm_blend_ps(a, b, 0x33);
| ^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
```
Note that #85155 is a reduced version of a case happening in the wild, to indirect users of the `rustfft` crate, as seen in https://github.com/ejmahler/RustFFT/issues/74. The crate had a few of these out-of-range immediates. Here's how the diagnostics in this PR would have looked on one of its examples before it was fixed:
<details>
```
error[E0080]: evaluation of constant value failed
--> ./stdarch/crates/core_arch/src/macros.rs:8:9
|
8 | assert!(IMM >= MIN && IMM <= MAX, "IMM value not in expected range");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'IMM value not in expected range', ./stdarch/crates/core_arch/src/macros.rs:8:9
|
= note: this error originates in the macro `$crate::panic::panic_2015` (in Nightly builds, run with -Z macro-backtrace for more info)
note: the above error was encountered while instantiating `fn _mm_blend_ps::<51_i32>`
--> /tmp/RustFFT/src/avx/avx_vector.rs:1314:23
|
1314 | let blended = _mm_blend_ps(rows[0], rows[2], 0x33);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: the above error was encountered while instantiating `fn _mm_permute_pd::<5_i32>`
--> /tmp/RustFFT/src/avx/avx_vector.rs:1859:9
|
1859 | _mm_permute_pd(self, 0x05)
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
note: the above error was encountered while instantiating `fn _mm_permute_pd::<15_i32>`
--> /tmp/RustFFT/src/avx/avx_vector.rs:1863:32
|
1863 | (_mm_movedup_pd(self), _mm_permute_pd(self, 0x0F))
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0080`.
error: could not compile `rustfft`
To learn more, run the command again with --verbose.
```
</details>
I've developed and discussed this with them, so maybe r? `@oli-obk` -- but feel free to redirect to someone else of course.
(I'm not sure we can say that this PR definitely closes issue 85155, as it's still unclear exactly which diagnostics and information would be interesting to report in such cases -- and we've discussed printing backtraces before. I have prototypes of some complete and therefore noisy backtraces I showed Oli, but we decided to not include them in this PR for now)