From a7e8c891c5403ad9e8db3a79dd3dced1a8c214a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Orhun=20Parmaks=C4=B1z?= Date: Sat, 7 Dec 2024 21:40:19 +0300 Subject: [PATCH] feat: add pub_static_now_mutable lint (#1020) This new lint is for public static variables which might be mutable later on. This would require them to use an unsafe block which is breaking. --- src/lints/pub_static_now_mutable.ron | 51 +++++++++++++++++++ src/query.rs | 1 + .../pub_static_now_mutable/new/Cargo.toml | 7 +++ .../pub_static_now_mutable/new/src/lib.rs | 24 +++++++++ .../pub_static_now_mutable/old/Cargo.toml | 7 +++ .../pub_static_now_mutable/old/src/lib.rs | 25 +++++++++ .../query_execution/pub_static_missing.snap | 13 +++++ .../pub_static_now_mutable.snap | 18 +++++++ 8 files changed, 146 insertions(+) create mode 100644 src/lints/pub_static_now_mutable.ron create mode 100644 test_crates/pub_static_now_mutable/new/Cargo.toml create mode 100644 test_crates/pub_static_now_mutable/new/src/lib.rs create mode 100644 test_crates/pub_static_now_mutable/old/Cargo.toml create mode 100644 test_crates/pub_static_now_mutable/old/src/lib.rs create mode 100644 test_outputs/query_execution/pub_static_now_mutable.snap diff --git a/src/lints/pub_static_now_mutable.ron b/src/lints/pub_static_now_mutable.ron new file mode 100644 index 00000000..746700d3 --- /dev/null +++ b/src/lints/pub_static_now_mutable.ron @@ -0,0 +1,51 @@ +SemverQuery( + id: "pub_static_now_mutable", + human_readable_name: "pub static is now mutable", + description: "An immutable static became mutable and thus an unsafe block is required to use it", + required_update: Major, + lint_level: Deny, + reference_link: Some("https://google.github.io/comprehensive-rust/unsafe-rust/mutable-static.html"), + query: r#" + { + CrateDiff { + baseline { + item { + ... on Static { + visibility_limit @filter(op: "=", value: ["$public"]) + mutable @filter(op: "!=", value: ["$true"]) + + importable_path { + path @output @tag + public_api @filter(op: "=", value: ["$true"]) + } + } + } + } + current { + item { + ... on Static { + visibility_limit @filter(op: "=", value: ["$public"]) + mutable @filter(op: "=", value: ["$true"]) + static_name: name @output + + importable_path { + path @filter(op: "=", value: ["%path"]) + public_api @filter(op: "=", value: ["$true"]) + } + + span_: span @optional { + filename @output + begin_line @output + } + } + } + } + } + }"#, + arguments: { + "public": "public", + "true": true, + }, + error_message: "An immutable static is now mutable and thus an unsafe block is required to use it", + per_result_error_template: Some("{{static_name}} in file {{span_filename}}:{{span_begin_line}}"), +) diff --git a/src/query.rs b/src/query.rs index cba71674..419b22d7 100644 --- a/src/query.rs +++ b/src/query.rs @@ -1099,6 +1099,7 @@ add_lints!( pub_static_missing, pub_static_mut_now_immutable, pub_static_now_doc_hidden, + pub_static_now_mutable, repr_c_removed, repr_packed_added, repr_packed_removed, diff --git a/test_crates/pub_static_now_mutable/new/Cargo.toml b/test_crates/pub_static_now_mutable/new/Cargo.toml new file mode 100644 index 00000000..a6022262 --- /dev/null +++ b/test_crates/pub_static_now_mutable/new/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "pub_static_now_mutable" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/pub_static_now_mutable/new/src/lib.rs b/test_crates/pub_static_now_mutable/new/src/lib.rs new file mode 100644 index 00000000..d7bf086b --- /dev/null +++ b/test_crates/pub_static_now_mutable/new/src/lib.rs @@ -0,0 +1,24 @@ +// Basic Test cases +pub static mut STATIC_A: i32 = 0; +pub static mut STATIC_B: i32 = 0; +static mut STATIC_C: i32 = 0; + +// Test case for #[doc(hidden)] pub static +#[doc(hidden)] +pub static mut DOC_HIDDEN_STATIC_A: i32 = 0; + +// Renaming or making a static #[doc(hidden)] along with making it mutable +// should trigger only one lint +pub static mut DOC_HIDDEN_STATIC_B: i32 = 0; +pub static mut STATIC_RENAME: i32 = 0; + +// Testing for static defined in private module +mod PRIVATE_MODULE { + pub static mut STATIC_C: i32 = 0; +} + +// Testing for static defined in #[doc(hidden)] module +#[doc(hidden)] +pub mod DOC_HIDDEN_MODULE { + pub static mut STATIC_C: i32 = 0; +} diff --git a/test_crates/pub_static_now_mutable/old/Cargo.toml b/test_crates/pub_static_now_mutable/old/Cargo.toml new file mode 100644 index 00000000..a6022262 --- /dev/null +++ b/test_crates/pub_static_now_mutable/old/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "pub_static_now_mutable" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/pub_static_now_mutable/old/src/lib.rs b/test_crates/pub_static_now_mutable/old/src/lib.rs new file mode 100644 index 00000000..96d5536a --- /dev/null +++ b/test_crates/pub_static_now_mutable/old/src/lib.rs @@ -0,0 +1,25 @@ +// Basic Test cases +pub static STATIC_A: i32 = 0; +pub static mut STATIC_B: i32 = 0; +static STATIC_C: i32 = 0; + +// Test case for #[doc(hidden)] pub static +#[doc(hidden)] +pub static DOC_HIDDEN_STATIC_A: i32 = 0; + +// Renaming or making a static #[doc(hidden)] along with making it mutable +// should trigger only one lint +#[doc(hidden)] +pub static DOC_HIDDEN_STATIC_B: i32 = 0; +pub static STATIC_RENAMED: i32 = 0; + +// Testing for static defined in private module +mod PRIVATE_MODULE { + pub static STATIC_C: i32 = 0; +} + +// Testing for static defined in #[doc(hidden)] module +#[doc(hidden)] +pub mod DOC_HIDDEN_MODULE { + pub static STATIC_C: i32 = 0; +} diff --git a/test_outputs/query_execution/pub_static_missing.snap b/test_outputs/query_execution/pub_static_missing.snap index b8e60c0e..f4ad2b60 100644 --- a/test_outputs/query_execution/pub_static_missing.snap +++ b/test_outputs/query_execution/pub_static_missing.snap @@ -1,6 +1,7 @@ --- source: src/query.rs expression: "&query_execution_results" +snapshot_kind: text --- { "./test_crates/pub_static_missing/": [ @@ -149,4 +150,16 @@ expression: "&query_execution_results" "visibility_limit": String("public"), }, ], + "./test_crates/pub_static_now_mutable/": [ + { + "name": String("STATIC_RENAMED"), + "path": List([ + String("pub_static_now_mutable"), + String("STATIC_RENAMED"), + ]), + "span_begin_line": Uint64(14), + "span_filename": String("src/lib.rs"), + "visibility_limit": String("public"), + }, + ], } diff --git a/test_outputs/query_execution/pub_static_now_mutable.snap b/test_outputs/query_execution/pub_static_now_mutable.snap new file mode 100644 index 00000000..4f476c68 --- /dev/null +++ b/test_outputs/query_execution/pub_static_now_mutable.snap @@ -0,0 +1,18 @@ +--- +source: src/query.rs +expression: "&query_execution_results" +snapshot_kind: text +--- +{ + "./test_crates/pub_static_now_mutable/": [ + { + "path": List([ + String("pub_static_now_mutable"), + String("STATIC_A"), + ]), + "span_begin_line": Uint64(2), + "span_filename": String("src/lib.rs"), + "static_name": String("STATIC_A"), + }, + ], +}