Decouple `CheckLintNameResult` from `rustc_lint`
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index 752c222..32c1d5d 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -25,7 +25,9 @@
 use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
 use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths};
 use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingEnv, TypingMode};
-use rustc_session::lint::{FutureIncompatibleInfo, Lint, LintExpectationId, LintId};
+use rustc_session::lint::{
+    CheckLintNameResult, FutureIncompatibleInfo, Lint, LintExpectationId, LintId, TargetLint,
+};
 use rustc_session::{DynLintStore, Session};
 use rustc_span::edit_distance::find_best_match_for_names;
 use rustc_span::{Ident, Span, Symbol, sym};
@@ -69,26 +71,19 @@ fn lint_groups_iter(&self) -> Box<dyn Iterator<Item = rustc_session::LintGroup>
             rustc_session::LintGroup { name, lints, is_externally_loaded }
         }))
     }
-}
 
-/// The target of the `by_name` map, which accounts for renaming/deprecation.
-#[derive(Debug)]
-enum TargetLint {
-    /// A direct lint target
-    Id(LintId),
+    fn check_lint_name(
+        &self,
+        lint_name: &str,
+        tool_name: Option<Symbol>,
+        registered_tools: &RegisteredTools,
+    ) -> CheckLintNameResult<'_> {
+        self.check_lint_name(lint_name, tool_name, registered_tools)
+    }
 
