From a05406cdf1ae969b8bf3d7a069034e2186393586 Mon Sep 17 00:00:00 2001 From: "Tobin C. Harding" Date: Fri, 21 Feb 2025 13:56:16 +1100 Subject: [PATCH] Introduce pedantic lint config Configure `clippy` to do warn for pedantic lints and fix warnings. --- Cargo.toml | 126 ++++++++++++++++++++++++++++++++++++++++++++- src/buf_encoder.rs | 4 +- src/display.rs | 2 +- src/error.rs | 25 ++++----- src/iter.rs | 6 +++ src/lib.rs | 4 +- src/parse.rs | 2 +- src/serde.rs | 18 +++---- 8 files changed, 159 insertions(+), 28 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d2cabb4..f64d0d6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,130 @@ name = "wrap_array" name = "serde" required-features = ["std", "serde"] - [lints.clippy] +# Exclude lints we don't think are valuable. +needless_question_mark = "allow" # https://github.com/rust-bitcoin/rust-bitcoin/pull/2134 +manual_range_contains = "allow" # More readable than clippy's format. +# Exhaustive list of pedantic clippy lints +assigning_clones = "warn" +bool_to_int_with_if = "warn" +borrow_as_ptr = "warn" +case_sensitive_file_extension_comparisons = "warn" +cast_lossless = "warn" +cast_possible_truncation = "allow" # All casts should include a code comment (except test code). +cast_possible_wrap = "allow" # Same as above re code comment. +cast_precision_loss = "warn" +cast_ptr_alignment = "warn" +cast_sign_loss = "allow" # All casts should include a code comment (except in test code). +checked_conversions = "warn" +cloned_instead_of_copied = "warn" +copy_iterator = "warn" +default_trait_access = "warn" +doc_link_with_quotes = "warn" +doc_markdown = "warn" +empty_enum = "warn" +enum_glob_use = "warn" +expl_impl_clone_on_copy = "warn" +explicit_deref_methods = "warn" +explicit_into_iter_loop = "warn" +explicit_iter_loop = "warn" +filter_map_next = "warn" +flat_map_option = "warn" +float_cmp = "allow" # Bitcoin floats are typically limited to 8 decimal places and we want them exact. +fn_params_excessive_bools = "warn" +from_iter_instead_of_collect = "warn" +if_not_else = "warn" +ignored_unit_patterns = "warn" +implicit_clone = "warn" +implicit_hasher = "warn" +inconsistent_struct_constructor = "warn" +index_refutable_slice = "warn" +inefficient_to_string = "warn" +inline_always = "warn" +into_iter_without_iter = "warn" +invalid_upcast_comparisons = "warn" +items_after_statements = "warn" +iter_filter_is_ok = "warn" +iter_filter_is_some = "warn" +iter_not_returning_iterator = "warn" +iter_without_into_iter = "warn" +large_digit_groups = "warn" +large_futures = "warn" +large_stack_arrays = "warn" +large_types_passed_by_value = "warn" +linkedlist = "warn" +macro_use_imports = "warn" +manual_assert = "warn" +manual_instant_elapsed = "warn" +manual_is_power_of_two = "warn" +manual_is_variant_and = "warn" +manual_let_else = "warn" +manual_ok_or = "warn" +manual_string_new = "warn" +many_single_char_names = "warn" +map_unwrap_or = "warn" +match_bool = "allow" # Adds extra indentation and LOC. +match_on_vec_items = "warn" +match_same_arms = "allow" # Collapses things that are conceptually unrelated to each other. +match_wild_err_arm = "warn" +match_wildcard_for_single_variants = "warn" +maybe_infinite_iter = "warn" +mismatching_type_param_order = "warn" missing_errors_doc = "warn" +missing_fields_in_debug = "warn" +missing_panics_doc = "warn" +must_use_candidate = "allow" # Useful for audit but many false positives. +mut_mut = "warn" +naive_bytecount = "warn" +needless_bitwise_bool = "warn" +needless_continue = "warn" +needless_for_each = "warn" +needless_pass_by_value = "warn" +needless_raw_string_hashes = "warn" +no_effect_underscore_binding = "warn" +no_mangle_with_rust_abi = "warn" +option_as_ref_cloned = "warn" +option_option = "warn" +ptr_as_ptr = "warn" +ptr_cast_constness = "warn" +pub_underscore_fields = "warn" +range_minus_one = "warn" +range_plus_one = "warn" +redundant_closure_for_method_calls = "warn" +redundant_else = "warn" +ref_as_ptr = "warn" +ref_binding_to_reference = "warn" +ref_option = "warn" +ref_option_ref = "warn" +return_self_not_must_use = "warn" +same_functions_in_if_condition = "warn" +semicolon_if_nothing_returned = "warn" +should_panic_without_expect = "warn" +similar_names = "allow" # Too many (subjectively) false positives. +single_char_pattern = "warn" +single_match_else = "warn" +stable_sort_primitive = "warn" +str_split_at_newline = "warn" +string_add_assign = "warn" +struct_excessive_bools = "warn" +struct_field_names = "warn" +too_many_lines = "warn" +transmute_ptr_to_ptr = "warn" +trivially_copy_pass_by_ref = "warn" +unchecked_duration_subtraction = "warn" +unicode_not_nfc = "warn" +uninlined_format_args = "allow" # This is a subjective style choice. +unnecessary_box_returns = "warn" +unnecessary_join = "warn" +unnecessary_literal_bound = "warn" +unnecessary_wraps = "warn" +unnested_or_patterns = "warn" +unreadable_literal = "warn" +unsafe_derive_deserialize = "warn" +unused_async = "warn" +unused_self = "warn" +used_underscore_binding = "warn" +used_underscore_items = "warn" +verbose_bit_mask = "warn" +wildcard_imports = "warn" +zero_sized_map_values = "warn" diff --git a/src/buf_encoder.rs b/src/buf_encoder.rs index 6a0faab..c643c2f 100644 --- a/src/buf_encoder.rs +++ b/src/buf_encoder.rs @@ -51,7 +51,7 @@ impl BufEncoder { #[inline] #[allow(clippy::let_unit_value)] // Allow the unit value of the const check pub fn new(case: Case) -> Self { - let _ = Self::_CHECK_EVEN_CAPACITY; + let () = Self::_CHECK_EVEN_CAPACITY; BufEncoder { buf: ArrayString::new(), table: case.table() } } @@ -80,7 +80,7 @@ impl BufEncoder { I: IntoIterator, I::Item: Borrow, { - self.put_bytes_inner(bytes.into_iter()) + self.put_bytes_inner(bytes.into_iter()); } #[inline] diff --git a/src/display.rs b/src/display.rs index ecc5b33..ba58b4e 100644 --- a/src/display.rs +++ b/src/display.rs @@ -98,7 +98,7 @@ pub trait DisplayHex: Copy + sealed::IsRef + sealed::Sealed { // We don't expect `std` to ever be buggy, so the bug is most likely in the `Display` // impl of `Self::Display`. panic!("The implementation of Display for {} returned an error when it shouldn't", name) - }) + }); } /// Hints how many bytes to reserve when creating a `String`. diff --git a/src/error.rs b/src/error.rs index 8b9902a..99c83ff 100644 --- a/src/error.rs +++ b/src/error.rs @@ -79,11 +79,12 @@ impl From for ToBytesError { impl fmt::Display for ToBytesError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use ToBytesError::*; + use ToBytesError as E; match *self { - InvalidChar(ref e) => write_err!(f, "invalid char, failed to create bytes from hex"; e), - OddLengthString(ref e) => + E::InvalidChar(ref e) => + write_err!(f, "invalid char, failed to create bytes from hex"; e), + E::OddLengthString(ref e) => write_err!(f, "odd length, failed to create bytes from hex"; e), } } @@ -92,11 +93,11 @@ impl fmt::Display for ToBytesError { #[cfg(feature = "std")] impl std::error::Error for ToBytesError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use ToBytesError::*; + use ToBytesError as E; match *self { - InvalidChar(ref e) => Some(e), - OddLengthString(ref e) => Some(e), + E::InvalidChar(ref e) => Some(e), + E::OddLengthString(ref e) => Some(e), } } } @@ -222,11 +223,11 @@ impl From for ToArrayError { impl fmt::Display for ToArrayError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - use ToArrayError::*; + use ToArrayError as E; match *self { - InvalidChar(ref e) => write_err!(f, "failed to parse hex digit"; e), - InvalidLength(ref e) => write_err!(f, "failed to parse hex"; e), + E::InvalidChar(ref e) => write_err!(f, "failed to parse hex digit"; e), + E::InvalidLength(ref e) => write_err!(f, "failed to parse hex"; e), } } } @@ -234,11 +235,11 @@ impl fmt::Display for ToArrayError { #[cfg(feature = "std")] impl std::error::Error for ToArrayError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { - use ToArrayError::*; + use ToArrayError as E; match *self { - InvalidChar(ref e) => Some(e), - InvalidLength(ref e) => Some(e), + E::InvalidChar(ref e) => Some(e), + E::InvalidLength(ref e) => Some(e), } } } diff --git a/src/iter.rs b/src/iter.rs index 40cb003..460c7ed 100644 --- a/src/iter.rs +++ b/src/iter.rs @@ -442,6 +442,8 @@ mod tests { #[test] #[should_panic] + // Don't test panic message because it is from `debug_assert`. + #[allow(clippy::should_panic_without_expect)] fn hex_to_bytes_slice_drain_panic_empty() { let hex = "deadbeef"; let iter = HexToBytesIter::new_unchecked(hex); @@ -451,6 +453,8 @@ mod tests { #[test] #[should_panic] + // Don't test panic message because it is from `debug_assert`. + #[allow(clippy::should_panic_without_expect)] fn hex_to_bytes_slice_drain_panic_too_small() { let hex = "deadbeef"; let iter = HexToBytesIter::new_unchecked(hex); @@ -460,6 +464,8 @@ mod tests { #[test] #[should_panic] + // Don't test panic message because it is from `debug_assert`. + #[allow(clippy::should_panic_without_expect)] fn hex_to_bytes_slice_drain_panic_too_big() { let hex = "deadbeef"; let iter = HexToBytesIter::new_unchecked(hex); diff --git a/src/lib.rs b/src/lib.rs index 1d56ad3..72e4fc1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -46,7 +46,7 @@ extern crate alloc; #[doc(hidden)] pub mod _export { - /// A re-export of core::* + /// A re-export of `core::*`. pub mod _core { pub use core::*; } @@ -171,6 +171,6 @@ mod tests { fn parse_hex_into_vector() { let got = hex!("deadbeef"); let want = vec![0xde, 0xad, 0xbe, 0xef]; - assert_eq!(got, want) + assert_eq!(got, want); } } diff --git a/src/parse.rs b/src/parse.rs index c53e5ce..b3caaee 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -134,7 +134,7 @@ mod tests { assert_eq!( <[u8; 4]>::from_hex(len_sixteen).unwrap_err(), InvalidLengthError { invalid: 16, expected: 8 }.into() - ) + ); } #[test] diff --git a/src/serde.rs b/src/serde.rs index cdf4cd0..0d3e618 100644 --- a/src/serde.rs +++ b/src/serde.rs @@ -55,10 +55,10 @@ where T: Serialize + DisplayHex, { // Don't do anything special when not human readable. - if !serializer.is_human_readable() { - serde::Serialize::serialize(&data, serializer) - } else { + if serializer.is_human_readable() { serializer.collect_str(&format_args!("{:x}", data.as_hex())) + } else { + serde::Serialize::serialize(&data, serializer) } } @@ -76,10 +76,10 @@ where T: Serialize + DisplayHex, { // Don't do anything special when not human readable. - if !serializer.is_human_readable() { - serde::Serialize::serialize(&data, serializer) - } else { + if serializer.is_human_readable() { serializer.collect_str(&format_args!("{:X}", data.as_hex())) + } else { + serde::Serialize::serialize(&data, serializer) } } @@ -155,9 +155,9 @@ where } // Don't do anything special when not human readable. - if !d.is_human_readable() { - serde::Deserialize::deserialize(d) - } else { + if d.is_human_readable() { d.deserialize_map(HexVisitor(PhantomData)) + } else { + serde::Deserialize::deserialize(d) } }