From a4a71ae5c085cf797dcb88dab3844d1959baa839 Mon Sep 17 00:00:00 2001 From: shreyans Date: Wed, 12 Mar 2025 16:16:40 +0530 Subject: [PATCH 1/6] Add enum_variant_unmarked_non_exhaustive lint. --- .../enum_variant_unmarked_non_exhaustive.ron | 64 +++++++++++++++++++ src/query.rs | 1 + .../new/Cargo.toml | 7 ++ .../new/src/lib.rs | 20 ++++++ .../old/Cargo.toml | 7 ++ .../old/src/lib.rs | 23 +++++++ .../enum_variant_unmarked_non_exhaustive.snap | 48 ++++++++++++++ 7 files changed, 170 insertions(+) create mode 100644 src/lints/enum_variant_unmarked_non_exhaustive.ron create mode 100644 test_crates/enum_variant_unmarked_non_exhaustive/new/Cargo.toml create mode 100644 test_crates/enum_variant_unmarked_non_exhaustive/new/src/lib.rs create mode 100644 test_crates/enum_variant_unmarked_non_exhaustive/old/Cargo.toml create mode 100644 test_crates/enum_variant_unmarked_non_exhaustive/old/src/lib.rs create mode 100644 test_outputs/query_execution/enum_variant_unmarked_non_exhaustive.snap diff --git a/src/lints/enum_variant_unmarked_non_exhaustive.ron b/src/lints/enum_variant_unmarked_non_exhaustive.ron new file mode 100644 index 00000000..4cc25e13 --- /dev/null +++ b/src/lints/enum_variant_unmarked_non_exhaustive.ron @@ -0,0 +1,64 @@ +SemverQuery( + id: "enum_variant_unmarked_non_exhaustive", + human_readable_name: "enum variant unmarked #[non_exhaustive]", + description: "A Public API enum variant 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 { + baseline { + item { + ... on Enum { + visibility_limit @filter(op: "=", value: ["$public"]) @output + attrs @filter(op: "not_contains", value: ["$non_exhaustive"]) + + importable_path { + path @output @tag + public_api @filter(op: "=", value: ["$true"]) + } + + variant { + variant_name: name @output @tag + public_api_eligible @filter(op: "=", value: ["$true"]) + attrs @filter(op: "contains", value: ["$non_exhaustive"]) + } + } + } + } + current { + item { + ... on Enum { + visibility_limit @filter(op: "=", value: ["$public"]) + name @output + + importable_path { + path @filter(op: "=", value: ["%path"]) + public_api @filter(op: "=", value: ["$true"]) + } + + variant { + name @filter(op: "=", value: ["%variant_name"]) + public_api_eligible @filter(op: "=", value: ["$true"]) + attrs @filter(op: "not_contains", value: ["$non_exhaustive"]) + + span_: span @optional { + filename @output + begin_line @output + end_line @output + } + } + } + } + } + } + }"#, + arguments: { + "public": "public", + "non_exhaustive": "#[non_exhaustive]", + "true": true, + }, + error_message: "The #[non_exhaustive] attribute has been removed from a variant of a public enum, forcing exhaustive pattern matching in downstream crates.", + per_result_error_template: Some("variant {{name}}:{{variant_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..245d54e4 100644 --- a/src/query.rs +++ b/src/query.rs @@ -1250,6 +1250,7 @@ add_lints!( enum_variant_marked_deprecated, enum_variant_marked_non_exhaustive, enum_variant_missing, + enum_variant_unmarked_non_exhaustive, exported_function_changed_abi, feature_missing, feature_not_enabled_by_default, diff --git a/test_crates/enum_variant_unmarked_non_exhaustive/new/Cargo.toml b/test_crates/enum_variant_unmarked_non_exhaustive/new/Cargo.toml new file mode 100644 index 00000000..21e7cef0 --- /dev/null +++ b/test_crates/enum_variant_unmarked_non_exhaustive/new/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "enum_variant_unmarked_non_exhaustive" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/enum_variant_unmarked_non_exhaustive/new/src/lib.rs b/test_crates/enum_variant_unmarked_non_exhaustive/new/src/lib.rs new file mode 100644 index 00000000..eb8506e2 --- /dev/null +++ b/test_crates/enum_variant_unmarked_non_exhaustive/new/src/lib.rs @@ -0,0 +1,20 @@ +#![no_std] + +pub enum ExhaustiveEnum { + VariantA, + VariantB, +} + +// This enum is already non-exhaustive +// Changes to its variants should not trigger the lint +#[non_exhaustive] +pub enum NonExhaustiveEnum { + Variant1, + Variant2, +} + +// This enum is private and should not trigger the lint +enum PrivateEnum { + VariantX, + VariantY, +} \ No newline at end of file diff --git a/test_crates/enum_variant_unmarked_non_exhaustive/old/Cargo.toml b/test_crates/enum_variant_unmarked_non_exhaustive/old/Cargo.toml new file mode 100644 index 00000000..21e7cef0 --- /dev/null +++ b/test_crates/enum_variant_unmarked_non_exhaustive/old/Cargo.toml @@ -0,0 +1,7 @@ +[package] +publish = false +name = "enum_variant_unmarked_non_exhaustive" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/test_crates/enum_variant_unmarked_non_exhaustive/old/src/lib.rs b/test_crates/enum_variant_unmarked_non_exhaustive/old/src/lib.rs new file mode 100644 index 00000000..b6ae06a0 --- /dev/null +++ b/test_crates/enum_variant_unmarked_non_exhaustive/old/src/lib.rs @@ -0,0 +1,23 @@ +#![no_std] + +pub enum ExhaustiveEnum { + #[non_exhaustive] + VariantA, + VariantB, +} + +// This enum is already non-exhaustive +// Changes to its variants should not trigger the lint +#[non_exhaustive] +pub enum NonExhaustiveEnum { + #[non_exhaustive] + Variant1, + Variant2, +} + +// This enum is private and should not trigger the lint +enum PrivateEnum { + #[non_exhaustive] + VariantX, + VariantY, +} \ No newline at end of file diff --git a/test_outputs/query_execution/enum_variant_unmarked_non_exhaustive.snap b/test_outputs/query_execution/enum_variant_unmarked_non_exhaustive.snap new file mode 100644 index 00000000..0110a9ab --- /dev/null +++ b/test_outputs/query_execution/enum_variant_unmarked_non_exhaustive.snap @@ -0,0 +1,48 @@ +--- +source: src/query.rs +expression: "&query_execution_results" +--- +{ + "./test_crates/enum_no_repr_variant_discriminant_changed/": [ + { + "name": String("DiscriminantIsChangedAndVariantNoLongerNonExhaustive"), + "path": List([ + String("enum_no_repr_variant_discriminant_changed"), + String("DiscriminantIsChangedAndVariantNoLongerNonExhaustive"), + ]), + "span_begin_line": Uint64(103), + "span_end_line": Uint64(103), + "span_filename": String("src/lib.rs"), + "variant_name": String("First"), + "visibility_limit": String("public"), + }, + ], + "./test_crates/enum_tuple_variant_field_added/": [ + { + "name": String("PublicEnum"), + "path": List([ + String("enum_tuple_variant_field_added"), + String("PublicEnum"), + ]), + "span_begin_line": Uint64(10), + "span_end_line": Uint64(10), + "span_filename": String("src/lib.rs"), + "variant_name": String("TupleVariantWithFieldAddedBecomesExhaustive"), + "visibility_limit": String("public"), + }, + ], + "./test_crates/enum_variant_unmarked_non_exhaustive/": [ + { + "name": String("ExhaustiveEnum"), + "path": List([ + String("enum_variant_unmarked_non_exhaustive"), + String("ExhaustiveEnum"), + ]), + "span_begin_line": Uint64(4), + "span_end_line": Uint64(4), + "span_filename": String("src/lib.rs"), + "variant_name": String("VariantA"), + "visibility_limit": String("public"), + }, + ], +} From 4b973dc7225f19ba0212cea26695245592bbdeb4 Mon Sep 17 00:00:00 2001 From: shreyans Date: Fri, 14 Mar 2025 04:38:58 +0530 Subject: [PATCH 2/6] Fixed trailing lines. --- src/lints/enum_variant_unmarked_non_exhaustive.ron | 2 +- test_crates/enum_variant_unmarked_non_exhaustive/new/src/lib.rs | 2 +- test_crates/enum_variant_unmarked_non_exhaustive/old/src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lints/enum_variant_unmarked_non_exhaustive.ron b/src/lints/enum_variant_unmarked_non_exhaustive.ron index 4cc25e13..60cd4b20 100644 --- a/src/lints/enum_variant_unmarked_non_exhaustive.ron +++ b/src/lints/enum_variant_unmarked_non_exhaustive.ron @@ -61,4 +61,4 @@ SemverQuery( }, error_message: "The #[non_exhaustive] attribute has been removed from a variant of a public enum, forcing exhaustive pattern matching in downstream crates.", per_result_error_template: Some("variant {{name}}:{{variant_name}} in {{span_filename}}:{{span_begin_line}}"), -) \ No newline at end of file +) diff --git a/test_crates/enum_variant_unmarked_non_exhaustive/new/src/lib.rs b/test_crates/enum_variant_unmarked_non_exhaustive/new/src/lib.rs index eb8506e2..0c3888e2 100644 --- a/test_crates/enum_variant_unmarked_non_exhaustive/new/src/lib.rs +++ b/test_crates/enum_variant_unmarked_non_exhaustive/new/src/lib.rs @@ -17,4 +17,4 @@ pub enum NonExhaustiveEnum { enum PrivateEnum { VariantX, VariantY, -} \ No newline at end of file +} diff --git a/test_crates/enum_variant_unmarked_non_exhaustive/old/src/lib.rs b/test_crates/enum_variant_unmarked_non_exhaustive/old/src/lib.rs index b6ae06a0..c8008136 100644 --- a/test_crates/enum_variant_unmarked_non_exhaustive/old/src/lib.rs +++ b/test_crates/enum_variant_unmarked_non_exhaustive/old/src/lib.rs @@ -20,4 +20,4 @@ enum PrivateEnum { #[non_exhaustive] VariantX, VariantY, -} \ No newline at end of file +} From 0eeca4a93fd70ad594c83e65b1e97690cdc1f438 Mon Sep 17 00:00:00 2001 From: shreyans Date: Fri, 21 Mar 2025 10:34:42 +0530 Subject: [PATCH 3/6] Renamed the lint, updated description and error message, modified test cases --- ...enum_variant_no_longer_non_exhaustive.ron} | 9 ++++----- src/query.rs | 2 +- .../new/Cargo.toml | 2 +- .../new/src/lib.rs | 15 ++++++++++++++ .../old/Cargo.toml | 2 +- .../old/src/lib.rs | 11 +++------- .../new/src/lib.rs | 20 ------------------- ...num_variant_no_longer_non_exhaustive.snap} | 18 ++++++++++++++--- 8 files changed, 40 insertions(+), 39 deletions(-) rename src/lints/{enum_variant_unmarked_non_exhaustive.ron => enum_variant_no_longer_non_exhaustive.ron} (83%) rename test_crates/{enum_variant_unmarked_non_exhaustive => enum_variant_no_longer_non_exhaustive}/new/Cargo.toml (62%) create mode 100644 test_crates/enum_variant_no_longer_non_exhaustive/new/src/lib.rs rename test_crates/{enum_variant_unmarked_non_exhaustive => enum_variant_no_longer_non_exhaustive}/old/Cargo.toml (62%) rename test_crates/{enum_variant_unmarked_non_exhaustive => enum_variant_no_longer_non_exhaustive}/old/src/lib.rs (56%) delete mode 100644 test_crates/enum_variant_unmarked_non_exhaustive/new/src/lib.rs rename test_outputs/query_execution/{enum_variant_unmarked_non_exhaustive.snap => enum_variant_no_longer_non_exhaustive.snap} (71%) diff --git a/src/lints/enum_variant_unmarked_non_exhaustive.ron b/src/lints/enum_variant_no_longer_non_exhaustive.ron similarity index 83% rename from src/lints/enum_variant_unmarked_non_exhaustive.ron rename to src/lints/enum_variant_no_longer_non_exhaustive.ron index 60cd4b20..bf8b9fa1 100644 --- a/src/lints/enum_variant_unmarked_non_exhaustive.ron +++ b/src/lints/enum_variant_no_longer_non_exhaustive.ron @@ -1,7 +1,7 @@ SemverQuery( - id: "enum_variant_unmarked_non_exhaustive", - human_readable_name: "enum variant unmarked #[non_exhaustive]", - description: "A Public API enum variant is no longer #[non_exhaustive]", + id: "enum_variant_no_longer_non_exhaustive", + human_readable_name: "enum variant no longer #[non_exhaustive]", + description: "A pub enum variant is no longer #[non_exhaustive], potentially causing breaking changes if new fields 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"), @@ -12,7 +12,6 @@ SemverQuery( item { ... on Enum { visibility_limit @filter(op: "=", value: ["$public"]) @output - attrs @filter(op: "not_contains", value: ["$non_exhaustive"]) importable_path { path @output @tag @@ -59,6 +58,6 @@ SemverQuery( "non_exhaustive": "#[non_exhaustive]", "true": true, }, - error_message: "The #[non_exhaustive] attribute has been removed from a variant of a public enum, forcing exhaustive pattern matching in downstream crates.", + error_message: "A pub enum variant is no longer #[non_exhaustive], potentially causing breaking changes if new fields are added.", per_result_error_template: Some("variant {{name}}:{{variant_name}} in {{span_filename}}:{{span_begin_line}}"), ) diff --git a/src/query.rs b/src/query.rs index 245d54e4..08a98651 100644 --- a/src/query.rs +++ b/src/query.rs @@ -1250,7 +1250,7 @@ add_lints!( enum_variant_marked_deprecated, enum_variant_marked_non_exhaustive, enum_variant_missing, - enum_variant_unmarked_non_exhaustive, + enum_variant_no_longer_non_exhaustive, exported_function_changed_abi, feature_missing, feature_not_enabled_by_default, diff --git a/test_crates/enum_variant_unmarked_non_exhaustive/new/Cargo.toml b/test_crates/enum_variant_no_longer_non_exhaustive/new/Cargo.toml similarity index 62% rename from test_crates/enum_variant_unmarked_non_exhaustive/new/Cargo.toml rename to test_crates/enum_variant_no_longer_non_exhaustive/new/Cargo.toml index 21e7cef0..518a2d47 100644 --- a/test_crates/enum_variant_unmarked_non_exhaustive/new/Cargo.toml +++ b/test_crates/enum_variant_no_longer_non_exhaustive/new/Cargo.toml @@ -1,6 +1,6 @@ [package] publish = false -name = "enum_variant_unmarked_non_exhaustive" +name = "enum_variant_no_longer_non_exhaustive" version = "0.1.0" edition = "2021" diff --git a/test_crates/enum_variant_no_longer_non_exhaustive/new/src/lib.rs b/test_crates/enum_variant_no_longer_non_exhaustive/new/src/lib.rs new file mode 100644 index 00000000..4708344e --- /dev/null +++ b/test_crates/enum_variant_no_longer_non_exhaustive/new/src/lib.rs @@ -0,0 +1,15 @@ +#![no_std] + +pub enum ExhaustiveEnum { + Variant, +} + +#[non_exhaustive] +pub enum NonExhaustiveEnum { + Variant, +} + +// This enum is private and should not trigger the lint +enum PrivateEnum { + Variant, +} diff --git a/test_crates/enum_variant_unmarked_non_exhaustive/old/Cargo.toml b/test_crates/enum_variant_no_longer_non_exhaustive/old/Cargo.toml similarity index 62% rename from test_crates/enum_variant_unmarked_non_exhaustive/old/Cargo.toml rename to test_crates/enum_variant_no_longer_non_exhaustive/old/Cargo.toml index 21e7cef0..518a2d47 100644 --- a/test_crates/enum_variant_unmarked_non_exhaustive/old/Cargo.toml +++ b/test_crates/enum_variant_no_longer_non_exhaustive/old/Cargo.toml @@ -1,6 +1,6 @@ [package] publish = false -name = "enum_variant_unmarked_non_exhaustive" +name = "enum_variant_no_longer_non_exhaustive" version = "0.1.0" edition = "2021" diff --git a/test_crates/enum_variant_unmarked_non_exhaustive/old/src/lib.rs b/test_crates/enum_variant_no_longer_non_exhaustive/old/src/lib.rs similarity index 56% rename from test_crates/enum_variant_unmarked_non_exhaustive/old/src/lib.rs rename to test_crates/enum_variant_no_longer_non_exhaustive/old/src/lib.rs index c8008136..7c665e3e 100644 --- a/test_crates/enum_variant_unmarked_non_exhaustive/old/src/lib.rs +++ b/test_crates/enum_variant_no_longer_non_exhaustive/old/src/lib.rs @@ -2,22 +2,17 @@ pub enum ExhaustiveEnum { #[non_exhaustive] - VariantA, - VariantB, + Variant, } -// This enum is already non-exhaustive -// Changes to its variants should not trigger the lint #[non_exhaustive] pub enum NonExhaustiveEnum { #[non_exhaustive] - Variant1, - Variant2, + Variant, } // This enum is private and should not trigger the lint enum PrivateEnum { #[non_exhaustive] - VariantX, - VariantY, + Variant, } diff --git a/test_crates/enum_variant_unmarked_non_exhaustive/new/src/lib.rs b/test_crates/enum_variant_unmarked_non_exhaustive/new/src/lib.rs deleted file mode 100644 index 0c3888e2..00000000 --- a/test_crates/enum_variant_unmarked_non_exhaustive/new/src/lib.rs +++ /dev/null @@ -1,20 +0,0 @@ -#![no_std] - -pub enum ExhaustiveEnum { - VariantA, - VariantB, -} - -// This enum is already non-exhaustive -// Changes to its variants should not trigger the lint -#[non_exhaustive] -pub enum NonExhaustiveEnum { - Variant1, - Variant2, -} - -// This enum is private and should not trigger the lint -enum PrivateEnum { - VariantX, - VariantY, -} diff --git a/test_outputs/query_execution/enum_variant_unmarked_non_exhaustive.snap b/test_outputs/query_execution/enum_variant_no_longer_non_exhaustive.snap similarity index 71% rename from test_outputs/query_execution/enum_variant_unmarked_non_exhaustive.snap rename to test_outputs/query_execution/enum_variant_no_longer_non_exhaustive.snap index 0110a9ab..530a19f3 100644 --- a/test_outputs/query_execution/enum_variant_unmarked_non_exhaustive.snap +++ b/test_outputs/query_execution/enum_variant_no_longer_non_exhaustive.snap @@ -31,17 +31,29 @@ expression: "&query_execution_results" "visibility_limit": String("public"), }, ], - "./test_crates/enum_variant_unmarked_non_exhaustive/": [ + "./test_crates/enum_variant_no_longer_non_exhaustive/": [ { "name": String("ExhaustiveEnum"), "path": List([ - String("enum_variant_unmarked_non_exhaustive"), + String("enum_variant_no_longer_non_exhaustive"), String("ExhaustiveEnum"), ]), "span_begin_line": Uint64(4), "span_end_line": Uint64(4), "span_filename": String("src/lib.rs"), - "variant_name": String("VariantA"), + "variant_name": String("Variant"), + "visibility_limit": String("public"), + }, + { + "name": String("NonExhaustiveEnum"), + "path": List([ + String("enum_variant_no_longer_non_exhaustive"), + String("NonExhaustiveEnum"), + ]), + "span_begin_line": Uint64(9), + "span_end_line": Uint64(9), + "span_filename": String("src/lib.rs"), + "variant_name": String("Variant"), "visibility_limit": String("public"), }, ], From 30473b4b6ef6f9bb748cea6a20bfd45775dac24e Mon Sep 17 00:00:00 2001 From: shreyans Date: Fri, 21 Mar 2025 10:48:30 +0530 Subject: [PATCH 4/6] used enum_name to output name of the enum --- src/lints/enum_variant_no_longer_non_exhaustive.ron | 4 ++-- .../enum_variant_no_longer_non_exhaustive.snap | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/lints/enum_variant_no_longer_non_exhaustive.ron b/src/lints/enum_variant_no_longer_non_exhaustive.ron index bf8b9fa1..df79e1c9 100644 --- a/src/lints/enum_variant_no_longer_non_exhaustive.ron +++ b/src/lints/enum_variant_no_longer_non_exhaustive.ron @@ -30,7 +30,7 @@ SemverQuery( item { ... on Enum { visibility_limit @filter(op: "=", value: ["$public"]) - name @output + enum_name: name @output importable_path { path @filter(op: "=", value: ["%path"]) @@ -59,5 +59,5 @@ SemverQuery( "true": true, }, error_message: "A pub enum variant is no longer #[non_exhaustive], potentially causing breaking changes if new fields are added.", - per_result_error_template: Some("variant {{name}}:{{variant_name}} in {{span_filename}}:{{span_begin_line}}"), + per_result_error_template: Some("variant {{enum_name}}:{{variant_name}} in {{span_filename}}:{{span_begin_line}}"), ) diff --git a/test_outputs/query_execution/enum_variant_no_longer_non_exhaustive.snap b/test_outputs/query_execution/enum_variant_no_longer_non_exhaustive.snap index 530a19f3..06604672 100644 --- a/test_outputs/query_execution/enum_variant_no_longer_non_exhaustive.snap +++ b/test_outputs/query_execution/enum_variant_no_longer_non_exhaustive.snap @@ -5,7 +5,7 @@ expression: "&query_execution_results" { "./test_crates/enum_no_repr_variant_discriminant_changed/": [ { - "name": String("DiscriminantIsChangedAndVariantNoLongerNonExhaustive"), + "enum_name": String("DiscriminantIsChangedAndVariantNoLongerNonExhaustive"), "path": List([ String("enum_no_repr_variant_discriminant_changed"), String("DiscriminantIsChangedAndVariantNoLongerNonExhaustive"), @@ -19,7 +19,7 @@ expression: "&query_execution_results" ], "./test_crates/enum_tuple_variant_field_added/": [ { - "name": String("PublicEnum"), + "enum_name": String("PublicEnum"), "path": List([ String("enum_tuple_variant_field_added"), String("PublicEnum"), @@ -33,7 +33,7 @@ expression: "&query_execution_results" ], "./test_crates/enum_variant_no_longer_non_exhaustive/": [ { - "name": String("ExhaustiveEnum"), + "enum_name": String("ExhaustiveEnum"), "path": List([ String("enum_variant_no_longer_non_exhaustive"), String("ExhaustiveEnum"), @@ -45,7 +45,7 @@ expression: "&query_execution_results" "visibility_limit": String("public"), }, { - "name": String("NonExhaustiveEnum"), + "enum_name": String("NonExhaustiveEnum"), "path": List([ String("enum_variant_no_longer_non_exhaustive"), String("NonExhaustiveEnum"), From 5dcfd9b566f3f6219d0ac3646fd62c158f2d0e43 Mon Sep 17 00:00:00 2001 From: shreyans Date: Fri, 21 Mar 2025 11:40:04 +0530 Subject: [PATCH 5/6] Added more test cases --- .../new/src/lib.rs | 57 +++++++++- .../old/src/lib.rs | 67 ++++++++++- ...enum_variant_no_longer_non_exhaustive.snap | 104 ++++++++++++++++-- 3 files changed, 212 insertions(+), 16 deletions(-) diff --git a/test_crates/enum_variant_no_longer_non_exhaustive/new/src/lib.rs b/test_crates/enum_variant_no_longer_non_exhaustive/new/src/lib.rs index 4708344e..ea1a6bf2 100644 --- a/test_crates/enum_variant_no_longer_non_exhaustive/new/src/lib.rs +++ b/test_crates/enum_variant_no_longer_non_exhaustive/new/src/lib.rs @@ -1,14 +1,65 @@ #![no_std] -pub enum ExhaustiveEnum { - Variant, +// This pub enum's variant is no longer #[non_exhaustive], should trigger the lint. +pub enum ExhaustiveEnumUnitVariant { + UnitVariant, +} + +// This pub enum's variant is no longer #[non_exhaustive], should trigger the lint. +#[non_exhaustive] +pub enum NonExhaustiveEnumUnitVariant { + UnitVariant, +} + +// This pub enum's variant is no longer #[non_exhaustive], should trigger the lint. +pub enum ExhaustiveEnumTupleVariant { + TupleVariant(i32, i64), } +// This pub enum's variant is no longer #[non_exhaustive], should trigger the lint. #[non_exhaustive] -pub enum NonExhaustiveEnum { +pub enum NonExhaustiveEnumTupleVariant { + TupleVariant(i32, i64), +} + +// This pub enum's variant is no longer #[non_exhaustive], should trigger the lint. +pub enum ExhaustiveEnumStructVariant { + StructVariant { f: i32 }, +} + +// This pub enum's variant is no longer #[non_exhaustive], should trigger the lint. +#[non_exhaustive] +pub enum NonExhaustiveEnumStructVariant { + StructVariant { f: i32 }, +} + +// This enum has a mix of variant types to test different variant kinds +pub enum MixedVariantKinds { + // Unit variant to be no longer #[non_exhaustive] + UnitVariant, + // Tuple variant to be no longer #[non_exhaustive] + TupleVariant(i32, i64), + // Struct variant to be no longer #[non_exhaustive] + StructVariant { field1: bool, field2: u32 }, +} + +// This enum's variant is already exhaustive and should not trigger the lint. +pub enum EnumWithAlreadyExhaustiveVariant { + ExhaustiveVariant, +} + +// This enum is hidden with #[doc(hidden)] and should not trigger the lint +#[doc(hidden)] +pub enum HiddenEnum { Variant, } +// This enum has a hidden variant that should not trigger the lint +pub enum EnumWithHiddenVariant { + #[doc(hidden)] + HiddenVariantToBeExhaustive, +} + // This enum is private and should not trigger the lint enum PrivateEnum { Variant, diff --git a/test_crates/enum_variant_no_longer_non_exhaustive/old/src/lib.rs b/test_crates/enum_variant_no_longer_non_exhaustive/old/src/lib.rs index 7c665e3e..c9a53f39 100644 --- a/test_crates/enum_variant_no_longer_non_exhaustive/old/src/lib.rs +++ b/test_crates/enum_variant_no_longer_non_exhaustive/old/src/lib.rs @@ -1,16 +1,77 @@ #![no_std] -pub enum ExhaustiveEnum { +// This pub enum's variant is no longer #[non_exhaustive], should trigger the lint. +pub enum ExhaustiveEnumUnitVariant { #[non_exhaustive] - Variant, + UnitVariant, +} + +// This pub enum's variant is no longer #[non_exhaustive], should trigger the lint. +#[non_exhaustive] +pub enum NonExhaustiveEnumUnitVariant { + #[non_exhaustive] + UnitVariant, +} + +// This pub enum's variant is no longer #[non_exhaustive], should trigger the lint. +pub enum ExhaustiveEnumTupleVariant { + #[non_exhaustive] + TupleVariant(i32, i64), +} + +// This pub enum's variant is no longer #[non_exhaustive], should trigger the lint. +#[non_exhaustive] +pub enum NonExhaustiveEnumTupleVariant { + #[non_exhaustive] + TupleVariant(i32, i64), +} + +// This pub enum's variant is no longer #[non_exhaustive], should trigger the lint. +pub enum ExhaustiveEnumStructVariant { + #[non_exhaustive] + StructVariant { f: i32 }, } +// This pub enum's variant is no longer #[non_exhaustive], should trigger the lint. #[non_exhaustive] -pub enum NonExhaustiveEnum { +pub enum NonExhaustiveEnumStructVariant { + #[non_exhaustive] + StructVariant { f: i32 }, +} + +// This enum has a mix of variant types to test different variant kinds +pub enum MixedVariantKinds { + // Unit variant to be no longer #[non_exhaustive] + #[non_exhaustive] + UnitVariant, + // Tuple variant to be no longer #[non_exhaustive] + #[non_exhaustive] + TupleVariant(i32, i64), + // Struct variant to be no longer #[non_exhaustive] + #[non_exhaustive] + StructVariant { field1: bool, field2: u32 }, +} + +// This enum's variant is already exhaustive and should not trigger the lint. +pub enum EnumWithAlreadyExhaustiveVariant { + ExhaustiveVariant, +} + + +// This enum is hidden with #[doc(hidden)] and should not trigger the lint +#[doc(hidden)] +pub enum HiddenEnum { #[non_exhaustive] Variant, } +// This enum has a hidden variant that should not trigger the lint +pub enum EnumWithHiddenVariant { + #[non_exhaustive] + #[doc(hidden)] + HiddenVariantToBeExhaustive, +} + // This enum is private and should not trigger the lint enum PrivateEnum { #[non_exhaustive] diff --git a/test_outputs/query_execution/enum_variant_no_longer_non_exhaustive.snap b/test_outputs/query_execution/enum_variant_no_longer_non_exhaustive.snap index 06604672..e32032f3 100644 --- a/test_outputs/query_execution/enum_variant_no_longer_non_exhaustive.snap +++ b/test_outputs/query_execution/enum_variant_no_longer_non_exhaustive.snap @@ -33,27 +33,111 @@ expression: "&query_execution_results" ], "./test_crates/enum_variant_no_longer_non_exhaustive/": [ { - "enum_name": String("ExhaustiveEnum"), + "enum_name": String("ExhaustiveEnumUnitVariant"), "path": List([ String("enum_variant_no_longer_non_exhaustive"), - String("ExhaustiveEnum"), + String("ExhaustiveEnumUnitVariant"), ]), - "span_begin_line": Uint64(4), - "span_end_line": Uint64(4), + "span_begin_line": Uint64(5), + "span_end_line": Uint64(5), "span_filename": String("src/lib.rs"), - "variant_name": String("Variant"), + "variant_name": String("UnitVariant"), "visibility_limit": String("public"), }, { - "enum_name": String("NonExhaustiveEnum"), + "enum_name": String("NonExhaustiveEnumUnitVariant"), "path": List([ String("enum_variant_no_longer_non_exhaustive"), - String("NonExhaustiveEnum"), + String("NonExhaustiveEnumUnitVariant"), ]), - "span_begin_line": Uint64(9), - "span_end_line": Uint64(9), + "span_begin_line": Uint64(11), + "span_end_line": Uint64(11), "span_filename": String("src/lib.rs"), - "variant_name": String("Variant"), + "variant_name": String("UnitVariant"), + "visibility_limit": String("public"), + }, + { + "enum_name": String("ExhaustiveEnumTupleVariant"), + "path": List([ + String("enum_variant_no_longer_non_exhaustive"), + String("ExhaustiveEnumTupleVariant"), + ]), + "span_begin_line": Uint64(16), + "span_end_line": Uint64(16), + "span_filename": String("src/lib.rs"), + "variant_name": String("TupleVariant"), + "visibility_limit": String("public"), + }, + { + "enum_name": String("NonExhaustiveEnumTupleVariant"), + "path": List([ + String("enum_variant_no_longer_non_exhaustive"), + String("NonExhaustiveEnumTupleVariant"), + ]), + "span_begin_line": Uint64(22), + "span_end_line": Uint64(22), + "span_filename": String("src/lib.rs"), + "variant_name": String("TupleVariant"), + "visibility_limit": String("public"), + }, + { + "enum_name": String("ExhaustiveEnumStructVariant"), + "path": List([ + String("enum_variant_no_longer_non_exhaustive"), + String("ExhaustiveEnumStructVariant"), + ]), + "span_begin_line": Uint64(27), + "span_end_line": Uint64(27), + "span_filename": String("src/lib.rs"), + "variant_name": String("StructVariant"), + "visibility_limit": String("public"), + }, + { + "enum_name": String("NonExhaustiveEnumStructVariant"), + "path": List([ + String("enum_variant_no_longer_non_exhaustive"), + String("NonExhaustiveEnumStructVariant"), + ]), + "span_begin_line": Uint64(33), + "span_end_line": Uint64(33), + "span_filename": String("src/lib.rs"), + "variant_name": String("StructVariant"), + "visibility_limit": String("public"), + }, + { + "enum_name": String("MixedVariantKinds"), + "path": List([ + String("enum_variant_no_longer_non_exhaustive"), + String("MixedVariantKinds"), + ]), + "span_begin_line": Uint64(39), + "span_end_line": Uint64(39), + "span_filename": String("src/lib.rs"), + "variant_name": String("UnitVariant"), + "visibility_limit": String("public"), + }, + { + "enum_name": String("MixedVariantKinds"), + "path": List([ + String("enum_variant_no_longer_non_exhaustive"), + String("MixedVariantKinds"), + ]), + "span_begin_line": Uint64(41), + "span_end_line": Uint64(41), + "span_filename": String("src/lib.rs"), + "variant_name": String("TupleVariant"), + "visibility_limit": String("public"), + }, + { + "enum_name": String("MixedVariantKinds"), + "path": List([ + String("enum_variant_no_longer_non_exhaustive"), + String("MixedVariantKinds"), + ]), + "span_begin_line": Uint64(43), + "span_end_line": Uint64(43), + "span_filename": String("src/lib.rs"), + "variant_name": String("StructVariant"), "visibility_limit": String("public"), }, ], From efd6bcaace89ddb02806592404cc0005f305e0fa Mon Sep 17 00:00:00 2001 From: Predrag Gruevski <2348618+obi1kenobi@users.noreply.github.com> Date: Mon, 24 Mar 2025 18:45:32 -0400 Subject: [PATCH 6/6] Apply suggestions from code review --- src/lints/enum_variant_no_longer_non_exhaustive.ron | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lints/enum_variant_no_longer_non_exhaustive.ron b/src/lints/enum_variant_no_longer_non_exhaustive.ron index df79e1c9..4ffb5369 100644 --- a/src/lints/enum_variant_no_longer_non_exhaustive.ron +++ b/src/lints/enum_variant_no_longer_non_exhaustive.ron @@ -1,7 +1,7 @@ SemverQuery( id: "enum_variant_no_longer_non_exhaustive", human_readable_name: "enum variant no longer #[non_exhaustive]", - description: "A pub enum variant is no longer #[non_exhaustive], potentially causing breaking changes if new fields are added.", + description: "A pub enum variant is no longer #[non_exhaustive]. Future fields added to this variant will cause a breaking change.", required_update: Minor, lint_level: Allow, reference_link: Some("https://doc.rust-lang.org/reference/attributes/type_system.html#the-non_exhaustive-attribute"), @@ -58,6 +58,6 @@ SemverQuery( "non_exhaustive": "#[non_exhaustive]", "true": true, }, - error_message: "A pub enum variant is no longer #[non_exhaustive], potentially causing breaking changes if new fields are added.", + error_message: "A pub enum variant is no longer #[non_exhaustive]. Future fields added to this variant will cause a breaking change.", per_result_error_template: Some("variant {{enum_name}}:{{variant_name}} in {{span_filename}}:{{span_begin_line}}"), )