Skip to content

Commit f75c503

Browse files
emilkclaudeDandandan
authored
Enable more clippy lints (apache#24466)
## Which issue does this PR close? - Part of apache#18467. ## Rationale for this change Turn on all `clippy::pedantic` lints, and do opt-out instead of opt-in. Then enable these lints (remove their opt-outs): ## What changes are included in this PR? One commit per lint, each removing its `"allow"` line from `Cargo.toml` and fixing every site. Review one commit at a time! Let me know if you disagree with any and I'll revert it | Lint | Sites | Fix | | ---------------------------------------------------------------------------------------------------------- | ----: | ------------------------------------------------------- | | [`collapsible_else_if`](https://rust-lang.github.io/rust-clippy/master/index.html#collapsible_else_if) | 1 | flatten `else { if .. }` into `else if` | | [`range_plus_one`](https://rust-lang.github.io/rust-clippy/master/index.html#range_plus_one) | 12 | `a..=b` instead of `a..b + 1` | | [`stable_sort_primitive`](https://rust-lang.github.io/rust-clippy/master/index.html#stable_sort_primitive) | 14 | `sort_unstable` where stability cannot be observed | | [`comparison_chain`](https://rust-lang.github.io/rust-clippy/master/index.html#comparison_chain) | 3 | `match Ord::cmp` instead of an `if`/`else if` chain | | [`should_panic_without_expect`](https://rust-lang.github.io/rust-clippy/master/index.html#should_panic_without_expect) | 1 | name the expected panic message | | [`manual_assert_eq`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_assert_eq) | 25 | `assert_eq!`/`assert_ne!` so failures print both values | | [`needless_for_each`](https://rust-lang.github.io/rust-clippy/master/index.html#needless_for_each) | 47 | `for` loops instead of `for_each` | | [`manual_let_else`](https://rust-lang.github.io/rust-clippy/master/index.html#manual_let_else) | 106 | `let .. else` instead of a diverging `match` | ## Are these changes tested? `cargo clippy --workspace --all-targets --all-features` reports no warnings, and the extended test suite passes. The changes are mechanical and behavior-preserving, so no new tests. ## Are there any user-facing changes? No. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: Daniël Heres <danielheres@gmail.com>
1 parent 9213bb5 commit f75c503

115 files changed

Lines changed: 676 additions & 825 deletions

File tree

Some content is hidden

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

Cargo.toml

Lines changed: 71 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -213,123 +213,126 @@ zstd = { version = "0.13", default-features = false }
213213
# See https://github.com/apache/datafusion/issues/18467 for the ongoing effort of
214214
# picking useful non-default lints.
215215
[workspace.lints.clippy]
216+
all = { level = "warn", priority = -1 }
217+
pedantic = { level = "warn", priority = -1 }
218+
216219
# https://github.com/apache/datafusion/issues/18881
217220
allow_attributes = "warn"
218221
as_ptr_cast_mut = "warn"
219-
assigning_clones = "warn"
220-
bool_to_int_with_if = "warn"
221222
branches_sharing_code = "warn"
222-
checked_conversions = "warn"
223223
clear_with_drain = "warn"
224224
coerce_container_to_any = "warn"
225225
debug_assert_with_mut_call = "warn"
226-
decimal_bitwise_operands = "warn"
227226
default_union_representation = "warn"
228227
doc_include_without_cfg = "warn"
229-
duration_suboptimal_units = "warn"
230-
elidable_lifetime_names = "warn"
231228
empty_enum_variants_with_brackets = "warn"
232-
empty_enums = "warn"
233229
equatable_if_let = "warn"
234230
exit = "warn"
235-
expl_impl_clone_on_copy = "warn"
236-
explicit_deref_methods = "warn"
237-
filter_map_next = "warn"
238-
flat_map_option = "warn"
239-
fn_params_excessive_bools = "warn"
240231
fn_to_numeric_cast_any = "warn"
241-
ignore_without_reason = "warn"
242232
imprecise_flops = "warn"
243-
inconsistent_struct_constructor = "warn"
244-
index_refutable_slice = "warn"
245-
inefficient_to_string = "warn"
246233
infinite_loop = "warn"
247-
into_iter_without_iter = "warn"
248-
invalid_upcast_comparisons = "warn"
249-
ip_constant = "warn"
250-
iter_filter_is_ok = "warn"
251-
iter_filter_is_some = "warn"
252-
iter_not_returning_iterator = "warn"
253234
iter_on_empty_collections = "warn"
254235
iter_on_single_items = "warn"
255-
iter_without_into_iter = "warn"
256-
# Detects large stack-allocated futures that may cause stack overflow crashes (see threshold in clippy.toml)
257-
large_futures = "warn"
258236
large_include_file = "warn"
259-
# Like `large_futures`, these guard against stack overflows
260-
large_stack_arrays = "warn"
237+
# Guards against stack overflows
261238
large_stack_frames = "warn"
262-
large_types_passed_by_value = "warn"
263-
linkedlist = "warn"
264239
# Catches `"{foo}"` where the string is never actually formatted
265240
literal_string_with_formatting_args = "warn"
266-
macro_use_imports = "warn"
267-
manual_assert = "warn"
268-
manual_ilog2 = "warn"
269-
manual_instant_elapsed = "warn"
270-
manual_is_power_of_two = "warn"
271-
manual_is_variant_and = "warn"
272-
# `(a + b) / 2` can overflow; `a.midpoint(b)` cannot
273-
manual_midpoint = "warn"
274-
match_wild_err_arm = "warn"
275241
mem_forget = "warn"
276-
mismatching_type_param_order = "warn"
277-
mut_mut = "warn"
278-
# https://github.com/apache/datafusion/issues/18503
279-
needless_pass_by_value = "warn"
280242
needless_type_cast = "warn"
281243
negative_feature_names = "warn"
282-
# Prefer `std::sync::LazyLock` over the `lazy_static`/`once_cell` crates
283-
non_std_lazy_statics = "warn"
284244
non_zero_suggestions = "warn"
285245
nonstandard_macro_braces = "warn"
286-
option_as_ref_cloned = "warn"
287-
option_option = "warn"
288246
or_fun_call = "warn"
289247
path_buf_push_overwrite = "warn"
290248
pathbuf_init_then_push = "warn"
291249
precedence_bits = "warn"
292-
ptr_cast_constness = "warn"
293-
pub_underscore_fields = "warn"
294250
pub_without_shorthand = "warn"
295251
rc_mutex = "warn"
296-
ref_as_ptr = "warn"
297-
ref_option_ref = "warn"
298252
rest_pat_in_fully_bound_structs = "warn"
299-
# Catches copy-paste bugs in `if`/`else if` chains
300-
same_functions_in_if_condition = "warn"
301-
same_length_and_capacity = "warn"
302-
# Catches a `&self` argument that is only threaded through recursive calls
303-
self_only_used_in_recursion = "warn"
304253
# Avoids hashing the key twice
305254
set_contains_or_insert = "warn"
306255
single_option_map = "warn"
307-
str_split_at_newline = "warn"
308-
string_add_assign = "warn"
309256
string_lit_as_bytes = "warn"
310257
string_lit_chars_any = "warn"
311258
suspicious_xor_used_as_pow = "warn"
312259
trailing_empty_array = "warn"
313260
trait_duplication_in_bounds = "warn"
314-
transmute_ptr_to_ptr = "warn"
315-
# Subtracting `Instant`s panics on overflow; use `saturating_duration_since`
316-
unchecked_time_subtraction = "warn"
317261
uninhabited_references = "warn"
318-
uninlined_format_args = "warn"
319-
unnecessary_box_returns = "warn"
320-
# `{:?}` on a `Path` quotes and escapes it; `{}` on `.display()` does not
321-
unnecessary_debug_formatting = "warn"
322-
unnecessary_lazy_evaluations = "warn"
323262
unnecessary_safety_doc = "warn"
324263
unnecessary_self_imports = "warn"
325264
unnecessary_struct_initialization = "warn"
326-
unused_async = "warn"
327265
unused_peekable = "warn"
328266
unused_rounding = "warn"
329-
used_underscore_binding = "warn"
330267
verbose_file_reads = "warn"
331268
wildcard_dependencies = "warn"
332-
zero_sized_map_values = "warn"
269+
270+
# Pedantic lints we opt out of, with the number of hits at the time we enabled `pedantic`.
271+
# Some of these we should consider enabling.
272+
borrow_as_ptr = "allow" # 6 hits
273+
case_sensitive_file_extension_comparisons = "allow" # 1 hit
274+
cast_lossless = "allow" # 361 hits
275+
cast_possible_truncation = "allow" # 911 hits
276+
cast_possible_wrap = "allow" # 493 hits
277+
cast_precision_loss = "allow" # 266 hits
278+
cast_ptr_alignment = "allow" # 5 hits
279+
cast_sign_loss = "allow" # 440 hits
280+
cloned_instead_of_copied = "allow" # 38 hits
281+
default_trait_access = "allow" # 221 hits
282+
doc_comment_double_space_linebreaks = "allow" # 6 hits
283+
doc_link_with_quotes = "allow" # 25 hits
284+
doc_markdown = "allow" # 4933 hits; needs a long `doc-valid-idents` list in `clippy.toml`
285+
enum_glob_use = "allow" # 98 hits
286+
explicit_into_iter_loop = "allow" # 55 hits
287+
explicit_iter_loop = "allow" # 189 hits
288+
float_cmp = "allow" # 8 hits; exact float comparisons are often intentional here
289+
format_collect = "allow" # 4 hits
290+
format_push_string = "allow" # 34 hits
291+
from_iter_instead_of_collect = "allow" # 51 hits
292+
if_not_else = "allow" # 133 hits
293+
ignored_unit_patterns = "allow" # 52 hits
294+
implicit_clone = "allow" # 198 hits
295+
implicit_hasher = "allow" # 17 hits
296+
inline_always = "allow" # 45 hits
297+
items_after_statements = "allow" # 171 hits
298+
large_digit_groups = "allow" # 3 hits
299+
manual_string_new = "allow" # 84 hits
300+
many_single_char_names = "allow" # 12 hits; short names are idiomatic in the numeric kernels
301+
map_unwrap_or = "allow" # 198 hits
302+
match_bool = "allow" # 46 hits
303+
match_same_arms = "allow" # 261 hits
304+
match_wildcard_for_single_variants = "allow" # 132 hits
305+
missing_errors_doc = "allow" # 1807 hits
306+
missing_fields_in_debug = "allow" # 29 hits
307+
missing_panics_doc = "allow" # 244 hits
308+
must_use_candidate = "allow" # 2726 hits
309+
needless_bitwise_bool = "allow" # 1 hit
310+
needless_continue = "allow" # 37 hits
311+
needless_raw_string_hashes = "allow" # 540 hits
312+
no_effect_underscore_binding = "allow" # 1 hit
313+
ptr_as_ptr = "allow" # 83 hits
314+
redundant_closure_for_method_calls = "allow" # 686 hits
315+
redundant_else = "allow" # 48 hits
316+
ref_option = "allow" # 36 hits
317+
return_self_not_must_use = "allow" # 644 hits
318+
semicolon_if_nothing_returned = "allow" # 1353 hits
319+
similar_names = "allow" # 228 hits; too many false positives, e.g. `expr`/`exprs`
320+
single_char_pattern = "allow" # 23 hits
321+
single_match_else = "allow" # 155 hits
322+
struct_excessive_bools = "allow" # 24 hits
323+
struct_field_names = "allow" # 14 hits
324+
too_many_lines = "allow" # 484 hits
325+
trivially_copy_pass_by_ref = "allow" # 74 hits
326+
unicode_not_nfc = "allow" # 2 hits
327+
unnecessary_literal_bound = "allow" # 471 hits
328+
unnecessary_semicolon = "allow" # 185 hits
329+
unnecessary_trailing_comma = "allow" # 49 hits
330+
unnecessary_wraps = "allow" # 427 hits
331+
unnested_or_patterns = "allow" # 68 hits
332+
unreadable_literal = "allow" # 502 hits
333+
unused_self = "allow" # 69 hits
334+
used_underscore_items = "allow" # 28 hits
335+
wildcard_imports = "allow" # 48 hits; `use crate::prelude::*` is idiomatic
333336

334337
[workspace.lints.rust]
335338
unexpected_cfgs = { level = "warn", check-cfg = [

benchmarks/src/sort_pushdown.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ impl RunOpt {
122122
}
123123
}
124124
}
125-
ids.sort();
125+
ids.sort_unstable();
126126
ids
127127
}
128128

