about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs2
-rw-r--r--compiler/rustc_lint/src/builtin.rs9
-rw-r--r--compiler/rustc_lint/src/early.rs3
-rw-r--r--compiler/rustc_lint/src/internal.rs6
-rw-r--r--compiler/rustc_lint/src/late.rs38
-rw-r--r--compiler/rustc_lint/src/levels.rs115
-rw-r--r--compiler/rustc_lint/src/lib.rs26
-rw-r--r--compiler/rustc_lint/src/passes.rs10
-rw-r--r--compiler/rustc_lint/src/types.rs2
-rw-r--r--compiler/rustc_lint/src/unused.rs4
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs9
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs20
-rw-r--r--compiler/rustc_middle/Cargo.toml1
-rw-r--r--compiler/rustc_middle/src/query/mod.rs6
-rw-r--r--src/librustdoc/lint.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/cognitive_complexity.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/ctfe.rs40
-rw-r--r--src/tools/clippy/clippy_lints/src/declare_clippy_lint.rs30
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs3
-rw-r--r--src/tools/clippy/tests/ui-internal/author.rs (renamed from src/tools/clippy/tests/ui/author.rs)2
-rw-r--r--src/tools/clippy/tests/ui-internal/author.stdout (renamed from src/tools/clippy/tests/ui/author.stdout)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/blocks.rs (renamed from src/tools/clippy/tests/ui/author/blocks.rs)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/blocks.stdout (renamed from src/tools/clippy/tests/ui/author/blocks.stdout)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/call.rs (renamed from src/tools/clippy/tests/ui/author/call.rs)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/call.stdout (renamed from src/tools/clippy/tests/ui/author/call.stdout)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/if.rs (renamed from src/tools/clippy/tests/ui/author/if.rs)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/if.stdout (renamed from src/tools/clippy/tests/ui/author/if.stdout)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/issue_3849.rs (renamed from src/tools/clippy/tests/ui/author/issue_3849.rs)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/issue_3849.stdout (renamed from src/tools/clippy/tests/ui/author/issue_3849.stdout)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/loop.rs (renamed from src/tools/clippy/tests/ui/author/loop.rs)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/loop.stdout (renamed from src/tools/clippy/tests/ui/author/loop.stdout)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/macro_in_closure.rs (renamed from src/tools/clippy/tests/ui/author/macro_in_closure.rs)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/macro_in_closure.stdout (renamed from src/tools/clippy/tests/ui/author/macro_in_closure.stdout)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/macro_in_loop.rs (renamed from src/tools/clippy/tests/ui/author/macro_in_loop.rs)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/macro_in_loop.stdout (renamed from src/tools/clippy/tests/ui/author/macro_in_loop.stdout)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/matches.rs (renamed from src/tools/clippy/tests/ui/author/matches.rs)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/matches.stdout (renamed from src/tools/clippy/tests/ui/author/matches.stdout)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/repeat.rs (renamed from src/tools/clippy/tests/ui/author/repeat.rs)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/repeat.stdout (renamed from src/tools/clippy/tests/ui/author/repeat.stdout)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/struct.rs (renamed from src/tools/clippy/tests/ui/author/struct.rs)0
-rw-r--r--src/tools/clippy/tests/ui-internal/author/struct.stdout (renamed from src/tools/clippy/tests/ui/author/struct.stdout)0
-rw-r--r--src/tools/clippy/tests/ui/no_lints.rs3
-rw-r--r--tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs10
-rw-r--r--tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr2
45 files changed, 291 insertions, 56 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 4d54b5aeb4e..01e814e7d7f 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4029,6 +4029,7 @@ dependencies = [
  "rustc_hir",
  "rustc_hir_pretty",
  "rustc_index",
+ "rustc_lint_defs",
  "rustc_macros",
  "rustc_query_system",
  "rustc_serialize",
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index b73412a4b1d..9311af28f54 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -223,7 +223,7 @@ impl AttrItem {
         self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span))
     }
 
