Vastly improves coverage spans for macros
Fixes: #84561
This resolves problems where macros like `trace!(...)` would show zero coverage if tracing was disabled, and `assert_eq!(...)` would show zero coverage if the assertion did not fail, because only one coverage span was generated, for the branch.
This PR started with an idea that I could just drop branching blocks with same span as expanded macro. (See the fixed issue for more details.)
That did help, but it didn't resolve everything.
I also needed to add a span specifically for the macro name (plus `!`) to ensure the macro gets coverage even if it's internal expansion adds conditional branching blocks that are retained, and would otherwise drop the outer span. Now that outer span is _only_ the `(argument, list)`, which can safely be dropped now), because the macro name has its own span.
While testing, I also noticed the spanview debug output can cause an ICE on a function with no body. The
workaround for this is included in this PR (separate commit).
r? `@tmandry`
cc? `@wesleywiser`
Implement RFC 1260 with feature_name `imported_main`.
This is the second extraction part of #84062 plus additional adjustments.
This (mostly) implements RFC 1260.
However there's still one test case failure in the extern crate case. Maybe `LocalDefId` doesn't work here? I'm not sure.
cc https://github.com/rust-lang/rust/issues/28937
r? `@petrochenkov`
use correct feature flag for impl-block-level trait bounds on const fn
I am not sure what that special hack was needed for, but it doesn't seem needed any more...
This removes the last use of the `const_fn` feature flag -- Cc https://github.com/rust-lang/rust/issues/84510
r? `@oli-obk`
Adds feature-gated `#[no_coverage]` function attribute, to fix derived Eq `0` coverage issue #83601
Derived Eq no longer shows uncovered
The Eq trait has a special hidden function. MIR `InstrumentCoverage`
would add this function to the coverage map, but it is never called, so
the `Eq` trait would always appear uncovered.
Fixes: #83601
The fix required creating a new function attribute `no_coverage` to mark
functions that should be ignored by `InstrumentCoverage` and the
coverage `mapgen` (during codegen).
Adding a `no_coverage` feature gate with tracking issue #84605.
r? `@tmandry`
cc: `@wesleywiser`
Improve coverage spans for chained function calls
Fixes: #84180
For chained function calls separated by the `?` try operator, the
function call following the try operator produced a MIR `Call` span that
matched the span of the first call. The `?` try operator started a new
span, so the second call got no span.
It turns out the MIR `Call` terminator has a `func` `Operand`
for the `Constant` representing the function name, and the function
name's Span can be used to reset the starting position of the span.
r? `@tmandry`
cc: `@wesleywiser`
The Eq trait has a special hidden function. MIR `InstrumentCoverage`
would add this function to the coverage map, but it is never called, so
the `Eq` trait would always appear uncovered.
Fixes: #83601
The fix required creating a new function attribute `no_coverage` to mark
functions that should be ignored by `InstrumentCoverage` and the
coverage `mapgen` (during codegen).
While testing, I also noticed two other issues:
* spanview debug file output ICEd on a function with no body. The
workaround for this is included in this PR.
* `assert_*!()` macro coverage can appear covered if followed by another
`assert_*!()` macro. Normally they appear uncovered. I submitted a new
Issue #84561, and added a coverage test to demonstrate this issue.
Fix coverage ICE because fn_sig can have a span that crosses file bou…
Fixes: #83792
MIR `InstrumentCoverage` assumed the `FnSig` span was contained within a
single file, but this is not always the case. Some macro constructions
can result in a span that starts in one `SourceFile` and ends in a
different one.
The `FnSig` span is included in coverage results as long as that span is
in the same `SourceFile` and the same macro context, but by assuming the
`FnSig` span's `hi()` and `lo()` were in the same file, I took this for
granted, and checked only that the `FnSig` `hi()` was in the same
`SourceFile` as the `body_span`.
I actually drop the `hi()` though, and extend the `FnSig` span to the
`body_span.lo()`, so I really should have simply checked that the
`FnSig` span's `lo()` was in the `SourceFile` of the `body_span`.
r? `@tmandry`
cc: `@wesleywiser`
Fixes: #84180
For chained function calls separated by the `?` try operator, the
function call following the try operator produced a MIR `Call` span that
matched the span of the first call. The `?` try operator started a new
span, so the second call got no span.
It turns out the MIR `Call` terminator has a `func` `Operand`
for the `Constant` representing the function name, and the function
name's Span can be used to reset the starting position of the span.
further split up const_fn feature flag
This continues the work on splitting up `const_fn` into separate feature flags:
* `const_fn_trait_bound` for `const fn` with trait bounds
* `const_fn_unsize` for unsizing coercions in `const fn` (looks like only `dyn` unsizing is still guarded here)
I don't know if there are even any things left that `const_fn` guards... at least libcore and liballoc do not need it any more.
`@oli-obk` are you currently able to do reviews?
Fixes: #83792
MIR `InstrumentCoverage` assumed the `FnSig` span was contained within a
single file, but this is not always the case. Some macro constructions
can result in a span that starts in one `SourceFile` and ends in a
different one.
The `FnSig` span is included in coverage results as long as that span is
in the same `SourceFile` and the same macro context, but by assuming the
`FnSig` span's `hi()` and `lo()` were in the same file, I took this for
granted, and checked only that the `FnSig` `hi()` was in the same
`SourceFile` as the `body_span`.
I actually drop the `hi()` though, and extend the `FnSig` span to the
`body_span.lo()`, so I really should have simply checked that the
`FnSig` span's `lo()` was in the `SourceFile` of the `body_span`.
Implement a lint that highlights all moves larger than a configured limit
Tracking issue: #83518
[MCP 420](https://github.com/rust-lang/compiler-team/issues/420) still ~blazing~ in progress
r? ```@pnkfelix```
The main open issue I see with this minimal impl of the feature is that the lint is immediately "stable" (so it can be named on stable), even if it is never executed on stable. I don't think we have the concept of unstable lint names or hiding lint names without an active feature gate, so that would be a bigger change.
Suggest `.as_ref()` on borrow error involving `Option`/`Result`
When encountering a E0382 borrow error involving an `Option` or `Result`
provide a suggestion to use `.as_ref()` on the prior move location to
avoid the move.
Fix#84165.
coverage of async function bodies should match non-async
This fixes some missing coverage within async function bodies.
Commit 1 demonstrates the problem in the fixed issue, and commit 2 corrects it.
Fixes: #83985
When encountering a E0382 borrow error involving an `Option` or `Result`
provide a suggestion to use `.as_ref()` on the prior move location to
avoid the move.
Fix#84165.
This message is emitted as guidance by the compiler when a developer attempts to reassign a value to an immutable variable. Following the message will always currently work, but it may not always be the best course of action; following the 'consider ...' messaging pattern provides a hint to the developer that it could be wise to explore other alternatives.
Don't concatenate binders across types
Partially addresses #83737
There's actually two issues that I uncovered in #83737. The first is that we are concatenating bound vars across types, i.e. in
```
F: Fn(&()) -> &mut (dyn Future<Output = ()> + Unpin)
```
the bound vars on `Future` get set as `for<anon>` since those are the binders on `Fn(&()`. This is obviously wrong, since we should only concatenate directly nested trait refs. This is solved here by introducing a new `TraitRefBoundary` scope, that we put around the "syntactical" trait refs and basically don't allow concatenation across.
Now, this alone *shouldn't* be a super terrible problem. At least not until you consider the other issue, which is a much more elusive and harder to design a "perfect" fix. A repro can be seen in:
```
use core::future::Future;
async fn handle<F>(slf: &F)
where
F: Fn(&()) -> &mut (dyn for<'a> Future<Output = ()> + Unpin),
{
(slf)(&()).await;
}
```
Notice the `for<'a>` around `Future`. Here, `'a` is unused, so the `for<'a>` Binder gets changed to a `for<>` Binder in the generator witness, but the "local decl" still has it. This has heavy intersections with region anonymization and erasing. Luckily, it's not *super* common to find this unique set of circumstances. It only became apparently because of the first issue mentioned here. However, this *is* still a problem, so I'm leaving #83737 open.
r? `@nikomatsakis`
Use AnonConst for asm! constants
This replaces the old system which used explicit promotion. See #83169 for more background.
The syntax for `const` operands is still the same as before: `const <expr>`.
Fixes#83169
Because the implementation is heavily based on inline consts, we suffer from the same issues:
- We lose the ability to use expressions derived from generics. See the deleted tests in `src/test/ui/asm/const.rs`.
- We are hitting the same ICEs as inline consts, for example #78174. It is unlikely that we will be able to stabilize this before inline consts are stabilized.