diff --git a/Cargo.toml b/Cargo.toml index eda23858f3c..2cd468d07bd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" diff --git a/crates/capi/src/traceback.rs b/crates/capi/src/traceback.rs index 5b264b1ddbc..8728ba5fab5 100644 --- a/crates/capi/src/traceback.rs +++ b/crates/capi/src/traceback.rs @@ -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(()) diff --git a/crates/common/src/boxvec.rs b/crates/common/src/boxvec.rs index 675420259cb..42a9935dc30 100644 --- a/crates/common/src/boxvec.rs +++ b/crates/common/src/boxvec.rs @@ -127,7 +127,7 @@ impl BoxVec { 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); diff --git a/crates/common/src/cformat.rs b/crates/common/src/cformat.rs index 7dbe1076975..373fdebe13a 100644 --- a/crates/common/src/cformat.rs +++ b/crates/common/src/cformat.rs @@ -160,16 +160,22 @@ pub trait FormatBuf: Extend + Default + FromIterator + From { type Char: FormatChar; + fn chars(&self) -> impl Iterator; + 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 + From { fn to_char_lossy(self) -> char; + fn eq_char(self, c: char) -> bool; } diff --git a/crates/derive-impl/src/pyclass.rs b/crates/derive-impl/src/pyclass.rs index 0cc0faa113a..d892db17ef6 100644 --- a/crates/derive-impl/src/pyclass.rs +++ b/crates/derive-impl/src/pyclass.rs @@ -1671,11 +1671,14 @@ impl ItemMeta for SlotItemMeta { I: core::iter::Iterator, { 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()) diff --git a/crates/jit/src/instructions.rs b/crates/jit/src/instructions.rs index 61780a243c0..6aff9f093e5 100644 --- a/crates/jit/src/instructions.rs +++ b/crates/jit/src/instructions.rs @@ -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 diff --git a/crates/sre_engine/src/string.rs b/crates/sre_engine/src/string.rs index 83b80ad81f9..6c8b9a567b4 100644 --- a/crates/sre_engine/src/string.rs +++ b/crates/sre_engine/src/string.rs @@ -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); diff --git a/crates/stdlib/src/_asyncio.rs b/crates/stdlib/src/_asyncio.rs index 90114900e89..ee5e207d4d4 100644 --- a/crates/stdlib/src/_asyncio.rs +++ b/crates/stdlib/src/_asyncio.rs @@ -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()) diff --git a/crates/vm/src/builtins/dict.rs b/crates/vm/src/builtins/dict.rs index 4b2b7c7541e..b1a2d1a493b 100644 --- a/crates/vm/src/builtins/dict.rs +++ b/crates/vm/src/builtins/dict.rs @@ -342,10 +342,10 @@ impl PyDict { default: OptionalArg, 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] @@ -360,6 +360,7 @@ impl PyDict { } #[pymethod] + #[must_use] pub fn copy(&self) -> Self { Self { entries: self.entries.clone(), diff --git a/crates/vm/src/builtins/getset.rs b/crates/vm/src/builtins/getset.rs index ff132fb7471..ab538922a76 100644 --- a/crates/vm/src/builtins/getset.rs +++ b/crates/vm/src/builtins/getset.rs @@ -70,6 +70,7 @@ impl GetDescriptor for PyGetSet { } impl PyGetSet { + #[must_use] pub fn new(name: String, class: &'static Py) -> Self { Self { name, @@ -79,6 +80,7 @@ impl PyGetSet { } } + #[must_use] pub fn with_get(mut self, getter: G) -> Self where G: IntoPyGetterFunc, @@ -87,6 +89,7 @@ impl PyGetSet { self } + #[must_use] pub fn with_set(mut self, setter: S) -> Self where S: IntoPySetterFunc, diff --git a/crates/vm/src/builtins/memory.rs b/crates/vm/src/builtins/memory.rs index d063bf0144f..ec622896555 100644 --- a/crates/vm/src/builtins/memory.rs +++ b/crates/vm/src/builtins/memory.rs @@ -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(), diff --git a/crates/vm/src/builtins/str.rs b/crates/vm/src/builtins/str.rs index 212b14c7487..69109c943e8 100644 --- a/crates/vm/src/builtins/str.rs +++ b/crates/vm/src/builtins/str.rs @@ -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(), + ) } } diff --git a/crates/vm/src/bytes_inner.rs b/crates/vm/src/bytes_inner.rs index 983e5f6328b..08518deb1c4 100644 --- a/crates/vm/src/bytes_inner.rs +++ b/crates/vm/src/bytes_inner.rs @@ -407,7 +407,9 @@ impl PyBytesInner { let mut new: Vec = 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 } diff --git a/crates/vm/src/frame.rs b/crates/vm/src/frame.rs index f1ed31d7189..a59de0a4aed 100644 --- a/crates/vm/src/frame.rs +++ b/crates/vm/src/frame.rs @@ -8933,7 +8933,7 @@ impl ExecutingFrame<'_> { } else if iter.downcast_ref_if_exact::(vm).is_some() { Some(Instruction::ForIterTuple) } else if iter.downcast_ref_if_exact::(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) { diff --git a/crates/vm/src/stdlib/sys.rs b/crates/vm/src/stdlib/sys.rs index 5e3ba265eaa..dbce74a5ddb 100644 --- a/crates/vm/src/stdlib/sys.rs +++ b/crates/vm/src/stdlib/sys.rs @@ -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, diff --git a/crates/vm/src/types/slot_defs.rs b/crates/vm/src/types/slot_defs.rs index 956bc6fa4d1..8637f811272 100644 --- a/crates/vm/src/types/slot_defs.rs +++ b/crates/vm/src/types/slot_defs.rs @@ -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] diff --git a/crates/vm/src/vm/interpreter.rs b/crates/vm/src/vm/interpreter.rs index ecdfea01a29..770e493415e 100644 --- a/crates/vm/src/vm/interpreter.rs +++ b/crates/vm/src/vm/interpreter.rs @@ -229,6 +229,7 @@ impl InterpreterBuilder { /// }) /// .build(); /// ``` + #[must_use] pub fn init_hook(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(mut self, frozen: I) -> Self where I: IntoIterator,