/// 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_error_messages::MultiSpan; use rustc_lint_defs::{BuiltinLintDiag, Lint, LintId}; use crate::{DynSend, LintDiagnostic, LintDiagnosticBox}; /// 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>), Builtin(BuiltinLintDiag), } impl std::fmt::Debug for DecorateDiagCompat { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("DecorateDiagCompat").finish() } } impl !LintDiagnostic<'_, ()> for BuiltinLintDiag {} impl LintDiagnostic<'a, ()> + DynSend + 'static> From for DecorateDiagCompat { #[inline] fn from(d: D) -> Self { Self::Dynamic(Box::new(d)) } } impl From for DecorateDiagCompat { #[inline] fn from(b: BuiltinLintDiag) -> Self { Self::Builtin(b) } } /// Lints that are buffered up early on in the `Session` before the /// `LintLevels` is calculated. #[derive(Debug)] pub struct BufferedEarlyLint { /// The span of code that we are linting on. pub span: Option, /// The `NodeId` of the AST node that generated the lint. pub node_id: NodeId, /// A lint Id that can be passed to /// `rustc_lint::early::EarlyContextAndPass::check_id`. pub lint_id: LintId, /// Customization of the `Diag<'_>` for the lint. pub diagnostic: DecorateDiagCompat, } #[derive(Default, Debug)] pub struct LintBuffer { pub map: FxIndexMap>, } impl LintBuffer { pub fn add_early_lint(&mut self, early_lint: BufferedEarlyLint) { self.map.entry(early_lint.node_id).or_default().push(early_lint); } pub fn take(&mut self, id: NodeId) -> Vec { // FIXME(#120456) - is `swap_remove` correct? self.map.swap_remove(&id).unwrap_or_default() } pub fn buffer_lint( &mut self, lint: &'static Lint, node_id: NodeId, span: impl Into, decorate: impl Into, ) { self.add_early_lint(BufferedEarlyLint { lint_id: LintId::of(lint), node_id, span: Some(span.into()), diagnostic: decorate.into(), }); } }