Skip to content

Commit df1f415

Browse files
authored
Rollup merge of rust-lang#98884 - davidtwco:translation-on-lints-derive, r=oli-obk
macros: `LintDiagnostic` derive - Move `LintDiagnosticBuilder` into `rustc_errors` so that a diagnostic derive can refer to it. - Introduce a `DecorateLint` trait, which is equivalent to `SessionDiagnostic` or `AddToDiagnostic` but for lints. Necessary without making more changes to the lint infrastructure as `DecorateLint` takes a `LintDiagnosticBuilder` and re-uses all of the existing logic for determining what type of diagnostic a lint should be emitted as (e.g. error/warning). - Various refactorings of the diagnostic derive machinery (extracting `build_field_mapping` helper and moving `sess` field out of the `DiagnosticDeriveBuilder`). - Introduce a `LintDiagnostic` derive macro that works almost exactly like the `SessionDiagnostic` derive macro except that it derives a `DecorateLint` implementation instead. A new derive is necessary for this because `SessionDiagnostic` is intended for when the generated code creates the diagnostic. `AddToDiagnostic` could have been used but it would have required more changes to the lint machinery. ~~At time of opening this pull request, ignore all of the commits from rust-lang#98624, it's just the last few commits that are new.~~ r? `@oli-obk`
2 parents 707c0d9 + 9d864c8 commit df1f415

File tree

25 files changed

+965
-683
lines changed

25 files changed

