-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Rename ErrorReported
-> ErrorGuaranteed
#93244
Conversation
This comment has been minimized.
This comment has been minimized.
We could probably let this sit to see if anyone else from @rust-lang/compiler has opinions on the bikeshed. |
Honestly, I think ErrorReported is more clear. Even with delay_span_bug, an error does get emitted (or it might be an ICE, I don't recall) even if a diagnostic isn't emitted. |
The problem with the name is one of ordering/causality. With
|
I don't have strong feeling here myself. I understand Eddy's point, but also think the usage with |
☔ The latest upstream changes (presumably #93245) made this pull request unmergeable. Please resolve the merge conflicts. |
I wouldn't say that, given that |
@jackh726 Do you think |
ErrorGuaranteed sounds good |
ErrorReported
-> ErrorGuaranteed
Forgot to leave a comment, but I meant to say that this LGTM, I just want more @rust-lang/compiler eyes on it. |
I am nervous about this. In fact, this precise usage has gotten us into trouble before. |
The problem is this:
|
@nikomatsakis That seems like an abuse of |
Well, that's the opposite of |
Isn't that precisely why we have To avoid There's currently over 150 It seems much more work than what we can do more immediately, but maybe I'm missing a subtle detail. |
I'm a bit confused about the case @nikomatsakis is worried about; is it when we've already emitted a I guess one "cheap" way we can solve this is to make Another alternative would be some kind of error code enum, for a little bit more precise matching. A benefit of this is we could in theory use that to deduplicate previously-emitted errors (so, if we slowly change I think a key difference between I can understand @nikomatsakis's point, kind of. But I don't know the best way to solve it. Maybe a solution is to move any errors that are emitted solely from a |
To be clear, my example is not theoretical: we actually had this bug. I forget the precise details, but it went something like this: Some parts of the code ran at many times. At some points they could see that a given situation would result in a region error, so they returned But region inference had not run yet. When it did go to run, it observed the |
Hmm, ok, I agree that Generating an ICE is obviously suboptimal, but it's not unsoundness. |
I'm personally quite happy with the name, but an alternative could be |
I think I am happy so long as we have a rustc-dev-guide chapter explaining when it is ok to use "error guaranteed" (and outlining when it is not -- i.e., the scenario I wrote above). |
I have rebased this PR and open a PR on the rustc-dev-guide to document @rustbot modify labels: +S-waiting-on-review -S-waiting-on-author |
r? @oli-obk Assigning to myself as it was previously unassigned |
☔ The latest upstream changes (presumably #94392) made this pull request unmergeable. Please resolve the merge conflicts. |
r=me after a rebase @bors p=1 bitrotty |
@oli-obk rebased! |
@bors r+ |
📌 Commit e489a94 has been approved by |
☀️ Test successful - checks-actions |
Finished benchmarking commit (08504c6): comparison url. Summary: This benchmark run did not return any relevant results. If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf. @rustbot label: -perf-regression |
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 rust-lang#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: * rust-lang#69426 and it's ongoing implementation: rust-lang#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 * rust-lang#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 rust-lang#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`
r? @eddyb
cc #93222 #69426
The idea is that we would like to use it for both errors and
delay_span_bug
. Its semantics indicate a guarantee that compilation will fail.