Skip to content

Commit

Permalink
lint: add diagnostic translation migration lints
Browse files Browse the repository at this point in the history
Introduce allow-by-default lints for checking whether diagnostics are
written in `SessionDiagnostic`/`AddSubdiagnostic` impls and whether
diagnostics are translatable. These lints can be denied for modules once
they are fully migrated to impls and translation.

Signed-off-by: David Wood <[email protected]>
  • Loading branch information
davidtwco committed Jun 10, 2022
1 parent 52ee2a2 commit 5ba81fa
Show file tree
Hide file tree
Showing 15 changed files with 327 additions and 37 deletions.
3 changes: 3 additions & 0 deletions compiler/rustc_error_messages/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#![feature(let_chains)]
#![feature(once_cell)]
#![feature(path_try_exists)]
#![feature(rustc_attrs)]
#![feature(type_alias_impl_trait)]

use fluent_bundle::FluentResource;
Expand Down Expand Up @@ -241,6 +242,7 @@ type FluentId = Cow<'static, str>;
/// message so messages of this type must be combined with a `DiagnosticMessage` (using
/// `DiagnosticMessage::with_subdiagnostic_message`) before rendering. However, subdiagnostics from
/// the `SessionSubdiagnostic` derive refer to Fluent identifiers directly.
#[rustc_diagnostic_item = "SubdiagnosticMessage"]
pub enum SubdiagnosticMessage {
/// Non-translatable diagnostic message.
// FIXME(davidtwco): can a `Cow<'static, str>` be used here?
Expand Down Expand Up @@ -281,6 +283,7 @@ impl<S: Into<String>> From<S> for SubdiagnosticMessage {
///
/// Intended to be removed once diagnostics are entirely translatable.
#[derive(Clone, Debug, PartialEq, Eq, Hash, Encodable, Decodable)]
#[rustc_diagnostic_item = "DiagnosticMessage"]
pub enum DiagnosticMessage {
/// Non-translatable diagnostic message.
// FIXME(davidtwco): can a `Cow<'static, str>` be used here?
Expand Down
8 changes: 8 additions & 0 deletions compiler/rustc_errors/src/diagnostic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ impl<'source> Into<FluentValue<'source>> for DiagnosticArgValue<'source> {

/// Trait implemented by error types. This should not be implemented manually. Instead, use
/// `#[derive(SessionSubdiagnostic)]` -- see [rustc_macros::SessionSubdiagnostic].
#[rustc_diagnostic_item = "AddSubdiagnostic"]
pub trait AddSubdiagnostic {
/// Add a subdiagnostic to an existing diagnostic.
fn add_to_diagnostic(self, diag: &mut Diagnostic);
Expand Down Expand Up @@ -283,6 +284,7 @@ impl Diagnostic {
///
/// This span is *not* considered a ["primary span"][`MultiSpan`]; only
/// the `Span` supplied when creating the diagnostic is primary.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_label(&mut self, span: Span, label: impl Into<SubdiagnosticMessage>) -> &mut Self {
self.span.push_span_label(span, self.subdiagnostic_message_to_diagnostic_message(label));
self
Expand Down Expand Up @@ -401,6 +403,7 @@ impl Diagnostic {
}

/// Add a note attached to this diagnostic.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn note(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self {
self.sub(Level::Note, msg, MultiSpan::new(), None);
self
Expand All @@ -423,6 +426,7 @@ impl Diagnostic {

/// Prints the span with a note above it.
/// This is like [`Diagnostic::note()`], but it gets its own span.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_note<S: Into<MultiSpan>>(
&mut self,
sp: S,
Expand All @@ -444,13 +448,15 @@ impl Diagnostic {
}

/// Add a warning attached to this diagnostic.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn warn(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self {
self.sub(Level::Warning, msg, MultiSpan::new(), None);
self
}

/// Prints the span with a warning above it.
/// This is like [`Diagnostic::warn()`], but it gets its own span.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_warn<S: Into<MultiSpan>>(
&mut self,
sp: S,
Expand All @@ -461,6 +467,7 @@ impl Diagnostic {
}

/// Add a help message attached to this diagnostic.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn help(&mut self, msg: impl Into<SubdiagnosticMessage>) -> &mut Self {
self.sub(Level::Help, msg, MultiSpan::new(), None);
self
Expand All @@ -474,6 +481,7 @@ impl Diagnostic {

/// Prints the span with some help above it.
/// This is like [`Diagnostic::help()`], but it gets its own span.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_help<S: Into<MultiSpan>>(
&mut self,
sp: S,
Expand Down
23 changes: 23 additions & 0 deletions compiler/rustc_errors/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#![feature(let_else)]
#![feature(never_type)]
#![feature(adt_const_params)]
#![feature(rustc_attrs)]
#![allow(incomplete_features)]
#![allow(rustc::potential_query_instability)]

Expand Down Expand Up @@ -644,6 +645,7 @@ impl Handler {
/// Attempting to `.emit()` the builder will only emit if either:
/// * `can_emit_warnings` is `true`
/// * `is_force_warn` was set in `DiagnosticId::Lint`
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_warn(
&self,
span: impl Into<MultiSpan>,
Expand All @@ -655,6 +657,7 @@ impl Handler {
}

/// Construct a builder at the `Allow` level at the given `span` and with the `msg`.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_allow(
&self,
span: impl Into<MultiSpan>,
Expand All @@ -667,6 +670,7 @@ impl Handler {

/// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
/// Also include a code.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_warn_with_code(
&self,
span: impl Into<MultiSpan>,
Expand All @@ -683,16 +687,19 @@ impl Handler {
/// Attempting to `.emit()` the builder will only emit if either:
/// * `can_emit_warnings` is `true`
/// * `is_force_warn` was set in `DiagnosticId::Lint`
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
DiagnosticBuilder::new(self, Level::Warning, msg)
}

/// Construct a builder at the `Allow` level with the `msg`.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_allow(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
DiagnosticBuilder::new(self, Level::Allow, msg)
}

/// Construct a builder at the `Expect` level with the `msg`.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_expect(
&self,
msg: impl Into<DiagnosticMessage>,
Expand All @@ -702,6 +709,7 @@ impl Handler {
}

/// Construct a builder at the `Error` level at the given `span` and with the `msg`.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_err(
&self,
span: impl Into<MultiSpan>,
Expand All @@ -713,6 +721,7 @@ impl Handler {
}

/// Construct a builder at the `Error` level at the given `span`, with the `msg`, and `code`.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_err_with_code(
&self,
span: impl Into<MultiSpan>,
Expand All @@ -726,6 +735,7 @@ impl Handler {

/// Construct a builder at the `Error` level with the `msg`.
// FIXME: This method should be removed (every error should have an associated error code).
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_err(
&self,
msg: impl Into<DiagnosticMessage>,
Expand All @@ -740,6 +750,7 @@ impl Handler {
}

/// Construct a builder at the `Error` level with the `msg` and the `code`.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_err_with_code(
&self,
msg: impl Into<DiagnosticMessage>,
Expand All @@ -751,6 +762,7 @@ impl Handler {
}

/// Construct a builder at the `Warn` level with the `msg` and the `code`.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_warn_with_code(
&self,
msg: impl Into<DiagnosticMessage>,
Expand All @@ -762,6 +774,7 @@ impl Handler {
}

/// Construct a builder at the `Fatal` level at the given `span` and with the `msg`.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_fatal(
&self,
span: impl Into<MultiSpan>,
Expand All @@ -773,6 +786,7 @@ impl Handler {
}

/// Construct a builder at the `Fatal` level at the given `span`, with the `msg`, and `code`.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_span_fatal_with_code(
&self,
span: impl Into<MultiSpan>,
Expand All @@ -785,28 +799,33 @@ impl Handler {
}

/// Construct a builder at the `Error` level with the `msg`.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> {
DiagnosticBuilder::new_fatal(self, msg)
}

/// Construct a builder at the `Help` level with the `msg`.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_help(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
DiagnosticBuilder::new(self, Level::Help, msg)
}

/// Construct a builder at the `Note` level with the `msg`.
#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn struct_note_without_error(
&self,
msg: impl Into<DiagnosticMessage>,
) -> DiagnosticBuilder<'_, ()> {
DiagnosticBuilder::new(self, Level::Note, msg)
}

#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_fatal(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) -> ! {
self.emit_diag_at_span(Diagnostic::new(Fatal, msg), span);
FatalError.raise()
}

#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_fatal_with_code(
&self,
span: impl Into<MultiSpan>,
Expand All @@ -817,6 +836,7 @@ impl Handler {
FatalError.raise()
}

#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_err(
&self,
span: impl Into<MultiSpan>,
Expand All @@ -825,6 +845,7 @@ impl Handler {
self.emit_diag_at_span(Diagnostic::new(Error { lint: false }, msg), span).unwrap()
}

#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_err_with_code(
&self,
span: impl Into<MultiSpan>,
Expand All @@ -837,10 +858,12 @@ impl Handler {
);
}

#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_warn(&self, span: impl Into<MultiSpan>, msg: impl Into<DiagnosticMessage>) {
self.emit_diag_at_span(Diagnostic::new(Warning, msg), span);
}

#[cfg_attr(not(bootstrap), rustc_lint_diagnostics)]
pub fn span_warn_with_code(
&self,
span: impl Into<MultiSpan>,
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_feature/src/builtin_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -615,6 +615,9 @@ pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
// Used by the `rustc::potential_query_instability` lint to warn methods which
// might not be stable during incremental compilation.
rustc_attr!(rustc_lint_query_instability, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),
// Used by the `rustc::untranslatable_diagnostic` and `rustc::diagnostic_outside_of_impl` lints
// to assist in changes to diagnostic APIs.
rustc_attr!(rustc_lint_diagnostics, Normal, template!(Word), WarnFollowing, INTERNAL_UNSTABLE),

// ==========================================================================
// Internal attributes, Const related:
Expand Down
Loading

0 comments on commit 5ba81fa

Please sign in to comment.