+965
-683
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -4009,6 +4009,7 @@ dependencies = [
40094009
"rustc_hir",
40104010
"rustc_index",
40114011
"rustc_infer",
4012+
"rustc_macros",
40124013
"rustc_middle",
40134014
"rustc_parse_format",
40144015
"rustc_session",

compiler/rustc_errors/src/diagnostic.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use crate::snippet::Style;
22
use crate::{
3-
CodeSuggestion, DiagnosticMessage, Level, MultiSpan, SubdiagnosticMessage, Substitution,
4-
SubstitutionPart, SuggestionStyle,
3+
CodeSuggestion, DiagnosticMessage, EmissionGuarantee, Level, LintDiagnosticBuilder, MultiSpan,
4+
SubdiagnosticMessage, Substitution, SubstitutionPart, SuggestionStyle,
55
};
66
use rustc_data_structures::stable_map::FxHashMap;
77
use rustc_error_messages::FluentValue;
@@ -168,6 +168,14 @@ pub trait AddSubdiagnostic {
168168
fn add_to_diagnostic(self, diag: &mut Diagnostic);
169169
}
170170

171+
/// Trait implemented by lint types. This should not be implemented manually. Instead, use
172+
/// `#[derive(LintDiagnostic)]` -- see [rustc_macros::LintDiagnostic].
173+
#[rustc_diagnostic_item = "DecorateLint"]
174+
pub trait DecorateLint<'a, G: EmissionGuarantee> {
175+
/// Decorate and emit a lint.
176+
fn decorate_lint(self, diag: LintDiagnosticBuilder<'a, G>);
177+
}
178+
171179
#[must_use]
172180
#[derive(Clone, Debug, Encodable, Decodable)]
173181
pub struct Diagnostic {

compiler/rustc_errors/src/diagnostic_builder.rs

+23
Original file line numberDiff line numberDiff line change
@@ -589,3 +589,26 @@ macro_rules! struct_span_err {
589589
macro_rules! error_code {
590590
($code:ident) => {{ $crate::DiagnosticId::Error(stringify!($code).to_owned()) }};
591591
}
592+
593+
/// Wrapper around a `DiagnosticBuilder` for creating lints.
594+
pub struct LintDiagnosticBuilder<'a, G: EmissionGuarantee>(DiagnosticBuilder<'a, G>);
595+
596+
impl<'a, G: EmissionGuarantee> LintDiagnosticBuilder<'a, G> {
597+
/// Return the inner `DiagnosticBuilder`, first setting the primary message to `msg`.
598+
pub fn build(mut self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'a, G> {
599+
self.0.set_primary_message(msg);
600+
self.0.set_is_lint();
601+
self.0
602+
}
603+
604+
/// Create a `LintDiagnosticBuilder` from some existing `DiagnosticBuilder`.
605+
pub fn new(err: DiagnosticBuilder<'a, G>) -> LintDiagnosticBuilder<'a, G> {
606+
LintDiagnosticBuilder(err)
607+
}
608+
}
609+
610+
impl<'a> LintDiagnosticBuilder<'a, ErrorGuaranteed> {
611+
pub fn forget_guarantee(self) -> LintDiagnosticBuilder<'a, ()> {
612+
LintDiagnosticBuilder(self.0.forget_guarantee())
613+
}
614+
}

compiler/rustc_errors/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -370,10 +370,10 @@ impl fmt::Display for ExplicitBug {
370370
impl error::Error for ExplicitBug {}
371371

372372
pub use diagnostic::{
373-
AddSubdiagnostic, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId,
373+
AddSubdiagnostic, DecorateLint, Diagnostic, DiagnosticArg, DiagnosticArgValue, DiagnosticId,
374374
DiagnosticStyledString, IntoDiagnosticArg, SubDiagnostic,
375375
};
376-
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee};
376+
pub use diagnostic_builder::{DiagnosticBuilder, EmissionGuarantee, LintDiagnosticBuilder};
377377
use std::backtrace::Backtrace;
378378

379379
/// A handler deals with errors and other compiler output.

compiler/rustc_lint/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,4 @@ rustc_trait_selection = { path = "../rustc_trait_selection" }
2222
rustc_parse_format = { path = "../rustc_parse_format" }
2323
rustc_infer = { path = "../rustc_infer" }
2424
rustc_type_ir = { path = "../rustc_type_ir" }
25+
rustc_macros = { path = "../rustc_macros" }

compiler/rustc_lint/src/builtin.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -32,15 +32,16 @@ use rustc_ast_pretty::pprust::{self, expr_to_string};
3232
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
3333
use rustc_data_structures::stack::ensure_sufficient_stack;
3434
use rustc_errors::{
35-
fluent, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString, MultiSpan,
35+
fluent, Applicability, Diagnostic, DiagnosticMessage, DiagnosticStyledString,
36+
LintDiagnosticBuilder, MultiSpan,
3637
};
3738
use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, GateIssue, Stability};
3839
use rustc_hir as hir;
3940
use rustc_hir::def::{DefKind, Res};
4041
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
4142
use rustc_hir::{ForeignItemKind, GenericParamKind, HirId, PatKind, PredicateOrigin};
4243
use rustc_index::vec::Idx;
43-
use rustc_middle::lint::{in_external_macro, LintDiagnosticBuilder};
44+
use rustc_middle::lint::in_external_macro;
4445
use rustc_middle::ty::layout::{LayoutError, LayoutOf};
4546
use rustc_middle::ty::print::with_no_trimmed_paths;
4647
use rustc_middle::ty::subst::GenericArgKind;

compiler/rustc_lint/src/context.rs

+21-2
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,13 @@ use rustc_ast::util::unicode::TEXT_FLOW_CONTROL_CHARS;
2222
use rustc_data_structures::fx::FxHashMap;
2323
use rustc_data_structures::sync;
2424
use rustc_errors::{add_elided_lifetime_in_path_suggestion, struct_span_err};
25-
use rustc_errors::{Applicability, MultiSpan, SuggestionStyle};
25+
use rustc_errors::{
26+
Applicability, DecorateLint, LintDiagnosticBuilder, MultiSpan, SuggestionStyle,
27+
};
2628
use rustc_hir as hir;
2729
use rustc_hir::def::Res;
2830
use rustc_hir::def_id::{CrateNum, DefId};
2931
use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
30-
use rustc_middle::lint::LintDiagnosticBuilder;
3132
use rustc_middle::middle::privacy::AccessLevels;
3233
use rustc_middle::middle::stability;
3334
use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
@@ -871,6 +872,17 @@ pub trait LintContext: Sized {
871872
decorate: impl for<'a> FnOnce(LintDiagnosticBuilder<'a, ()>),
872873
);
873874

