Skip to content

Commit 09b67ae

Browse files
authored
chore: more lints (#762)
Add more lints to our codebase. I have taken all lints that are allowed by default, and made either either warnings or strong denies. **I have not added any lints from the [pedantic](https://rust-lang.github.io/rust-clippy/master/index.html?groups=pedantic) group, as those tend to be opinionated and I don't think should be enforced on a shared codebase.** Unfortunately, there is an [open cargo issue](rust-lang/cargo#8170) which makes it impossible to enable/disable lints based on the `#[cfg(test)]` or `#[cfg(feature = "...")]` features, hence I have had to enable lints for either the whole codebase (`[target.'cfg(all())']`), or for runtime-only code `[target.'cfg(target_arch = "wasm32")']`. The changeset is huge but just because I tackled all the new lints generated, so reviewing the new lints (in case some are unwanted or in case I missed some) would be sufficient, since the CI has been updated to verify all lints are properly addressed. Last but not least, I had to enable the `-Dwarnings` flag for ALL clippy invocations, so also on local machines, because it's not possible to pass custom `--cfg` either to rustc via cargo, e.g., `cargo clippy -- --cfg ci` and then have a `[target.'cfg(ci)']` entry in the config file. This might go away in future versions of cargo (we are currently on 1.74), but until then we either never fail on the CI, or we fail for everything also locally, and I think the latter is a better choice. This is also because rustc takes additional flags either from the `RUSTFLAGS` env variable or the `.cargo/config.toml` file. Hence specifying `RUSTFLAGS="-Dwarnings"` in the CI would not enable any additional lints as the env variable would take precedence over the config file, rendering them useless.
1 parent f057961 commit 09b67ae

File tree

107 files changed

+889
-661
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

107 files changed

+889
-661
lines changed

.cargo/config.toml

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,61 @@
1-
# Deployment runtime lints
2-
[target.'cfg(all(target_arch = "wasm32", not(test)))']
1+
# Unfortunately we cannot add any lints based on `cfg(test)` nor `cfg(feature = "feat")`: https://github.com/rust-lang/cargo/issues/8170.
2+
# Hence, we can only define lints that are applied codebase-wide (including tests), and lints that are applied only to runtime code.
3+
4+
# Codebase-wide lints.
5+
[target.'cfg(all())']
6+
rustflags = [
7+
# We need to deny warnings here instead of with the `RUSTFLAGS` env since the env variable would completely override these settings -> https://github.com/rust-lang/cargo/issues/5376.
8+
"-Dwarnings",
9+
"-Wclippy::as_underscore",
10+
"-Wclippy::assertions_on_result_states",
11+
"-Wclippy::branches_sharing_code",
12+
"-Wclippy::clear_with_drain",
13+
"-Wclippy::clone_on_ref_ptr",
14+
"-Wclippy::collection_is_never_read",
15+
"-Wclippy::derive_partial_eq_without_eq",
16+
"-Wclippy::else_if_without_else",
17+
"-Wclippy::empty_drop",
18+
"-Wclippy::empty_structs_with_brackets",
19+
"-Wclippy::equatable_if_let",
20+
"-Wclippy::if_then_some_else_none",
21+
"-Wclippy::impl_trait_in_params",
22+
"-Wclippy::iter_on_empty_collections",
23+
"-Wclippy::iter_on_single_items",
24+
"-Wclippy::iter_with_drain",
25+
"-Wclippy::needless_collect",
26+
"-Wclippy::needless_pass_by_ref_mut",
27+
"-Wclippy::negative_feature_names",
28+
"-Wclippy::option_if_let_else",
29+
"-Wclippy::or_fun_call",
30+
"-Wclippy::pub_without_shorthand",
31+
"-Wclippy::redundant_clone",
32+
"-Wclippy::redundant_type_annotations",
33+
"-Wclippy::ref_patterns",
34+
"-Wclippy::rest_pat_in_fully_bound_structs",
35+
"-Wclippy::suspicious_operation_groupings",
36+
"-Wclippy::type_repetition_in_bounds",
37+
"-Wclippy::unnecessary_self_imports",
38+
"-Wclippy::unnecessary_struct_initialization",
39+
"-Wclippy::unneeded_field_pattern",
40+
"-Wclippy::unused_peekable",
41+
"-Wclippy::useless_let_if_seq",
42+
"-Wclippy::wildcard_dependencies",
43+
# TODO: Add after upgrading to 1.76
44+
# "-Wclippy::infinite_loop",
45+
# TODO: Add after upgrading to 1.77
46+
#"-Wclippy::empty_enum_variants_with_brackets"
47+
# TODO: Add after upgrading to 1.80
48+
#"-Wclippy::renamed_function_params"
49+
# TODO: Add after upgrading to 1.81
50+
#"-Wclippy::cfg_not_test"
51+
#"-Wclippy::allow_attributes",
52+
# "-Wclippy::allow_attributes_without_reason",
53+
# TODO: Add after upgrading to 1.83
54+
#"-Wclippy::unused_trait_names"
55+
]
56+
57+
# Deployment runtime lints.
58+
[target.'cfg(target_arch = "wasm32")']
359
rustflags = [
460
"-Dclippy::arithmetic_side_effects",
561
"-Dclippy::as_conversions",
@@ -12,15 +68,29 @@ rustflags = [
1268
"-Dclippy::index_refutable_slice",
1369
"-Dclippy::indexing_slicing",
1470
"-Dclippy::lossy_float_literal",
71+
"-Dclippy::modulo_arithmetic",
1572
"-Dclippy::panic",
1673
"-Dclippy::string_slice",
1774
"-Dclippy::todo",
1875
"-Dclippy::unimplemented",
1976
"-Dclippy::unreachable",
2077
"-Dclippy::unwrap_used",
2178
"-Funsafe_code",
79+
"-Wclippy::alloc_instead_of_core",
80+
"-Wclippy::decimal_literal_representation",
81+
"-Wclippy::default_numeric_fallback",
82+
"-Wclippy::error_impl_error",
2283
"-Wclippy::integer_division",
23-
"-Wclippy::modulo_arithmetic",
84+
"-Wclippy::let_underscore_must_use",
85+
"-Wclippy::let_underscore_untyped",
86+
"-Wclippy::missing_const_for_fn",
87+
"-Wclippy::mixed_read_write_in_expression",
2488
"-Wclippy::print_stderr",
2589
"-Wclippy::print_stdout",
90+
"-Wclippy::shadow_reuse",
91+
"-Wclippy::shadow_same",
92+
"-Wclippy::shadow_unrelated",
93+
"-Wclippy::str_to_string",
94+
"-Wclippy::string_slice",
95+
"-Wclippy::string_to_string",
2696
]

.github/workflows/check-code.yml

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ jobs:
3939
env:
4040
# Configured by the Docker image. We can't change this unless the image does it.
4141
CARGO_HOME: /usr/local/cargo
42-
RUSTFLAGS: -D warnings
4342
SKIP_WASM_BUILD: 1
4443
needs: get-commit-head
4544
if: ${{ !contains(needs.get-commit-head.outputs.headCommitMsg, 'ci-skip-rust') }}
@@ -71,7 +70,7 @@ jobs:
7170
save-always: true
7271

7372
- name: Run `cargo clippy`
74-
run: cargo clippy --locked ${{ matrix.cargo-flags }}
73+
run: cargo clippy --locked --no-deps ${{ matrix.cargo-flags }}
7574

7675
cargo-fmt:
7776
name: Check formatting

crates/assets/src/asset.rs

Lines changed: 57 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -109,8 +109,8 @@ pub mod v1 {
109109
where
110110
I: AsRef<[u8]> + Into<Vec<u8>>,
111111
{
112-
let input = input.as_ref();
113-
let input_length = input.len();
112+
let input_ref = input.as_ref();
113+
let input_length = input_ref.len();
114114
if !(MINIMUM_ASSET_ID_LENGTH..=MAXIMUM_ASSET_ID_LENGTH).contains(&input_length) {
115115
log::trace!(
116116
"Length of provided input {} is not included in the inclusive range [{},{}]",
@@ -122,12 +122,12 @@ pub mod v1 {
122122
}
123123

124124
let AssetComponents {
125-
namespace,
126-
reference,
127-
identifier,
128-
} = split_components(input);
125+
namespace: encoded_namespace,
126+
reference: encoded_reference,
127+
identifier: encoded_identifier,
128+
} = split_components(input_ref);
129129

130-
match (namespace, reference, identifier) {
130+
match (encoded_namespace, encoded_reference, encoded_identifier) {
131131
// "slip44:" assets -> https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-20.md
132132
(Some(SLIP44_NAMESPACE), _, Some(_)) => {
133133
log::trace!("Slip44 namespace does not accept an asset identifier.");
@@ -145,27 +145,27 @@ pub mod v1 {
145145
EvmSmartContractFungibleReference::from_utf8_encoded(erc20_reference).map(Self::Erc20)
146146
}
147147
// "erc721:" assets -> https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-22.md
148-
(Some(ERC721_NAMESPACE), Some(erc721_reference), identifier) => {
148+
(Some(ERC721_NAMESPACE), Some(erc721_reference), erc721_identifier) => {
149149
let reference = EvmSmartContractFungibleReference::from_utf8_encoded(erc721_reference)?;
150-
let identifier = identifier.map_or(Ok(None), |id| {
150+
let identifier = erc721_identifier.map_or(Ok(None), |id| {
151151
EvmSmartContractNonFungibleIdentifier::from_utf8_encoded(id).map(Some)
152152
})?;
153153
Ok(Self::Erc721(EvmSmartContractNonFungibleReference(
154154
reference, identifier,
155155
)))
156156
}
157157
// "erc1155:" assets-> https://github.com/ChainAgnostic/CAIPs/blob/master/CAIPs/caip-29.md
158-
(Some(ERC1155_NAMESPACE), Some(erc1155_reference), identifier) => {
158+
(Some(ERC1155_NAMESPACE), Some(erc1155_reference), erc1155_identifier) => {
159159
let reference = EvmSmartContractFungibleReference::from_utf8_encoded(erc1155_reference)?;
160-
let identifier = identifier.map_or(Ok(None), |id| {
160+
let identifier = erc1155_identifier.map_or(Ok(None), |id| {
161161
EvmSmartContractNonFungibleIdentifier::from_utf8_encoded(id).map(Some)
162162
})?;
163163
Ok(Self::Erc1155(EvmSmartContractNonFungibleReference(
164164
reference, identifier,
165165
)))
166166
}
167167
// Generic yet valid asset IDs
168-
_ => GenericAssetId::from_utf8_encoded(input).map(Self::Generic),
168+
_ => GenericAssetId::from_utf8_encoded(input_ref).map(Self::Generic),
169169
}
170170
}
171171
}
@@ -276,23 +276,20 @@ pub mod v1 {
276276
/// Split the given input into its components, i.e., namespace, reference,
277277
/// and identifier, if the proper separators are found.
278278
fn split_components(input: &[u8]) -> AssetComponents {
279-
let mut split = input.splitn(2, |c| *c == ASSET_NAMESPACE_REFERENCE_SEPARATOR);
280-
let (namespace, reference) = (split.next(), split.next());
279+
let mut namespace_reference_split = input.splitn(2, |c| *c == ASSET_NAMESPACE_REFERENCE_SEPARATOR);
280+
let (parsed_namespace, reference) = (namespace_reference_split.next(), namespace_reference_split.next());
281281

282282
// Split the remaining reference to extract the identifier, if present
283-
let (reference, identifier) = if let Some(r) = reference {
284-
let mut split = r.splitn(2, |c| *c == ASSET_REFERENCE_IDENTIFIER_SEPARATOR);
283+
let (parsed_reference, parsed_identifier) = reference.map_or((reference, None), |r| {
284+
let mut reference_identifier_split = r.splitn(2, |c| *c == ASSET_REFERENCE_IDENTIFIER_SEPARATOR);
285285
// Split the reference further, if present
286-
(split.next(), split.next())
287-
} else {
288-
// Return the old reference, which is None if we are at this point
289-
(reference, None)
290-
};
286+
(reference_identifier_split.next(), reference_identifier_split.next())
287+
});
291288

292289
AssetComponents {
293-
namespace,
294-
reference,
295-
identifier,
290+
namespace: parsed_namespace,
291+
reference: parsed_reference,
292+
identifier: parsed_identifier,
296293
}
297294
}
298295

@@ -315,10 +312,10 @@ pub mod v1 {
315312
where
316313
I: AsRef<[u8]> + Into<Vec<u8>>,
317314
{
318-
let input = input.as_ref();
319-
check_reference_length_bounds(input)?;
315+
let input_ref = input.as_ref();
316+
check_reference_length_bounds(input_ref)?;
320317

321-
let decoded = str::from_utf8(input).map_err(|_| {
318+
let decoded = str::from_utf8(input_ref).map_err(|_| {
322319
log::trace!("Provided input is not a valid UTF8 string as expected by a Slip44 reference.");
323320
ReferenceError::InvalidFormat
324321
})?;
@@ -359,7 +356,7 @@ pub mod v1 {
359356

360357
// Getters
361358
impl Slip44Reference {
362-
pub fn inner(&self) -> &U256 {
359+
pub const fn inner(&self) -> &U256 {
363360
&self.0
364361
}
365362
}
@@ -383,9 +380,9 @@ pub mod v1 {
383380
where
384381
I: AsRef<[u8]> + Into<Vec<u8>>,
385382
{
386-
let input = input.as_ref();
383+
let input_ref = input.as_ref();
387384
// If the prefix is "0x" => parse the address
388-
if let [b'0', b'x', contract_address @ ..] = input {
385+
if let [b'0', b'x', contract_address @ ..] = input_ref {
389386
check_reference_length_bounds(contract_address)?;
390387

391388
let decoded = hex::decode(contract_address).map_err(|_| {
@@ -407,7 +404,7 @@ pub mod v1 {
407404

408405
// Getters
409406
impl EvmSmartContractFungibleReference {
410-
pub fn inner(&self) -> &[u8] {
407+
pub const fn inner(&self) -> &[u8] {
411408
&self.0
412409
}
413410
}
@@ -431,11 +428,11 @@ pub mod v1 {
431428

432429
// Getters
433430
impl EvmSmartContractNonFungibleReference {
434-
pub fn smart_contract(&self) -> &EvmSmartContractFungibleReference {
431+
pub const fn smart_contract(&self) -> &EvmSmartContractFungibleReference {
435432
&self.0
436433
}
437434

438-
pub fn identifier(&self) -> &Option<EvmSmartContractNonFungibleIdentifier> {
435+
pub const fn identifier(&self) -> &Option<EvmSmartContractNonFungibleIdentifier> {
439436
&self.1
440437
}
441438
}
@@ -457,10 +454,10 @@ pub mod v1 {
457454
where
458455
I: AsRef<[u8]> + Into<Vec<u8>>,
459456
{
460-
let input = input.as_ref();
461-
check_identifier_length_bounds(input)?;
457+
let input_ref = input.as_ref();
458+
check_identifier_length_bounds(input_ref)?;
462459

463-
input.iter().try_for_each(|c| {
460+
input_ref.iter().try_for_each(|c| {
464461
if !c.is_ascii_digit() {
465462
log::trace!("Provided input has some invalid values as expected by a smart contract-based asset identifier.");
466463
Err(IdentifierError::InvalidFormat)
@@ -470,7 +467,7 @@ pub mod v1 {
470467
})?;
471468

472469
Ok(Self(
473-
Vec::<u8>::from(input)
470+
Vec::<u8>::from(input_ref)
474471
.try_into()
475472
.map_err(|_| IdentifierError::InvalidFormat)?,
476473
))
@@ -519,12 +516,13 @@ pub mod v1 {
519516
} = split_components(input.as_ref());
520517

521518
match (namespace, reference, identifier) {
522-
(Some(namespace), Some(reference), identifier) => Ok(Self {
523-
namespace: GenericAssetNamespace::from_utf8_encoded(namespace)?,
524-
reference: GenericAssetReference::from_utf8_encoded(reference)?,
519+
(Some(encoded_namespace), Some(encoded_reference), encoded_identifier) => Ok(Self {
520+
namespace: GenericAssetNamespace::from_utf8_encoded(encoded_namespace)?,
521+
reference: GenericAssetReference::from_utf8_encoded(encoded_reference)?,
525522
// Transform Option<Result> to Result<Option> and bubble Err case up, keeping Ok(Option) for
526523
// successful cases.
527-
id: identifier.map_or(Ok(None), |id| GenericAssetIdentifier::from_utf8_encoded(id).map(Some))?,
524+
id: encoded_identifier
525+
.map_or(Ok(None), |id| GenericAssetIdentifier::from_utf8_encoded(id).map(Some))?,
528526
}),
529527
_ => Err(Error::InvalidFormat),
530528
}
@@ -533,13 +531,13 @@ pub mod v1 {
533531

534532
// Getters
535533
impl GenericAssetId {
536-
pub fn namespace(&self) -> &GenericAssetNamespace {
534+
pub const fn namespace(&self) -> &GenericAssetNamespace {
537535
&self.namespace
538536
}
539-
pub fn reference(&self) -> &GenericAssetReference {
537+
pub const fn reference(&self) -> &GenericAssetReference {
540538
&self.reference
541539
}
542-
pub fn id(&self) -> &Option<GenericAssetIdentifier> {
540+
pub const fn id(&self) -> &Option<GenericAssetIdentifier> {
543541
&self.id
544542
}
545543
}
@@ -557,19 +555,19 @@ pub mod v1 {
557555
where
558556
I: AsRef<[u8]> + Into<Vec<u8>>,
559557
{
560-
let input = input.as_ref();
561-
check_namespace_length_bounds(input)?;
558+
let input_ref = input.as_ref();
559+
check_namespace_length_bounds(input_ref)?;
562560

563-
input.iter().try_for_each(|c| {
564-
if !matches!(c, b'-' | b'a'..=b'z' | b'0'..=b'9') {
561+
input_ref.iter().try_for_each(|c| {
562+
if !matches!(*c, b'-' | b'a'..=b'z' | b'0'..=b'9') {
565563
log::trace!("Provided input has some invalid values as expected by a generic asset namespace.");
566564
Err(NamespaceError::InvalidFormat)
567565
} else {
568566
Ok(())
569567
}
570568
})?;
571569
Ok(Self(
572-
Vec::<u8>::from(input)
570+
Vec::<u8>::from(input_ref)
573571
.try_into()
574572
.map_err(|_| NamespaceError::InvalidFormat)?,
575573
))
@@ -607,19 +605,19 @@ pub mod v1 {
607605
where
608606
I: AsRef<[u8]> + Into<Vec<u8>>,
609607
{
610-
let input = input.as_ref();
611-
check_reference_length_bounds(input)?;
608+
let input_ref = input.as_ref();
609+
check_reference_length_bounds(input_ref)?;
612610

613-
input.iter().try_for_each(|c| {
614-
if !matches!(c, b'-' | b'.' | b'%' | b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9') {
611+
input_ref.iter().try_for_each(|c| {
612+
if !matches!(*c, b'-' | b'.' | b'%' | b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9') {
615613
log::trace!("Provided input has some invalid values as expected by a generic asset reference.");
616614
Err(ReferenceError::InvalidFormat)
617615
} else {
618616
Ok(())
619617
}
620618
})?;
621619
Ok(Self(
622-
Vec::<u8>::from(input)
620+
Vec::<u8>::from(input_ref)
623621
.try_into()
624622
.map_err(|_| ReferenceError::InvalidFormat)?,
625623
))
@@ -657,19 +655,19 @@ pub mod v1 {
657655
where
658656
I: AsRef<[u8]> + Into<Vec<u8>>,
659657
{
660-
let input = input.as_ref();
661-
check_identifier_length_bounds(input)?;
658+
let input_ref = input.as_ref();
659+
check_identifier_length_bounds(input_ref)?;
662660

663-
input.iter().try_for_each(|c| {
664-
if !matches!(c, b'-' | b'.' | b'%' | b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9') {
661+
input_ref.iter().try_for_each(|c| {
662+
if !matches!(*c, b'-' | b'.' | b'%' | b'a'..=b'z' | b'A'..=b'Z' | b'0'..=b'9') {
665663
log::trace!("Provided input has some invalid values as expected by a generic asset identifier.");
666664
Err(IdentifierError::InvalidFormat)
667665
} else {
668666
Ok(())
669667
}
670668
})?;
671669
Ok(Self(
672-
Vec::<u8>::from(input)
670+
Vec::<u8>::from(input_ref)
673671
.try_into()
674672
.map_err(|_| IdentifierError::InvalidFormat)?,
675673
))

0 commit comments

Comments
 (0)