-    /// Temporary renaming, used for easing migration pain; see #16545
-    Renamed(String, LintId),
-
-    /// Lint with this name existed previously, but has been removed/deprecated.
-    /// The string argument is the reason for removal.
-    Removed(String),
-
-    /// A lint name that should give no warnings and have no effect.
-    ///
-    /// This is used by rustc to avoid warning about old rustdoc lints before rustdoc registers
-    /// them as tool lints.
-    Ignored,
+    fn find_lints(&self, lint_name: &str) -> Option<&[LintId]> {
+        self.find_lints(lint_name)
+    }
 }
 
 struct LintAlias {
@@ -103,29 +98,6 @@ struct LintGroup {
     depr: Option<LintAlias>,
 }
 
-#[derive(Debug)]
-pub enum CheckLintNameResult<'a> {
-    Ok(&'a [LintId]),
-    /// Lint doesn't exist. Potentially contains a suggestion for a correct lint name.
-    NoLint(Option<(Symbol, bool)>),
-    /// The lint refers to a tool that has not been registered.
-    NoTool,
-    /// The lint has been renamed to a new name.
-    Renamed(String),
-    /// The lint has been removed due to the given reason.
-    Removed(String),
-
-    /// The lint is from a tool. The `LintId` will be returned as if it were a
-    /// rustc lint. The `Option<String>` indicates if the lint has been
-    /// renamed.
-    Tool(&'a [LintId], Option<String>),
-
-    /// The lint is from a tool. Either the lint does not exist in the tool or
-    /// the code was not compiled with the tool and therefore the lint was
-    /// never added to the `LintStore`.
-    MissingTool,
-}
-
 impl LintStore {
     pub fn new() -> LintStore {
         LintStore {
@@ -304,6 +276,10 @@ pub fn register_removed(&mut self, name: &str, reason: &str) {
         self.by_name.insert(name.into(), Removed(reason.into()));
     }
 
+    pub fn get_lint_by_name(&self, lint_name: &str) -> Option<&TargetLint> {
+        self.by_name.get(lint_name)
+    }
+
     pub fn find_lints(&self, lint_name: &str) -> Option<&[LintId]> {
         match self.by_name.get(lint_name) {
             Some(Id(lint_id)) => Some(slice::from_ref(lint_id)),
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 2b859b6..64303de 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -22,12 +22,14 @@
     self, FORBIDDEN_LINT_GROUPS, RENAMED_AND_REMOVED_LINTS, SINGLE_USE_LIFETIMES,
     UNFULFILLED_LINT_EXPECTATIONS, UNKNOWN_LINTS, UNUSED_ATTRIBUTES,
 };
-use rustc_session::lint::{Level, Lint, LintExpectationId, LintId};
+use rustc_session::lint::{
+    CheckLintNameResult, Level, Lint, LintExpectationId, LintId, TargetLint,
+};
 use rustc_span::{DUMMY_SP, Span, Symbol, sym};
 use tracing::{debug, instrument};
 
 use crate::builtin::MISSING_DOCS;
-use crate::context::{CheckLintNameResult, LintStore};
+use crate::context::LintStore;
 use crate::errors::{
     CheckNameUnknownTool, MalformedAttribute, MalformedAttributeSub, OverruledAttribute,
     OverruledAttributeSub, RequestedLevel, UnknownToolInScopedLint, UnsupportedGroup,
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 2f773b9..e4106cb 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -128,7 +128,7 @@
 
 #[rustfmt::skip]
 pub use builtin::{MissingDoc, SoftLints};
-pub use context::{CheckLintNameResult, EarlyContext, LateContext, LintContext, LintStore};
+pub use context::{EarlyContext, LateContext, LintContext, LintStore};
 pub use early::diagnostics::{DecorateAttrLint, DecorateBuiltinLint};
 pub use early::{EarlyCheckNode, check_ast_node};
 pub use late::{check_crate, late_lint_mod, unerased_lint_store};
@@ -136,7 +136,9 @@
 pub use passes::{EarlyLintPass, LateLintPass};
 pub use rustc_errors::BufferedEarlyLint;
 pub use rustc_session::lint::Level::{self, *};
-pub use rustc_session::lint::{FutureIncompatibleInfo, Lint, LintId, LintPass, LintVec};
+pub use rustc_session::lint::{
+    CheckLintNameResult, FutureIncompatibleInfo, Lint, LintId, LintPass, LintVec,
+};
 
 pub fn provide(providers: &mut Providers) {
     levels::provide(providers);
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 1c86d55..f16e9a9 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -583,6 +583,26 @@ pub fn default_level(&self, edition: Edition) -> Level {
     }
 }
 
+/// The target of the `by_name` map, which accounts for renaming/deprecation.
+#[derive(Debug)]
+pub enum TargetLint {
+    /// A direct lint target
+    Id(LintId),
+
+    /// Temporary renaming, used for easing migration pain; see #16545
+    Renamed(String, LintId),
+
+    /// Lint with this name existed previously, but has been removed/deprecated.
+    /// The string argument is the reason for removal.
+    Removed(String),
+
+    /// A lint name that should give no warnings and have no effect.
+    ///
+    /// This is used by rustc to avoid warning about old rustdoc lints before rustdoc registers
+    /// them as tool lints.
+    Ignored,
+}
+
 /// Identifies a lint known to the compiler.
 #[derive(Clone, Copy, Debug)]
 pub struct LintId {
@@ -810,6 +830,31 @@ pub enum FormatWarning {
     InvalidSpecifier { name: String, span: Span },
 }
 
+#[derive(Debug)]
+pub enum CheckLintNameResult<'a> {
+    Ok(&'a [LintId]),
+    /// Lint doesn't exist. Potentially contains a suggestion for a correct lint name.
+    NoLint(Option<(Symbol, bool)>),
+    /// The lint refers to a tool that has not been registered.
+    NoTool,
+    /// The lint has been renamed to a new name.
+    Renamed(Symbol),
+    /// Lint that previously was part of rustc, but now is part of external lint tool
+    RenamedToolLint(Symbol),
+    /// The lint has been removed due to the given reason.
+    Removed(String),
+
+    /// The lint is from a tool. The `LintId` will be returned as if it were a
+    /// rustc lint. The `Option<String>` indicates if the lint has been
+    /// renamed.
+    Tool(&'a [LintId], Option<String>),
+
+    /// The lint is from a tool. Either the lint does not exist in the tool or
+    /// the code was not compiled with the tool and therefore the lint was
+    /// never added to the `LintStore`.
+    MissingTool,
+}
+
 pub type RegisteredTools = FxIndexSet<Ident>;
 
 /// Declares a static item of type `&'static Lint`.
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index a9e7f15..786cf0a3 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -40,7 +40,7 @@
     Input, InstrumentCoverage, OptLevel, OutFileName, OutputType, SwitchWithOptPath,
 };
 use crate::filesearch::FileSearch;
-use crate::lint::LintId;
+use crate::lint::{CheckLintNameResult, LintId, RegisteredTools};
 use crate::parse::{ParseSess, add_feature_diagnostics};
 use crate::search_paths::SearchPath;
 use crate::{errors, filesearch, lint};
@@ -81,6 +81,15 @@ pub struct CompilerIO {
 pub trait DynLintStore: Any + DynSync + DynSend {
     /// Provides a way to access lint groups without depending on `rustc_lint`
     fn lint_groups_iter(&self) -> Box<dyn Iterator<Item = LintGroup> + '_>;
+
+    fn check_lint_name(
+        &self,
+        lint_name: &str,
+        tool_name: Option<Symbol>,
+        registered_tools: &RegisteredTools,
+    ) -> CheckLintNameResult<'_>;
+
+    fn find_lints(&self, lint_name: &str) -> Option<&[LintId]>;
 }
 
 /// Represents the data associated with a compilation