From 0190457a9fccf8662c8d5f9a8bddcdeb8da7e6d0 Mon Sep 17 00:00:00 2001 From: Alex Macleod Date: Fri, 28 Feb 2025 15:10:57 +0000 Subject: [PATCH] Test that no nightly versions exist in the rust repo --- .../infrastructure/changelog_update.md | 5 +- clippy_dev/src/update_lints.rs | 11 +-- clippy_lints/src/deprecated_lints.rs | 99 ++++--------------- clippy_lints/src/lib.rs | 3 +- tests/compile-test.rs | 20 ++-- tests/lint-definitions.rs | 35 +++++++ ...nvention.rs => lint-message-convention.rs} | 0 7 files changed, 74 insertions(+), 99 deletions(-) create mode 100644 tests/lint-definitions.rs rename tests/{lint_message_convention.rs => lint-message-convention.rs} (100%) diff --git a/book/src/development/infrastructure/changelog_update.md b/book/src/development/infrastructure/changelog_update.md index 212b1b87b691..18ce3b81812f 100644 --- a/book/src/development/infrastructure/changelog_update.md +++ b/book/src/development/infrastructure/changelog_update.md @@ -112,7 +112,10 @@ that label in the changelog. If you can, remove the `beta-accepted` labels ### 4. Update `clippy::version` attributes Next, make sure to check that the `#[clippy::version]` attributes for the newly -added, renamed and deprecated lints contain the correct version. +added and deprecated lints contain the correct version. + +Newly created lints will have `#[clippy::version = "nightly"]` and be handled +during the sync, but many existing PRs will still have an incorrect version. [changelog]: https://github.com/rust-lang/rust-clippy/blob/master/CHANGELOG.md [forge]: https://forge.rust-lang.org/ diff --git a/clippy_dev/src/update_lints.rs b/clippy_dev/src/update_lints.rs index 119cb27ab9b9..8b26dfc7ffd9 100644 --- a/clippy_dev/src/update_lints.rs +++ b/clippy_dev/src/update_lints.rs @@ -201,11 +201,7 @@ pub fn rename(old_name: &str, new_name: &str, uplift: bool) { insert_at_marker( s, "// end renamed lints. used by `cargo dev rename_lint`", - &format!( - "#[clippy::version = \"nightly\"]\n \ - (\"{}\", \"{}\"),\n ", - lint.old_name, lint.new_name, - ), + &format!("(\"{}\", \"{}\"),\n ", lint.old_name, lint.new_name,), ) }); @@ -562,6 +558,7 @@ impl DeprecatedLint { } } +#[derive(Debug)] struct RenamedLint { old_name: String, new_name: String, @@ -765,10 +762,10 @@ fn parse_contents(contents: &str, module: &str, lints: &mut Vec) { /// Parse a source file looking for `declare_deprecated_lint` macro invocations. fn parse_deprecated_contents(contents: &str, deprecated: &mut Vec, renamed: &mut Vec) { - let Some((_, contents)) = contents.split_once("\ndeclare_with_version! { DEPRECATED") else { + let Some((_, contents)) = contents.split_once("\ndeprecated![") else { return; }; - let Some((deprecated_src, renamed_src)) = contents.split_once("\ndeclare_with_version! { RENAMED") else { + let Some((deprecated_src, renamed_src)) = contents.split_once("\npub const RENAMED") else { return; }; diff --git a/clippy_lints/src/deprecated_lints.rs b/clippy_lints/src/deprecated_lints.rs index 5ff2cba9d1ae..06ccaa45ef5b 100644 --- a/clippy_lints/src/deprecated_lints.rs +++ b/clippy_lints/src/deprecated_lints.rs @@ -1,19 +1,28 @@ // This file is managed by `cargo dev rename_lint` and `cargo dev deprecate_lint`. // Prefer to use those when possible. -macro_rules! declare_with_version { - ($name:ident($name_version:ident): &[$ty:ty] = &[$( +#[derive(Copy, Clone, Debug)] +pub struct Deprecation { + pub name: &'static str, + pub reason: &'static str, + pub version: &'static str, +} + +macro_rules! deprecated { + ($( #[clippy::version = $version:literal] - $e:expr, - )*]) => { - pub static $name: &[$ty] = &[$($e),*]; - #[allow(unused)] - pub static $name_version: &[&str] = &[$($version),*]; + ($name:literal, $reason:literal), + )*) => { + pub const DEPRECATED: &[Deprecation] = &[$(Deprecation { + name: $name, + reason: $reason, + version: $version, + }),*]; }; } #[rustfmt::skip] -declare_with_version! { DEPRECATED(DEPRECATED_VERSION): &[(&str, &str)] = &[ +deprecated![ #[clippy::version = "pre 1.29.0"] ("clippy::should_assert_eq", "`assert!(a == b)` can now print the values the same way `assert_eq!(a, b) can"), #[clippy::version = "pre 1.29.0"] @@ -43,145 +52,77 @@ declare_with_version! { DEPRECATED(DEPRECATED_VERSION): &[(&str, &str)] = &[ #[clippy::version = "nightly"] ("clippy::option_map_or_err_ok", "`clippy::manual_ok_or` covers this case"), // end deprecated lints. used by `cargo dev deprecate_lint` -]} +]; #[rustfmt::skip] -declare_with_version! { RENAMED(RENAMED_VERSION): &[(&str, &str)] = &[ - #[clippy::version = ""] +pub const RENAMED: &[(&str, &str)] = &[ ("clippy::almost_complete_letter_range", "clippy::almost_complete_range"), - #[clippy::version = ""] ("clippy::blacklisted_name", "clippy::disallowed_names"), - #[clippy::version = ""] ("clippy::block_in_if_condition_expr", "clippy::blocks_in_conditions"), - #[clippy::version = ""] ("clippy::block_in_if_condition_stmt", "clippy::blocks_in_conditions"), - #[clippy::version = ""] ("clippy::blocks_in_if_conditions", "clippy::blocks_in_conditions"), - #[clippy::version = ""] ("clippy::box_vec", "clippy::box_collection"), - #[clippy::version = ""] ("clippy::const_static_lifetime", "clippy::redundant_static_lifetimes"), - #[clippy::version = ""] ("clippy::cyclomatic_complexity", "clippy::cognitive_complexity"), - #[clippy::version = ""] ("clippy::derive_hash_xor_eq", "clippy::derived_hash_with_manual_eq"), - #[clippy::version = ""] ("clippy::disallowed_method", "clippy::disallowed_methods"), - #[clippy::version = ""] ("clippy::disallowed_type", "clippy::disallowed_types"), - #[clippy::version = ""] ("clippy::eval_order_dependence", "clippy::mixed_read_write_in_expression"), - #[clippy::version = "1.51.0"] ("clippy::find_map", "clippy::manual_find_map"), - #[clippy::version = "1.53.0"] ("clippy::filter_map", "clippy::manual_filter_map"), - #[clippy::version = ""] ("clippy::fn_address_comparisons", "unpredictable_function_pointer_comparisons"), - #[clippy::version = ""] ("clippy::identity_conversion", "clippy::useless_conversion"), - #[clippy::version = "pre 1.29.0"] ("clippy::if_let_redundant_pattern_matching", "clippy::redundant_pattern_matching"), - #[clippy::version = ""] ("clippy::if_let_some_result", "clippy::match_result_ok"), - #[clippy::version = ""] ("clippy::incorrect_clone_impl_on_copy_type", "clippy::non_canonical_clone_impl"), - #[clippy::version = ""] ("clippy::incorrect_partial_ord_impl_on_ord_type", "clippy::non_canonical_partial_ord_impl"), - #[clippy::version = ""] ("clippy::integer_arithmetic", "clippy::arithmetic_side_effects"), - #[clippy::version = ""] ("clippy::logic_bug", "clippy::overly_complex_bool_expr"), - #[clippy::version = ""] ("clippy::new_without_default_derive", "clippy::new_without_default"), - #[clippy::version = ""] ("clippy::option_and_then_some", "clippy::bind_instead_of_map"), - #[clippy::version = ""] ("clippy::option_expect_used", "clippy::expect_used"), - #[clippy::version = ""] ("clippy::option_map_unwrap_or", "clippy::map_unwrap_or"), - #[clippy::version = ""] ("clippy::option_map_unwrap_or_else", "clippy::map_unwrap_or"), - #[clippy::version = ""] ("clippy::option_unwrap_used", "clippy::unwrap_used"), - #[clippy::version = ""] ("clippy::overflow_check_conditional", "clippy::panicking_overflow_checks"), - #[clippy::version = ""] ("clippy::ref_in_deref", "clippy::needless_borrow"), - #[clippy::version = ""] ("clippy::result_expect_used", "clippy::expect_used"), - #[clippy::version = ""] ("clippy::result_map_unwrap_or_else", "clippy::map_unwrap_or"), - #[clippy::version = ""] ("clippy::result_unwrap_used", "clippy::unwrap_used"), - #[clippy::version = ""] ("clippy::single_char_push_str", "clippy::single_char_add_str"), - #[clippy::version = ""] ("clippy::stutter", "clippy::module_name_repetitions"), - #[clippy::version = ""] ("clippy::thread_local_initializer_can_be_made_const", "clippy::missing_const_for_thread_local"), - #[clippy::version = ""] ("clippy::to_string_in_display", "clippy::recursive_format_impl"), - #[clippy::version = ""] ("clippy::unwrap_or_else_default", "clippy::unwrap_or_default"), - #[clippy::version = ""] ("clippy::zero_width_space", "clippy::invisible_characters"), - #[clippy::version = ""] ("clippy::cast_ref_to_mut", "invalid_reference_casting"), - #[clippy::version = ""] ("clippy::clone_double_ref", "suspicious_double_ref_op"), - #[clippy::version = ""] ("clippy::cmp_nan", "invalid_nan_comparisons"), - #[clippy::version = "nightly"] ("clippy::double_neg", "double_negations"), - #[clippy::version = ""] ("clippy::drop_bounds", "drop_bounds"), - #[clippy::version = ""] ("clippy::drop_copy", "dropping_copy_types"), - #[clippy::version = ""] ("clippy::drop_ref", "dropping_references"), - #[clippy::version = ""] ("clippy::fn_null_check", "useless_ptr_null_checks"), - #[clippy::version = ""] ("clippy::for_loop_over_option", "for_loops_over_fallibles"), - #[clippy::version = ""] ("clippy::for_loop_over_result", "for_loops_over_fallibles"), - #[clippy::version = ""] ("clippy::for_loops_over_fallibles", "for_loops_over_fallibles"), - #[clippy::version = ""] ("clippy::forget_copy", "forgetting_copy_types"), - #[clippy::version = ""] ("clippy::forget_ref", "forgetting_references"), - #[clippy::version = ""] ("clippy::into_iter_on_array", "array_into_iter"), - #[clippy::version = ""] ("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"), - #[clippy::version = ""] ("clippy::invalid_ref", "invalid_value"), - #[clippy::version = ""] ("clippy::invalid_utf8_in_unchecked", "invalid_from_utf8_unchecked"), - #[clippy::version = ""] ("clippy::let_underscore_drop", "let_underscore_drop"), - #[clippy::version = "1.80.0"] ("clippy::maybe_misused_cfg", "unexpected_cfgs"), - #[clippy::version = ""] ("clippy::mem_discriminant_non_enum", "enum_intrinsics_non_enums"), - #[clippy::version = "1.80.0"] ("clippy::mismatched_target_os", "unexpected_cfgs"), - #[clippy::version = ""] ("clippy::panic_params", "non_fmt_panics"), - #[clippy::version = ""] ("clippy::positional_named_format_parameters", "named_arguments_used_positionally"), - #[clippy::version = ""] ("clippy::temporary_cstring_as_ptr", "dangling_pointers_from_temporaries"), - #[clippy::version = ""] ("clippy::undropped_manually_drops", "undropped_manually_drops"), - #[clippy::version = ""] ("clippy::unknown_clippy_lints", "unknown_lints"), - #[clippy::version = ""] ("clippy::unused_label", "unused_labels"), - #[clippy::version = ""] ("clippy::vtable_address_comparisons", "ambiguous_wide_pointer_comparisons"), - #[clippy::version = ""] ("clippy::reverse_range_loop", "clippy::reversed_empty_ranges"), // end renamed lints. used by `cargo dev rename_lint` -]} +]; diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index f00ae5a9731c..42e51c82323e 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -408,6 +408,7 @@ mod zombie_processes; use clippy_config::{Conf, get_configuration_metadata, sanitize_explanation}; use clippy_utils::macros::FormatArgsStorage; +use deprecated_lints::Deprecation; use rustc_data_structures::fx::FxHashSet; use rustc_lint::{Lint, LintId}; use utils::attr_collector::{AttrCollector, AttrStorage}; @@ -585,7 +586,7 @@ pub fn register_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) { for (old_name, new_name) in deprecated_lints::RENAMED { store.register_renamed(old_name, new_name); } - for (name, reason) in deprecated_lints::DEPRECATED { + for Deprecation { name, reason, .. } in deprecated_lints::DEPRECATED { store.register_removed(name, reason); } diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 837096d00620..a294a89be258 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -7,7 +7,7 @@ use cargo_metadata::diagnostic::{Applicability, Diagnostic}; use clippy_config::ClippyConfiguration; use clippy_lints::LintInfo; use clippy_lints::declared_lints::LINTS; -use clippy_lints::deprecated_lints::{DEPRECATED, DEPRECATED_VERSION, RENAMED}; +use clippy_lints::deprecated_lints::{DEPRECATED, Deprecation, RENAMED}; use pulldown_cmark::{Options, Parser, html}; use rinja::Template; use rinja::filters::Safe; @@ -24,7 +24,7 @@ use std::ffi::{OsStr, OsString}; use std::fmt::Write; use std::path::{Path, PathBuf}; use std::sync::mpsc::{Sender, channel}; -use std::{fs, iter, thread}; +use std::{fs, thread}; // Test dependencies may need an `extern crate` here to ensure that they show up // in the depinfo file (otherwise cargo thinks they are unused) @@ -466,10 +466,7 @@ impl DiagnosticCollector { let mut metadata: Vec = LINTS .iter() .map(|lint| LintMetadata::new(lint, &applicabilities, &configs)) - .chain( - iter::zip(DEPRECATED, DEPRECATED_VERSION) - .map(|((lint, reason), version)| LintMetadata::new_deprecated(lint, reason, version)), - ) + .chain(DEPRECATED.iter().copied().map(LintMetadata::new_deprecated)) .collect(); metadata.sort_unstable_by(|a, b| a.id.cmp(&b.id)); @@ -568,24 +565,25 @@ impl LintMetadata { } } - fn new_deprecated(name: &str, reason: &str, version: &'static str) -> Self { + fn new_deprecated(deprecated: Deprecation) -> Self { // The reason starts with a lowercase letter and ends without a period. // This needs to be fixed for the website. - let mut reason = reason.to_owned(); + let mut reason = deprecated.reason.to_owned(); if let Some(reason) = reason.get_mut(0..1) { reason.make_ascii_uppercase(); } Self { - id: name.strip_prefix("clippy::").unwrap().into(), + id: deprecated.name.strip_prefix("clippy::").unwrap().into(), id_location: None, group: "deprecated", level: "none", docs: format!( "### What it does\n\n\ Nothing. This lint has been deprecated\n\n\ - ### Deprecation reason\n\n{reason}.\n", + ### Deprecation reason\n\n{}.\n", + deprecated.reason, ), - version, + version: deprecated.version, applicability: Applicability::Unspecified, } } diff --git a/tests/lint-definitions.rs b/tests/lint-definitions.rs new file mode 100644 index 000000000000..80bbf8fd56cc --- /dev/null +++ b/tests/lint-definitions.rs @@ -0,0 +1,35 @@ +#![feature(rustc_private)] + +use clippy_lints::declared_lints::LINTS; +use clippy_lints::deprecated_lints::DEPRECATED; +use test_utils::IS_RUSTC_TEST_SUITE; + +mod test_utils; + +#[test] +fn no_nightly_versions_in_rust_repo() { + if !IS_RUSTC_TEST_SUITE { + return; + } + + let mut failed = false; + + for lint in LINTS { + if lint.version == Some("nightly") { + let name = lint.name_lower(); + let location = lint.location.replace("#L", ":"); + println!(r#"{location}: {name} has #[clippy::version = "nightly"]"#); + failed = true; + } + } + + for deprecation in DEPRECATED { + if deprecation.version == "nightly" { + let name = deprecation.name.strip_prefix("clippy::").unwrap(); + println!(r#"clippy_lints/src/deprecated_lints.rs: {name} has #[clippy::version = "nightly"]"#); + failed = true; + } + } + + assert!(!failed); +} diff --git a/tests/lint_message_convention.rs b/tests/lint-message-convention.rs similarity index 100% rename from tests/lint_message_convention.rs rename to tests/lint-message-convention.rs