From 3b50f084cae173a96d9233cdf3a1c8ecc808aa01 Mon Sep 17 00:00:00 2001 From: shreyans Date: Wed, 12 Mar 2025 03:35:15 +0530 Subject: [PATCH 1/5] Add lint. --- src/lints/enum_unmarked_non_exhaustive.ron | 47 +++++++++++++++++++ src/query.rs | 1 + .../new/Cargo.toml | 7 +++ .../new/src/lib.rs | 6 +++ .../old/Cargo.toml | 7 +++ .../old/src/lib.rs | 7 +++ .../enum_unmarked_non_exhaustive.snap | 42 +++++++++++++++++ 7 files changed, 117 insertions(+) create mode 100644 src/lints/enum_unmarked_non_exhaustive.ron create mode 100644 test_crates/enum_unmarked_non_exhaustive/new/Cargo.toml create mode 100644 test_crates/enum_unmarked_non_exhaustive/new/src/lib.rs create mode 100644 test_crates/enum_unmarked_non_exhaustive/old/Cargo.toml create mode 100644 test_crates/enum_unmarked_non_exhaustive/old/src/lib.rs create mode 100644 test_outputs/query_execution/enum_unmarked_non_exhaustive.snap diff --git a/src/lints/enum_unmarked_non_exhaustive.ron b/src/lints/enum_unmarked_non_exhaustive.ron new file mode 100644 index 00000000..05cf07ac --- /dev/null +++ b/src/lints/enum_unmarked_non_exhaustive.ron @@ -0,0 +1,47 @@ +SemverQuery( + id: "enum_unmarked_non_exhaustive", + human_readable_name: "enum unmarked #[non_exhaustive]", + description: "A Public API enum is no longer #[non_exhaustive]", + required_update: Minor, + lint_level: Allow, + reference_link: Some("https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute"), + query: r#" + { + CrateDiff { + current { + item { + ... on Enum { + visibility_limit @filter(op: "=", value: ["$public"]) @output + name @output @tag + attrs @filter(op: "not_contains", value: ["$non_exhaustive"]) + importable_path { + path @output @tag + } + span_: span @optional { + filename @output + begin_line @output + } + } + } + } + baseline { + item { + ... on Enum { + visibility_limit @filter(op: "=", value: ["$public"]) + name @filter(op: "=", value: ["%name"]) + attrs @filter(op: "contains", value: ["$non_exhaustive"]) + importable_path { + path @filter(op: "=", value: ["%path"]) + } + } + } + } + } + }"#, + arguments: { + "public": "public", + "non_exhaustive": "#[non_exhaustive]", + }, + error_message: "A Public API enum is no longer #[non_exhaustive]. External code may assume all variants are known, causing breaking changes if new ones are added.", + per_result_error_template: Some("enum {{name}} in {{span_filename}}:{{span_begin_line}}"), +) \ No newline at end of file diff --git a/src/query.rs b/src/query.rs index 43a8916d..8358cb1a 100644 --- a/src/query.rs +++ b/src/query.rs @@ -1246,6 +1246,7 @@ add_lints!( enum_tuple_variant_field_missing, enum_tuple_variant_field_now_doc_hidden, enum_unit_variant_changed_kind, + enum_unmarked_non_exhaustive, enum_variant_added, enum_variant_marked_deprecated, enum_variant_marked_non_exhaustive, diff --git a/test_crates/enum_unmarked_non_exhaustive/new/Cargo.toml b/test_crates/enum_unmarked_non_exhaustive/new/Cargo.toml new file mode 100644 index 00000000..592795fa --- /dev/null +++ b/test_crates/enum_unmarked_non_exhaustive/new/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "enum_unmarked_non_exhaustive" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/enum_unmarked_non_exhaustive/new/src/lib.rs b/test_crates/enum_unmarked_non_exhaustive/new/src/lib.rs new file mode 100644 index 00000000..c7fb1b8c --- /dev/null +++ b/test_crates/enum_unmarked_non_exhaustive/new/src/lib.rs @@ -0,0 +1,6 @@ +#![no_std] + +pub enum SimpleEnum { + VariantA, + VariantB, +} \ No newline at end of file diff --git a/test_crates/enum_unmarked_non_exhaustive/old/Cargo.toml b/test_crates/enum_unmarked_non_exhaustive/old/Cargo.toml new file mode 100644 index 00000000..592795fa --- /dev/null +++ b/test_crates/enum_unmarked_non_exhaustive/old/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "enum_unmarked_non_exhaustive" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/enum_unmarked_non_exhaustive/old/src/lib.rs b/test_crates/enum_unmarked_non_exhaustive/old/src/lib.rs new file mode 100644 index 00000000..c75edb1f --- /dev/null +++ b/test_crates/enum_unmarked_non_exhaustive/old/src/lib.rs @@ -0,0 +1,7 @@ +#![no_std] + +#[non_exhaustive] +pub enum SimpleEnum { + VariantA, + VariantB, +} \ No newline at end of file diff --git a/test_outputs/query_execution/enum_unmarked_non_exhaustive.snap b/test_outputs/query_execution/enum_unmarked_non_exhaustive.snap new file mode 100644 index 00000000..f59d139a --- /dev/null +++ b/test_outputs/query_execution/enum_unmarked_non_exhaustive.snap @@ -0,0 +1,42 @@ +--- +source: src/query.rs +expression: "&query_execution_results" +--- +{ + "./test_crates/enum_repr_variant_discriminant_changed/": [ + { + "name": String("DiscriminantIsChangedButAVariantIsNonExhaustive"), + "path": List([ + String("enum_repr_variant_discriminant_changed"), + String("DiscriminantIsChangedButAVariantIsNonExhaustive"), + ]), + "span_begin_line": Uint64(23), + "span_filename": String("src/lib.rs"), + "visibility_limit": String("public"), + }, + ], + "./test_crates/enum_unmarked_non_exhaustive/": [ + { + "name": String("SimpleEnum"), + "path": List([ + String("enum_unmarked_non_exhaustive"), + String("SimpleEnum"), + ]), + "span_begin_line": Uint64(3), + "span_filename": String("src/lib.rs"), + "visibility_limit": String("public"), + }, + ], + "./test_crates/type_mismatched_generic_lifetimes/": [ + { + "name": String("Either"), + "path": List([ + String("type_mismatched_generic_lifetimes"), + String("Either"), + ]), + "span_begin_line": Uint64(7), + "span_filename": String("src/lib.rs"), + "visibility_limit": String("public"), + }, + ], +} From 0743f8d16c0bb29471d6d331040ea0e4f38d7307 Mon Sep 17 00:00:00 2001 From: shreyans Date: Fri, 14 Mar 2025 04:35:52 +0530 Subject: [PATCH 2/5] Fixed trailing lines. --- src/lints/enum_unmarked_non_exhaustive.ron | 2 +- test_crates/enum_unmarked_non_exhaustive/new/src/lib.rs | 2 +- test_crates/enum_unmarked_non_exhaustive/old/src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lints/enum_unmarked_non_exhaustive.ron b/src/lints/enum_unmarked_non_exhaustive.ron index 05cf07ac..1bf98d88 100644 --- a/src/lints/enum_unmarked_non_exhaustive.ron +++ b/src/lints/enum_unmarked_non_exhaustive.ron @@ -44,4 +44,4 @@ SemverQuery( }, error_message: "A Public API enum is no longer #[non_exhaustive]. External code may assume all variants are known, causing breaking changes if new ones are added.", per_result_error_template: Some("enum {{name}} in {{span_filename}}:{{span_begin_line}}"), -) \ No newline at end of file +) diff --git a/test_crates/enum_unmarked_non_exhaustive/new/src/lib.rs b/test_crates/enum_unmarked_non_exhaustive/new/src/lib.rs index c7fb1b8c..a749e306 100644 --- a/test_crates/enum_unmarked_non_exhaustive/new/src/lib.rs +++ b/test_crates/enum_unmarked_non_exhaustive/new/src/lib.rs @@ -3,4 +3,4 @@ pub enum SimpleEnum { VariantA, VariantB, -} \ No newline at end of file +} diff --git a/test_crates/enum_unmarked_non_exhaustive/old/src/lib.rs b/test_crates/enum_unmarked_non_exhaustive/old/src/lib.rs index c75edb1f..bc4adf8d 100644 --- a/test_crates/enum_unmarked_non_exhaustive/old/src/lib.rs +++ b/test_crates/enum_unmarked_non_exhaustive/old/src/lib.rs @@ -4,4 +4,4 @@ pub enum SimpleEnum { VariantA, VariantB, -} \ No newline at end of file +} From e535e7b995f0821ed0d59c697e26f71da0b815ba Mon Sep 17 00:00:00 2001 From: shreyans Date: Fri, 21 Mar 2025 06:37:10 +0530 Subject: [PATCH 3/5] Improved readability of code --- src/lints/enum_unmarked_non_exhaustive.ron | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/lints/enum_unmarked_non_exhaustive.ron b/src/lints/enum_unmarked_non_exhaustive.ron index 1bf98d88..28ac200b 100644 --- a/src/lints/enum_unmarked_non_exhaustive.ron +++ b/src/lints/enum_unmarked_non_exhaustive.ron @@ -13,10 +13,13 @@ SemverQuery( ... on Enum { visibility_limit @filter(op: "=", value: ["$public"]) @output name @output @tag + attrs @filter(op: "not_contains", value: ["$non_exhaustive"]) + importable_path { path @output @tag } + span_: span @optional { filename @output begin_line @output @@ -29,7 +32,9 @@ SemverQuery( ... on Enum { visibility_limit @filter(op: "=", value: ["$public"]) name @filter(op: "=", value: ["%name"]) + attrs @filter(op: "contains", value: ["$non_exhaustive"]) + importable_path { path @filter(op: "=", value: ["%path"]) } From 0049cfbe62f47da7bb9d81214c4b6591afa0029e Mon Sep 17 00:00:00 2001 From: shreyans Date: Fri, 21 Mar 2025 08:10:00 +0530 Subject: [PATCH 4/5] Renamed the lint and fixed capitalization. --- ....ron => enum_no_longer_non_exhaustive.ron} | 12 +++++------ src/query.rs | 2 +- .../new/Cargo.toml | 2 +- .../new/src/lib.rs | 0 .../old/Cargo.toml | 2 +- .../old/src/lib.rs | 0 ...nap => enum_no_longer_non_exhaustive.snap} | 20 +++++++++---------- 7 files changed, 18 insertions(+), 20 deletions(-) rename src/lints/{enum_unmarked_non_exhaustive.ron => enum_no_longer_non_exhaustive.ron} (76%) rename test_crates/{enum_unmarked_non_exhaustive => enum_no_longer_non_exhaustive}/new/Cargo.toml (66%) rename test_crates/{enum_unmarked_non_exhaustive => enum_no_longer_non_exhaustive}/new/src/lib.rs (100%) rename test_crates/{enum_unmarked_non_exhaustive => enum_no_longer_non_exhaustive}/old/Cargo.toml (66%) rename test_crates/{enum_unmarked_non_exhaustive => enum_no_longer_non_exhaustive}/old/src/lib.rs (100%) rename test_outputs/query_execution/{enum_unmarked_non_exhaustive.snap => enum_no_longer_non_exhaustive.snap} (91%) diff --git a/src/lints/enum_unmarked_non_exhaustive.ron b/src/lints/enum_no_longer_non_exhaustive.ron similarity index 76% rename from src/lints/enum_unmarked_non_exhaustive.ron rename to src/lints/enum_no_longer_non_exhaustive.ron index 28ac200b..c5dcf928 100644 --- a/src/lints/enum_unmarked_non_exhaustive.ron +++ b/src/lints/enum_no_longer_non_exhaustive.ron @@ -1,7 +1,7 @@ SemverQuery( - id: "enum_unmarked_non_exhaustive", - human_readable_name: "enum unmarked #[non_exhaustive]", - description: "A Public API enum is no longer #[non_exhaustive]", + id: "enum_no_longer_non_exhaustive", + human_readable_name: "enum no longer #[non_exhaustive]", + description: "A pub enum is no longer #[non_exhaustive]", required_update: Minor, lint_level: Allow, reference_link: Some("https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute"), @@ -12,7 +12,7 @@ SemverQuery( item { ... on Enum { visibility_limit @filter(op: "=", value: ["$public"]) @output - name @output @tag + name @output attrs @filter(op: "not_contains", value: ["$non_exhaustive"]) @@ -31,8 +31,6 @@ SemverQuery( item { ... on Enum { visibility_limit @filter(op: "=", value: ["$public"]) - name @filter(op: "=", value: ["%name"]) - attrs @filter(op: "contains", value: ["$non_exhaustive"]) importable_path { @@ -47,6 +45,6 @@ SemverQuery( "public": "public", "non_exhaustive": "#[non_exhaustive]", }, - error_message: "A Public API enum is no longer #[non_exhaustive]. External code may assume all variants are known, causing breaking changes if new ones are added.", + error_message: "A pub enum is no longer #[non_exhaustive]. Pattern-matching outside its crate is now exhaustive, potentially causing breaking changes if new variants are added.", per_result_error_template: Some("enum {{name}} in {{span_filename}}:{{span_begin_line}}"), ) diff --git a/src/query.rs b/src/query.rs index 013308b9..dd33803d 100644 --- a/src/query.rs +++ b/src/query.rs @@ -1232,6 +1232,7 @@ add_lints!( enum_marked_non_exhaustive, enum_missing, enum_must_use_added, + enum_no_longer_non_exhaustive, enum_no_repr_variant_discriminant_changed, enum_now_doc_hidden, enum_repr_int_changed, @@ -1247,7 +1248,6 @@ add_lints!( enum_tuple_variant_field_missing, enum_tuple_variant_field_now_doc_hidden, enum_unit_variant_changed_kind, - enum_unmarked_non_exhaustive, enum_variant_added, enum_variant_marked_deprecated, enum_variant_marked_non_exhaustive, diff --git a/test_crates/enum_unmarked_non_exhaustive/new/Cargo.toml b/test_crates/enum_no_longer_non_exhaustive/new/Cargo.toml similarity index 66% rename from test_crates/enum_unmarked_non_exhaustive/new/Cargo.toml rename to test_crates/enum_no_longer_non_exhaustive/new/Cargo.toml index 592795fa..4dbb2138 100644 --- a/test_crates/enum_unmarked_non_exhaustive/new/Cargo.toml +++ b/test_crates/enum_no_longer_non_exhaustive/new/Cargo.toml @@ -1,6 +1,6 @@ [package] publish = false -name = "enum_unmarked_non_exhaustive" +name = "enum_no_longer_non_exhaustive" version = "0.1.0" edition = "2021" diff --git a/test_crates/enum_unmarked_non_exhaustive/new/src/lib.rs b/test_crates/enum_no_longer_non_exhaustive/new/src/lib.rs similarity index 100% rename from test_crates/enum_unmarked_non_exhaustive/new/src/lib.rs rename to test_crates/enum_no_longer_non_exhaustive/new/src/lib.rs diff --git a/test_crates/enum_unmarked_non_exhaustive/old/Cargo.toml b/test_crates/enum_no_longer_non_exhaustive/old/Cargo.toml similarity index 66% rename from test_crates/enum_unmarked_non_exhaustive/old/Cargo.toml rename to test_crates/enum_no_longer_non_exhaustive/old/Cargo.toml index 592795fa..4dbb2138 100644 --- a/test_crates/enum_unmarked_non_exhaustive/old/Cargo.toml +++ b/test_crates/enum_no_longer_non_exhaustive/old/Cargo.toml @@ -1,6 +1,6 @@ [package] publish = false -name = "enum_unmarked_non_exhaustive" +name = "enum_no_longer_non_exhaustive" version = "0.1.0" edition = "2021" diff --git a/test_crates/enum_unmarked_non_exhaustive/old/src/lib.rs b/test_crates/enum_no_longer_non_exhaustive/old/src/lib.rs similarity index 100% rename from test_crates/enum_unmarked_non_exhaustive/old/src/lib.rs rename to test_crates/enum_no_longer_non_exhaustive/old/src/lib.rs diff --git a/test_outputs/query_execution/enum_unmarked_non_exhaustive.snap b/test_outputs/query_execution/enum_no_longer_non_exhaustive.snap similarity index 91% rename from test_outputs/query_execution/enum_unmarked_non_exhaustive.snap rename to test_outputs/query_execution/enum_no_longer_non_exhaustive.snap index f59d139a..f7adc9e8 100644 --- a/test_outputs/query_execution/enum_unmarked_non_exhaustive.snap +++ b/test_outputs/query_execution/enum_no_longer_non_exhaustive.snap @@ -3,26 +3,26 @@ source: src/query.rs expression: "&query_execution_results" --- { - "./test_crates/enum_repr_variant_discriminant_changed/": [ + "./test_crates/enum_no_longer_non_exhaustive/": [ { - "name": String("DiscriminantIsChangedButAVariantIsNonExhaustive"), + "name": String("SimpleEnum"), "path": List([ - String("enum_repr_variant_discriminant_changed"), - String("DiscriminantIsChangedButAVariantIsNonExhaustive"), + String("enum_no_longer_non_exhaustive"), + String("SimpleEnum"), ]), - "span_begin_line": Uint64(23), + "span_begin_line": Uint64(3), "span_filename": String("src/lib.rs"), "visibility_limit": String("public"), }, ], - "./test_crates/enum_unmarked_non_exhaustive/": [ + "./test_crates/enum_repr_variant_discriminant_changed/": [ { - "name": String("SimpleEnum"), + "name": String("DiscriminantIsChangedButAVariantIsNonExhaustive"), "path": List([ - String("enum_unmarked_non_exhaustive"), - String("SimpleEnum"), + String("enum_repr_variant_discriminant_changed"), + String("DiscriminantIsChangedButAVariantIsNonExhaustive"), ]), - "span_begin_line": Uint64(3), + "span_begin_line": Uint64(23), "span_filename": String("src/lib.rs"), "visibility_limit": String("public"), }, From b0ac12d1f56ad86258489b27c3724086e654467f Mon Sep 17 00:00:00 2001 From: shreyans Date: Fri, 21 Mar 2025 09:14:32 +0530 Subject: [PATCH 5/5] Improved description of the lint and modified the test case. --- src/lints/enum_no_longer_non_exhaustive.ron | 2 +- test_crates/enum_no_longer_non_exhaustive/new/src/lib.rs | 5 ++--- test_crates/enum_no_longer_non_exhaustive/old/src/lib.rs | 5 ++--- .../query_execution/enum_no_longer_non_exhaustive.snap | 4 ++-- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/lints/enum_no_longer_non_exhaustive.ron b/src/lints/enum_no_longer_non_exhaustive.ron index c5dcf928..9008ca60 100644 --- a/src/lints/enum_no_longer_non_exhaustive.ron +++ b/src/lints/enum_no_longer_non_exhaustive.ron @@ -1,7 +1,7 @@ SemverQuery( id: "enum_no_longer_non_exhaustive", human_readable_name: "enum no longer #[non_exhaustive]", - description: "A pub enum is no longer #[non_exhaustive]", + description: "A pub enum is no longer #[non_exhaustive]. Pattern-matching outside its crate is now exhaustive, potentially causing breaking changes if new variants are added.", required_update: Minor, lint_level: Allow, reference_link: Some("https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute"), diff --git a/test_crates/enum_no_longer_non_exhaustive/new/src/lib.rs b/test_crates/enum_no_longer_non_exhaustive/new/src/lib.rs index a749e306..4b4ac7e2 100644 --- a/test_crates/enum_no_longer_non_exhaustive/new/src/lib.rs +++ b/test_crates/enum_no_longer_non_exhaustive/new/src/lib.rs @@ -1,6 +1,5 @@ #![no_std] -pub enum SimpleEnum { - VariantA, - VariantB, +pub enum NonExhaustiveEnum { + Variant, } diff --git a/test_crates/enum_no_longer_non_exhaustive/old/src/lib.rs b/test_crates/enum_no_longer_non_exhaustive/old/src/lib.rs index bc4adf8d..1c410a7c 100644 --- a/test_crates/enum_no_longer_non_exhaustive/old/src/lib.rs +++ b/test_crates/enum_no_longer_non_exhaustive/old/src/lib.rs @@ -1,7 +1,6 @@ #![no_std] #[non_exhaustive] -pub enum SimpleEnum { - VariantA, - VariantB, +pub enum NonExhaustiveEnum { + Variant, } diff --git a/test_outputs/query_execution/enum_no_longer_non_exhaustive.snap b/test_outputs/query_execution/enum_no_longer_non_exhaustive.snap index f7adc9e8..af4c9f10 100644 --- a/test_outputs/query_execution/enum_no_longer_non_exhaustive.snap +++ b/test_outputs/query_execution/enum_no_longer_non_exhaustive.snap @@ -5,10 +5,10 @@ expression: "&query_execution_results" { "./test_crates/enum_no_longer_non_exhaustive/": [ { - "name": String("SimpleEnum"), + "name": String("NonExhaustiveEnum"), "path": List([ String("enum_no_longer_non_exhaustive"), - String("SimpleEnum"), + String("NonExhaustiveEnum"), ]), "span_begin_line": Uint64(3), "span_filename": String("src/lib.rs"),