more clippy rules (#8050)

* `checked_conversions`

* duration_suboptimal_units

* inefficient_to_string

* iter_on_single_items

* needless_collect

* needless_for_each

* ptr_offset_by_literal

* return_self_not_must_use
This commit is contained in:
Shahar Naveh authored and GitHub committed 2026-06-10 11:13:42 +09:00
1 parent 5e926e2891
commit dc81e050c6
17 files changed
+75 -46

No files matched your search

+16
View File
@@ -368,6 +368,10 @@ tests_outside_test_module = "warn"
debug_assert_with_mut_call = "warn"
derive_partial_eq_without_eq = "warn"
imprecise_flops = "warn"
iter_on_empty_collections = "warn"
iter_on_single_items = "warn"
literal_string_with_formatting_args = "warn"
needless_collect = "warn"
or_fun_call = "warn"
redundant_clone = "warn"
search_is_some = "warn"
@@ -379,9 +383,11 @@ use_self = "warn"
useless_let_if_seq = "warn"
# pedantic lints to enforce gradually
checked_conversions = "warn"
cloned_instead_of_copied = "warn"
collapsible_else_if = "warn"
comparison_chain = "warn"
duration_suboptimal_units = "warn"
explicit_into_iter_loop = "warn"
explicit_iter_loop = "warn"
filter_map_next = "warn"
@@ -389,11 +395,21 @@ flat_map_option = "warn"
format_collect = "warn"
from_iter_instead_of_collect = "warn"
inconsistent_struct_constructor = "warn"
index_refutable_slice = "warn"
inefficient_to_string = "warn"
iter_filter_is_ok = "warn"
iter_filter_is_some = "warn"
manual_is_variant_and = "warn"
map_unwrap_or = "warn"
match_bool = "warn"
must_use_candidate = "warn"
mut_mut = "warn"
needless_bitwise_bool = "warn"
needless_for_each = "warn"
option_as_ref_cloned = "warn"
ptr_offset_by_literal = "warn"
redundant_else = "warn"
return_self_not_must_use = "warn"
uninlined_format_args = "warn"
unnecessary_wraps = "warn"
unnested_or_patterns = "warn"
+1 -3
View File
@@ -14,9 +14,7 @@ pub unsafe extern "C" fn PyTraceBack_Print(tb: *mut PyObject, file: *mut PyObjec
let tb_module = vm.import("traceback", 0)?;
let print_tb = tb_module.get_attr("print_tb", vm)?;
let kwargs: KwArgs = [("file".to_string(), file.to_owned())]
.into_iter()
.collect();
let kwargs: KwArgs = core::iter::once(("file".to_string(), file.to_owned())).collect();
print_tb.call(FuncArgs::new(vec![tb.to_owned()], kwargs), vm)?;
Ok(())
+1 -1
View File
@@ -127,7 +127,7 @@ impl<T> BoxVec<T> {
let p: *mut _ = self.get_unchecked_ptr(index);
// Shift everything over to make space. (Duplicating the
// `index`th element into two consecutive places.)
ptr::copy(p, p.offset(1), len - index);
ptr::copy(p, p.add(1), len - index);
// Write it in, overwriting the first copy of the `index`th
// element.
ptr::write(p, element);
+6
View File
@@ -160,16 +160,22 @@ pub trait FormatBuf:
Extend<Self::Char> + Default + FromIterator<Self::Char> + From<String>
{
type Char: FormatChar;
fn chars(&self) -> impl Iterator<Item = Self::Char>;
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
#[must_use]
fn concat(self, other: Self) -> Self;
}
pub trait FormatChar: Copy + Into<CodePoint> + From<u8> {
fn to_char_lossy(self) -> char;
fn eq_char(self, c: char) -> bool;
}
+8 -5
View File
@@ -1671,11 +1671,14 @@ impl ItemMeta for SlotItemMeta {
I: core::iter::Iterator<Item = NestedMeta>,
{
let meta_map = if let Some(nested_meta) = nested.next() {
match nested_meta {
NestedMeta::Meta(meta) => {
Some([("name".to_owned(), (0, meta))].iter().cloned().collect())
}
_ => None,
if let NestedMeta::Meta(meta) = nested_meta {
Some(
core::iter::once(&("name".to_owned(), (0, meta)))
.cloned()
.collect(),
)
} else {
None
}
} else {
Some(HashMap::default())
+2
View File
@@ -109,6 +109,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
}
fn store_variable(&mut self, idx: oparg::VarNum, val: JitValue) -> Result<(), JitCompileError> {
#[expect(clippy::mut_mut, reason = "This seems like a false positive")]
let builder = &mut self.builder;
let ty = val.to_jit_type().ok_or(JitCompileError::NotSupported)?;
let local = self.variables[idx].get_or_insert_with(|| {
@@ -147,6 +148,7 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> {
}
fn get_or_create_block(&mut self, label: Label) -> Block {
#[expect(clippy::mut_mut, reason = "This seems like a false positive")]
let builder = &mut self.builder;
*self
.label_to_block
+9 -9
View File
@@ -75,7 +75,7 @@ impl StrDrive for &[u8] {
#[inline]
fn back_peek(cursor: &StringCursor) -> u32 {
unsafe { *cursor.ptr.offset(-1) as u32 }
unsafe { *cursor.ptr.sub(1) as u32 }
}
#[inline]
@@ -227,7 +227,7 @@ impl StrDrive for &Wtf8 {
const unsafe fn next_code_point(ptr: &mut *const u8) -> u32 {
// Decode UTF-8
let x = unsafe { **ptr };
*ptr = unsafe { ptr.offset(1) };
*ptr = unsafe { ptr.add(1) };
if x < 128 {
return x as u32;
@@ -240,7 +240,7 @@ const unsafe fn next_code_point(ptr: &mut *const u8) -> u32 {
// SAFETY: `bytes` produces an UTF-8-like string,
// so the iterator must produce a value here.
let y = unsafe { **ptr };
*ptr = unsafe { ptr.offset(1) };
*ptr = unsafe { ptr.add(1) };
let mut ch = utf8_acc_cont_byte(init, y);
if x >= 0xE0 {
// [[x y z] w] case
@@ -248,7 +248,7 @@ const unsafe fn next_code_point(ptr: &mut *const u8) -> u32 {
// SAFETY: `bytes` produces an UTF-8-like string,
// so the iterator must produce a value here.
let z = unsafe { **ptr };
*ptr = unsafe { ptr.offset(1) };
*ptr = unsafe { ptr.add(1) };
let y_z = utf8_acc_cont_byte((y & CONT_MASK) as u32, z);
ch = (init << 12) | y_z;
if x >= 0xF0 {
@@ -257,7 +257,7 @@ const unsafe fn next_code_point(ptr: &mut *const u8) -> u32 {
// SAFETY: `bytes` produces an UTF-8-like string,
// so the iterator must produce a value here.
let w = unsafe { **ptr };
*ptr = unsafe { ptr.offset(1) };
*ptr = unsafe { ptr.add(1) };
ch = ((init & 7) << 18) | utf8_acc_cont_byte(y_z, w);
}
}
@@ -274,7 +274,7 @@ const unsafe fn next_code_point(ptr: &mut *const u8) -> u32 {
#[inline]
const unsafe fn next_code_point_reverse(ptr: &mut *const u8) -> u32 {
// Decode UTF-8
*ptr = unsafe { ptr.offset(-1) };
*ptr = unsafe { ptr.sub(1) };
let w = match unsafe { **ptr } {
next_byte if next_byte < 128 => return next_byte as u32,
back_byte => back_byte,
@@ -285,19 +285,19 @@ const unsafe fn next_code_point_reverse(ptr: &mut *const u8) -> u32 {
let mut ch;
// SAFETY: `bytes` produces an UTF-8-like string,
// so the iterator must produce a value here.
*ptr = unsafe { ptr.offset(-1) };
*ptr = unsafe { ptr.sub(1) };
let z = unsafe { **ptr };
ch = utf8_first_byte(z, 2);
if utf8_is_cont_byte(z) {
// SAFETY: `bytes` produces an UTF-8-like string,
// so the iterator must produce a value here.
*ptr = unsafe { ptr.offset(-1) };
*ptr = unsafe { ptr.sub(1) };
let y = unsafe { **ptr };
ch = utf8_first_byte(y, 3);
if utf8_is_cont_byte(y) {
// SAFETY: `bytes` produces an UTF-8-like string,
// so the iterator must produce a value here.
*ptr = unsafe { ptr.offset(-1) };
*ptr = unsafe { ptr.sub(1) };
let x = unsafe { **ptr };
ch = utf8_first_byte(x, 4);
ch = utf8_acc_cont_byte(ch, y);
+4 -4
View File
@@ -564,7 +564,7 @@ pub(crate) mod _asyncio {
let args = if let Some(ctx) = context {
FuncArgs::new(
vec![callback, future_arg],
KwArgs::new([("context".to_owned(), ctx)].into_iter().collect()),
KwArgs::new(core::iter::once(("context".to_owned(), ctx)).collect()),
)
} else {
FuncArgs::new(vec![callback, future_arg], KwArgs::default())
@@ -1494,7 +1494,7 @@ pub(crate) mod _asyncio {
let args = if let Some(ctx) = context {
FuncArgs::new(
vec![callback, task_arg],
KwArgs::new([("context".to_owned(), ctx)].into_iter().collect()),
KwArgs::new(core::iter::once(("context".to_owned(), ctx)).collect()),
)
} else {
FuncArgs::new(vec![callback, task_arg], KwArgs::default())
@@ -1522,7 +1522,7 @@ pub(crate) mod _asyncio {
let cancel_args = if let Some(ref m) = msg_value {
FuncArgs::new(
vec![],
KwArgs::new([("msg".to_owned(), m.clone())].into_iter().collect()),
KwArgs::new(core::iter::once(("msg".to_owned(), m.clone())).collect()),
)
} else {
FuncArgs::new(vec![], KwArgs::default())
@@ -2202,7 +2202,7 @@ pub(crate) mod _asyncio {
let cancel_args = if let Some(ref m) = cancel_msg {
FuncArgs::new(
vec![],
KwArgs::new([("msg".to_owned(), m.clone())].into_iter().collect()),
KwArgs::new(core::iter::once(("msg".to_owned(), m.clone())).collect()),
)
} else {
FuncArgs::new(vec![], KwArgs::default())
+5 -4
View File
@@ -382,10 +382,10 @@ impl PyDict {
default: OptionalArg<PyObjectRef>,
vm: &VirtualMachine,
) -> PyResult {
match self.entries.get(vm, &*key)? {
Some(value) => Ok(value),
None => Ok(default.unwrap_or_none(vm)),
}
Ok(self
.entries
.get(vm, &*key)?
.unwrap_or_else(|| default.unwrap_or_none(vm)))
}
#[pymethod]
@@ -400,6 +400,7 @@ impl PyDict {
}
#[pymethod]
#[must_use]
pub fn copy(&self) -> Self {
Self {
entries: self.entries.clone(),
+3
View File
@@ -70,6 +70,7 @@ impl GetDescriptor for PyGetSet {
}
impl PyGetSet {
#[must_use]
pub fn new(name: String, class: &'static Py<PyType>) -> Self {
Self {
name,
@@ -79,6 +80,7 @@ impl PyGetSet {
}
}
#[must_use]
pub fn with_get<G, X>(mut self, getter: G) -> Self
where
G: IntoPyGetterFunc<X>,
@@ -87,6 +89,7 @@ impl PyGetSet {
self
}
#[must_use]
pub fn with_set<S, X>(mut self, setter: S) -> Self
where
S: IntoPySetterFunc<X>,
+2 -1
View File
@@ -117,7 +117,8 @@ impl PyMemoryView {
Ok(zelf)
}
/// this should be the only way to create a memoryview from another memoryview
/// this should be the only way to create a memoryview from another memoryview.
#[must_use]
pub fn new_view(&self) -> Self {
let zelf = Self {
buffer: self.buffer.clone(),
+8 -10
View File
@@ -1886,22 +1886,20 @@ impl ToPyObject for Wtf8Buf {
impl ToPyObject for char {
fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef {
let cp = self as u32;
if cp <= u8::MAX as u32 {
vm.ctx.latin1_char(cp as u8).into()
} else {
vm.ctx.new_str(self).into()
}
u8::try_from(cp).map_or_else(
|_| vm.ctx.new_str(self).into(),
|v| vm.ctx.latin1_char(v).into(),
)
}
}
impl ToPyObject for CodePoint {
fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef {
let cp = self.to_u32();
if cp <= u8::MAX as u32 {
vm.ctx.latin1_char(cp as u8).into()
} else {
vm.ctx.new_str(self).into()
}
u8::try_from(cp).map_or_else(
|_| vm.ctx.new_str(self).into(),
|v| vm.ctx.latin1_char(v).into(),
)
}
}
+3 -1
View File
@@ -407,7 +407,9 @@ impl PyBytesInner {
let mut new: Vec<u8> = Vec::with_capacity(self.elements.len());
if let Some((first, second)) = self.elements.split_first() {
new.push(first.to_ascii_uppercase());
second.iter().for_each(|x| new.push(x.to_ascii_lowercase()));
for x in second {
new.push(x.to_ascii_lowercase());
}
}
new
}
+1 -1
View File
@@ -8933,7 +8933,7 @@ impl ExecutingFrame<'_> {
} else if iter.downcast_ref_if_exact::<PyTupleIterator>(vm).is_some() {
Some(Instruction::ForIterTuple)
} else if iter.downcast_ref_if_exact::<PyGenerator>(vm).is_some()
&& jump_delta <= i16::MAX as u32
&& i16::try_from(jump_delta).is_ok()
&& self.for_iter_has_end_for_shape(instr_idx, jump_delta)
&& !self.specialization_eval_frame_active(vm)
{
+1 -1
View File
@@ -1129,7 +1129,7 @@ pub mod sys {
let tb_module = vm.import("traceback", 0)?;
let print_tb = tb_module.get_attr("print_tb", vm)?;
let stderr_obj = super::get_stderr(vm)?;
let kwargs: KwArgs = [("file".to_string(), stderr_obj)].into_iter().collect();
let kwargs: KwArgs = core::iter::once(("file".to_string(), stderr_obj)).collect();
let _ = print_tb.call(
FuncArgs::new(vec![unraisable.exc_traceback.clone()], kwargs),
vm,
+3 -6
View File
@@ -1503,16 +1503,13 @@ mod tests {
#[test]
fn find_by_name() {
// __len__ appears in both sequence and mapping
let len_defs: Vec<_> = find_slot_defs_by_name("__len__").collect();
assert_eq!(len_defs.len(), 2);
assert_eq!(find_slot_defs_by_name("__len__").count(), 2);
// __init__ appears once
let init_defs: Vec<_> = find_slot_defs_by_name("__init__").collect();
assert_eq!(init_defs.len(), 1);
assert_eq!(find_slot_defs_by_name("__init__").count(), 1);
// __add__ appears in number (left/right) and sequence
let add_defs: Vec<_> = find_slot_defs_by_name("__add__").collect();
assert_eq!(add_defs.len(), 2); // NbAdd(Left) and SqConcat
assert_eq!(find_slot_defs_by_name("__add__").count(), 2); // NbAdd(Left) and SqConcat
}
#[test]
+2
View File
@@ -229,6 +229,7 @@ impl InterpreterBuilder {
/// })
/// .build();
/// ```
#[must_use]
pub fn init_hook<F>(mut self, init: F) -> Self
where
F: FnOnce(&mut VirtualMachine) + 'static,
@@ -250,6 +251,7 @@ impl InterpreterBuilder {
/// // In practice: .add_frozen_modules(rustpython_pylib::FROZEN_STDLIB)
/// .build();
/// ```
#[must_use]
pub fn add_frozen_modules<I>(mut self, frozen: I) -> Self
where
I: IntoIterator<Item = (&'static str, FrozenModule)>,