-
-
Notifications
You must be signed in to change notification settings - Fork 78
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add the
enum_repr_variant_discriminant_changed
lint.
Addresses a checkbox in #898.
- Loading branch information
1 parent
fe144fc
commit 0cd2058
Showing
11 changed files
with
272 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
SemverQuery( | ||
id: "enum_repr_variant_discriminant_changed", | ||
human_readable_name: "variant of an enum with explicit repr changed discriminant", | ||
description: "The variant of an enum with explicit repr() had its discriminant change from its previous value.", | ||
reference: Some("The variant of an enum with an explicit repr() had its discriminant value change. This breaks downstream code that accessed the discriminant via pointer casting."), | ||
required_update: Major, | ||
lint_level: Deny, | ||
reference_link: Some("https://doc.rust-lang.org/reference/items/enumerations.html#pointer-casting"), | ||
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"]) | ||
} | ||
attribute { | ||
old_attr: raw_attribute @output | ||
content { | ||
base @filter(op: "=", value: ["$repr"]) | ||
argument { | ||
base @filter(op: "regex", value: ["$repr_regex"]) | ||
} | ||
} | ||
} | ||
variant { | ||
variant_name: name @output @tag | ||
discriminant { | ||
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"]) | ||
} | ||
attribute { | ||
new_attr: raw_attribute @output | ||
content { | ||
base @filter(op: "=", value: ["$repr"]) | ||
argument { | ||
base @filter(op: "regex", value: ["$repr_regex"]) | ||
} | ||
} | ||
} | ||
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", | ||
"repr": "repr", | ||
"repr_regex": "[ui](\\d+|size)", | ||
"true": true, | ||
}, | ||
error_message: "An enum variant has changed its discriminant value. The enum has a defined primitive representation, so this breaks downstream code that used the discriminant value via an unsafe pointer cast.", | ||
per_result_error_template: Some("variant {{enum_name}}::{{variant_name}} {{old_value}} -> {{new_value}} in {{span_filename}}:{{span_begin_line}}"), | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
7 changes: 7 additions & 0 deletions
7
test_crates/enum_repr_variant_discriminant_changed/new/Cargo.toml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[package] | ||
publish = false | ||
name = "enum_repr_variant_discriminant_changed" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] |
25 changes: 25 additions & 0 deletions
25
test_crates/enum_repr_variant_discriminant_changed/new/src/lib.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
// Explicit discriminant changed values. By doing so, it changed the implicit | ||
// discriminant's value as well. Should be reported. | ||
#[repr(isize)] | ||
pub enum ExplicitAndImplicitDiscriminantsAreChanged { | ||
First = 2, | ||
Second, | ||
Third = 5, | ||
} | ||
|
||
// Discriminant changed values. Having #[non_exhaustive] on the enum should not have any effect | ||
// on the API or ABI breakage. Should be reported. | ||
#[repr(i16)] | ||
#[non_exhaustive] | ||
pub enum DiscriminantIsChanged { | ||
First = 1, | ||
} | ||
|
||
// Discriminant changed values, while the other variant is marked `non_exhaustive`. | ||
// The variant's exhaustiveness is not relevant for pointer casting, so this should be reported. | ||
#[repr(u32)] | ||
pub enum DiscriminantIsChangedButAVariantIsNonExhaustive { | ||
#[non_exhaustive] | ||
First, | ||
Second = 2, | ||
} |
7 changes: 7 additions & 0 deletions
7
test_crates/enum_repr_variant_discriminant_changed/old/Cargo.toml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
[package] | ||
publish = false | ||
name = "enum_repr_variant_discriminant_changed" | ||
version = "0.1.0" | ||
edition = "2021" | ||
|
||
[dependencies] |
26 changes: 26 additions & 0 deletions
26
test_crates/enum_repr_variant_discriminant_changed/old/src/lib.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
// Explicit discriminant changed values. By doing so, it changed the implicit | ||
// discriminant's value as well. Should be reported. | ||
#[repr(isize)] | ||
pub enum ExplicitAndImplicitDiscriminantsAreChanged { | ||
First = 1, | ||
Second, | ||
Third = 5, | ||
} | ||
|
||
// Discriminant changed values. Having #[non_exhaustive] on the enum should not have any effect | ||
// on the API or ABI breakage. Should be reported. | ||
#[repr(i16)] | ||
#[non_exhaustive] | ||
pub enum DiscriminantIsChanged { | ||
First, | ||
} | ||
|
||
// Discriminant changed values, while the other variant is marked `non_exhaustive`. | ||
// The variant's exhaustiveness is not relevant for pointer casting, so this should be reported. | ||
#[non_exhaustive] | ||
#[repr(u32)] | ||
pub enum DiscriminantIsChangedButAVariantIsNonExhaustive { | ||
#[non_exhaustive] | ||
First, | ||
Second, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
86 changes: 86 additions & 0 deletions
86
test_outputs/query_execution/enum_repr_variant_discriminant_changed.snap
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
--- | ||
source: src/query.rs | ||
expression: "&query_execution_results" | ||
snapshot_kind: text | ||
--- | ||
{ | ||
"./test_crates/enum_no_repr_variant_discriminant_changed/": [ | ||
{ | ||
"enum_name": String("FieldlessWithDiscrimants"), | ||
"new_attr": String("#[repr(u8)]"), | ||
"new_value": String("21"), | ||
"old_attr": String("#[repr(u8)]"), | ||
"old_value": String("20"), | ||
"path": List([ | ||
String("enum_no_repr_variant_discriminant_changed"), | ||
String("FieldlessWithDiscrimants"), | ||
]), | ||
"span_begin_line": Uint64(68), | ||
"span_filename": String("src/lib.rs"), | ||
"variant_name": String("Last"), | ||
"visibility_limit": String("public"), | ||
}, | ||
], | ||
"./test_crates/enum_repr_variant_discriminant_changed/": [ | ||
{ | ||
"enum_name": String("ExplicitAndImplicitDiscriminantsAreChanged"), | ||
"new_attr": String("#[repr(isize)]"), | ||
"new_value": String("2"), | ||
"old_attr": String("#[repr(isize)]"), | ||
"old_value": String("1"), | ||
"path": List([ | ||
String("enum_repr_variant_discriminant_changed"), | ||
String("ExplicitAndImplicitDiscriminantsAreChanged"), | ||
]), | ||
"span_begin_line": Uint64(5), | ||
"span_filename": String("src/lib.rs"), | ||
"variant_name": String("First"), | ||
"visibility_limit": String("public"), | ||
}, | ||
{ | ||
"enum_name": String("ExplicitAndImplicitDiscriminantsAreChanged"), | ||
"new_attr": String("#[repr(isize)]"), | ||
"new_value": String("3"), | ||
"old_attr": String("#[repr(isize)]"), | ||
"old_value": String("2"), | ||
"path": List([ | ||
String("enum_repr_variant_discriminant_changed"), | ||
String("ExplicitAndImplicitDiscriminantsAreChanged"), | ||
]), | ||
"span_begin_line": Uint64(6), | ||
"span_filename": String("src/lib.rs"), | ||
"variant_name": String("Second"), | ||
"visibility_limit": String("public"), | ||
}, | ||
{ | ||
"enum_name": String("DiscriminantIsChanged"), | ||
"new_attr": String("#[repr(i16)]"), | ||
"new_value": String("1"), | ||
"old_attr": String("#[repr(i16)]"), | ||
"old_value": String("0"), | ||
"path": List([ | ||
String("enum_repr_variant_discriminant_changed"), | ||
String("DiscriminantIsChanged"), | ||
]), | ||
"span_begin_line": Uint64(15), | ||
"span_filename": String("src/lib.rs"), | ||
"variant_name": String("First"), | ||
"visibility_limit": String("public"), | ||
}, | ||
{ | ||
"enum_name": String("DiscriminantIsChangedButAVariantIsNonExhaustive"), | ||
"new_attr": String("#[repr(u32)]"), | ||
"new_value": String("2"), | ||
"old_attr": String("#[repr(u32)]"), | ||
"old_value": String("1"), | ||
"path": List([ | ||
String("enum_repr_variant_discriminant_changed"), | ||
String("DiscriminantIsChangedButAVariantIsNonExhaustive"), | ||
]), | ||
"span_begin_line": Uint64(24), | ||
"span_filename": String("src/lib.rs"), | ||
"variant_name": String("Second"), | ||
"visibility_limit": String("public"), | ||
}, | ||
], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters