This is an automated email from the ASF dual-hosted git repository.
Jefffrey pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/main by this push:
new 43117679ed Enable `allow_attributes` lint for array and schema crates
(#10625)
43117679ed is described below
commit 43117679ed9fcf0c05443d3195871125ee0e4244
Author: WaterWhisperer <[email protected]>
AuthorDate: Thu Aug 13 09:02:13 2026 +0800
Enable `allow_attributes` lint for array and schema crates (#10625)
# Which issue does this PR close?
<!--
We generally require a GitHub issue to be filed for all bug fixes and
enhancements and this helps us generate change logs for our releases.
You can link an issue to this PR using the GitHub syntax.
-->
- Part of #10458.
# Rationale for this change
<!--
Why are you proposing this change? If this is already explained clearly
in the issue then this section is not needed.
Explaining clearly why changes are proposed helps reviewers understand
your changes and offer better suggestions for fixes.
-->
Enable `clippy::allow_attributes` for two crates
# What changes are included in this PR?
<!--
There is no need to duplicate the description in the issue here but it
is sometimes worth providing a summary of the individual changes in this
PR.
-->
- Enable `clippy::allow_attributes` for `arrow-array` and
`arrow-schema`.
- Replace active `allow` with `expect` attributes.
# Are these changes tested?
<!--
We typically require tests for all PRs in order to:
1. Prevent the code from being accidentally broken by subsequent changes
2. Serve as another way to document the expected behavior of the code
If tests are not included in your PR, please explain why (for example,
are they covered by existing tests)?
If this PR claims a performance improvement, please include evidence
such as benchmark results.
-->
Yes.
`cargo clippy --workspace --all-targets --all-features -- -D warnings`
# Are there any user-facing changes?
<!--
If there are user-facing changes then we may require documentation to be
updated before approving the PR.
If there are any breaking changes to public APIs, please call them out.
-->
No.
---
arrow-array/src/array/boolean_array.rs | 2 +-
arrow-array/src/array/dictionary_array.rs | 4 ++--
arrow-array/src/array/fixed_size_binary_array.rs | 6 +++---
arrow-array/src/array/map_array.rs | 1 -
arrow-array/src/array/mod.rs | 1 -
arrow-array/src/array/union_array.rs | 3 ---
arrow-array/src/ffi.rs | 4 ++--
arrow-array/src/ffi_stream.rs | 2 --
arrow-array/src/iterator.rs | 7 ++-----
arrow-array/src/lib.rs | 1 +
arrow-schema/src/ffi.rs | 10 +++-------
arrow-schema/src/field.rs | 24 ++++++++++++------------
arrow-schema/src/lib.rs | 1 +
arrow-schema/src/schema.rs | 12 ++++++------
14 files changed, 33 insertions(+), 45 deletions(-)
diff --git a/arrow-array/src/array/boolean_array.rs
b/arrow-array/src/array/boolean_array.rs
index 33a62f3151..5b5dcb0daf 100644
--- a/arrow-array/src/array/boolean_array.rs
+++ b/arrow-array/src/array/boolean_array.rs
@@ -840,7 +840,7 @@ impl BooleanArray {
///
/// Panics if the iterator does not report an upper bound on `size_hint()`.
#[inline]
- #[allow(
+ #[expect(
private_bounds,
reason = "We will expose BooleanAdapter if there is a need"
)]
diff --git a/arrow-array/src/array/dictionary_array.rs
b/arrow-array/src/array/dictionary_array.rs
index 0c465ec144..7766f952a6 100644
--- a/arrow-array/src/array/dictionary_array.rs
+++ b/arrow-array/src/array/dictionary_array.rs
@@ -488,7 +488,7 @@ impl<K: ArrowDictionaryKeyType> DictionaryArray<K> {
/// Returns `PrimitiveDictionaryBuilder` of this dictionary array for
mutating
/// its keys and values if the underlying data buffer is not shared by
others.
- #[allow(clippy::result_large_err)]
+ #[expect(clippy::result_large_err)]
pub fn into_primitive_dict_builder<V>(self) ->
Result<PrimitiveDictionaryBuilder<K, V>, Self>
where
V: ArrowPrimitiveType,
@@ -545,7 +545,7 @@ impl<K: ArrowDictionaryKeyType> DictionaryArray<K> {
/// assert_eq!(typed.value(1), 11);
/// assert_eq!(typed.value(2), 21);
/// ```
- #[allow(clippy::result_large_err)]
+ #[expect(clippy::result_large_err)]
pub fn unary_mut<F, V>(self, op: F) -> Result<DictionaryArray<K>,
DictionaryArray<K>>
where
V: ArrowPrimitiveType,
diff --git a/arrow-array/src/array/fixed_size_binary_array.rs
b/arrow-array/src/array/fixed_size_binary_array.rs
index 254e00cd6a..0bfe006621 100644
--- a/arrow-array/src/array/fixed_size_binary_array.rs
+++ b/arrow-array/src/array/fixed_size_binary_array.rs
@@ -758,7 +758,7 @@ impl TryFrom<Vec<Option<&[u8]>>> for FixedSizeBinaryArray {
type Error = ArrowError;
fn try_from(v: Vec<Option<&[u8]>>) -> Result<Self, Self::Error> {
- #[allow(deprecated)]
+ #[expect(deprecated)]
Self::try_from_sparse_iter(v.into_iter())
}
}
@@ -1065,7 +1065,7 @@ mod tests {
fn test_all_none_fixed_size_binary_array_from_sparse_iter() {
let none_option: Option<[u8; 32]> = None;
let input_arg = vec![none_option, none_option, none_option];
- #[allow(deprecated)]
+ #[expect(deprecated)]
let arr =
FixedSizeBinaryArray::try_from_sparse_iter(input_arg.into_iter()).unwrap();
assert_eq!(0, arr.value_length());
assert_eq!(3, arr.len())
@@ -1080,7 +1080,7 @@ mod tests {
None,
Some(vec![13, 14]),
];
- #[allow(deprecated)]
+ #[expect(deprecated)]
let arr =
FixedSizeBinaryArray::try_from_sparse_iter(input_arg.iter().cloned()).unwrap();
assert_eq!(2, arr.value_length());
assert_eq!(5, arr.len());
diff --git a/arrow-array/src/array/map_array.rs
b/arrow-array/src/array/map_array.rs
index 0d041831d6..7f90f0ffd2 100644
--- a/arrow-array/src/array/map_array.rs
+++ b/arrow-array/src/array/map_array.rs
@@ -436,7 +436,6 @@ impl MapArray {
/// // Or you could fill the last 2 generics manually for the key array
item and value array item
/// // let map_array = MapArray::from_vec_of_maps::<StringArray,
Int32Array, &str, i32>(map, ordered);
///```
- #[allow(clippy::type_complexity)]
pub fn from_vec_of_maps<KeyArray, ValueArray, K, V>(
input: Vec<Option<Entries<K, Option<V>>>>,
ordered: bool,
diff --git a/arrow-array/src/array/mod.rs b/arrow-array/src/array/mod.rs
index 8a5e476846..589044fdd8 100644
--- a/arrow-array/src/array/mod.rs
+++ b/arrow-array/src/array/mod.rs
@@ -1246,7 +1246,6 @@ mod tests {
}
#[test]
- #[allow(unused_parens)]
fn test_null_runs() {
for r in [DataType::Int16, DataType::Int32, DataType::Int64] {
let data_type = DataType::RunEndEncoded(
diff --git a/arrow-array/src/array/union_array.rs
b/arrow-array/src/array/union_array.rs
index 4f96ba49d8..9c57a702b4 100644
--- a/arrow-array/src/array/union_array.rs
+++ b/arrow-array/src/array/union_array.rs
@@ -378,7 +378,6 @@ impl UnionArray {
/// # Ok(())
/// # }
/// ```
- #[allow(clippy::type_complexity)]
pub fn into_parts(
self,
) -> (
@@ -1016,8 +1015,6 @@ enum SparseStrategy {
#[repr(usize)]
enum Mask {
Zero = 0,
- // false positive, see https://github.com/rust-lang/rust-clippy/issues/8043
- #[allow(clippy::enum_clike_unportable_variant)]
Max = usize::MAX,
}
diff --git a/arrow-array/src/ffi.rs b/arrow-array/src/ffi.rs
index 4e132b4cc4..21e309a50d 100644
--- a/arrow-array/src/ffi.rs
+++ b/arrow-array/src/ffi.rs
@@ -480,7 +480,7 @@ impl ImportedArrowArray<'_> {
let len = self.buffer_len(1, variadic_buffer_lengths, dt)?;
// first buffer is the null buffer => add(1)
// we assume that pointer is aligned for `i32`, as Utf8 uses
`i32` offsets.
- #[allow(clippy::cast_ptr_alignment)]
+ #[expect(clippy::cast_ptr_alignment)]
let offset_buffer = self.array.buffer(1) as *const i32;
// get last offset
(unsafe { *offset_buffer.add(len / size_of::<i32>() - 1) }) as
usize
@@ -494,7 +494,7 @@ impl ImportedArrowArray<'_> {
let len = self.buffer_len(1, variadic_buffer_lengths, dt)?;
// first buffer is the null buffer => add(1)
// we assume that pointer is aligned for `i64`, as Large uses
`i64` offsets.
- #[allow(clippy::cast_ptr_alignment)]
+ #[expect(clippy::cast_ptr_alignment)]
let offset_buffer = self.array.buffer(1) as *const i64;
// get last offset
(unsafe { *offset_buffer.add(len / size_of::<i64>() - 1) }) as
usize
diff --git a/arrow-array/src/ffi_stream.rs b/arrow-array/src/ffi_stream.rs
index f307416bbf..aeb7ca0918 100644
--- a/arrow-array/src/ffi_stream.rs
+++ b/arrow-array/src/ffi_stream.rs
@@ -95,7 +95,6 @@ const ENOSYS: i32 = 38;
/// This was created by bindgen
#[repr(C)]
#[derive(Debug)]
-#[allow(non_camel_case_types)]
pub struct FFI_ArrowArrayStream {
/// C function to get schema from the stream
pub get_schema:
@@ -318,7 +317,6 @@ fn get_stream_schema(stream_ptr: *mut FFI_ArrowArrayStream)
-> Result<SchemaRef>
impl ArrowArrayStreamReader {
/// Creates a new `ArrowArrayStreamReader` from a `FFI_ArrowArrayStream`.
/// This is used to import from the C Stream Interface.
- #[allow(dead_code)]
pub fn try_new(mut stream: FFI_ArrowArrayStream) -> Result<Self> {
if stream.release.is_none() {
return Err(ArrowError::CDataInterface(
diff --git a/arrow-array/src/iterator.rs b/arrow-array/src/iterator.rs
index d954c9ce2f..6b15fc8dfc 100644
--- a/arrow-array/src/iterator.rs
+++ b/arrow-array/src/iterator.rs
@@ -734,9 +734,9 @@ mod tests {
let mut actual = actual.clone();
let mut expected = expected.clone();
for _ in 0..expected.len() {
- #[allow(clippy::iter_nth_zero)]
+ #[expect(clippy::iter_nth_zero)]
let actual_val = actual.nth(0);
- #[allow(clippy::iter_nth_zero)]
+ #[expect(clippy::iter_nth_zero)]
let expected_val = expected.nth(0);
assert_eq!(actual_val, expected_val, "Failed on nth(0)");
}
@@ -773,9 +773,7 @@ mod tests {
let mut actual = actual.clone();
let mut expected = expected.clone();
for _ in 0..expected.len() {
- #[allow(clippy::iter_nth_zero)]
let actual_val = actual.nth_back(0);
- #[allow(clippy::iter_nth_zero)]
let expected_val = expected.nth_back(0);
assert_eq!(actual_val, expected_val, "Failed on
nth_back(0)");
}
@@ -900,7 +898,6 @@ mod tests {
let result = if self.reverse {
iter.rfold(Some(1), cb)
} else {
- #[allow(clippy::manual_try_fold)]
iter.fold(Some(1), cb)
};
diff --git a/arrow-array/src/lib.rs b/arrow-array/src/lib.rs
index a5f9bf5e71..a2e5f7033e 100644
--- a/arrow-array/src/lib.rs
+++ b/arrow-array/src/lib.rs
@@ -226,6 +226,7 @@
html_favicon_url =
"https://arrow.apache.org/img/arrow-logo_chevrons_black-txt_transparent-bg.svg"
)]
#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(clippy::allow_attributes)]
#![deny(rustdoc::broken_intra_doc_links)]
#![warn(missing_docs)]
diff --git a/arrow-schema/src/ffi.rs b/arrow-schema/src/ffi.rs
index 2279d2d50f..3788e80338 100644
--- a/arrow-schema/src/ffi.rs
+++ b/arrow-schema/src/ffi.rs
@@ -73,7 +73,6 @@ bitflags! {
///
#[repr(C)]
#[derive(Debug)]
-#[allow(non_camel_case_types)]
pub struct FFI_ArrowSchema {
/// Null-terminated, UTF8-encoded string describing the data type
pub format: *const c_char,
@@ -354,11 +353,8 @@ impl FFI_ArrowSchema {
} else {
let mut pos = 0;
- // On some platforms, c_char = u8, and on some, c_char = i8. Where
c_char = u8, clippy
- // wants to complain that we're casting to the same type, but if
we remove the cast,
- // this will fail to compile on the other platforms. So we must
allow it.
- #[allow(clippy::unnecessary_cast)]
- let buffer: *const u8 = self.metadata as *const u8;
+ // On some platforms, c_char = u8, and on some, c_char = i8.
+ let buffer = self.metadata.cast::<u8>();
fn next_four_bytes(buffer: *const u8, pos: &mut isize) -> [u8; 4] {
let out = unsafe {
@@ -978,7 +974,7 @@ mod tests {
#[test]
fn test_dictionary_ordered() {
- #[allow(deprecated)]
+ #[expect(deprecated)]
let schema = Schema::new(vec![Field::new_dict(
"dict",
DataType::Dictionary(Box::new(DataType::Int32),
Box::new(DataType::Utf8)),
diff --git a/arrow-schema/src/field.rs b/arrow-schema/src/field.rs
index 66874f6672..f360b46c08 100644
--- a/arrow-schema/src/field.rs
+++ b/arrow-schema/src/field.rs
@@ -171,7 +171,7 @@ impl Field {
/// Field::new("field_name", DataType::Int32, true);
/// ```
pub fn new(name: impl Into<String>, data_type: DataType, nullable: bool)
-> Self {
- #[allow(deprecated)]
+ #[expect(deprecated)]
Field {
name: name.into(),
data_type,
@@ -212,7 +212,7 @@ impl Field {
dict_id: i64,
dict_is_ordered: bool,
) -> Self {
- #[allow(deprecated)]
+ #[expect(deprecated)]
Field {
name: name.into(),
data_type,
@@ -694,7 +694,7 @@ impl Field {
self.fields()
.into_iter()
.filter(|&field| {
- #[allow(deprecated)]
+ #[expect(deprecated)]
let matching_dict_id = field.dict_id == id;
matches!(field.data_type(), DataType::Dictionary(_, _)) &&
matching_dict_id
})
@@ -709,7 +709,7 @@ impl Field {
)]
pub const fn dict_id(&self) -> Option<i64> {
match self.data_type {
- #[allow(deprecated)]
+ #[expect(deprecated)]
DataType::Dictionary(_, _) => Some(self.dict_id),
_ => None,
}
@@ -1053,7 +1053,7 @@ mod test {
fn test_new_dict_with_string() {
// Fields should allow owned Strings to support reuse
let s = "c1";
- #[allow(deprecated)]
+ #[expect(deprecated)]
Field::new_dict(s, DataType::Int64, false, 4, false);
}
@@ -1192,7 +1192,7 @@ mod test {
#[test]
fn test_fields_with_dict_id() {
- #[allow(deprecated)]
+ #[expect(deprecated)]
let dict1 = Field::new_dict(
"dict1",
DataType::Dictionary(DataType::Utf8.into(),
DataType::Int32.into()),
@@ -1200,7 +1200,7 @@ mod test {
10,
false,
);
- #[allow(deprecated)]
+ #[expect(deprecated)]
let dict2 = Field::new_dict(
"dict2",
DataType::Dictionary(DataType::Int32.into(),
DataType::Int8.into()),
@@ -1237,11 +1237,11 @@ mod test {
false,
);
- #[allow(deprecated)]
+ #[expect(deprecated)]
for field in field.fields_with_dict_id(10) {
assert_eq!(dict1, *field);
}
- #[allow(deprecated)]
+ #[expect(deprecated)]
for field in field.fields_with_dict_id(20) {
assert_eq!(dict2, *field);
}
@@ -1256,7 +1256,7 @@ mod test {
#[test]
fn test_field_comparison_case() {
// dictionary-encoding properties not used for field comparison
- #[allow(deprecated)]
+ #[expect(deprecated)]
let dict1 = Field::new_dict(
"dict1",
DataType::Dictionary(DataType::Utf8.into(),
DataType::Int32.into()),
@@ -1264,7 +1264,7 @@ mod test {
10,
false,
);
- #[allow(deprecated)]
+ #[expect(deprecated)]
let dict2 = Field::new_dict(
"dict1",
DataType::Dictionary(DataType::Utf8.into(),
DataType::Int32.into()),
@@ -1276,7 +1276,7 @@ mod test {
assert_eq!(dict1, dict2);
assert_eq!(get_field_hash(&dict1), get_field_hash(&dict2));
- #[allow(deprecated)]
+ #[expect(deprecated)]
let dict1 = Field::new_dict(
"dict0",
DataType::Dictionary(DataType::Utf8.into(),
DataType::Int32.into()),
diff --git a/arrow-schema/src/lib.rs b/arrow-schema/src/lib.rs
index 4f6771a1c9..0d2ce0d56b 100644
--- a/arrow-schema/src/lib.rs
+++ b/arrow-schema/src/lib.rs
@@ -22,6 +22,7 @@
html_favicon_url =
"https://arrow.apache.org/img/arrow-logo_chevrons_black-txt_transparent-bg.svg"
)]
#![cfg_attr(docsrs, feature(doc_cfg))]
+#![deny(clippy::allow_attributes)]
#![warn(missing_docs)]
mod datatype;
diff --git a/arrow-schema/src/schema.rs b/arrow-schema/src/schema.rs
index 54e513635b..ca7d3dadb4 100644
--- a/arrow-schema/src/schema.rs
+++ b/arrow-schema/src/schema.rs
@@ -381,7 +381,7 @@ impl Schema {
note = "The ability to preserve dictionary IDs will be removed. With
it, all functions related to it."
)]
pub fn fields_with_dict_id(&self, dict_id: i64) -> Vec<&Field> {
- #[allow(deprecated)]
+ #[expect(deprecated)]
self.fields
.iter()
.flat_map(|f| f.fields_with_dict_id(dict_id))
@@ -716,7 +716,7 @@ mod tests {
assert_eq!(first_name.name(), "first_name");
assert_eq!(first_name.data_type(), &DataType::Utf8);
assert!(!first_name.is_nullable());
- #[allow(deprecated)]
+ #[expect(deprecated)]
let dict_id = first_name.dict_id();
assert_eq!(dict_id, None);
assert_eq!(first_name.dict_is_ordered(), None);
@@ -735,7 +735,7 @@ mod tests {
interests.data_type(),
&DataType::Dictionary(Box::new(DataType::Int32),
Box::new(DataType::Utf8))
);
- #[allow(deprecated)]
+ #[expect(deprecated)]
let dict_id = interests.dict_id();
assert_eq!(dict_id, Some(123));
assert_eq!(interests.dict_is_ordered(), Some(true));
@@ -1177,7 +1177,7 @@ mod tests {
fn schema_field_with_dict_id() {
let schema = person_schema();
- #[allow(deprecated)]
+ #[expect(deprecated)]
let fields_dict_123: Vec<_> = schema
.fields_with_dict_id(123)
.iter()
@@ -1185,7 +1185,7 @@ mod tests {
.collect();
assert_eq!(fields_dict_123, vec!["interests"]);
- #[allow(deprecated)]
+ #[expect(deprecated)]
let is_empty = schema.fields_with_dict_id(456).is_empty();
assert!(is_empty);
}
@@ -1207,7 +1207,7 @@ mod tests {
])),
false,
),
- #[allow(deprecated)]
+ #[expect(deprecated)]
Field::new_dict(
"interests",
DataType::Dictionary(Box::new(DataType::Int32),
Box::new(DataType::Utf8)),