-    fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
+    pub fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
         match &self.args {
             AttrArgs::Delimited(args) if args.delim == Delimiter::Parenthesis => {
                 MetaItemKind::list_from_tokens(args.tokens.clone())
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 70d51c92750..3ee4980a948 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -73,7 +73,6 @@ use crate::{
     EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext,
     fluent_generated as fluent,
 };
-
 declare_lint! {
     /// The `while_true` lint detects `while true { }`.
     ///
@@ -241,7 +240,8 @@ declare_lint! {
     /// behavior.
     UNSAFE_CODE,
     Allow,
-    "usage of `unsafe` code and other potentially unsound constructs"
+    "usage of `unsafe` code and other potentially unsound constructs",
+    @eval_always = true
 }
 
 declare_lint_pass!(UnsafeCode => [UNSAFE_CODE]);
@@ -389,6 +389,7 @@ declare_lint! {
     report_in_external_macro
 }
 
+#[derive(Default)]
 pub struct MissingDoc;
 
 impl_lint_pass!(MissingDoc => [MISSING_DOCS]);
@@ -819,8 +820,8 @@ pub struct DeprecatedAttr {
 
 impl_lint_pass!(DeprecatedAttr => []);
 
-impl DeprecatedAttr {
-    pub fn new() -> DeprecatedAttr {
+impl Default for DeprecatedAttr {
+    fn default() -> Self {
         DeprecatedAttr { depr_attrs: deprecated_attributes() }
     }
 }
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index a6210aa520f..e2247d3a1f6 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -309,6 +309,9 @@ impl LintPass for RuntimeCombinedEarlyLintPass<'_> {
     fn name(&self) -> &'static str {
         panic!()
     }
+    fn get_lints(&self) -> crate::LintVec {
+        panic!()
+    }
 }
 
 macro_rules! impl_early_lint_pass {
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index 94cc58e4956..7dec6dbdc05 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -429,7 +429,8 @@ declare_tool_lint! {
     pub rustc::UNTRANSLATABLE_DIAGNOSTIC,
     Deny,
     "prevent creation of diagnostics which cannot be translated",
-    report_in_external_macro: true
+    report_in_external_macro: true,
+    @eval_always = true
 }
 
 declare_tool_lint! {
@@ -442,7 +443,8 @@ declare_tool_lint! {
     pub rustc::DIAGNOSTIC_OUTSIDE_OF_IMPL,
     Deny,
     "prevent diagnostic creation outside of `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls",
-    report_in_external_macro: true
+    report_in_external_macro: true,
+    @eval_always = true
 }
 
 declare_lint_pass!(Diagnostics => [UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL]);
diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs
index 6d5903ac467..9b1877599ba 100644
--- a/compiler/rustc_lint/src/late.rs
+++ b/compiler/rustc_lint/src/late.rs
@@ -26,11 +26,12 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_session::Session;
 use rustc_session::lint::LintPass;
+use rustc_session::lint::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`].
 ///
@@ -326,6 +327,9 @@ impl LintPass for RuntimeCombinedLateLintPass<'_, '_> {
     fn name(&self) -> &'static str {
         panic!()
     }
+    fn get_lints(&self) -> crate::LintVec {
+        panic!()
+    }
 }
 
 macro_rules! impl_late_lint_pass {
@@ -361,13 +365,20 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
     // Note: `passes` is often empty. In that case, it's faster to run
     // `builtin_lints` directly rather than bundling it up into the
     // `RuntimeCombinedLateLintPass`.
-    let late_module_passes = &unerased_lint_store(tcx.sess).late_module_passes;
-    if late_module_passes.is_empty() {
+    let store = unerased_lint_store(tcx.sess);
+
+    if store.late_module_passes.is_empty() {
         late_lint_mod_inner(tcx, module_def_id, context, builtin_lints);
     } else {
-        let mut passes: Vec<_> = late_module_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect();
-        passes.push(Box::new(builtin_lints));
-        let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] };
+        let builtin_lints = Box::new(builtin_lints) as Box<dyn LateLintPass<'tcx>>;
+        let mut binding = store
+            .late_module_passes
+            .iter()
+            .map(|mk_pass| (mk_pass)(tcx))
+            .chain(std::iter::once(builtin_lints))
+            .collect::<Vec<_>>();
+
+        let pass = RuntimeCombinedLateLintPass { passes: binding.as_mut_slice() };
         late_lint_mod_inner(tcx, module_def_id, context, pass);
     }
 }
@@ -398,7 +409,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() {
@@ -416,7 +427,18 @@ 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(());
+
+    let mut filtered_passes: Vec<Box<dyn LateLintPass<'tcx>>> = passes
+        .into_iter()
+        .filter(|pass| {
+            let lints = (**pass).get_lints();
+            !lints.iter().all(|lint| lints_that_dont_need_to_run.contains(&LintId::of(lint)))
+        })
+        .collect();
+
+    filtered_passes.push(Box::new(HardwiredLints));
+    let pass = RuntimeCombinedLateLintPass { passes: &mut filtered_passes[..] };
     late_lint_crate_inner(tcx, context, pass);
 }
 
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index ff2ae69e1db..97a95787422 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -1,9 +1,9 @@
 use rustc_ast_pretty::pprust;
-use rustc_data_structures::fx::FxIndexMap;
+use rustc_data_structures::fx::{FxIndexMap, FxIndexSet};
 use rustc_errors::{Diag, LintDiagnostic, MultiSpan};
 use rustc_feature::{Features, GateIssue};
-use rustc_hir::HirId;
 use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir::{CRATE_HIR_ID, HirId};
 use rustc_index::IndexVec;
 use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
@@ -115,6 +115,38 @@ impl LintLevelSets {
     }
 }
 
+fn lints_that_dont_need_to_run(tcx: TyCtxt<'_>, (): ()) -> FxIndexSet<LintId> {
+    let store = unerased_lint_store(&tcx.sess);
+
+    let map = tcx.shallow_lint_levels_on(rustc_hir::CRATE_OWNER_ID);
+
+    let dont_need_to_run: FxIndexSet<LintId> = store
+        .get_lints()
+        .into_iter()
+        .filter_map(|lint| {
+            if !lint.eval_always {
+                let lint_level = map.lint_level_id_at_node(tcx, LintId::of(lint), CRATE_HIR_ID);
+                if matches!(lint_level, (Level::Allow, ..))
+                    || (matches!(lint_level, (.., LintLevelSource::Default)))
+                        && lint.default_level(tcx.sess.edition()) == Level::Allow
+                {
+                    Some(LintId::of(lint))
+                } else {
+                    None
+                }
+            } else {
+                None
+            }
+        })
+        .collect();
+
+    let mut visitor = LintLevelMaximum { tcx, dont_need_to_run };
+    visitor.process_opts();
+    tcx.hir().walk_attributes(&mut visitor);
+
+    visitor.dont_need_to_run
+}
+
 #[instrument(level = "trace", skip(tcx), ret)]
 fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLevelMap {
     let store = unerased_lint_store(tcx.sess);
@@ -301,6 +333,83 @@ impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, LintLevelQueryMap<'tcx>> {
     }
 }
 
+/// Visitor with the only function of visiting every item-like in a crate and
+/// computing the highest level that every lint gets put to.
+///
+/// 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 LintLevelMaximum<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    /// The actual list of detected lints.
+    dont_need_to_run: FxIndexSet<LintId>,
+}
+
+impl<'tcx> LintLevelMaximum<'tcx> {
+    fn process_opts(&mut self) {
+        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 LintLevelMaximum<'tcx> {
+    type NestedFilter = nested_filter::All;
+
+    fn nested_visit_map(&mut self) -> Self::Map {
+        self.tcx.hir()
+    }
+
+    /// FIXME(blyxyas): In a future revision, we should also graph #![allow]s,
+    /// but that is handled with more care
+    fn visit_attribute(&mut self, attribute: &'tcx ast::Attribute) {
+        if matches!(
+            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 };
+            // Lint attributes are always a metalist inside a
+            // metalist (even with just one lint).
+            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(
+                    // Lint attributes can only have literals
+                    ident,
+                ) else {
+                    return;
+                };
+                for lint in lints {
+                    self.dont_need_to_run.swap_remove(&lint);
+                }
+            }
+        }
+    }
+}
+
 pub struct LintLevelsBuilder<'s, P> {
     sess: &'s Session,
     features: &'s Features,
@@ -934,7 +1043,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
 }
 
 pub(crate) fn provide(providers: &mut Providers) {
-    *providers = Providers { shallow_lint_levels_on, ..*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 a7faab0868d..5389860e23b 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -170,7 +170,7 @@ early_lint_methods!(
     [
         pub BuiltinCombinedEarlyLintPass,
         [
-            UnusedParens: UnusedParens::new(),
+            UnusedParens: UnusedParens::default(),
             UnusedBraces: UnusedBraces,
             UnusedImportBraces: UnusedImportBraces,
             UnsafeCode: UnsafeCode,
@@ -178,7 +178,7 @@ early_lint_methods!(
             AnonymousParameters: AnonymousParameters,
             EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::default(),
             NonCamelCaseTypes: NonCamelCaseTypes,
-            DeprecatedAttr: DeprecatedAttr::new(),
+            DeprecatedAttr: DeprecatedAttr::default(),
             WhileTrue: WhileTrue,
             NonAsciiIdents: NonAsciiIdents,
             HiddenUnicodeCodepoints: HiddenUnicodeCodepoints,
@@ -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::lint_vec());
 
     add_lint_group!(
         "nonstandard_style",
@@ -602,25 +602,25 @@ fn register_builtins(store: &mut LintStore) {
 }
 
 fn register_internals(store: &mut LintStore) {
-    store.register_lints(&LintPassImpl::get_lints());
+    store.register_lints(&LintPassImpl::lint_vec());
     store.register_early_pass(|| Box::new(LintPassImpl));
-    store.register_lints(&DefaultHashTypes::get_lints());
+    store.register_lints(&DefaultHashTypes::lint_vec());
     store.register_late_mod_pass(|_| Box::new(DefaultHashTypes));
-    store.register_lints(&QueryStability::get_lints());
+    store.register_lints(&QueryStability::lint_vec());
     store.register_late_mod_pass(|_| Box::new(QueryStability));
-    store.register_lints(&ExistingDocKeyword::get_lints());
+    store.register_lints(&ExistingDocKeyword::lint_vec());
     store.register_late_mod_pass(|_| Box::new(ExistingDocKeyword));
-    store.register_lints(&TyTyKind::get_lints());
+    store.register_lints(&TyTyKind::lint_vec());
     store.register_late_mod_pass(|_| Box::new(TyTyKind));
-    store.register_lints(&TypeIr::get_lints());
+    store.register_lints(&TypeIr::lint_vec());
     store.register_late_mod_pass(|_| Box::new(TypeIr));
-    store.register_lints(&Diagnostics::get_lints());
+    store.register_lints(&Diagnostics::lint_vec());
     store.register_late_mod_pass(|_| Box::new(Diagnostics));
-    store.register_lints(&BadOptAccess::get_lints());
+    store.register_lints(&BadOptAccess::lint_vec());
     store.register_late_mod_pass(|_| Box::new(BadOptAccess));
-    store.register_lints(&PassByValue::get_lints());
+    store.register_lints(&PassByValue::lint_vec());
     store.register_late_mod_pass(|_| Box::new(PassByValue));
-    store.register_lints(&SpanUseEqCtxt::get_lints());
+    store.register_lints(&SpanUseEqCtxt::lint_vec());
     store.register_late_mod_pass(|_| Box::new(SpanUseEqCtxt));
     // FIXME(davidtwco): deliberately do not include `UNTRANSLATABLE_DIAGNOSTIC` and
     // `DIAGNOSTIC_OUTSIDE_OF_IMPL` here because `-Wrustc::internal` is provided to every crate and
diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs
index 75ae994a86b..9d84d36e779 100644
--- a/compiler/rustc_lint/src/passes.rs
+++ b/compiler/rustc_lint/src/passes.rs
@@ -110,7 +110,7 @@ macro_rules! declare_combined_late_lint_pass {
 
             $v fn get_lints() -> $crate::LintVec {
                 let mut lints = Vec::new();
-                $(lints.extend_from_slice(&$pass::get_lints());)*
+                $(lints.extend_from_slice(&$pass::lint_vec());)*
                 lints
             }
         }
@@ -124,6 +124,9 @@ macro_rules! declare_combined_late_lint_pass {
             fn name(&self) -> &'static str {
                 panic!()
             }
+            fn get_lints(&self) -> LintVec {
+                panic!()
+            }
         }
     )
 }
@@ -222,7 +225,7 @@ macro_rules! declare_combined_early_lint_pass {
 
             $v fn get_lints() -> $crate::LintVec {
                 let mut lints = Vec::new();
-                $(lints.extend_from_slice(&$pass::get_lints());)*
+                $(lints.extend_from_slice(&$pass::lint_vec());)*
                 lints
             }
         }
@@ -236,6 +239,9 @@ macro_rules! declare_combined_early_lint_pass {
             fn name(&self) -> &'static str {
                 panic!()
             }
+            fn get_lints(&self) -> LintVec {
+                panic!()
+            }
         }
     )
 }
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index 60ff925b40e..0751d35cb9c 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -167,7 +167,7 @@ declare_lint! {
     "detects ambiguous wide pointer comparisons"
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Default)]
 pub(crate) struct TypeLimits {
     /// Id of the last visited negated expression
     negated_expr_id: Option<hir::HirId>,
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index ddc18c755a8..bbb290c9459 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -1025,8 +1025,8 @@ pub(crate) struct UnusedParens {
     parens_in_cast_in_lt: Vec<ast::NodeId>,
 }
 
-impl UnusedParens {
-    pub(crate) fn new() -> Self {
+impl Default for UnusedParens {
+    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 a4c49a15905..06a3e4a6743 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -377,7 +377,8 @@ declare_lint! {
     /// will not overflow.
     pub ARITHMETIC_OVERFLOW,
     Deny,
-    "arithmetic operation overflows"
+    "arithmetic operation overflows",
+    @eval_always = true
 }
 
 declare_lint! {
@@ -401,7 +402,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",
+    @eval_always = true
 }
 
 declare_lint! {
@@ -632,7 +634,8 @@ declare_lint! {
     /// is only available in a newer version.
     pub UNKNOWN_LINTS,
     Warn,
-    "unrecognized lint attribute"
+    "unrecognized lint attribute",
+    @eval_always = true
 }
 
 declare_lint! {
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index c01fa5c54d6..601784f9732 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -312,6 +312,10 @@ pub struct Lint {
     pub feature_gate: Option<Symbol>,
 
     pub crate_level_only: bool,
+
+    /// `true` if this lint should not be filtered out under any circustamces
+    /// (e.g. the unknown_attributes lint)
+    pub eval_always: bool,
 }
 
 /// Extra information for a future incompatibility lint.
@@ -456,6 +460,7 @@ impl Lint {
             future_incompatible: None,
             feature_gate: None,
             crate_level_only: false,
+            eval_always: false,
         }
     }
 
@@ -864,6 +869,7 @@ macro_rules! declare_lint {
         );
     );
     ($(#[$attr:meta])* $vis: vis $NAME: ident, $Level: ident, $desc: expr,
+     $(@eval_always = $eval_always:literal)?
      $(@feature_gate = $gate:ident;)?
      $(@future_incompatible = FutureIncompatibleInfo {
         reason: $reason:expr,
@@ -885,6 +891,7 @@ macro_rules! declare_lint {
                 ..$crate::FutureIncompatibleInfo::default_fields_for_macro()
             }),)?
             $(edition_lint_opts: Some(($crate::Edition::$lint_edition, $crate::$edition_level)),)?
+            $(eval_always: $eval_always,)?
             ..$crate::Lint::default_fields_for_macro()
         };
     );
@@ -894,20 +901,23 @@ macro_rules! declare_lint {
 macro_rules! declare_tool_lint {
     (
         $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level: ident, $desc: expr
+        $(, @eval_always = $eval_always:literal)?
         $(, @feature_gate = $gate:ident;)?
     ) => (
-        $crate::declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, false $(, @feature_gate = $gate;)?}
+        $crate::declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, false $(, @eval_always = $eval_always)? $(, @feature_gate = $gate;)?}
     );
     (
         $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
         report_in_external_macro: $rep:expr
+        $(, @eval_always = $eval_always: literal)?
         $(, @feature_gate = $gate:ident;)?
     ) => (
-         $crate::declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, $rep $(, @feature_gate = $gate;)?}
+         $crate::declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, $rep  $(, @eval_always = $eval_always)? $(, @feature_gate = $gate;)?}
     );
     (
         $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
         $external:expr
+        $(, @eval_always = $eval_always: literal)?
         $(, @feature_gate = $gate:ident;)?
     ) => (
         $(#[$attr])*
@@ -921,6 +931,7 @@ macro_rules! declare_tool_lint {
             is_externally_loaded: true,
             $(feature_gate: Some(rustc_span::symbol::sym::$gate),)?
             crate_level_only: false,
+            $(eval_always: $eval_always,)?
             ..$crate::Lint::default_fields_for_macro()
         };
     );
@@ -930,6 +941,7 @@ pub type LintVec = Vec<&'static Lint>;
 
 pub trait LintPass {
     fn name(&self) -> &'static str;
+    fn get_lints(&self) -> LintVec;
 }
 
 /// Implements `LintPass for $ty` with the given list of `Lint` statics.
@@ -938,9 +950,11 @@ macro_rules! impl_lint_pass {
     ($ty:ty => [$($lint:expr),* $(,)?]) => {
         impl $crate::LintPass for $ty {
             fn name(&self) -> &'static str { stringify!($ty) }
+            fn get_lints(&self) -> $crate::LintVec { vec![$($lint),*] }
         }
         impl $ty {
-            pub fn get_lints() -> $crate::LintVec { vec![$($lint),*] }
+            #[allow(unused)]
+            pub fn lint_vec() -> $crate::LintVec { vec![$($lint),*] }
         }
     };
 }
diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml
index 8cb602d9ea8..485d1c14df3 100644
--- a/compiler/rustc_middle/Cargo.toml
+++ b/compiler/rustc_middle/Cargo.toml
@@ -27,6 +27,7 @@ rustc_graphviz = { path = "../rustc_graphviz" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_hir_pretty = { path = "../rustc_hir_pretty" }
 rustc_index = { path = "../rustc_index" }
+rustc_lint_defs = { path = "../rustc_lint_defs" }
 rustc_macros = { path = "../rustc_macros" }
 rustc_query_system = { path = "../rustc_query_system" }
 rustc_serialize = { path = "../rustc_serialize" }
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 94bdb913528..d7a60a843b7 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,6 +423,11 @@ rustc_queries! {
         desc { "computing `#[expect]`ed lints in this crate" }
     }
 
+    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" }
+    }
+
     query expn_that_defined(key: DefId) -> rustc_span::ExpnId {
         desc { |tcx| "getting the expansion that defined `{}`", tcx.def_path_str(key) }
         separate_provide_extern
diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs
index bdfdeeabc5a..2afb9e549d9 100644
--- a/src/librustdoc/lint.rs
+++ b/src/librustdoc/lint.rs
@@ -31,9 +31,9 @@ where
     allowed_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned());
 
     let lints = || {
-        lint::builtin::HardwiredLints::get_lints()
+        lint::builtin::HardwiredLints::lint_vec()
             .into_iter()
-            .chain(rustc_lint::SoftLints::get_lints())
+            .chain(rustc_lint::SoftLints::lint_vec())
     };
 
     let lint_opts = lints()
diff --git a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
index 495d8ce3fa7..477435236a5 100644
--- a/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
+++ b/src/tools/clippy/clippy_lints/src/cognitive_complexity.rs
@@ -31,6 +31,7 @@ declare_clippy_lint! {
     pub COGNITIVE_COMPLEXITY,
     nursery,
     "functions that should be split up into multiple functions"
+    @eval_always = true
 }
 
 pub struct CognitiveComplexity {
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..2fe37a64db6
--- /dev/null
+++ b/src/tools/clippy/clippy_lints/src/ctfe.rs
@@ -0,0 +1,40 @@
+use rustc_hir::def_id::LocalDefId;
+use rustc_hir::intravisit::FnKind;
+use rustc_hir::{Body, FnDecl};
+use rustc_lint::Level::Deny;
+use rustc_lint::{LateContext, LateLintPass, Lint};
+use rustc_session::declare_lint_pass;
+use rustc_span::Span;
+
+/// Ensures that Constant-time Function Evaluation is being done (specifically, MIR lint passes).
+/// As Clippy deactivates codegen, this lint ensures that CTFE (used in hard errors) is still ran.
+pub static CLIPPY_CTFE: &Lint = &Lint {
+    name: &"clippy::CLIPPY_CTFE",
+    default_level: Deny,
+    desc: "Ensure CTFE is being made",
+    edition_lint_opts: None,
+    report_in_external_macro: true,
+    future_incompatible: None,
+    is_externally_loaded: true,
+    crate_level_only: false,
+    eval_always: true,
+    ..Lint::default_fields_for_macro()
+};
+
+// No static CLIPPY_CTFE_INFO because we want this lint to be invisible
+
+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/declare_clippy_lint.rs b/src/tools/clippy/clippy_lints/src/declare_clippy_lint.rs
index b1e39c70baa..a785a9d377c 100644
--- a/src/tools/clippy/clippy_lints/src/declare_clippy_lint.rs
+++ b/src/tools/clippy/clippy_lints/src/declare_clippy_lint.rs
@@ -9,6 +9,7 @@ macro_rules! declare_clippy_lint {
         $desc:literal,
         $version_expr:expr,
         $version_lit:literal
+        $(, $eval_always: literal)?
     ) => {
         rustc_session::declare_tool_lint! {
             $(#[doc = $lit])*
@@ -17,6 +18,7 @@ macro_rules! declare_clippy_lint {
             $category,
             $desc,
             report_in_external_macro:true
+            $(, @eval_always = $eval_always)?
         }
 
         pub(crate) static ${concat($lint_name, _INFO)}: &'static crate::LintInfo = &crate::LintInfo {
@@ -33,11 +35,12 @@ macro_rules! declare_clippy_lint {
         pub $lint_name:ident,
         restriction,
         $desc:literal
+        $(@eval_always = $eval_always: literal)?
     ) => {
         declare_clippy_lint! {@
             $(#[doc = $lit])*
             pub $lint_name, Allow, crate::LintCategory::Restriction, $desc,
-            Some($version), $version
+            Some($version), $version $(, $eval_always)?
         }
     };
     (
@@ -46,12 +49,12 @@ macro_rules! declare_clippy_lint {
         pub $lint_name:ident,
         style,
         $desc:literal
+        $(@eval_always = $eval_always: literal)?
     ) => {
         declare_clippy_lint! {@
             $(#[doc = $lit])*
             pub $lint_name, Warn, crate::LintCategory::Style, $desc,
-            Some($version), $version
-
+            Some($version), $version $(, $eval_always)?
         }
     };
     (
@@ -60,11 +63,12 @@ macro_rules! declare_clippy_lint {
         pub $lint_name:ident,
         correctness,
         $desc:literal
+        $(@eval_always = $eval_always: literal)?
     ) => {
         declare_clippy_lint! {@
             $(#[doc = $lit])*
             pub $lint_name, Deny, crate::LintCategory::Correctness, $desc,
-            Some($version), $version
+            Some($version), $version $(, $eval_always)?
 
         }
     };
@@ -74,11 +78,12 @@ macro_rules! declare_clippy_lint {
         pub $lint_name:ident,
         perf,
         $desc:literal
+        $(@eval_always = $eval_always: literal)?
     ) => {
         declare_clippy_lint! {@
             $(#[doc = $lit])*
             pub $lint_name, Warn, crate::LintCategory::Perf, $desc,
-            Some($version), $version
+            Some($version), $version $(, $eval_always)?
         }
     };
     (
@@ -87,11 +92,12 @@ macro_rules! declare_clippy_lint {
         pub $lint_name:ident,
         complexity,
         $desc:literal
+        $(@eval_always = $eval_always: literal)?
     ) => {
         declare_clippy_lint! {@
             $(#[doc = $lit])*
             pub $lint_name, Warn, crate::LintCategory::Complexity, $desc,
-            Some($version), $version
+            Some($version), $version $(, $eval_always)?
         }
     };
     (
@@ -100,11 +106,12 @@ macro_rules! declare_clippy_lint {
         pub $lint_name:ident,
         suspicious,
         $desc:literal
+        $(@eval_always = $eval_always: literal)?
     ) => {
         declare_clippy_lint! {@
             $(#[doc = $lit])*
             pub $lint_name, Warn, crate::LintCategory::Suspicious, $desc,
-            Some($version), $version
+            Some($version), $version $(, $eval_always)?
         }
     };
     (
@@ -113,11 +120,12 @@ macro_rules! declare_clippy_lint {
         pub $lint_name:ident,
         nursery,
         $desc:literal
+        $(@eval_always = $eval_always: literal)?
     ) => {
         declare_clippy_lint! {@
             $(#[doc = $lit])*
             pub $lint_name, Allow, crate::LintCategory::Nursery, $desc,
-            Some($version), $version
+            Some($version), $version $(, $eval_always)?
         }
     };
     (
@@ -126,11 +134,12 @@ macro_rules! declare_clippy_lint {
         pub $lint_name:ident,
         pedantic,
         $desc:literal
+        $(@eval_always = $eval_always: literal)?
     ) => {
         declare_clippy_lint! {@
             $(#[doc = $lit])*
             pub $lint_name, Allow, crate::LintCategory::Pedantic, $desc,
-            Some($version), $version
+            Some($version), $version $(, $eval_always)?
         }
     };
     (
@@ -139,11 +148,12 @@ macro_rules! declare_clippy_lint {
         pub $lint_name:ident,
         cargo,
         $desc:literal
+        $(@eval_always = $eval_always: literal)?
     ) => {
         declare_clippy_lint! {@
             $(#[doc = $lit])*
             pub $lint_name, Allow, crate::LintCategory::Cargo, $desc,
-            Some($version), $version
+            Some($version), $version $(, $eval_always)?
         }
     };
 
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 6e29dde2211..14110539709 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, do not remove (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/tests/ui/author.rs b/src/tools/clippy/tests/ui-internal/author.rs
index 0a1be356896..eb1f3e3f870 100644
--- a/src/tools/clippy/tests/ui/author.rs
+++ b/src/tools/clippy/tests/ui-internal/author.rs
@@ -1,3 +1,5 @@
+#![warn(clippy::author)]
+
 fn main() {
     #[clippy::author]
     let x: char = 0x45 as char;
diff --git a/src/tools/clippy/tests/ui/author.stdout b/src/tools/clippy/tests/ui-internal/author.stdout
index eed704e82fe..eed704e82fe 100644
--- a/src/tools/clippy/tests/ui/author.stdout
+++ b/src/tools/clippy/tests/ui-internal/author.stdout
diff --git a/src/tools/clippy/tests/ui/author/blocks.rs b/src/tools/clippy/tests/ui-internal/author/blocks.rs
index 164f7d0d9d6..164f7d0d9d6 100644
--- a/src/tools/clippy/tests/ui/author/blocks.rs
+++ b/src/tools/clippy/tests/ui-internal/author/blocks.rs
diff --git a/src/tools/clippy/tests/ui/author/blocks.stdout b/src/tools/clippy/tests/ui-internal/author/blocks.stdout
index 6bf48d5ba4e..6bf48d5ba4e 100644
--- a/src/tools/clippy/tests/ui/author/blocks.stdout
+++ b/src/tools/clippy/tests/ui-internal/author/blocks.stdout
diff --git a/src/tools/clippy/tests/ui/author/call.rs b/src/tools/clippy/tests/ui-internal/author/call.rs
index e99c3c41dc4..e99c3c41dc4 100644
--- a/src/tools/clippy/tests/ui/author/call.rs
+++ b/src/tools/clippy/tests/ui-internal/author/call.rs
diff --git a/src/tools/clippy/tests/ui/author/call.stdout b/src/tools/clippy/tests/ui-internal/author/call.stdout
index 59d4da490fe..59d4da490fe 100644
--- a/src/tools/clippy/tests/ui/author/call.stdout
+++ b/src/tools/clippy/tests/ui-internal/author/call.stdout
diff --git a/src/tools/clippy/tests/ui/author/if.rs b/src/tools/clippy/tests/ui-internal/author/if.rs
index 946088ab346..946088ab346 100644
--- a/src/tools/clippy/tests/ui/author/if.rs
+++ b/src/tools/clippy/tests/ui-internal/author/if.rs
diff --git a/src/tools/clippy/tests/ui/author/if.stdout b/src/tools/clippy/tests/ui-internal/author/if.stdout
index a85dcddd331..a85dcddd331 100644
--- a/src/tools/clippy/tests/ui/author/if.stdout
+++ b/src/tools/clippy/tests/ui-internal/author/if.stdout
diff --git a/src/tools/clippy/tests/ui/author/issue_3849.rs b/src/tools/clippy/tests/ui-internal/author/issue_3849.rs
index 5f65746d71f..5f65746d71f 100644
--- a/src/tools/clippy/tests/ui/author/issue_3849.rs
+++ b/src/tools/clippy/tests/ui-internal/author/issue_3849.rs
diff --git a/src/tools/clippy/tests/ui/author/issue_3849.stdout b/src/tools/clippy/tests/ui-internal/author/issue_3849.stdout
index a5a8c0304ee..a5a8c0304ee 100644
--- a/src/tools/clippy/tests/ui/author/issue_3849.stdout
+++ b/src/tools/clippy/tests/ui-internal/author/issue_3849.stdout
diff --git a/src/tools/clippy/tests/ui/author/loop.rs b/src/tools/clippy/tests/ui-internal/author/loop.rs
index ff5b6100117..ff5b6100117 100644
--- a/src/tools/clippy/tests/ui/author/loop.rs
+++ b/src/tools/clippy/tests/ui-internal/author/loop.rs
diff --git a/src/tools/clippy/tests/ui/author/loop.stdout b/src/tools/clippy/tests/ui-internal/author/loop.stdout
index 609d2491061..609d2491061 100644
--- a/src/tools/clippy/tests/ui/author/loop.stdout
+++ b/src/tools/clippy/tests/ui-internal/author/loop.stdout
diff --git a/src/tools/clippy/tests/ui/author/macro_in_closure.rs b/src/tools/clippy/tests/ui-internal/author/macro_in_closure.rs
index 444e6a12165..444e6a12165 100644
--- a/src/tools/clippy/tests/ui/author/macro_in_closure.rs
+++ b/src/tools/clippy/tests/ui-internal/author/macro_in_closure.rs
diff --git a/src/tools/clippy/tests/ui/author/macro_in_closure.stdout b/src/tools/clippy/tests/ui-internal/author/macro_in_closure.stdout
index 66caf382d89..66caf382d89 100644
--- a/src/tools/clippy/tests/ui/author/macro_in_closure.stdout
+++ b/src/tools/clippy/tests/ui-internal/author/macro_in_closure.stdout
diff --git a/src/tools/clippy/tests/ui/author/macro_in_loop.rs b/src/tools/clippy/tests/ui-internal/author/macro_in_loop.rs
index 8a520501f8d..8a520501f8d 100644
--- a/src/tools/clippy/tests/ui/author/macro_in_loop.rs
+++ b/src/tools/clippy/tests/ui-internal/author/macro_in_loop.rs
diff --git a/src/tools/clippy/tests/ui/author/macro_in_loop.stdout b/src/tools/clippy/tests/ui-internal/author/macro_in_loop.stdout
index 3f9be297c33..3f9be297c33 100644
--- a/src/tools/clippy/tests/ui/author/macro_in_loop.stdout
+++ b/src/tools/clippy/tests/ui-internal/author/macro_in_loop.stdout
diff --git a/src/tools/clippy/tests/ui/author/matches.rs b/src/tools/clippy/tests/ui-internal/author/matches.rs
index 674e07ec2d3..674e07ec2d3 100644
--- a/src/tools/clippy/tests/ui/author/matches.rs
+++ b/src/tools/clippy/tests/ui-internal/author/matches.rs
diff --git a/src/tools/clippy/tests/ui/author/matches.stdout b/src/tools/clippy/tests/ui-internal/author/matches.stdout
index 91b3b6f6877..91b3b6f6877 100644
--- a/src/tools/clippy/tests/ui/author/matches.stdout
+++ b/src/tools/clippy/tests/ui-internal/author/matches.stdout
diff --git a/src/tools/clippy/tests/ui/author/repeat.rs b/src/tools/clippy/tests/ui-internal/author/repeat.rs
index d8e9d589e68..d8e9d589e68 100644
--- a/src/tools/clippy/tests/ui/author/repeat.rs
+++ b/src/tools/clippy/tests/ui-internal/author/repeat.rs
diff --git a/src/tools/clippy/tests/ui/author/repeat.stdout b/src/tools/clippy/tests/ui-internal/author/repeat.stdout
index d9e3f864f12..d9e3f864f12 100644
--- a/src/tools/clippy/tests/ui/author/repeat.stdout
+++ b/src/tools/clippy/tests/ui-internal/author/repeat.stdout
diff --git a/src/tools/clippy/tests/ui/author/struct.rs b/src/tools/clippy/tests/ui-internal/author/struct.rs
index a99bdfc1313..a99bdfc1313 100644
--- a/src/tools/clippy/tests/ui/author/struct.rs
+++ b/src/tools/clippy/tests/ui-internal/author/struct.rs
diff --git a/src/tools/clippy/tests/ui/author/struct.stdout b/src/tools/clippy/tests/ui-internal/author/struct.stdout
index 0b332d5e7d0..0b332d5e7d0 100644
--- a/src/tools/clippy/tests/ui/author/struct.stdout
+++ b/src/tools/clippy/tests/ui-internal/author/struct.stdout
diff --git a/src/tools/clippy/tests/ui/no_lints.rs b/src/tools/clippy/tests/ui/no_lints.rs
new file mode 100644
index 00000000000..a8467bb6ef7
--- /dev/null
+++ b/src/tools/clippy/tests/ui/no_lints.rs
@@ -0,0 +1,3 @@
+#![deny(clippy::all)]
+
+fn main() {}
\ No newline at end of file
diff --git a/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs b/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs
index c3df917ed12..6eb698c96f6 100644
--- a/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs
+++ b/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs
@@ -6,7 +6,7 @@
 extern crate rustc_middle;
 extern crate rustc_session;
 
-use rustc_session::lint::{LintPass, LintVec};
+use rustc_session::lint::{LintPass, LintVec, Lint};
 use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
 
 declare_lint! {
@@ -21,6 +21,10 @@ impl LintPass for Foo { //~ERROR implementing `LintPass` by hand
     fn name(&self) -> &'static str {
         "Foo"
     }
+
+    fn get_lints(&self) -> Vec<&'static Lint> {
+        vec![TEST_LINT]
+    }
 }
 
 macro_rules! custom_lint_pass_macro {
@@ -31,6 +35,10 @@ macro_rules! custom_lint_pass_macro {
             fn name(&self) -> &'static str {
                 "Custom"
             }
+
+            fn get_lints(&self) -> Vec<&'static Lint> {
+                vec![TEST_LINT]
+            }
         }
     };
 }
diff --git a/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr b/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr
index ad6e93334cd..824eb35424d 100644
--- a/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr
+++ b/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr
@@ -12,7 +12,7 @@ LL | #![deny(rustc::lint_pass_impl_without_macro)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: implementing `LintPass` by hand
-  --> $DIR/lint_pass_impl_without_macro.rs:30:14
+  --> $DIR/lint_pass_impl_without_macro.rs:34:14
    |
 LL |         impl LintPass for Custom {
    |              ^^^^^^^^