use std::borrow::Cow;
use std::fmt;
use std::hash::{Hash, Hasher};
+use std::panic::Location;
/// Error type for `Diagnostic`'s `suggestions` field, indicating that
/// `.disable_suggestions()` was called on the `Diagnostic`.
/// Trait implemented by error types. This should not be implemented manually. Instead, use
/// `#[derive(Subdiagnostic)]` -- see [rustc_macros::Subdiagnostic].
-#[cfg_attr(bootstrap, rustc_diagnostic_item = "AddSubdiagnostic")]
-#[cfg_attr(not(bootstrap), rustc_diagnostic_item = "AddToDiagnostic")]
+#[rustc_diagnostic_item = "AddToDiagnostic"]
pub trait AddToDiagnostic
where
Self: Sized,
/// If diagnostic is from Lint, custom hash function ignores notes
/// otherwise hash is based on the all the fields
pub is_lint: bool,
+
+ /// With `-Ztrack_diagnostics` enabled,
+ /// we print where in rustc this error was emitted.
+ pub emitted_at: DiagnosticLocation,
+}
+
+#[derive(Clone, Debug, Encodable, Decodable)]
+pub struct DiagnosticLocation {
+ file: Cow<'static, str>,
+ line: u32,
+ col: u32,
+}
+
+impl DiagnosticLocation {
+ #[track_caller]
+ fn caller() -> Self {
+ let loc = Location::caller();
+ DiagnosticLocation { file: loc.file().into(), line: loc.line(), col: loc.column() }
+ }
+}
+
+impl fmt::Display for DiagnosticLocation {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ write!(f, "{}:{}:{}", self.file, self.line, self.col)
+ }
}
#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
}
impl Diagnostic {
+ #[track_caller]
pub fn new<M: Into<DiagnosticMessage>>(level: Level, message: M) -> Self {
Diagnostic::new_with_code(level, None, message)
}
+ #[track_caller]
pub fn new_with_code<M: Into<DiagnosticMessage>>(
level: Level,
code: Option<DiagnosticId>,
args: Default::default(),
sort_span: DUMMY_SP,
is_lint: false,
+ emitted_at: DiagnosticLocation::caller(),
}
}