about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_interface/src/passes.rs2
-rw-r--r--compiler/rustc_lint/src/builtin.rs7
-rw-r--r--compiler/rustc_lint/src/late.rs64
-rw-r--r--compiler/rustc_lint/src/levels.rs202
-rw-r--r--compiler/rustc_lint/src/lib.rs2
-rw-r--r--compiler/rustc_lint/src/passes.rs13
-rw-r--r--compiler/rustc_lint/src/unused.rs2
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs5
-rw-r--r--compiler/rustc_middle/src/query/mod.rs3
-rw-r--r--compiler/rustc_session/src/session.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/asm_syntax.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/cognitive_complexity.rs54
-rw-r--r--src/tools/clippy/clippy_lints/src/ctfe.rs54
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs3
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/author.rs (renamed from src/tools/clippy/clippy_lints/src/utils/internal_lints/author.rs)12
-rw-r--r--src/tools/clippy/clippy_lints/src/utils/mod.rs1
16 files changed, 276 insertions, 151 deletions
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index fd850d2f39a..608d66184f0 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -972,7 +972,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
                         tcx.ensure().check_mod_privacy(module);
                     });
                 });
-            }
+            } // { sess.time("mir_checking", || { tcx.hir().mir_for }) }
         );
 
         // This check has to be run after all lints are done processing. We don't
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index acd12f7f20d..33c87bbfb70 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -20,6 +20,7 @@
 //! If you define a new `LateLintPass`, you will also need to add it to the
 //! `late_lint_methods!` invocation in `lib.rs`.
 
+use std::default::Default;
 use std::fmt::Write;
 
 use ast::token::TokenKind;
@@ -73,12 +74,10 @@ use crate::{
     EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext,
     fluent_generated as fluent,
 };
-
-use std::default::Default;
-use std::fmt::Write;
+// use std::fmt::Write;
 
 // hardwired lints from rustc_lint_defs
-pub use rustc_session::lint::builtin::*;
+// pub use rustc_session::lint::builtin::*;
 
 declare_lint! {
     /// The `while_true` lint detects `while true { }`.
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index c7187ee1b30..f8bd873cdf5 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -24,13 +24,12 @@ use rustc_hir::def_id::{LocalDefId, LocalModDefId};
 use rustc_hir::{HirId, intravisit as hir_visit};
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_session::Session;
-use rustc_session::lint::LintPass;
+use rustc_session::{Session, lint::{LintPass, builtin::HardwiredLints}};
 use rustc_span::Span;
 use tracing::debug;
 
 use crate::passes::LateLintPassObject;
-use crate::{LateContext, LateLintPass, LintStore};
+use crate::{LateContext, LateLintPass, LintId, LintStore};
 
 /// Extract the [`LintStore`] from [`Session`].
 ///
@@ -371,29 +370,24 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
     } else {
         let passes: Vec<_> =
             store.late_module_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect();
-
         // Filter unused lints
-        let (lints_that_actually_run, lints_allowed) = &**tcx.lints_that_can_emit(());
-        // let lints_that_actually_run = &lints_that_can_emit.0;
-        // let lints_allowed = &lints_that_can_emit.1;
-
-        // Now, we'll filtered passes in a way that discards any lint that won't trigger.
-        // If any lint is a given pass is detected to be emitted, we will keep that pass.
-        // Otherwise, we don't
+        let lints_that_dont_need_to_run = tcx.lints_that_dont_need_to_run(());
         let mut filtered_passes: Vec<Box<dyn LateLintPass<'tcx>>> = passes
             .into_iter()
             .filter(|pass| {
-                let pass = LintPass::get_lints(pass);
-                pass.iter().any(|&lint| {
-                    let lint_name = name_without_tool(&lint.name.to_lowercase()).to_string();
-                    lints_that_actually_run.contains(&lint_name)
-                        || (!lints_allowed.contains(&lint_name)
-                            && lint.default_level != crate::Level::Allow)
-                })
+                let lints = LintPass::get_lints(pass);
+                if lints.is_empty() {
+                    true
+                } else {
+                    lints
+                        .iter()
+                        .any(|lint| !lints_that_dont_need_to_run.contains(&LintId::of(lint)))
+                }
             })
             .collect();
 
         filtered_passes.push(Box::new(builtin_lints));
+        filtered_passes.push(Box::new(HardwiredLints));
 
         let pass = RuntimeCombinedLateLintPass { passes: &mut filtered_passes[..] };
         late_lint_mod_inner(tcx, module_def_id, context, pass);
@@ -426,7 +420,7 @@ fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>(
 
 fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) {
     // Note: `passes` is often empty.
-    let mut passes: Vec<_> =
+    let passes: Vec<_> =
         unerased_lint_store(tcx.sess).late_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect();
 
     if passes.is_empty() {
@@ -444,7 +438,30 @@ fn late_lint_crate<'tcx>(tcx: TyCtxt<'tcx>) {
         only_module: false,
     };
 
-    let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] };
+    let lints_that_dont_need_to_run = tcx.lints_that_dont_need_to_run(());
+
+    // dbg!(&lints_that_dont_need_to_run);
+    let mut filtered_passes: Vec<Box<dyn LateLintPass<'tcx>>> = passes
+        .into_iter()
+        .filter(|pass| {
+            let lints = LintPass::get_lints(pass);
+            !lints.iter().all(|lint| lints_that_dont_need_to_run.contains(&LintId::of(lint)))
+        })
+        .collect();
+
+    filtered_passes.push(Box::new(HardwiredLints));
+
+    // let mut filtered_passes: Vec<Box<dyn LateLintPass<'tcx>>> = passes
+    // .into_iter()
+    // .filter(|pass| {
+    //     let lints = LintPass::get_lints(pass);
+    //     lints.iter()
+    //         .any(|lint|
+    //             !lints_that_dont_need_to_run.contains(&LintId::of(lint)))
+    // }).collect();
+    //
+
+    let pass = RuntimeCombinedLateLintPass { passes: &mut filtered_passes[..] };
     late_lint_crate_inner(tcx, context, pass);
 }
 
