-
Notifications
You must be signed in to change notification settings - Fork 13.2k
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # 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.