From 924748717bfc90d3a34bed407d75eb6c988f9fc9 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 3 Mar 2026 17:21:16 +0100 Subject: [PATCH] Implement `Diagnostic` trait for `rustc_errors::DecorateDiagCompat` --- compiler/rustc_errors/src/decorate_diag.rs | 11 +++++------ compiler/rustc_lint/src/early.rs | 18 +++++++++++++++--- 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_errors/src/decorate_diag.rs b/compiler/rustc_errors/src/decorate_diag.rs index 5aef26ccf973..7e53b8195d5b 100644 --- a/compiler/rustc_errors/src/decorate_diag.rs +++ b/compiler/rustc_errors/src/decorate_diag.rs @@ -1,15 +1,16 @@ /// This module provides types and traits for buffering lints until later in compilation. use rustc_ast::node_id::NodeId; use rustc_data_structures::fx::FxIndexMap; +use rustc_data_structures::sync::DynSend; use rustc_error_messages::MultiSpan; use rustc_lint_defs::{BuiltinLintDiag, Lint, LintId}; -use crate::{DynSend, LintDiagnostic, LintDiagnosticBox}; +use crate::{Diag, DiagCtxtHandle, Diagnostic, Level}; /// We can't implement `LintDiagnostic` for `BuiltinLintDiag`, because decorating some of its /// variants requires types we don't have yet. So, handle that case separately. pub enum DecorateDiagCompat { - Dynamic(Box LintDiagnosticBox<'a, ()> + DynSend + 'static>), + Dynamic(Box FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSend + 'static>), Builtin(BuiltinLintDiag), } @@ -19,12 +20,10 @@ fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { } } -impl !LintDiagnostic<'_, ()> for BuiltinLintDiag {} - -impl LintDiagnostic<'a, ()> + DynSend + 'static> From for DecorateDiagCompat { +impl Diagnostic<'a, ()> + DynSend + 'static> From for DecorateDiagCompat { #[inline] fn from(d: D) -> Self { - Self::Dynamic(Box::new(d)) + Self::Dynamic(Box::new(|dcx, level| d.into_diag(dcx, level))) } } diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index a2ee7936685b..34381d2c5d48 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -7,7 +7,10 @@ use rustc_ast::visit::{self as ast_visit, Visitor, walk_list}; use rustc_ast::{self as ast, AttrVec, HasAttrs}; use rustc_data_structures::stack::ensure_sufficient_stack; -use rustc_errors::{BufferedEarlyLint, DecorateDiagCompat, LintBuffer}; +use rustc_data_structures::sync::DynSend; +use rustc_errors::{ + BufferedEarlyLint, DecorateDiagCompat, Diag, DiagCtxtHandle, Diagnostic, Level, LintBuffer, +}; use rustc_feature::Features; use rustc_middle::ty::{RegisteredTools, TyCtxt}; use rustc_session::Session; @@ -35,6 +38,16 @@ pub struct EarlyContextAndPass<'ecx, 'tcx, T: EarlyLintPass> { impl<'ecx, 'tcx, T: EarlyLintPass> EarlyContextAndPass<'ecx, 'tcx, T> { fn check_id(&mut self, id: ast::NodeId) { + struct BoxDiag( + Box FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSend + 'static>, + ); + + impl<'a> Diagnostic<'a, ()> for BoxDiag { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + (self.0)(dcx, level) + } + } + for early_lint in self.context.buffered.take(id) { let BufferedEarlyLint { span, node_id: _, lint_id, diagnostic } = early_lint; match diagnostic { @@ -50,8 +63,7 @@ fn check_id(&mut self, id: ast::NodeId) { ); } DecorateDiagCompat::Dynamic(d) => { - self.context - .opt_span_lint(lint_id.lint, span, |diag| d.decorate_lint_box(diag)); + self.context.opt_span_diag_lint(lint_id.lint, span, BoxDiag(d)); } } }