diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs index faff7f0b526..e484bef0e0b 100644 --- a/compiler/rustc_errors/src/diagnostic_builder.rs +++ b/compiler/rustc_errors/src/diagnostic_builder.rs @@ -99,16 +99,20 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> { } /// `ErrorGuaranteed::emit_producing_guarantee` uses this. - // FIXME(eddyb) make `ErrorGuaranteed` impossible to create outside `.emit()`. fn emit_producing_error_guaranteed(mut self) -> ErrorGuaranteed { let diag = self.take_diag(); - // Only allow a guarantee if the `level` wasn't switched to a - // non-error. The field isn't `pub`, but the whole `Diagnostic` can be - // overwritten with a new one, thanks to `DerefMut`. + // The only error levels that produce `ErrorGuaranteed` are + // `Error` and `DelayedBug`. But `DelayedBug` should never occur here + // because delayed bugs have their level changed to `Bug` when they are + // actually printed, so they produce an ICE. + // + // (Also, even though `level` isn't `pub`, the whole `Diagnostic` could + // be overwritten with a new one thanks to `DerefMut`. So this assert + // protects against that, too.) assert!( - diag.is_error(), - "emitted non-error ({:?}) diagnostic from `DiagnosticBuilder`", + matches!(diag.level, Level::Error | Level::DelayedBug), + "invalid diagnostic level ({:?})", diag.level, ); diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 7c62e3aa422..74cccda6cbf 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -931,6 +931,7 @@ impl DiagCtxt { /// This excludes lint errors and delayed bugs. pub fn has_errors(&self) -> Option { self.inner.borrow().has_errors().then(|| { + // FIXME(nnethercote) find a way to store an `ErrorGuaranteed`. #[allow(deprecated)] ErrorGuaranteed::unchecked_claim_error_was_emitted() }) @@ -942,6 +943,7 @@ impl DiagCtxt { let inner = self.inner.borrow(); let result = inner.has_errors() || inner.lint_err_count > 0; result.then(|| { + // FIXME(nnethercote) find a way to store an `ErrorGuaranteed`. #[allow(deprecated)] ErrorGuaranteed::unchecked_claim_error_was_emitted() }) @@ -954,6 +956,7 @@ impl DiagCtxt { let result = inner.has_errors() || inner.lint_err_count > 0 || !inner.delayed_bugs.is_empty(); result.then(|| { + // FIXME(nnethercote) find a way to store an `ErrorGuaranteed`. #[allow(deprecated)] ErrorGuaranteed::unchecked_claim_error_was_emitted() }) @@ -1238,6 +1241,7 @@ impl DiagCtxtInner { } } + // Return value is only `Some` if the level is `Error` or `DelayedBug`. fn emit_diagnostic(&mut self, mut diagnostic: Diagnostic) -> Option { assert!(diagnostic.level.can_be_top_or_sub().0); @@ -1316,6 +1320,7 @@ impl DiagCtxtInner { !self.emitted_diagnostics.insert(diagnostic_hash) }; + let level = diagnostic.level; let is_error = diagnostic.is_error(); let is_lint = diagnostic.is_lint.is_some(); @@ -1352,6 +1357,7 @@ impl DiagCtxtInner { self.emitter.emit_diagnostic(diagnostic); } + if is_error { if is_lint { self.lint_err_count += 1; @@ -1359,11 +1365,11 @@ impl DiagCtxtInner { self.err_count += 1; } self.panic_if_treat_err_as_bug(); + } - #[allow(deprecated)] - { - guaranteed = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()); - } + #[allow(deprecated)] + if level == Level::Error { + guaranteed = Some(ErrorGuaranteed::unchecked_claim_error_was_emitted()); } }); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index ea6766ea583..1a1e1de6734 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -2477,9 +2477,8 @@ where pub struct ErrorGuaranteed(()); impl ErrorGuaranteed { - /// To be used only if you really know what you are doing... ideally, we would find a way to - /// eliminate all calls to this method. - #[deprecated = "`Session::span_delayed_bug` should be preferred over this function"] + /// Don't use this outside of `DiagCtxtInner::emit_diagnostic`! + #[deprecated = "should only be used in `DiagCtxtInner::emit_diagnostic`"] pub fn unchecked_claim_error_was_emitted() -> Self { ErrorGuaranteed(()) }