Skip to content

Commit bb0584d

Browse files
committed
Move UnitHash into Methods lint pass
1 parent e213b6e commit bb0584d

File tree

7 files changed

+76
-83
lines changed

7 files changed

+76
-83
lines changed

clippy_lints/src/lib.register_all.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
208208
LintId::of(methods::SUSPICIOUS_MAP),
209209
LintId::of(methods::SUSPICIOUS_SPLITN),
210210
LintId::of(methods::UNINIT_ASSUMED_INIT),
211+
LintId::of(methods::UNIT_HASH),
211212
LintId::of(methods::UNNECESSARY_FILTER_MAP),
212213
LintId::of(methods::UNNECESSARY_FIND_MAP),
213214
LintId::of(methods::UNNECESSARY_FOLD),
@@ -326,7 +327,6 @@ store.register_group(true, "clippy::all", Some("clippy_all"), vec![
326327
LintId::of(types::VEC_BOX),
327328
LintId::of(unicode::INVISIBLE_CHARACTERS),
328329
LintId::of(uninit_vec::UNINIT_VEC),
329-
LintId::of(unit_hash::UNIT_HASH),
330330
LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
331331
LintId::of(unit_types::LET_UNIT_VALUE),
332332
LintId::of(unit_types::UNIT_ARG),

clippy_lints/src/lib.register_correctness.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ store.register_group(true, "clippy::correctness", Some("clippy_correctness"), ve
4242
LintId::of(methods::NONSENSICAL_OPEN_OPTIONS),
4343
LintId::of(methods::SUSPICIOUS_SPLITN),
4444
LintId::of(methods::UNINIT_ASSUMED_INIT),
45+
LintId::of(methods::UNIT_HASH),
4546
LintId::of(methods::ZST_OFFSET),
4647
LintId::of(minmax::MIN_MAX),
4748
LintId::of(non_octal_unix_permissions::NON_OCTAL_UNIX_PERMISSIONS),
@@ -67,7 +68,6 @@ store.register_group(true, "clippy::correctness", Some("clippy_correctness"), ve
6768
LintId::of(transmute::WRONG_TRANSMUTE),
6869
LintId::of(unicode::INVISIBLE_CHARACTERS),
6970
LintId::of(uninit_vec::UNINIT_VEC),
70-
LintId::of(unit_hash::UNIT_HASH),
7171
LintId::of(unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD),
7272
LintId::of(unit_types::UNIT_CMP),
7373
LintId::of(unnamed_address::FN_ADDRESS_COMPARISONS),

clippy_lints/src/lib.register_lints.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,6 +358,7 @@ store.register_lints(&[
358358
methods::SUSPICIOUS_MAP,
359359
methods::SUSPICIOUS_SPLITN,
360360
methods::UNINIT_ASSUMED_INIT,
361+
methods::UNIT_HASH,
361362
methods::UNNECESSARY_FILTER_MAP,
362363
methods::UNNECESSARY_FIND_MAP,
363364
methods::UNNECESSARY_FOLD,
@@ -558,7 +559,6 @@ store.register_lints(&[
558559
unicode::NON_ASCII_LITERAL,
559560
unicode::UNICODE_NOT_NFC,
560561
uninit_vec::UNINIT_VEC,
561-
unit_hash::UNIT_HASH,
562562
unit_return_expecting_ord::UNIT_RETURN_EXPECTING_ORD,
563563
unit_types::LET_UNIT_VALUE,
564564
unit_types::UNIT_ARG,

clippy_lints/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,6 @@ mod types;
371371
mod undocumented_unsafe_blocks;
372372
mod unicode;
373373
mod uninit_vec;
374-
mod unit_hash;
375374
mod unit_return_expecting_ord;
376375
mod unit_types;
377376
mod unnamed_address;
@@ -582,7 +581,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
582581
store.register_late_pass(|| Box::new(blocks_in_if_conditions::BlocksInIfConditions));
583582
store.register_late_pass(|| Box::new(unicode::Unicode));
584583
store.register_late_pass(|| Box::new(uninit_vec::UninitVec));
585-
store.register_late_pass(|| Box::new(unit_hash::UnitHash));
586584
store.register_late_pass(|| Box::new(unit_return_expecting_ord::UnitReturnExpectingOrd));
587585
store.register_late_pass(|| Box::new(strings::StringAdd));
588586
store.register_late_pass(|| Box::new(implicit_return::ImplicitReturn));

clippy_lints/src/methods/mod.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ mod string_extend_chars;
7878
mod suspicious_map;
7979
mod suspicious_splitn;
8080
mod uninit_assumed_init;
81+
mod unit_hash;
8182
mod unnecessary_filter_map;
8283
mod unnecessary_fold;
8384
mod unnecessary_iter_cloned;
@@ -2832,6 +2833,45 @@ declare_clippy_lint! {
28322833
"use of sort() when sort_unstable() is equivalent"
28332834
}
28342835

2836+
declare_clippy_lint! {
2837+
/// ### What it does
2838+
/// Detects `().hash(_)`.
2839+
///
2840+
/// ### Why is this bad?
2841+
/// Hashing a unit value doesn't do anything as the implementation of `Hash` for `()` is a no-op.
2842+
///
2843+
/// ### Example
2844+
/// ```rust
2845+
/// # use std::hash::Hash;
2846+
/// # use std::collections::hash_map::DefaultHasher;
2847+
/// # enum Foo { Empty, WithValue(u8) }
2848+
/// # use Foo::*;
2849+
/// # let mut state = DefaultHasher::new();
2850+
/// # let my_enum = Foo::Empty;
2851+
/// match my_enum {
2852+
/// Empty => ().hash(&mut state),
2853+
/// WithValue(x) => x.hash(&mut state),
2854+
/// }
2855+
/// ```
2856+
/// Use instead:
2857+
/// ```rust
2858+
/// # use std::hash::Hash;
2859+
/// # use std::collections::hash_map::DefaultHasher;
2860+
/// # enum Foo { Empty, WithValue(u8) }
2861+
/// # use Foo::*;
2862+
/// # let mut state = DefaultHasher::new();
2863+
/// # let my_enum = Foo::Empty;
2864+
/// match my_enum {
2865+
/// Empty => 0_u8.hash(&mut state),
2866+
/// WithValue(x) => x.hash(&mut state),
2867+
/// }
2868+
/// ```
2869+
#[clippy::version = "1.58.0"]
2870+
pub UNIT_HASH,
2871+
correctness,
2872+
"hashing a unit value, which does nothing"
2873+
}
2874+
28352875
pub struct Methods {
28362876
avoid_breaking_exported_api: bool,
28372877
msrv: Option<RustcVersion>,
@@ -2949,6 +2989,7 @@ impl_lint_pass!(Methods => [
29492989
RANGE_ZIP_WITH_LEN,
29502990
REPEAT_ONCE,
29512991
STABLE_SORT_PRIMITIVE,
2992+
UNIT_HASH,
29522993
]);
29532994

29542995
/// Extracts a method call name, args, and `Span` of the method name.
@@ -3258,6 +3299,9 @@ impl Methods {
32583299
get_last_with_len::check(cx, expr, recv, arg);
32593300
},
32603301
("get_or_insert_with", [arg]) => unnecessary_lazy_eval::check(cx, expr, recv, arg, "get_or_insert"),
3302+
("hash", [arg]) => {
3303+
unit_hash::check(cx, expr, recv, arg);
3304+
},
32613305
("is_file", []) => filetype_is_file::check(cx, expr, recv),
32623306
("is_digit", [radix]) => is_digit_ascii_radix::check(cx, expr, recv, radix, self.msrv),
32633307
("is_none", []) => check_is_some_is_none(cx, expr, recv, false),

clippy_lints/src/methods/unit_hash.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use clippy_utils::diagnostics::span_lint_and_then;
2+
use clippy_utils::is_trait_method;
3+
use clippy_utils::source::snippet;
4+
use rustc_errors::Applicability;
5+
use rustc_hir::Expr;
6+
use rustc_lint::LateContext;
7+
use rustc_span::sym;
8+
9+
use super::UNIT_HASH;
10+
11+
pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, recv: &'tcx Expr<'_>, arg: &'tcx Expr<'_>) {
12+
if is_trait_method(cx, expr, sym::Hash) && cx.typeck_results().expr_ty(recv).is_unit() {
13+
span_lint_and_then(
14+
cx,
15+
UNIT_HASH,
16+
expr.span,
17+
"this call to `hash` on the unit type will do nothing",
18+
|diag| {
19+
diag.span_suggestion(
20+
expr.span,
21+
"remove the call to `hash` or consider using",
22+
format!("0_u8.hash({})", snippet(cx, arg.span, ".."),),
23+
Applicability::MaybeIncorrect,
24+
);
25+
diag.note("the implementation of `Hash` for `()` is a no-op");
26+
},
27+
);
28+
}
29+
}

clippy_lints/src/unit_hash.rs

Lines changed: 0 additions & 78 deletions
This file was deleted.

0 commit comments

Comments
 (0)