Skip to content

Commit

Permalink
Add enum variant discriminant changed lint
Browse files Browse the repository at this point in the history
  • Loading branch information
dmatos2012 committed Sep 6, 2024
1 parent 269f88b commit 0e24e8e
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 0 deletions.
65 changes: 65 additions & 0 deletions src/lints/enum_variant_discriminant_changed.ron
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
SemverQuery(
id: "enum_variant_discriminant_changed",
human_readable_name: "Public enum's variant had its discriminant changed from its previous value",
description: "A public enum's variant had its discriminant changed from its previous value.",
reference: Some("The public enum's variant had its discriminant changed from its previous value. This can cause compatibility issues, which may break FFI use cases."),
required_update: Major,
lint_level: Deny,
reference_link: Some("https://doc.rust-lang.org/reference/items/enumerations.html#discriminants"),
query: r#"
{
CrateDiff {
baseline {
item {
... on Enum {
visibility_limit @filter(op: "=", value: ["$public"]) @output
enum_name: name @output @tag
importable_path {
path @output @tag
public_api @filter(op: "=", value: ["$true"])
}
variant {
variant_name: name @output @tag
discriminant @optional {
old_value: value @output @tag
}
}
}
}
}
current {
item {
... on Enum {
visibility_limit @filter(op: "=", value: ["$public"])
name @filter(op: "=", value: ["%enum_name"])
importable_path {
path @filter(op: "=", value: ["%path"])
public_api @filter(op: "=", value: ["$true"])
}
variant {
name @filter(op: "=", value: ["%variant_name"])
discriminant {
new_value: value @output @filter (op: "!=", value: ["%old_value"])
}
}
span_: span @optional {
filename @output
begin_line @output
}
}
}
}
}
}"#,
arguments: {
"public": "public",
"true": true,
},
error_message: "The public enum's variant had its discriminant changed from its previous value. This can cause compatibility issues, which may break FFI use cases.",
per_result_error_template: Some("variant {{enum_name}}::{{variant_name}} {{old_value}} -> {{new_value}} in {{span_filename}}:{{span_begin_line}}"),
)
1 change: 1 addition & 0 deletions src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,7 @@ add_lints!(
enum_tuple_variant_field_now_doc_hidden,
enum_unit_variant_changed_kind,
enum_variant_added,
enum_variant_discriminant_changed,
enum_variant_marked_non_exhaustive,
enum_variant_missing,
exported_function_changed_abi,
Expand Down
7 changes: 7 additions & 0 deletions test_crates/enum_variant_discriminant_changed/new/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
publish = false
name = "enum_variant_discriminant_changed"
version = "0.1.0"
edition = "2021"

[dependencies]
31 changes: 31 additions & 0 deletions test_crates/enum_variant_discriminant_changed/new/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Explicit discriminant changed values. By doing so, it changed the implicit
// discriminant's value as well, should be reported.
#[repr(u8, C)]
pub enum ExplicitAndImplicitDiscriminantsAreChanged {
First = 2,
Second,
Third = 5,
}

// Implicit discriminant changed values when becoming explicit, should be reported.
#[repr(u8)]
pub enum ImplicitDiscriminantBecomesExplicit {
Tuple(),
Struct,
Unit = 5,
}

// Discriminant changed to be doc hidden and explicit. Being doc hidden is not relevant
// since it's still part of the public API, should be reported.
pub enum DiscriminantBecomesDocHiddenAndExplicit {
First,
#[doc(hidden)]
Second = 2,
}

// Explicit discriminants changed values, but being private dominates, should not be
// reported.
enum PrivateEnum {
First = 10,
Second = 11,
}
7 changes: 7 additions & 0 deletions test_crates/enum_variant_discriminant_changed/old/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
publish = false
name = "enum_variant_discriminant_changed"
version = "0.1.0"
edition = "2021"

[dependencies]
30 changes: 30 additions & 0 deletions test_crates/enum_variant_discriminant_changed/old/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Explicit discriminant changed values. By doing so, it changed the implicit
// discriminant's value as well, should be reported.
#[repr(u8, C)]
pub enum ExplicitAndImplicitDiscriminantsAreChanged {
First = 1,
Second,
Third = 5,
}

// Implicit discriminant changed values when becoming explicit, should be reported.
#[repr(u8)]
pub enum ImplicitDiscriminantBecomesExplicit {
Tuple(),
Struct {},
Unit,
}

// Discriminant changed to be doc hidden and explicit. Being doc hidden is not relevant
// since it's still part of the public API, should be reported.
pub enum DiscriminantBecomesDocHiddenAndExplicit {
First,
Second,
}

// Explicit discriminants changed values, but being private dominates, should not be
// reported.
enum PrivateEnum {
First = 1,
Second = 2,
}
56 changes: 56 additions & 0 deletions test_outputs/enum_variant_discriminant_changed.output.ron
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
{
"./test_crates/enum_variant_discriminant_changed/": [
{
"enum_name": String("ExplicitAndImplicitDiscriminantsAreChanged"),
"new_value": String("2"),
"old_value": String("1"),
"path": List([
String("enum_variant_discriminant_changed"),
String("ExplicitAndImplicitDiscriminantsAreChanged"),
]),
"span_begin_line": Uint64(4),
"span_filename": String("src/lib.rs"),
"variant_name": String("First"),
"visibility_limit": String("public"),
},
{
"enum_name": String("ExplicitAndImplicitDiscriminantsAreChanged"),
"new_value": String("3"),
"old_value": String("2"),
"path": List([
String("enum_variant_discriminant_changed"),
String("ExplicitAndImplicitDiscriminantsAreChanged"),
]),
"span_begin_line": Uint64(4),
"span_filename": String("src/lib.rs"),
"variant_name": String("Second"),
"visibility_limit": String("public"),
},
{
"enum_name": String("ImplicitDiscriminantBecomesExplicit"),
"new_value": String("5"),
"old_value": String("2"),
"path": List([
String("enum_variant_discriminant_changed"),
String("ImplicitDiscriminantBecomesExplicit"),
]),
"span_begin_line": Uint64(12),
"span_filename": String("src/lib.rs"),
"variant_name": String("Unit"),
"visibility_limit": String("public"),
},
{
"enum_name": String("DiscriminantBecomesDocHiddenAndExplicit"),
"new_value": String("2"),
"old_value": String("1"),
"path": List([
String("enum_variant_discriminant_changed"),
String("DiscriminantBecomesDocHiddenAndExplicit"),
]),
"span_begin_line": Uint64(20),
"span_filename": String("src/lib.rs"),
"variant_name": String("Second"),
"visibility_limit": String("public"),
},
]
}

0 comments on commit 0e24e8e

Please sign in to comment.