about summary refs log tree commit diff
path: root/compiler/rustc_macros/src/diagnostics/mod.rs
diff options
context:
space:
mode:
authorDavid Wood <david.wood@huawei.com>2022-06-30 08:57:45 +0100
committerDavid Wood <david.wood@huawei.com>2022-07-05 16:00:21 +0100
commit9d864c8d56fee09abae2be2bed1d4dc1a86b457b (patch)
tree2a579870a01f5273c26b34f2f3d567e3c9b6b3e5 /compiler/rustc_macros/src/diagnostics/mod.rs
parent7f9d8480d665b8dcc7b1359372e394d455b6e29a (diff)
downloadrust-9d864c8d56fee09abae2be2bed1d4dc1a86b457b.tar.gz
rust-9d864c8d56fee09abae2be2bed1d4dc1a86b457b.zip
macros: add diagnostic derive for lints
`SessionDiagnostic` isn't suitable for use on lints as whether or not it
creates an error or a warning is decided at compile-time by the macro,
whereas lints decide this at runtime based on the location of the lint
being reported (as it will depend on the user's `allow`/`deny`
attributes, etc). Re-using most of the machinery for
`SessionDiagnostic`, this macro introduces a `LintDiagnostic` derive
which implements a `DecorateLint` trait, taking a
`LintDiagnosticBuilder` and adding to the lint according to the
diagnostic struct.
Diffstat (limited to 'compiler/rustc_macros/src/diagnostics/mod.rs')
-rw-r--r--compiler/rustc_macros/src/diagnostics/mod.rs53
1 files changed, 48 insertions, 5 deletions
diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs
index d60de7150c5..39979002666 100644
--- a/compiler/rustc_macros/src/diagnostics/mod.rs
+++ b/compiler/rustc_macros/src/diagnostics/mod.rs
@@ -1,10 +1,11 @@
 mod diagnostic;
+mod diagnostic_builder;
 mod error;
 mod fluent;
 mod subdiagnostic;
 mod utils;
 
-use diagnostic::SessionDiagnosticDerive;
+use diagnostic::{LintDiagnosticDerive, SessionDiagnosticDerive};
 pub(crate) use fluent::fluent_messages;
 use proc_macro2::TokenStream;
 use quote::format_ident;
@@ -58,11 +59,53 @@ use synstructure::Structure;
 /// See rustc dev guide for more examples on using the `#[derive(SessionDiagnostic)]`:
 /// <https://rustc-dev-guide.rust-lang.org/diagnostics/diagnostic-structs.html>
 pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream {
-    // Names for the diagnostic we build and the session we build it from.
-    let diag = format_ident!("diag");
-    let sess = format_ident!("sess");
+    SessionDiagnosticDerive::new(format_ident!("diag"), format_ident!("sess"), s).into_tokens()
+}
 
-    SessionDiagnosticDerive::new(diag, sess, s).into_tokens()
+/// Implements `#[derive(LintDiagnostic)]`, which allows for lints to be specified as a struct,
+/// independent from the actual lint emitting code.
+///
+/// ```ignore (rust)
+/// #[derive(LintDiagnostic)]
+/// #[lint(lint::atomic_ordering_invalid_fail_success)]
+/// pub struct AtomicOrderingInvalidLint {
+///     method: Symbol,
+///     success_ordering: Symbol,
+///     fail_ordering: Symbol,
+///     #[label(lint::fail_label)]
+///     fail_order_arg_span: Span,
+///     #[label(lint::success_label)]
+///     #[suggestion(
+///         code = "std::sync::atomic::Ordering::{success_suggestion}",
+///         applicability = "maybe-incorrect"
+///     )]
+///     success_order_arg_span: Span,
+/// }
+/// ```
+///
+/// ```fluent
+/// lint-atomic-ordering-invalid-fail-success = `{$method}`'s success ordering must be at least as strong as its failure ordering
+///     .fail-label = `{$fail_ordering}` failure ordering
+///     .success-label = `{$success_ordering}` success ordering
+///     .suggestion = consider using `{$success_suggestion}` success ordering instead
+/// ```
+///
+/// Then, later, to emit the error:
+///
+/// ```ignore (rust)
+/// cx.struct_span_lint(INVALID_ATOMIC_ORDERING, fail_order_arg_span, AtomicOrderingInvalidLint {
+///     method,
+///     success_ordering,
+///     fail_ordering,
+///     fail_order_arg_span,
+///     success_order_arg_span,
+/// });
+/// ```
+///
+/// See rustc dev guide for more examples on using the `#[derive(LintDiagnostic)]`:
+/// <https://rustc-dev-guide.rust-lang.org/diagnostics/sessiondiagnostic.html>
+pub fn lint_diagnostic_derive(s: Structure<'_>) -> TokenStream {
+    LintDiagnosticDerive::new(format_ident!("diag"), s).into_tokens()
 }
 
 /// Implements `#[derive(SessionSubdiagnostic)]`, which allows for labels, notes, helps and