benchmarks/src/sql_benchmark_runner.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -238,9 +238,9 @@ pub async fn load_benchmark_definitions_for_query(
238238
}
239239

240240
pub fn sort_benchmarks(benchmarks: &mut BTreeMap<String, Vec<SqlBenchmark>>) {
241-
benchmarks
242-
.values_mut()
243-
.for_each(|benchmarks| benchmarks.sort_by(|a, b| a.name().cmp(b.name())));
241+
for benchmarks in benchmarks.values_mut() {
242+
benchmarks.sort_by(|a, b| a.name().cmp(b.name()));
243+
}
244244
}
245245

246246
/// Applies benchmark, subgroup, and query filters to discovered benchmark groups.

datafusion-cli/src/helper.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,11 @@ impl CliHelper {
7575

7676
fn validate_input(&self, input: &str) -> Result<ValidationResult> {
7777
if let Some(sql) = input.strip_suffix(';') {
78-
let dialect = match dialect_from_str(self.dialect) {
79-
Some(dialect) => dialect,
80-
None => {
81-
return Ok(ValidationResult::Invalid(Some(format!(
82-
" 🤔 Invalid dialect: {}",
83-
self.dialect
84-
))));
85-
}
78+
let Some(dialect) = dialect_from_str(self.dialect) else {
79+
return Ok(ValidationResult::Invalid(Some(format!(
80+
" 🤔 Invalid dialect: {}",
81+
self.dialect
82+
))));
8683
};
8784
let lines = split_from_semicolon(sql);
8885
for line in lines {

datafusion-examples/examples/data_io/json_shredding.rs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -223,13 +223,10 @@ impl ScalarUDFImpl for JsonGetStr {
223223
args.args.len() == 2,
224224
"json_get_str requires exactly 2 arguments"
225225
);
226-
let key = match &args.args[0] {
227-
ColumnarValue::Scalar(ScalarValue::Utf8(Some(key))) => key,
228-
_ => {
229-
return Err(exec_datafusion_err!(
230-
"json_get_str first argument must be a string"
231-
));
232-
}
226+
let ColumnarValue::Scalar(ScalarValue::Utf8(Some(key))) = &args.args[0] else {
227+
return Err(exec_datafusion_err!(
228+
"json_get_str first argument must be a string"
229+
));
233230
};
234231
// We expect a string array that contains JSON strings
235232
let json_array = match &args.args[1] {

datafusion-examples/examples/data_io/parquet_exec_visitor.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,8 @@ impl ExecutionPlanVisitor for ParquetExecVisitor {
110110
{
111111
self.file_groups = Some(file_config.file_groups.clone());
112112

113-
let metrics = match data_source_exec.metrics() {
114-
None => return Ok(true),
115-
Some(metrics) => metrics,
113+
let Some(metrics) = data_source_exec.metrics() else {
114+
return Ok(true);
116115
};
117116
self.bytes_scanned = metrics.sum_by_name("bytes_scanned");
118117
}

datafusion/common/src/dfschema.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,9 +1340,8 @@ impl SchemaExt for Schema {
13401340
/// `format!("{q}.{name}")` when `qualifier` is `Some`, or just `name` when
13411341
/// `None`. We avoid going through the `fmt` machinery for performance reasons.
13421342
pub fn qualified_name(qualifier: Option<&TableReference>, name: &str) -> String {
1343-
let qualifier = match qualifier {
1344-
None => return name.to_string(),
1345-
Some(q) => q,
1343+
let Some(qualifier) = qualifier else {
1344+
return name.to_string();
13461345
};
13471346
let (first, second, third) = match qualifier {
13481347
TableReference::Bare { table } => (table.as_ref(), None, None),

datafusion/common/src/functional_dependencies.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ pub fn get_target_functional_dependencies(
541541
}
542542
(!combined_target_indices.is_empty()).then_some({
543543
let mut result = combined_target_indices.into_iter().collect::<Vec<_>>();
544-
result.sort();
544+
result.sort_unstable();
545545
result
546546
})
547547
}
@@ -563,7 +563,7 @@ pub fn get_required_group_by_exprs_indices(
563563
})
564564
.collect::<Option<Vec<_>>>()?;
565565

566-
groupby_expr_indices.sort();
566+
groupby_expr_indices.sort_unstable();
567567
for FunctionalDependence {
568568
source_indices,
569569
target_indices,

datafusion/common/src/hash_utils.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -214,14 +214,14 @@ fn hash_null<S: HashState>(
214214
multi_col: bool,
215215
) {
216216
if multi_col {
217-
hashes_buffer.iter_mut().for_each(|hash| {
217+
for hash in hashes_buffer {
218218
// stable hash for null value
219219
*hash = combine_hashes(random_state.hash_one(1), *hash);
220-
})
220+
}
221221
} else {
222-
hashes_buffer.iter_mut().for_each(|hash| {
222+
for hash in hashes_buffer {
223223
*hash = random_state.hash_one(1);
224-
})
224+
}
225225
}
226226
}
227227

datafusion/common/src/hash_utils/build_hasher.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,9 +193,9 @@ fn hash_null_with_hasher<S: BuildHasher>(
193193

194194
let null_hash = hash_builder.hash_one(1);
195195
if multi_col {
196-
hashes_buffer.iter_mut().for_each(|hash| {
196+
for hash in hashes_buffer {
197197
*hash = combine_hashes(null_hash, *hash);
198-
})
198+
}
199199
} else {
200200
hashes_buffer.fill(null_hash);
201201
}

0 commit comments

Comments
 (0)