@@ -482,10 +499,3 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) {
         },
     );
 }
-
-/// Format name ignoring the name, useful for filtering non-used lints.
-/// For example, 'clippy::my_lint' will turn into 'my_lint'
-pub(crate) fn name_without_tool(name: &str) -> &str {
-    // Doing some calculations here to account for those separators
-    name.rsplit("::").next().unwrap_or(name)
-}
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 527fc117351..f5323c295d0 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -1,5 +1,5 @@
 use rustc_ast_pretty::pprust;
-use rustc_data_structures::{fx::FxIndexMap, fx::FxIndexSet, sync::Lrc};
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_errors::{Diag, LintDiagnostic, MultiSpan};
 use rustc_feature::{Features, GateIssue};
 use rustc_hir::HirId;
@@ -31,7 +31,7 @@ use crate::errors::{
     OverruledAttributeSub, RequestedLevel, UnknownToolInScopedLint, UnsupportedGroup,
 };
 use crate::fluent_generated as fluent;
-use crate::late::{unerased_lint_store, name_without_tool};
+use crate::late::{unerased_lint_store /*name_without_tool*/};
 use crate::lints::{
     DeprecatedLintName, DeprecatedLintNameFromCommandLine, IgnoredUnlessCrateSpecified,
     OverruledAttributeLint, RemovedLint, RemovedLintFromCommandLine, RenamedLint,
@@ -115,34 +115,41 @@ impl LintLevelSets {
     }
 }
 
