summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_errors/src/diagnostic_builder.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_errors/src/diagnostic_builder.rs')
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs298
1 files changed, 87 insertions, 211 deletions
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index 85acf8ab5..3f66af1fc 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -1,9 +1,9 @@
use crate::diagnostic::IntoDiagnosticArg;
+use crate::{DiagCtxt, Level, MultiSpan, StashKey};
use crate::{
Diagnostic, DiagnosticId, DiagnosticMessage, DiagnosticStyledString, ErrorGuaranteed,
ExplicitBug, SubdiagnosticMessage,
};
-use crate::{Handler, Level, MultiSpan, StashKey};
use rustc_lint_defs::Applicability;
use rustc_span::source_map::Spanned;
@@ -18,19 +18,19 @@ use std::thread::panicking;
/// Trait implemented by error types. This should not be implemented manually. Instead, use
/// `#[derive(Diagnostic)]` -- see [rustc_macros::Diagnostic].
#[rustc_diagnostic_item = "IntoDiagnostic"]
-pub trait IntoDiagnostic<'a, T: EmissionGuarantee = ErrorGuaranteed> {
- /// Write out as a diagnostic out of `Handler`.
+pub trait IntoDiagnostic<'a, G: EmissionGuarantee = ErrorGuaranteed> {
+ /// Write out as a diagnostic out of `DiagCtxt`.
#[must_use]
- fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, T>;
+ fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, G>;
}
-impl<'a, T, E> IntoDiagnostic<'a, E> for Spanned<T>
+impl<'a, T, G> IntoDiagnostic<'a, G> for Spanned<T>
where
- T: IntoDiagnostic<'a, E>,
- E: EmissionGuarantee,
+ T: IntoDiagnostic<'a, G>,
+ G: EmissionGuarantee,
{
- fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, E> {
- let mut diag = self.node.into_diagnostic(handler);
+ fn into_diagnostic(self, dcx: &'a DiagCtxt) -> DiagnosticBuilder<'a, G> {
+ let mut diag = self.node.into_diagnostic(dcx);
diag.set_span(self.span);
diag
}
@@ -40,7 +40,7 @@ where
///
/// If there is some state in a downstream crate you would like to
/// access in the methods of `DiagnosticBuilder` here, consider
-/// extending `HandlerFlags`, accessed via `self.handler.flags`.
+/// extending `DiagCtxtFlags`.
#[must_use]
#[derive(Clone)]
pub struct DiagnosticBuilder<'a, G: EmissionGuarantee> {
@@ -74,8 +74,8 @@ struct DiagnosticBuilderInner<'a> {
enum DiagnosticBuilderState<'a> {
/// Initial state of a `DiagnosticBuilder`, before `.emit()` or `.cancel()`.
///
- /// The `Diagnostic` will be emitted through this `Handler`.
- Emittable(&'a Handler),
+ /// The `Diagnostic` will be emitted through this `DiagCtxt`.
+ Emittable(&'a DiagCtxt),
/// State of a `DiagnosticBuilder`, after `.emit()` or *during* `.cancel()`.
///
@@ -95,7 +95,7 @@ enum DiagnosticBuilderState<'a> {
// `DiagnosticBuilderState` should be pointer-sized.
rustc_data_structures::static_assert_size!(
DiagnosticBuilderState<'_>,
- std::mem::size_of::<&Handler>()
+ std::mem::size_of::<&DiagCtxt>()
);
/// Trait for types that `DiagnosticBuilder::emit` can return as a "guarantee"
@@ -110,32 +110,12 @@ pub trait EmissionGuarantee: Sized {
/// Creates a new `DiagnosticBuilder` that will return this type of guarantee.
#[track_caller]
fn make_diagnostic_builder(
- handler: &Handler,
+ dcx: &DiagCtxt,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, Self>;
}
impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> {
- /// Convenience function for internal use, clients should use one of the
- /// `struct_*` methods on [`Handler`].
- #[track_caller]
- pub(crate) fn new_guaranteeing_error<M: Into<DiagnosticMessage>>(
- handler: &'a Handler,
- message: M,
- ) -> Self {
- Self {
- inner: DiagnosticBuilderInner {
- state: DiagnosticBuilderState::Emittable(handler),
- diagnostic: Box::new(Diagnostic::new_with_code(
- Level::Error { lint: false },
- None,
- message,
- )),
- },
- _marker: PhantomData,
- }
- }
-
/// Discard the guarantee `.emit()` would return, in favor of having the
/// type `DiagnosticBuilder<'a, ()>`. This may be necessary whenever there
/// is a common codepath handling both errors and warnings.
@@ -148,11 +128,11 @@ impl<'a> DiagnosticBuilder<'a, ErrorGuaranteed> {
impl EmissionGuarantee for ErrorGuaranteed {
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
match db.inner.state {
- // First `.emit()` call, the `&Handler` is still available.
- DiagnosticBuilderState::Emittable(handler) => {
+ // First `.emit()` call, the `&DiagCtxt` is still available.
+ DiagnosticBuilderState::Emittable(dcx) => {
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
- let guar = handler.emit_diagnostic(&mut db.inner.diagnostic);
+ let guar = dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic);
// Only allow a guarantee if the `level` wasn't switched to a
// non-error - the field isn't `pub`, but the whole `Diagnostic`
@@ -186,38 +166,10 @@ impl EmissionGuarantee for ErrorGuaranteed {
#[track_caller]
fn make_diagnostic_builder(
- handler: &Handler,
+ dcx: &DiagCtxt,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, Self> {
- DiagnosticBuilder::new_guaranteeing_error(handler, msg)
- }
-}
-
-impl<'a> DiagnosticBuilder<'a, ()> {
- /// Convenience function for internal use, clients should use one of the
- /// `struct_*` methods on [`Handler`].
- #[track_caller]
- pub(crate) fn new<M: Into<DiagnosticMessage>>(
- handler: &'a Handler,
- level: Level,
- message: M,
- ) -> Self {
- let diagnostic = Diagnostic::new_with_code(level, None, message);
- Self::new_diagnostic(handler, diagnostic)
- }
-
- /// Creates a new `DiagnosticBuilder` with an already constructed
- /// diagnostic.
- #[track_caller]
- pub(crate) fn new_diagnostic(handler: &'a Handler, diagnostic: Diagnostic) -> Self {
- debug!("Created new diagnostic");
- Self {
- inner: DiagnosticBuilderInner {
- state: DiagnosticBuilderState::Emittable(handler),
- diagnostic: Box::new(diagnostic),
- },
- _marker: PhantomData,
- }
+ DiagnosticBuilder::new(dcx, Level::Error { lint: false }, msg)
}
}
@@ -225,11 +177,11 @@ impl<'a> DiagnosticBuilder<'a, ()> {
impl EmissionGuarantee for () {
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
match db.inner.state {
- // First `.emit()` call, the `&Handler` is still available.
- DiagnosticBuilderState::Emittable(handler) => {
+ // First `.emit()` call, the `&DiagCtxt` is still available.
+ DiagnosticBuilderState::Emittable(dcx) => {
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
- handler.emit_diagnostic(&mut db.inner.diagnostic);
+ dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic);
}
// `.emit()` was previously called, disallowed from repeating it.
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
@@ -237,10 +189,10 @@ impl EmissionGuarantee for () {
}
fn make_diagnostic_builder(
- handler: &Handler,
+ dcx: &DiagCtxt,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, Self> {
- DiagnosticBuilder::new(handler, Level::Warning(None), msg)
+ DiagnosticBuilder::new(dcx, Level::Warning(None), msg)
}
}
@@ -249,35 +201,13 @@ impl EmissionGuarantee for () {
#[derive(Copy, Clone)]
pub struct Noted;
-impl<'a> DiagnosticBuilder<'a, Noted> {
- /// Convenience function for internal use, clients should use one of the
- /// `struct_*` methods on [`Handler`].
- pub(crate) fn new_note(handler: &'a Handler, message: impl Into<DiagnosticMessage>) -> Self {
- let diagnostic = Diagnostic::new_with_code(Level::Note, None, message);
- Self::new_diagnostic_note(handler, diagnostic)
- }
-
- /// Creates a new `DiagnosticBuilder` with an already constructed
- /// diagnostic.
- pub(crate) fn new_diagnostic_note(handler: &'a Handler, diagnostic: Diagnostic) -> Self {
- debug!("Created new diagnostic");
- Self {
- inner: DiagnosticBuilderInner {
- state: DiagnosticBuilderState::Emittable(handler),
- diagnostic: Box::new(diagnostic),
- },
- _marker: PhantomData,
- }
- }
-}
-
impl EmissionGuarantee for Noted {
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
match db.inner.state {
- // First `.emit()` call, the `&Handler` is still available.
- DiagnosticBuilderState::Emittable(handler) => {
+ // First `.emit()` call, the `&DiagCtxt` is still available.
+ DiagnosticBuilderState::Emittable(dcx) => {
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
- handler.emit_diagnostic(&mut db.inner.diagnostic);
+ dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic);
}
// `.emit()` was previously called, disallowed from repeating it.
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
@@ -287,10 +217,10 @@ impl EmissionGuarantee for Noted {
}
fn make_diagnostic_builder(
- handler: &Handler,
+ dcx: &DiagCtxt,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, Self> {
- DiagnosticBuilder::new_note(handler, msg)
+ DiagnosticBuilder::new(dcx, Level::Note, msg)
}
}
@@ -299,37 +229,14 @@ impl EmissionGuarantee for Noted {
#[derive(Copy, Clone)]
pub struct Bug;
-impl<'a> DiagnosticBuilder<'a, Bug> {
- /// Convenience function for internal use, clients should use one of the
- /// `struct_*` methods on [`Handler`].
- #[track_caller]
- pub(crate) fn new_bug(handler: &'a Handler, message: impl Into<DiagnosticMessage>) -> Self {
- let diagnostic = Diagnostic::new_with_code(Level::Bug, None, message);
- Self::new_diagnostic_bug(handler, diagnostic)
- }
-
- /// Creates a new `DiagnosticBuilder` with an already constructed
- /// diagnostic.
- pub(crate) fn new_diagnostic_bug(handler: &'a Handler, diagnostic: Diagnostic) -> Self {
- debug!("Created new diagnostic bug");
- Self {
- inner: DiagnosticBuilderInner {
- state: DiagnosticBuilderState::Emittable(handler),
- diagnostic: Box::new(diagnostic),
- },
- _marker: PhantomData,
- }
- }
-}
-
impl EmissionGuarantee for Bug {
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
match db.inner.state {
- // First `.emit()` call, the `&Handler` is still available.
- DiagnosticBuilderState::Emittable(handler) => {
+ // First `.emit()` call, the `&DiagCtxt` is still available.
+ DiagnosticBuilderState::Emittable(dcx) => {
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
- handler.emit_diagnostic(&mut db.inner.diagnostic);
+ dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic);
}
// `.emit()` was previously called, disallowed from repeating it.
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
@@ -339,44 +246,21 @@ impl EmissionGuarantee for Bug {
}
fn make_diagnostic_builder(
- handler: &Handler,
+ dcx: &DiagCtxt,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, Self> {
- DiagnosticBuilder::new_bug(handler, msg)
- }
-}
-
-impl<'a> DiagnosticBuilder<'a, !> {
- /// Convenience function for internal use, clients should use one of the
- /// `struct_*` methods on [`Handler`].
- #[track_caller]
- pub(crate) fn new_fatal(handler: &'a Handler, message: impl Into<DiagnosticMessage>) -> Self {
- let diagnostic = Diagnostic::new_with_code(Level::Fatal, None, message);
- Self::new_diagnostic_fatal(handler, diagnostic)
- }
-
- /// Creates a new `DiagnosticBuilder` with an already constructed
- /// diagnostic.
- pub(crate) fn new_diagnostic_fatal(handler: &'a Handler, diagnostic: Diagnostic) -> Self {
- debug!("Created new diagnostic");
- Self {
- inner: DiagnosticBuilderInner {
- state: DiagnosticBuilderState::Emittable(handler),
- diagnostic: Box::new(diagnostic),
- },
- _marker: PhantomData,
- }
+ DiagnosticBuilder::new(dcx, Level::Bug, msg)
}
}
impl EmissionGuarantee for ! {
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
match db.inner.state {
- // First `.emit()` call, the `&Handler` is still available.
- DiagnosticBuilderState::Emittable(handler) => {
+ // First `.emit()` call, the `&DiagCtxt` is still available.
+ DiagnosticBuilderState::Emittable(dcx) => {
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
- handler.emit_diagnostic(&mut db.inner.diagnostic);
+ dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic);
}
// `.emit()` was previously called, disallowed from repeating it.
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
@@ -386,50 +270,21 @@ impl EmissionGuarantee for ! {
}
fn make_diagnostic_builder(
- handler: &Handler,
+ dcx: &DiagCtxt,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, Self> {
- DiagnosticBuilder::new_fatal(handler, msg)
- }
-}
-
-impl<'a> DiagnosticBuilder<'a, rustc_span::fatal_error::FatalError> {
- /// Convenience function for internal use, clients should use one of the
- /// `struct_*` methods on [`Handler`].
- #[track_caller]
- pub(crate) fn new_almost_fatal(
- handler: &'a Handler,
- message: impl Into<DiagnosticMessage>,
- ) -> Self {
- let diagnostic = Diagnostic::new_with_code(Level::Fatal, None, message);
- Self::new_diagnostic_almost_fatal(handler, diagnostic)
- }
-
- /// Creates a new `DiagnosticBuilder` with an already constructed
- /// diagnostic.
- pub(crate) fn new_diagnostic_almost_fatal(
- handler: &'a Handler,
- diagnostic: Diagnostic,
- ) -> Self {
- debug!("Created new diagnostic");
- Self {
- inner: DiagnosticBuilderInner {
- state: DiagnosticBuilderState::Emittable(handler),
- diagnostic: Box::new(diagnostic),
- },
- _marker: PhantomData,
- }
+ DiagnosticBuilder::new(dcx, Level::Fatal, msg)
}
}
impl EmissionGuarantee for rustc_span::fatal_error::FatalError {
fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self {
match db.inner.state {
- // First `.emit()` call, the `&Handler` is still available.
- DiagnosticBuilderState::Emittable(handler) => {
+ // First `.emit()` call, the `&DiagCtxt` is still available.
+ DiagnosticBuilderState::Emittable(dcx) => {
db.inner.state = DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation;
- handler.emit_diagnostic(&mut db.inner.diagnostic);
+ dcx.emit_diagnostic_without_consuming(&mut db.inner.diagnostic);
}
// `.emit()` was previously called, disallowed from repeating it.
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
@@ -439,10 +294,10 @@ impl EmissionGuarantee for rustc_span::fatal_error::FatalError {
}
fn make_diagnostic_builder(
- handler: &Handler,
+ dcx: &DiagCtxt,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, Self> {
- DiagnosticBuilder::new_almost_fatal(handler, msg)
+ DiagnosticBuilder::new(dcx, Level::Fatal, msg)
}
}
@@ -484,7 +339,35 @@ impl<G: EmissionGuarantee> DerefMut for DiagnosticBuilder<'_, G> {
}
impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
- /// Emit the diagnostic.
+ /// Convenience function for internal use, clients should use one of the
+ /// `struct_*` methods on [`DiagCtxt`].
+ #[track_caller]
+ pub(crate) fn new<M: Into<DiagnosticMessage>>(
+ dcx: &'a DiagCtxt,
+ level: Level,
+ message: M,
+ ) -> Self {
+ let diagnostic = Diagnostic::new(level, message);
+ Self::new_diagnostic(dcx, diagnostic)
+ }
+
+ /// Creates a new `DiagnosticBuilder` with an already constructed
+ /// diagnostic.
+ #[track_caller]
+ pub(crate) fn new_diagnostic(dcx: &'a DiagCtxt, diagnostic: Diagnostic) -> Self {
+ debug!("Created new diagnostic");
+ Self {
+ inner: DiagnosticBuilderInner {
+ state: DiagnosticBuilderState::Emittable(dcx),
+ diagnostic: Box::new(diagnostic),
+ },
+ _marker: PhantomData,
+ }
+ }
+
+ /// Emit the diagnostic. Does not consume `self`, which may be surprising,
+ /// but there are various places that rely on continuing to use `self`
+ /// after calling `emit`.
#[track_caller]
pub fn emit(&mut self) -> G {
G::diagnostic_builder_emit_producing_guarantee(self)
@@ -515,7 +398,7 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
/// Stashes diagnostic for possible later improvement in a different,
/// later stage of the compiler. The diagnostic can be accessed with
- /// the provided `span` and `key` through [`Handler::steal_diagnostic()`].
+ /// the provided `span` and `key` through [`DiagCtxt::steal_diagnostic()`].
///
/// As with `buffer`, this is unless the handler has disabled such buffering.
pub fn stash(self, span: Span, key: StashKey) {
@@ -526,18 +409,18 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
/// Converts the builder to a `Diagnostic` for later emission,
/// unless handler has disabled such buffering, or `.emit()` was called.
- pub fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a Handler)> {
- let handler = match self.inner.state {
- // No `.emit()` calls, the `&Handler` is still available.
- DiagnosticBuilderState::Emittable(handler) => handler,
+ pub fn into_diagnostic(mut self) -> Option<(Diagnostic, &'a DiagCtxt)> {
+ let dcx = match self.inner.state {
+ // No `.emit()` calls, the `&DiagCtxt` is still available.
+ DiagnosticBuilderState::Emittable(dcx) => dcx,
// `.emit()` was previously called, nothing we can do.
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {
return None;
}
};
- if handler.inner.lock().flags.dont_buffer_diagnostics
- || handler.inner.lock().flags.treat_err_as_bug.is_some()
+ if dcx.inner.lock().flags.dont_buffer_diagnostics
+ || dcx.inner.lock().flags.treat_err_as_bug.is_some()
{
self.emit();
return None;
@@ -554,13 +437,13 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
// actually emitted.
debug!("buffer: diagnostic={:?}", diagnostic);
- Some((diagnostic, handler))
+ Some((diagnostic, dcx))
}
- /// Retrieves the [`Handler`] if available
- pub fn handler(&self) -> Option<&Handler> {
+ /// Retrieves the [`DiagCtxt`] if available
+ pub fn dcx(&self) -> Option<&DiagCtxt> {
match self.inner.state {
- DiagnosticBuilderState::Emittable(handler) => Some(handler),
+ DiagnosticBuilderState::Emittable(dcx) => Some(dcx),
DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => None,
}
}
@@ -634,12 +517,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
found_extra: &dyn fmt::Display,
) -> &mut Self);
- forward!(pub fn note_unsuccessful_coercion(
- &mut self,
- expected: DiagnosticStyledString,
- found: DiagnosticStyledString,
- ) -> &mut Self);
-
forward!(pub fn note(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self);
forward!(pub fn note_once(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self);
forward!(pub fn span_note(
@@ -668,7 +545,6 @@ impl<'a, G: EmissionGuarantee> DiagnosticBuilder<'a, G> {
forward!(pub fn set_is_lint(&mut self,) -> &mut Self);
forward!(pub fn disable_suggestions(&mut self,) -> &mut Self);
- forward!(pub fn clear_suggestions(&mut self,) -> &mut Self);
forward!(pub fn multipart_suggestion(
&mut self,
@@ -764,15 +640,15 @@ impl Drop for DiagnosticBuilderInner<'_> {
fn drop(&mut self) {
match self.state {
// No `.emit()` or `.cancel()` calls.
- DiagnosticBuilderState::Emittable(handler) => {
+ DiagnosticBuilderState::Emittable(dcx) => {
if !panicking() {
- handler.emit_diagnostic(&mut Diagnostic::new(
+ dcx.emit_diagnostic(Diagnostic::new(
Level::Bug,
DiagnosticMessage::from(
"the following error was constructed but not emitted",
),
));
- handler.emit_diagnostic(&mut self.diagnostic);
+ dcx.emit_diagnostic_without_consuming(&mut self.diagnostic);
panic!("error was constructed but not emitted");
}
}