875+
/// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
876+
/// typically generated by `#[derive(LintDiagnostic)]`).
877+
fn emit_spanned_lint<S: Into<MultiSpan>>(
878+
&self,
879+
lint: &'static Lint,
880+
span: S,
881+
decorator: impl for<'a> DecorateLint<'a, ()>,
882+
) {
883+
self.lookup(lint, Some(span), |diag| decorator.decorate_lint(diag));
884+
}
885+
874886
fn struct_span_lint<S: Into<MultiSpan>>(
875887
&self,
876888
lint: &'static Lint,
@@ -879,6 +891,13 @@ pub trait LintContext: Sized {
879891
) {
880892
self.lookup(lint, Some(span), decorate);
881893
}
894+
895+
/// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
896+
/// generated by `#[derive(LintDiagnostic)]`).
897+
fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> DecorateLint<'a, ()>) {
898+
self.lookup(lint, None as Option<Span>, |diag| decorator.decorate_lint(diag));
899+
}
900+
882901
/// Emit a lint at the appropriate level, with no associated span.
883902
fn lint(
884903
&self,

compiler/rustc_lint/src/internal.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ impl LateLintPass<'_> for Diagnostics {
414414
let Impl { of_trait: Some(of_trait), .. } = impl_ &&
415415
let Some(def_id) = of_trait.trait_def_id() &&
416416
let Some(name) = cx.tcx.get_diagnostic_name(def_id) &&
417-
matches!(name, sym::SessionDiagnostic | sym::AddSubdiagnostic)
417+
matches!(name, sym::SessionDiagnostic | sym::AddSubdiagnostic | sym::DecorateLint)
418418
{
419419
found_impl = true;
420420
break;

compiler/rustc_lint/src/levels.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ use crate::late::unerased_lint_store;
33
use rustc_ast as ast;
44
use rustc_ast_pretty::pprust;
55
use rustc_data_structures::fx::FxHashMap;
6-
use rustc_errors::{struct_span_err, Applicability, Diagnostic, MultiSpan};
6+
use rustc_errors::{struct_span_err, Applicability, Diagnostic, LintDiagnosticBuilder, MultiSpan};
77
use rustc_hir as hir;
88
use rustc_hir::{intravisit, HirId};
99
use rustc_middle::hir::nested_filter;
1010
use rustc_middle::lint::{
11-
struct_lint_level, LevelAndSource, LintDiagnosticBuilder, LintExpectation, LintLevelMap,
12-
LintLevelSets, LintLevelSource, LintSet, LintStackIndex, COMMAND_LINE,
11+
struct_lint_level, LevelAndSource, LintExpectation, LintLevelMap, LintLevelSets,
12+
LintLevelSource, LintSet, LintStackIndex, COMMAND_LINE,
1313
};
1414
use rustc_middle::ty::query::Providers;
1515
use rustc_middle::ty::{RegisteredTools, TyCtxt};

compiler/rustc_lint/src/types.rs

+15-7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use rustc_data_structures::fx::FxHashSet;
55
use rustc_errors::{fluent, Applicability, DiagnosticMessage};
66
use rustc_hir as hir;
77
use rustc_hir::{is_range_literal, Expr, ExprKind, Node};
8+
use rustc_macros::LintDiagnostic;
89
use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
910
use rustc_middle::ty::subst::SubstsRef;
1011
use rustc_middle::ty::{self, AdtKind, DefIdTree, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable};
@@ -1553,13 +1554,20 @@ impl InvalidAtomicOrdering {
15531554
let Some(fail_ordering) = Self::match_ordering(cx, fail_order_arg) else { return };
15541555

15551556
if matches!(fail_ordering, sym::Release | sym::AcqRel) {
1556-
cx.struct_span_lint(INVALID_ATOMIC_ORDERING, fail_order_arg.span, |diag| {
1557-
diag.build(fluent::lint::atomic_ordering_invalid)
1558-
.set_arg("method", method)
1559-
.span_label(fail_order_arg.span, fluent::lint::label)
1560-
.help(fluent::lint::help)
1561-
.emit();
1562-
});
1557+
#[derive(LintDiagnostic)]
1558+
#[lint(lint::atomic_ordering_invalid)]
1559+
#[help]
1560+
struct InvalidAtomicOrderingDiag {
1561+
method: Symbol,
1562+
#[label]
1563+
fail_order_arg_span: Span,
1564+
}
1565+
1566+
cx.emit_spanned_lint(
1567+
INVALID_ATOMIC_ORDERING,
1568+
fail_order_arg.span,
1569+
InvalidAtomicOrderingDiag { method, fail_order_arg_span: fail_order_arg.span },
1570+
);
15631571
}
15641572

15651573
let Some(success_ordering) = Self::match_ordering(cx, success_order_arg) else { return };

0 commit comments

Comments
 (0)