-/// Walk the whole crate collecting nodes where lint levels change
-/// (e.g. `#[allow]` attributes), and joins that list with the warn-by-default
-/// (and not allowed in the crate) and CLI lints. The returned value is a tuple
-/// of 1. The lints that will emit (or at least, should run), and 2.
-/// The lints that are allowed at the crate level and will not emit.
-pub fn lints_that_can_emit(tcx: TyCtxt<'_>, (): ()) -> Lrc<(FxIndexSet<String>, FxIndexSet<String>)> {
-    let mut visitor = LintLevelMinimum::new(tcx);
-    visitor.process_opts();
-    tcx.hir().walk_attributes(&mut visitor);
-
+fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LintId> {
     let store = unerased_lint_store(&tcx.sess);
 
-    let lint_groups = store.get_lint_groups();
-    for group in lint_groups {
-        let binding = group.0.to_lowercase();
-        let group_name = name_without_tool(&binding).to_string();
-        if visitor.lints_that_actually_run.contains(&group_name) {
-            for lint in group.1 {
-                visitor.lints_that_actually_run.insert(name_without_tool(&lint.to_string()).to_string());
-            }
-        } else if visitor.lints_allowed.contains(&group_name) {
-            for lint in &group.1 {
-                visitor.lints_allowed.insert(name_without_tool(&lint.to_string()).to_string());
+    let dont_need_to_run: FxIndexSet<LintId> = store
+        .get_lints()
+        .into_iter()
+        .filter_map(|lint| {
+            if !lint.loadbearing && lint.default_level(tcx.sess.edition()) == Level::Allow {
+                Some(LintId::of(lint))
+            } else {
+                None
             }
-        }
-    }
+        })
+        .collect();
 
-    Lrc::new((visitor.lints_that_actually_run, visitor.lints_allowed))
+    let mut visitor = LintLevelMaximum { tcx, dont_need_to_run };
+    visitor.process_opts();
+    tcx.hir().walk_attributes(&mut visitor);
+
+    // let lint_groups = store.get_lint_groups();
+    // for group in lint_groups {
+    //     let binding = group.0.to_lowercase();
+    //     let group_name = name_without_tool(&binding).to_string();
+    //     if visitor.lints_that_actually_run.contains(&group_name) {
+    //         for lint in group.1 {
+    //             visitor.lints_that_actually_run.insert(name_without_tool(&lint.to_string()).to_string());
+    //         }
+    //     } else if visitor.lints_allowed.contains(&group_name) {
+    //         for lint in &group.1 {
+    //             visitor.lints_allowed.insert(name_without_tool(&lint.to_string()).to_string());
+    //         }
+    //     }
+    // }
+
+    visitor.dont_need_to_run
 }
 
 #[instrument(level = "trace", skip(tcx), ret)]
@@ -336,39 +343,29 @@ impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, LintLevelQueryMap<'tcx>> {
 ///
 /// E.g., if a crate has a global #![allow(lint)] attribute, but a single item
 /// uses #[warn(lint)], this visitor will set that lint level as `Warn`
-struct LintLevelMinimum<'tcx> {
+struct LintLevelMaximum<'tcx> {
     tcx: TyCtxt<'tcx>,
     /// The actual list of detected lints.
-    lints_that_actually_run: FxIndexSet<String>,
-    lints_allowed: FxIndexSet<String>,
+    dont_need_to_run: FxIndexSet<LintId>,
 }
 
-impl<'tcx> LintLevelMinimum<'tcx> {
-    pub fn new(tcx: TyCtxt<'tcx>) -> Self {
-        let mut lints_that_actually_run = FxIndexSet::default();
-        lints_that_actually_run.reserve(230);
-        let mut lints_allowed = FxIndexSet::default();
-        lints_allowed.reserve(100);
-        Self {
-            tcx,
-            // That magic number is the current number of lints + some more for possible future lints
-            lints_that_actually_run,
-            lints_allowed,
-        }
-    }
-
+impl<'tcx> LintLevelMaximum<'tcx> {
     fn process_opts(&mut self) {
-        for (lint, level) in &self.tcx.sess.opts.lint_opts {
-            if *level == Level::Allow {
-                self.lints_allowed.insert(lint.clone());
-            } else {
-                self.lints_that_actually_run.insert(lint.to_string());
+        let store = unerased_lint_store(self.tcx.sess);
+        for (lint_group, level) in &self.tcx.sess.opts.lint_opts {
+            if *level != Level::Allow {
+                let Ok(lints) = store.find_lints(lint_group) else {
+                    return;
+                };
+                for lint in lints {
+                    self.dont_need_to_run.swap_remove(&lint);
+                }
             }
         }
     }
 }
 
-impl<'tcx> Visitor<'tcx> for LintLevelMinimum<'tcx> {
+impl<'tcx> Visitor<'tcx> for LintLevelMaximum<'tcx> {
     type NestedFilter = nested_filter::All;
 
     fn nested_visit_map(&mut self) -> Self::Map {
@@ -376,42 +373,82 @@ impl<'tcx> Visitor<'tcx> for LintLevelMinimum<'tcx> {
     }
 
     fn visit_attribute(&mut self, attribute: &'tcx ast::Attribute) {
-        if let Some(meta) = attribute.meta() {
-            if [sym::warn, sym::deny, sym::forbid, sym::expect]
-                .iter()
-                .any(|kind| meta.has_name(*kind))
-            {
+        match Level::from_attr(attribute) {
+            Some(
+                Level::Warn
+                | Level::Deny
+                | Level::Forbid
+                | Level::Expect(..)
+                | Level::ForceWarn(..),
+            ) => {
+                let store = unerased_lint_store(self.tcx.sess);
+                let Some(meta) = attribute.meta() else { return };
                 // SAFETY: Lint attributes are always a metalist inside a
                 // metalist (even with just one lint).
-                for meta_list in meta.meta_item_list().unwrap() {
-                    // If it's a tool lint (e.g. clippy::my_clippy_lint)
-                    if let ast::NestedMetaItem::MetaItem(meta_item) = meta_list {
-                        if meta_item.path.segments.len() == 1 {
-                            self.lints_that_actually_run.insert(
-                                // SAFETY: Lint attributes can only have literals
-                                meta_list.ident().unwrap().name.as_str().to_string(),
-                            );
-                        } else {
-                            self.lints_that_actually_run
-                                .insert(meta_item.path.segments[1].ident.name.as_str().to_string());
-                        }
-                    }
-                }
-            // We handle #![allow]s differently, as these remove checking rather than adding.
-            } else if meta.has_name(sym::allow)
-                && let ast::AttrStyle::Inner = attribute.style
-            {
-                for meta_list in meta.meta_item_list().unwrap() {
-                    // If it's a tool lint (e.g. clippy::my_clippy_lint)
-                    if let ast::NestedMetaItem::MetaItem(meta_item) = meta_list {
-                        if meta_item.path.segments.len() == 1 {
-                            self.lints_allowed.insert(meta_list.name_or_empty().as_str().to_string());
-                        } else {
-                            self.lints_allowed
-                                .insert(meta_item.path.segments[1].ident.name.as_str().to_string());
-                        }
+                let Some(meta_item_list) = meta.meta_item_list() else { return };
+
+                for meta_list in meta_item_list {
+                    // Convert Path to String
+                    let Some(meta_item) = meta_list.meta_item() else { return };
+                    let ident: &str = &meta_item
+                        .path
+                        .segments
+                        .iter()
+                        .map(|segment| segment.ident.as_str())
+                        .collect::<Vec<&str>>()
+                        .join("::");
+                    let Ok(lints) = store.find_lints(
+                        // SAFETY: Lint attributes can only have literals
+                        ident,
+                    ) else {
+                        return;
+                    };
+                    for lint in lints {
+                        self.dont_need_to_run.swap_remove(&lint);
                     }
+                    // // If it's a tool lint (e.g. clippy::my_clippy_lint)
+                    // if let ast::NestedMetaItem::MetaItem(meta_item) = meta_list {
+                    //     if meta_item.path.segments.len() == 1 {
+                    //         let Ok(lints) = store.find_lints(
+                    //             // SAFETY: Lint attributes can only have literals
+                    //             meta_list.ident().unwrap().name.as_str(),
+                    //         ) else {
+                    //             return;
+                    //         };
+                    //         for lint in lints {
+                    //             dbg!("LINT REMOVED", &lint);
+                    //             self.dont_need_to_run.swap_remove(&lint);
+                    //         }
+                    //     } else {
+                    //         let Ok(lints) = store.find_lints(
+                    //             // SAFETY: Lint attributes can only have literals
+                    //             meta_item.path.segments[1].ident.name.as_str(),
+                    //         ) else {
+                    //             return;
+                    //         };
+                    //         for lint in lints {
+                    //             dbg!("LINT REMOVED", &lint);
+                    //             self.dont_need_to_run.swap_remove(&lint);
+                    //         }
+                    //     }
                 }
+                // We handle #![allow]s differently, as these remove checking rather than adding.
+            } // Some(Level::Allow) if ast::AttrStyle::Inner == attribute.style => {
+            //     for meta_list in meta.meta_item_list().unwrap() {
+            //         // If it's a tool lint (e.g. clippy::my_clippy_lint)
+            //         if let ast::NestedMetaItem::MetaItem(meta_item) = meta_list {
+            //             if meta_item.path.segments.len() == 1 {
+            //                 self.lints_allowed
+            //                     .insert(meta_list.name_or_empty().as_str().to_string());
+            //             } else {
+            //                 self.lints_allowed
+            //                     .insert(meta_item.path.segments[1].ident.name.as_str().to_string());
+            //             }
+            //         }
+            //     }
+            // }
+            _ => {
+                return;
             }
         }
     }
@@ -1047,8 +1084,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
 }
 
 pub(crate) fn provide(providers: &mut Providers) {
-    *providers =
-        Providers { shallow_lint_levels_on, lints_that_can_emit, ..*providers };
+    *providers = Providers { shallow_lint_levels_on, lints_that_dont_need_to_run, ..*providers };
 }
 
 pub(crate) fn parse_lint_and_tool_name(lint_name: &str) -> (Option<Symbol>, &str) {
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 5984810961f..11dd17bcd4a 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -199,7 +199,6 @@ late_lint_methods!(
             ForLoopsOverFallibles: ForLoopsOverFallibles,
             DerefIntoDynSupertrait: DerefIntoDynSupertrait,
             DropForgetUseless: DropForgetUseless,
-            HardwiredLints: HardwiredLints,
             ImproperCTypesDeclarations: ImproperCTypesDeclarations,
             ImproperCTypesDefinitions: ImproperCTypesDefinitions,
             InvalidFromUtf8: InvalidFromUtf8,
@@ -280,6 +279,7 @@ fn register_builtins(store: &mut LintStore) {
     store.register_lints(&BuiltinCombinedEarlyLintPass::get_lints());
     store.register_lints(&BuiltinCombinedModuleLateLintPass::get_lints());
     store.register_lints(&foreign_modules::get_lints());
+    store.register_lints(&HardwiredLints::default().get_lints());
 
     add_lint_group!(
         "nonstandard_style",
diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs
index 3750f90a044..6dbcdefe08d 100644
--- a/compiler/rustc_lint/src/passes.rs
+++ b/compiler/rustc_lint/src/passes.rs
@@ -70,7 +70,18 @@ macro_rules! declare_late_lint_pass {
 // for all the `check_*` methods.
 late_lint_methods!(declare_late_lint_pass, []);
 
-impl LateLintPass<'_> for HardwiredLints {}
+impl LateLintPass<'_> for HardwiredLints {
+    fn check_fn(
+        &mut self,
+        _: &LateContext<'_>,
+        _: rustc_hir::intravisit::FnKind<'_>,
+        _: &'_ rustc_hir::FnDecl<'_>,
+        _: &'_ rustc_hir::Body<'_>,
+        _: rustc_span::Span,
+        _: rustc_span::def_id::LocalDefId,
+    ) {
+    }
+}
 
 #[macro_export]
 macro_rules! expand_combined_late_lint_pass_method {
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index a05616bf486..a7ac847c018 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1026,7 +1026,7 @@ pub(crate) struct UnusedParens {
 }
 
 impl Default for UnusedParens {
-    fpub(crate) fn default() -> Self {
+    fn default() -> Self {
         Self { with_self_ty_parens: false, parens_in_cast_in_lt: Vec::new() }
     }
 }
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 5c3b1bb71f3..df86e9de22e 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -12,8 +12,6 @@ use rustc_span::edition::Edition;
 use crate::{FutureIncompatibilityReason, declare_lint, declare_lint_pass};
 
 declare_lint_pass! {
-    /// Does nothing as a lint pass, but registers some `Lint`s
-    /// that are used by other parts of the compiler.
     HardwiredLints => [
         // tidy-alphabetical-start
         ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
@@ -403,7 +401,8 @@ declare_lint! {
     /// `panic!` or `unreachable!` macro instead in case the panic is intended.
     pub UNCONDITIONAL_PANIC,
     Deny,
-    "operation will cause a panic at runtime"
+    "operation will cause a panic at runtime",
+    [loadbearing: true]
 }
 
 declare_lint! {
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index b6cb11a2a2c..99e166286d2 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -29,6 +29,7 @@ use rustc_hir::def_id::{
 use rustc_hir::lang_items::{LangItem, LanguageItems};
 use rustc_hir::{Crate, ItemLocalId, ItemLocalMap, TraitCandidate};
 use rustc_index::IndexVec;
+use rustc_lint_defs::LintId;
 use rustc_macros::rustc_queries;
 use rustc_query_system::ich::StableHashingContext;
 use rustc_query_system::query::{QueryCache, QueryMode, QueryState, try_get_cached};
@@ -422,7 +423,7 @@ rustc_queries! {
         desc { "computing `#[expect]`ed lints in this crate" }
     }
 
-    query lints_that_can_emit(_: ()) -> &'tcx Lrc<(FxIndexSet<String>, FxIndexSet<String>)> {
+    query lints_that_dont_need_to_run(_: ()) -> &'tcx FxIndexSet<LintId> {
         arena_cache
         desc { "Computing all lints that are explicitly enabled or with a default level greater than Allow" }
     }
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 27879d817b2..c8f46226a3e 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -187,6 +187,7 @@ pub struct Session {
     /// errors.
     pub ctfe_backtrace: Lock<CtfeBacktrace>,
 
+    // pub force_ctfe: bool,
     /// This tracks where `-Zunleash-the-miri-inside-of-you` was used to get around a
     /// const check, optionally with the relevant feature gate. We use this to
     /// warn about unleashing, but with a single diagnostic instead of dozens that
diff --git a/src/tools/clippy/clippy_lints/src/asm_syntax.rs b/src/tools/clippy/clippy_lints/src/asm_syntax.rs
index 9f3c24a9e80..69a8eb7d94e 100644
--- a/src/tools/clippy/clippy_lints/src/asm_syntax.rs
+++ b/src/tools/clippy/clippy_lints/src/asm_syntax.rs
@@ -3,7 +3,7 @@ use std::fmt;
 use clippy_utils::diagnostics::span_lint_and_then;
 use rustc_ast::ast::{Expr, ExprKind, InlineAsmOptions};
 use rustc_ast::{InlineAsm, Item, ItemKind};
-use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintPass, LintContext};
+use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext};
 use rustc_session::declare_lint_pass;
 use rustc_span::Span;
 use rustc_target::asm::InlineAsmArch;
diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
index 495d8ce3fa7..b027c289a7f 100644
--- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
+++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
@@ -8,30 +8,44 @@ use core::ops::ControlFlow;
 use rustc_ast::ast::Attribute;
 use rustc_hir::intravisit::FnKind;
 use rustc_hir::{Body, Expr, ExprKind, FnDecl};
-use rustc_lint::{LateContext, LateLintPass, LintContext};
+use rustc_lint::Level::Allow;
+use rustc_lint::{LateContext, LateLintPass, Lint, LintContext};
 use rustc_session::impl_lint_pass;
 use rustc_span::def_id::LocalDefId;
 use rustc_span::{Span, sym};
 
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for methods with high cognitive complexity.
-    ///
-    /// ### Why is this bad?
-    /// Methods of high cognitive complexity tend to be hard to
-    /// both read and maintain. Also LLVM will tend to optimize small methods better.
-    ///
-    /// ### Known problems
-    /// Sometimes it's hard to find a way to reduce the
-    /// complexity.
-    ///
-    /// ### Example
-    /// You'll see it when you get the warning.
-    #[clippy::version = "1.35.0"]
-    pub COGNITIVE_COMPLEXITY,
-    nursery,
-    "functions that should be split up into multiple functions"
-}
+use crate::LintInfo;
+
+pub static COGNITIVE_COMPLEXITY: &Lint = &Lint {
+    name: &"clippy::COGNITIVE_COMPLEXITY",
+    default_level: Allow,
+    desc: "functions that should be split up into multiple functions",
+    edition_lint_opts: None,
+    report_in_external_macro: true,
+    future_incompatible: None,
+    is_externally_loaded: true,
+    crate_level_only: false,
+    loadbearing: true,
+    ..Lint::default_fields_for_macro()
+};
+pub(crate) static COGNITIVE_COMPLEXITY_INFO: &'static LintInfo = &LintInfo {
+    lint: &COGNITIVE_COMPLEXITY,
+    category: crate::LintCategory::Nursery,
+    explanation: r"### What it does
+Checks for methods with high cognitive complexity.
+
+### Why is this bad?
+Methods of high cognitive complexity tend to be hard to both read and maintain.
+Also LLVM will tend to optimize small methods better.
+
+### Known problems
+Sometimes it's hard to find a way to reduce the complexity.
+
+### Example
+You'll see it when you get the warning.",
+    version: Some("1.35.0"),
+    location: "#L0",
+};
 
 pub struct CognitiveComplexity {
     limit: LimitStack,
diff --git a/src/tools/clippy/clippy_lints/src/ctfe.rs b/src/tools/clippy/clippy_lints/src/ctfe.rs
new file mode 100644
index 00000000000..7b9f71810a9
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/ctfe.rs
@@ -0,0 +1,54 @@
+use rustc_hir::def_id::LocalDefId;
+use rustc_hir::intravisit::FnKind;
+use rustc_hir::{Body, FnDecl};
+use rustc_lint::{LateContext, LateLintPass};
+use rustc_session::declare_lint_pass;
+use rustc_span::Span;
+
+declare_clippy_lint! {
+    /// ### What it does
+    /// Checks for comparisons where one side of the relation is
+    /// either the minimum or maximum value for its type and warns if it involves a
+    /// case that is always true or always false. Only integer and boolean types are
+    /// checked.
+    ///
+    /// ### Why is this bad?
+    /// An expression like `min <= x` may misleadingly imply
+    /// that it is possible for `x` to be less than the minimum. Expressions like
+    /// `max < x` are probably mistakes.
+    ///
+    /// ### Known problems
+    /// For `usize` the size of the current compile target will
+    /// be assumed (e.g., 64 bits on 64 bit systems). This means code that uses such
+    /// a comparison to detect target pointer width will trigger this lint. One can
+    /// use `mem::sizeof` and compare its value or conditional compilation
+    /// attributes
+    /// like `#[cfg(target_pointer_width = "64")] ..` instead.
+    ///
+    /// ### Example
+    /// ```no_run
+    /// let vec: Vec<isize> = Vec::new();
+    /// if vec.len() <= 0 {}
+    /// if 100 > i32::MAX {}
+    /// ```
+    #[clippy::version = "1.82.0"]
+    pub CLIPPY_CTFE,
+    correctness,
+    "a comparison with a maximum or minimum value that is always true or false"
+}
+
+declare_lint_pass! { ClippyCtfe => [CLIPPY_CTFE] }
+
+impl<'tcx> LateLintPass<'tcx> for ClippyCtfe {
+    fn check_fn(
+        &mut self,
+        cx: &LateContext<'_>,
+        _: FnKind<'tcx>,
+        _: &'tcx FnDecl<'tcx>,
+        _: &'tcx Body<'tcx>,
+        _: Span,
+        defid: LocalDefId,
+    ) {
+        cx.tcx.ensure().mir_drops_elaborated_and_const_checked(defid); // Lint
+    }
+}
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 6e29dde2211..a5d2f6a4122 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -65,6 +65,7 @@ extern crate clippy_utils;
 #[cfg_attr(feature = "internal", allow(clippy::missing_clippy_version_attribute))]
 mod utils;
 
+pub mod ctfe; // VERY important lint (rust#125116)
 pub mod declared_lints;
 pub mod deprecated_lints;
 
@@ -605,6 +606,8 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
         });
     }
 
+    store.register_late_pass(|_| Box::new(ctfe::ClippyCtfe));
+
     store.register_late_pass(move |_| Box::new(operators::arithmetic_side_effects::ArithmeticSideEffects::new(conf)));
     store.register_late_pass(|_| Box::new(utils::dump_hir::DumpHir));
     store.register_late_pass(|_| Box::new(utils::author::Author));
diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/author.rs b/src/tools/clippy/clippy_lints/src/utils/author.rs
index 0ed606a836e..f4e166327af 100644
--- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/author.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/author.rs
@@ -12,7 +12,7 @@ use rustc_span::symbol::{Ident, Symbol};
 use std::cell::Cell;
 use std::fmt::{Display, Formatter, Write as _};
 
-declare_clippy_lint!{
+declare_lint_pass!(
     /// ### What it does
     /// Generates clippy code that detects the offending pattern
     ///
@@ -44,13 +44,8 @@ declare_clippy_lint!{
     ///     // report your lint here
     /// }
     /// ```
-    #[clippy::version = "1.0.0"]
-    pub AUTHOR,
-    internal,
-    "The author lint, see documentation at <https://doc.rust-lang.org/nightly/clippy/development/adding_lints.html#author-lint>"
-};
-
-declare_lint_pass! { Author => [AUTHOR] }
+    Author => []
+);
 
 /// Writes a line of output with indentation added
 macro_rules! out {
@@ -803,3 +798,4 @@ fn path_to_string(path: &QPath<'_>) -> Result<String, ()> {
     inner(&mut s, path)?;
     Ok(s)
 }
+
diff --git a/src/tools/clippy/clippy_lints/src/utils/mod.rs b/src/tools/clippy/clippy_lints/src/utils/mod.rs
index abd10ac024c..13e9ead9a57 100644
--- a/src/tools/clippy/clippy_lints/src/utils/mod.rs
+++ b/src/tools/clippy/clippy_lints/src/utils/mod.rs
@@ -1,3 +1,4 @@
+pub mod author;
 pub mod dump_hir;
 pub mod format_args_collector;
 #[cfg(feature = "internal")]