Commit graph

165 commits

Author SHA1 Message Date
bors 10913c0001 Auto merge of #87835 - xFrednet:rfc-2383-expect-attribute-with-ids, r=wesleywiser
Implementation of the `expect` attribute (RFC 2383)

This is an implementation of the `expect` attribute as described in [RFC-2383](https://rust-lang.github.io/rfcs/2383-lint-reasons.html). The attribute allows the suppression of lint message by expecting them. Unfulfilled lint expectations (meaning no expected lint was caught) will emit the `unfulfilled_lint_expectations` lint at the `expect` attribute.

### Example
#### input
```rs
// required feature flag
#![feature(lint_reasons)]

#[expect(unused_mut)] // Will warn about an unfulfilled expectation
#[expect(unused_variables)] // Will be fulfilled by x
fn main() {
    let x = 0;
}
```

#### output

```txt
warning: this lint expectation is unfulfilled
  --> $DIR/trigger_lint.rs:3:1
   |
LL | #[expect(unused_mut)] // Will warn about an unfulfilled expectation
   |          ^^^^^^^^^^
   |
   = note: `#[warn(unfulfilled_lint_expectations)]` on by default
```

### Implementation

This implementation introduces `Expect` as a new lint level for diagnostics, which have been expected. All lint expectations marked via the `expect` attribute are collected in the [`LintLevelsBuilder`] and assigned an ID that is stored in the new lint level. The `LintLevelsBuilder` stores all found expectations and the data needed to emit the `unfulfilled_lint_expectations` in the [`LintLevelsMap`] which is the result of the [`lint_levels()`] query.

The [`rustc_errors::HandlerInner`] is the central error handler in rustc and handles the emission of all diagnostics. Lint message with the level `Expect` are suppressed during this emission, while the expectation ID is stored in a set which marks them as fulfilled. The last step is then so simply check if all expectations collected by the [`LintLevelsBuilder`] in the [`LintLevelsMap`] have been marked as fulfilled in the [`rustc_errors::HandlerInner`]. Otherwise, a new lint message will be emitted.

The implementation of the `LintExpectationId` required some special handling to make it stable between sessions. Lints can be emitted during [`EarlyLintPass`]es. At this stage, it's not possible to create a stable identifier. The level instead stores an unstable identifier, which is later converted to a stable `LintExpectationId`.

### Followup TO-DOs
All open TO-DOs have been marked with `FIXME` comments in the code. This is the combined list of them:

* [ ] The current implementation doesn't cover cases where the `unfulfilled_lint_expectations` lint is actually expected by another `expect` attribute.
   * This should be easily possible, but I wanted to get some feedback before putting more work into this.
   * This could also be done in a new PR to not add to much more code to this one
* [ ] Update unstable documentation to reflect this change.
* [ ] Update unstable expectation ids in [`HandlerInner::stashed_diagnostics`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.HandlerInner.html#structfield.stashed_diagnostics)

### Open questions
I also have a few open questions where I would like to get feedback on:
1. The RFC discussion included a suggestion to change the `expect` attribute to something else. (Initiated by `@Ixrec` [here](https://github.com/rust-lang/rfcs/pull/2383#issuecomment-378424091), suggestion from `@scottmcm` to use `#[should_lint(...)]` [here](https://github.com/rust-lang/rfcs/pull/2383#issuecomment-378648877)). No real conclusion was drawn on that point from my understanding. Is this still open for discussion, or was this discarded with the merge of the RFC?
2. How should the expect attribute deal with the new `force-warn` lint level?

---

This approach was inspired by a discussion with `@LeSeulArtichaut.`

RFC tracking issue: #54503

Mentoring/Implementation issue: #85549

[`LintLevelsBuilder`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/levels/struct.LintLevelsBuilder.html
[`LintLevelsMap`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/lint/struct.LintLevelMap.html
[`lint_levels()`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.lint_levels
[`rustc_errors::HandlerInner`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.HandlerInner.html
[`EarlyLintPass`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint/trait.EarlyLintPass.html
2022-03-03 18:59:32 +00:00
xFrednet defc056ccc
Address review comments 2022-03-02 17:46:12 +01:00
xFrednet 4887eb7b2d
Added panics for unreachable states for expectations (RFC 2383) 2022-03-02 17:46:11 +01:00
xFrednet aa2a0a83d9
Expect each lint in attribute individually (RFC-2383) 2022-03-02 17:46:09 +01:00
xFrednet 33a5945069
Make LintExpectationId stable between compilation sessions (RFC-2383) 2022-03-02 17:46:08 +01:00
xFrednet 2ca9037b61
Set LintExpectationId in level and collect fulfilled ones (RFC-2383)
* Collect lint expectations and set expectation ID in level (RFC-2383)
* Collect IDs of fulfilled lint expectations from diagnostics (RFC 2383)
2022-03-02 17:46:07 +01:00
xFrednet 9fef3d9e0a
Added Expect lint level and attribute (RFC-2383)
* Also added the `LintExpectationId` which will be used in future commits
2022-03-02 17:46:05 +01:00
mark e489a94dee rename ErrorReported -> ErrorGuaranteed 2022-03-02 09:45:25 -06:00
bors 48132caac2 Auto merge of #94427 - cjgillot:inline-fresh-expn, r=oli-obk
Only create a single expansion for each inline integration.

The inlining integrator used to create one expansion for each span from the callee body.
This PR reverses the logic to create a single expansion for the whole call,
which is more consistent with how macro expansions work for macros.

This should remove the large memory regression in #91743.
2022-02-28 08:25:26 +00:00
Camille GILLOT e77e4fcf89 Only create a single expansion for each inline integration. 2022-02-27 19:05:56 +01:00
Mark Rousskov 22c3a71de1 Switch bootstrap cfgs 2022-02-25 08:00:52 -05:00
bors d4de1f230c Auto merge of #93368 - eddyb:diagbld-guarantee, r=estebank
rustc_errors: let `DiagnosticBuilder::emit` return a "guarantee of emission".

That is, `DiagnosticBuilder` is now generic over the return type of `.emit()`, so we'll now have:
* `DiagnosticBuilder<ErrorReported>` for error (incl. fatal/bug) diagnostics
  * can only be created via a `const L: Level`-generic constructor, that limits allowed variants via a `where` clause, so not even `rustc_errors` can accidentally bypass this limitation
  * asserts `diagnostic.is_error()` on emission, just in case the construction restriction was bypassed (e.g. by replacing the whole `Diagnostic` inside `DiagnosticBuilder`)
  * `.emit()` returns `ErrorReported`, as a "proof" token that `.emit()` was called
    (though note that this isn't a real guarantee until after completing the work on
     #69426)
* `DiagnosticBuilder<()>` for everything else (warnings, notes, etc.)
  * can also be obtained from other `DiagnosticBuilder`s by calling `.forget_guarantee()`

This PR is a companion to other ongoing work, namely:
* #69426
  and it's ongoing implementation:
  #93222
  the API changes in this PR are needed to get statically-checked "only errors produce `ErrorReported` from `.emit()`", but doesn't itself provide any really strong guarantees without those other `ErrorReported` changes
* #93244
  would make the choices of API changes (esp. naming) in this PR fit better overall

In order to be able to let `.emit()` return anything trustable, several changes had to be made:
* `Diagnostic`'s `level` field is now private to `rustc_errors`, to disallow arbitrary "downgrade"s from "some kind of error" to "warning" (or anything else that doesn't cause compilation to fail)
  * it's still possible to replace the whole `Diagnostic` inside the `DiagnosticBuilder`, sadly, that's harder to fix, but it's unlikely enough that we can paper over it with asserts on `.emit()`
* `.cancel()` now consumes `DiagnosticBuilder`, preventing `.emit()` calls on a cancelled diagnostic
  * it's also now done internally, through `DiagnosticBuilder`-private state, instead of having a `Level::Cancelled` variant that can be read (or worse, written) by the user
  * this removes a hazard of calling `.cancel()` on an error then continuing to attach details to it, and even expect to be able to `.emit()` it
  * warnings were switched to *only* `can_emit_warnings` on emission (instead of pre-cancelling early)
  * `struct_dummy` was removed (as it relied on a pre-`Cancelled` `Diagnostic`)
* since `.emit()` doesn't consume the `DiagnosticBuilder` <sub>(I tried and gave up, it's much more work than this PR)</sub>,
  we have to make `.emit()` idempotent wrt the guarantees it returns
  * thankfully, `err.emit(); err.emit();` can return `ErrorReported` both times, as the second `.emit()` call has no side-effects *only* because the first one did do the appropriate emission
* `&mut Diagnostic` is now used in a lot of function signatures, which used to take `&mut DiagnosticBuilder` (in the interest of not having to make those functions generic)
  * the APIs were already mostly identical, allowing for low-effort porting to this new setup
  * only some of the suggestion methods needed some rework, to have the extra `DiagnosticBuilder` functionality on the `Diagnostic` methods themselves (that change is also present in #93259)
  * `.emit()`/`.cancel()` aren't available, but IMO calling them from an "error decorator/annotator" function isn't a good practice, and can lead to strange behavior (from the caller's perspective)
  * `.downgrade_to_delayed_bug()` was added, letting you convert any `.is_error()` diagnostic into a `delay_span_bug` one (which works because in both cases the guarantees available are the same)

This PR should ideally be reviewed commit-by-commit, since there is a lot of fallout in each.

r? `@estebank` cc `@Manishearth` `@nikomatsakis` `@mark-i-m`
2022-02-25 00:46:04 +00:00
Mark Rousskov 34319ff4e1 Avoid emitting full macro body into JSON 2022-02-24 11:16:45 -05:00
Eduard-Mihai Burtescu b7e95dee65 rustc_errors: let DiagnosticBuilder::emit return a "guarantee of emission". 2022-02-23 06:38:52 +00:00
Eduard-Mihai Burtescu 0b9d70cf6d rustc_errors: take self by value in DiagnosticBuilder::cancel. 2022-02-23 06:08:06 +00:00
Eduard-Mihai Burtescu 8562d6b752 rustc_errors: remove struct_dummy. 2022-02-23 05:38:24 +00:00
Eduard-Mihai Burtescu d4fc5ae25c rustc_errors: handle force_warn only through DiagnosticId::Lint. 2022-02-23 05:38:24 +00:00
Eduard-Mihai Burtescu 02ff9e0aef Replace &mut DiagnosticBuilder, in signatures, with &mut Diagnostic. 2022-02-23 05:38:19 +00:00
Eduard-Mihai Burtescu f24ff1815f rustc_errors: add downgrade_to_delayed_bug to Diagnostic itself. 2022-02-23 03:46:51 +00:00
Mark Rousskov 60b71f56e7 Remove support for JSON deserialization to Rust
This is no longer used by the compiler itself, and removing this support opens
the door to massively simplifying the Decodable/Decoder API by dropping the
self-describing deserialization support (necessary for JSON).
2022-02-20 18:58:21 -05:00
est31 2ef8af6619 Adopt let else in more places 2022-02-19 17:27:43 +01:00
lcnr a1a30f7548 add a rustc::query_stability lint 2022-02-01 10:15:59 +01:00
Eduard-Mihai Burtescu f5a32711dc rustc_errors: add a new assert for the size of PResult<()>. 2022-01-24 15:14:40 +00:00
Eduard-Mihai Burtescu a8dfa3757c rustc_errors: only box the diagnostic field in DiagnosticBuilder. 2022-01-24 11:23:14 +00:00
Eduard-Mihai Burtescu 68fa81baa3 rustc_errors: remove allow_suggestions from DiagnosticBuilder. 2022-01-24 10:49:10 +00:00
Matthias Krüger a1645e5b57
Rollup merge of #93229 - mark-i-m:noquiet, r=eddyb
Remove DiagnosticBuilder.quiet

r? `@eddyb`

cc https://github.com/rust-lang/rust/issues/69426 `@GuillaumeGomez` `@Manishearth`
2022-01-23 20:13:07 +01:00
mark cf382de0cc Remove DiagnosticBuilder.quiet 2022-01-23 00:11:13 -06:00
Nicholas Nethercote 416399dc10 Make Decodable and Decoder infallible.
`Decoder` has two impls:
- opaque: this impl is already partly infallible, i.e. in some places it
  currently panics on failure (e.g. if the input is too short, or on a
  bad `Result` discriminant), and in some places it returns an error
  (e.g. on a bad `Option` discriminant). The number of places where
  either happens is surprisingly small, just because the binary
  representation has very little redundancy and a lot of input reading
  can occur even on malformed data.
- json: this impl is fully fallible, but it's only used (a) for the
  `.rlink` file production, and there's a `FIXME` comment suggesting it
  should change to a binary format, and (b) in a few tests in
  non-fundamental ways. Indeed #85993 is open to remove it entirely.

And the top-level places in the compiler that call into decoding just
abort on error anyway. So the fallibility is providing little value, and
getting rid of it leads to some non-trivial performance improvements.

Much of this commit is pretty boring and mechanical. Some notes about
a few interesting parts:
- The commit removes `Decoder::{Error,error}`.
- `InternIteratorElement::intern_with`: the impl for `T` now has the same
  optimization for small counts that the impl for `Result<T, E>` has,
  because it's now much hotter.
- Decodable impls for SmallVec, LinkedList, VecDeque now all use
  `collect`, which is nice; the one for `Vec` uses unsafe code, because
  that gave better perf on some benchmarks.
2022-01-22 10:38:31 +11:00
bors 2e2c86eba2 Auto merge of #92070 - rukai:replace_vec_into_iter_with_array_into_iter, r=Mark-Simulacrum
Replace usages of vec![].into_iter with [].into_iter

`[].into_iter` is idiomatic over `vec![].into_iter` because its simpler and faster (unless the vec is optimized away in which case it would be the same)

So we should change all the implementation, documentation and tests to use it.

I skipped:
* `src/tools` - Those are copied in from upstream
* `src/test/ui` - Hard to tell if `vec![].into_iter` was used intentionally or not here and not much benefit to changing it.
*  any case where `vec![].into_iter` was used because we specifically needed a `Vec::IntoIter<T>`
*  any case where it looked like we were intentionally using `vec![].into_iter` to test it.
2022-01-11 14:23:24 +00:00
Lamb 3a77bb86ff Compute most of Public/Exported access level in rustc_resolve
Mak DefId to AccessLevel map in resolve for export

hir_id to accesslevel in resolve and applied in privacy
using local def id
removing tracing probes
making function not recursive and adding comments

Move most of Exported/Public res to rustc_resolve

moving public/export res to resolve

fix missing stability attributes in core, std and alloc

move code to access_levels.rs

return for some kinds instead of going through them

Export correctness, macro changes, comments

add comment for import binding

add comment for import binding

renmae to access level visitor, remove comments, move fn as closure, remove new_key

fmt

fix rebase

fix rebase

fmt

fmt

fix: move macro def to rustc_resolve

fix: reachable AccessLevel for enum variants

fmt

fix: missing stability attributes for other architectures

allow unreachable pub in rustfmt

fix: missing impl access level + renaming export to reexport

Missing impl access level was found thanks to a test in clippy
2022-01-09 21:33:14 +00:00
Lucas Kent 08829853d3 eplace usages of vec![].into_iter with [].into_iter 2022-01-09 14:09:25 +11:00
PFPoitras 304ede6bcc Stabilize iter::zip. 2021-12-14 18:50:31 -04:00
Matthias Krüger d96ce3ea8e
Rollup merge of #91394 - Mark-Simulacrum:bump-stage0, r=pietroalbini
Bump stage0 compiler

r? `@pietroalbini` (or anyone else)
2021-12-02 15:52:03 +01:00
Joshua Nelson 9de8a4a6fa Include lint errors in error count for -Ztreat-err-as-bug
This was a regression from https://github.com/rust-lang/rust/pull/87337;
the `panic_if_treat_err_as_bug` function only checked the number of hard
errors, not the number of lint errors.
2021-12-01 16:39:55 +00:00
Mark Rousskov b221c877e8 Apply cfg-bootstrap switch 2021-11-30 10:51:42 -05:00
Yuki Okushi 56c838cdc7
Rollup merge of #91358 - kd-collective:fix_typo, r=cjgillot
Fix small typo

Fix a typo in code commenting!
`accross` -> `across`
2021-11-30 17:29:10 +09:00
kijima 3c42a11895 Fix small typo 2021-11-30 01:31:10 +09:00
Lucas Kent df3e7a28f7 Refactor EmitterWriter::emit_suggestion_default 2021-11-27 01:13:37 +11:00
Esteban Kuber 143f784199 replace_tabs -> normalize_whitespace 2021-11-23 20:37:21 +00:00
Esteban Kuber a96fe02f6c Replace ZWJ with nothing in terminal output 2021-11-23 20:36:14 +00:00
Esteban Kuber 8f433adf75 Align multiline messages to their label (add left margin) 2021-11-20 19:19:33 +00:00
Josh Triplett 8c9bfaa5f3 Stabilize format_args_capture
Works as expected, and there are widespread reports of success with it,
as well as interest in it.
2021-11-15 10:14:29 +01:00
Joshua Nelson 0ac13bd430 Don't abort compilation after giving a lint error
The only reason to use `abort_if_errors` is when the program is so broken that either:
1. later passes get confused and ICE
2. any diagnostics from later passes would be noise

This is never the case for lints, because the compiler has to be able to deal with `allow`-ed lints.
So it can continue to lint and compile even if there are lint errors.
2021-11-08 01:22:28 +00:00
Esteban Küber c0b134582a
Lint against RTL unicode codepoints in literals and comments
Address CVE-2021-42574.
2021-10-31 13:14:04 +01:00
Mark Rousskov 3215eeb99f
Revert "Add rustc lint, warning when iterating over hashmaps" 2021-10-28 11:01:42 -04:00
bors 41d8c94d45 Auto merge of #89427 - estebank:collect-overlapping-impls, r=jackh726
Point at overlapping impls when type annotations are needed

Address https://github.com/rust-lang/rust/issues/89254.
2021-10-24 22:26:41 +00:00
Esteban Kuber 881a50c0b7 Always sort suggestions before emitting them 2021-10-24 20:28:44 +00:00
Matthias Krüger 87822b27ee
Rollup merge of #89558 - lcnr:query-stable-lint, r=estebank
Add rustc lint, warning when iterating over hashmaps

r? rust-lang/wg-incr-comp
2021-10-24 15:48:42 +02:00
Matthias Krüger 0f81c7faf5
Rollup merge of #89468 - FabianWolff:issue-89358, r=jackh726
Report fatal lexer errors in `--cfg` command line arguments

Fixes #89358. The erroneous behavior was apparently introduced by `@Mark-Simulacrum` in a678e31911; the idea is to silence individual parser errors and instead emit one catch-all error message after parsing. However, for the example in #89358, a fatal lexer error is created here:
edebf77e00/compiler/rustc_parse/src/lexer/mod.rs (L340-L349)

This fatal error aborts the compilation, and so the call to `new_parser_from_source_str()` never returns and the catch-all error message is never emitted. I have therefore changed the `SilentEmitter` to silence only non-fatal errors; with my changes, for the rustc invocation described in #89358:
```sh
rustc --cfg "abc\""
```
I get the following output:
```
error[E0765]: unterminated double quote string
  |
  = note: this error occurred on the command line: `--cfg=abc"`
```
2021-10-23 05:28:22 +02:00
bors 1af55d19c7 Auto merge of #89933 - est31:let_else, r=michaelwoerister
Adopt let_else across the compiler

This performs a substitution of code following the pattern:

```
let <id> = if let <pat> = ... { identity } else { ... : ! };
```

To simplify it to:

```
let <pat> = ... { identity } else { ... : ! };
```

By adopting the `let_else` feature (cc #87335).

The PR also updates the syn crate because the currently used version of the crate doesn't support `let_else` syntax yet.

Note: Generally I'm the person who *removes* usages of unstable features from the compiler, not adds more usages of them, but in this instance I think it hopefully helps the feature get stabilized sooner and in a better state. I have written a [comment](https://github.com/rust-lang/rust/issues/87335#issuecomment-944846205) on the tracking issue about my experience and what I feel could be improved before stabilization of `let_else`.
2021-10-19 14:41:39 +00:00