diff --git a/rules/S7424/metadata.json b/rules/S7424/metadata.json new file mode 100644 index 0000000000..2c63c08510 --- /dev/null +++ b/rules/S7424/metadata.json @@ -0,0 +1,2 @@ +{ +} diff --git a/rules/S7424/rust/metadata.json b/rules/S7424/rust/metadata.json new file mode 100644 index 0000000000..cc412abfd5 --- /dev/null +++ b/rules/S7424/rust/metadata.json @@ -0,0 +1,24 @@ +{ + "title": "Avoid manual PartialEq implementation with a derived Hash", + "type": "BUG", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "5min" + }, + "tags": [ + "clippy" + ], + "defaultSeverity": "Critical", + "ruleSpecification": "RSPEC-7424", + "sqKey": "S7424", + "scope": "All", + "defaultQualityProfiles": ["Sonar way"], + "quickfix": "unknown", + "code": { + "impacts": { + "RELIABILITY": "HIGH" + }, + "attribute": "LOGICAL" + } +} diff --git a/rules/S7424/rust/rule.adoc b/rules/S7424/rust/rule.adoc new file mode 100644 index 0000000000..5eba8660d3 --- /dev/null +++ b/rules/S7424/rust/rule.adoc @@ -0,0 +1,33 @@ + +== Why is this an issue? +Having a manual `PartialEq` implementation for types with a derived `Hash` can lead to inconsistencies. The contract `k1 == k2 ⇒ hash(k1) == hash(k2)` must always hold. Inconsistencies can cause undefined behaviors, especially when these types are used in collections such as `HashMap`. + + +=== Code examples + +==== Noncompliant code example +[source,rust,diff-id=1,diff-type=noncompliant] +---- +#[derive(Hash)] +struct Foo; + +impl PartialEq for Foo { + fn eq(&self, other: &Self) -> bool { + // Some custom equality logic + true // Noncompliant + } +} +---- + +==== Compliant solution + +[source,rust,diff-id=1,diff-type=compliant] +---- +#[derive(Hash, PartialEq)] +struct Foo; +---- + +== Resources +=== Documentation + +* Clippy Lints - https://rust-lang.github.io/rust-clippy/master/index.html#derived_hash_with_manual_eq