From afc11890b9752de519c38f80afa41ad4b2db3c35 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Sat, 27 Jun 2026 12:50:48 +0300 Subject: [PATCH 1/7] clippy `assigning_clones` --- Cargo.toml | 1 + crates/codegen/src/compile.rs | 2 +- crates/codegen/src/symboltable.rs | 3 ++- crates/vm/src/getpath.rs | 6 +++--- crates/vm/src/vm/vm_new.rs | 8 ++++---- 5 files changed, 11 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4781c95e101..41432a98bb5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -378,6 +378,7 @@ use_self = "warn" useless_let_if_seq = "warn" # pedantic lints to enforce gradually +assigning_clones = "warn" bool_to_int_with_if = "warn" checked_conversions = "warn" cloned_instead_of_copied = "warn" diff --git a/crates/codegen/src/compile.rs b/crates/codegen/src/compile.rs index 711ac392694..c63647f613a 100644 --- a/crates/codegen/src/compile.rs +++ b/crates/codegen/src/compile.rs @@ -2073,7 +2073,7 @@ impl<'warnings> Compiler<'warnings> { fn expose_annotation_format_parameter(code: &mut CodeObject) { if let Some(first) = code.varnames.first_mut() { - *first = "format".to_owned(); + *first = String::from("format"); } } diff --git a/crates/codegen/src/symboltable.rs b/crates/codegen/src/symboltable.rs index a78b49a6e90..a72b839f400 100644 --- a/crates/codegen/src/symboltable.rs +++ b/crates/codegen/src/symboltable.rs @@ -1632,8 +1632,9 @@ impl SymbolTableBuilder { } if type_params.is_none() { - self.class_name = prev_class.clone(); + self.class_name.clone_from(&prev_class); } + if let Some(arguments) = arguments { self.scan_expressions(&arguments.args, ExpressionContext::Load)?; for keyword in &arguments.keywords { diff --git a/crates/vm/src/getpath.rs b/crates/vm/src/getpath.rs index 38aa122db49..63454720178 100644 --- a/crates/vm/src/getpath.rs +++ b/crates/vm/src/getpath.rs @@ -121,7 +121,7 @@ pub fn init_path_config(settings: &Settings) -> Paths { // - sys.executable should be the launcher path (where user invoked Python) // - sys._base_executable should be the real Python executable let exe_dir = if let Ok(launcher) = crate::host_env::os::var("__PYVENV_LAUNCHER__") { - paths.executable = launcher.clone(); + paths.executable.clone_from(&launcher); paths.base_executable = real_executable; PathBuf::from(&launcher).parent().map(PathBuf::from) } else { @@ -152,7 +152,7 @@ pub fn init_path_config(settings: &Settings) -> Paths { paths.base_prefix = calculated_prefix; } else { // Not in venv: prefix == base_prefix - paths.prefix = calculated_prefix.clone(); + paths.prefix.clone_from(&calculated_prefix); paths.base_prefix = calculated_prefix; } @@ -163,7 +163,7 @@ pub fn init_path_config(settings: &Settings) -> Paths { } else { calculate_exec_prefix(search_dir.as_ref(), paths.prefix.as_ref()) }; - paths.base_exec_prefix = paths.base_prefix.clone(); + paths.base_exec_prefix.clone_from(&paths.base_prefix); // Step 7: Calculate base_executable (if not already set by __PYVENV_LAUNCHER__) if paths.base_executable.is_empty() { diff --git a/crates/vm/src/vm/vm_new.rs b/crates/vm/src/vm/vm_new.rs index 2c053bdf838..c71cf842520 100644 --- a/crates/vm/src/vm/vm_new.rs +++ b/crates/vm/src/vm/vm_new.rs @@ -794,10 +794,10 @@ impl VirtualMachine { }; if syntax_error_type.is(self.ctx.exceptions.tab_error) { - syntax_error_info.msg = "inconsistent use of tabs and spaces in indentation".to_owned(); - } - if syntax_error_type.is(self.ctx.exceptions.incomplete_input_error) { - syntax_error_info.msg = "incomplete input".to_owned(); + syntax_error_info.msg = + String::from("inconsistent use of tabs and spaces in indentation"); + } else if syntax_error_type.is(self.ctx.exceptions.incomplete_input_error) { + syntax_error_info.msg = String::from("incomplete input"); } let SyntaxErrorInfo { msg, narrow_caret } = syntax_error_info; From f40f7564407c1378e0118a621eff782666536fc2 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Sat, 27 Jun 2026 13:17:39 +0300 Subject: [PATCH 2/7] string_lit_as_bytes --- Cargo.toml | 1 + crates/common/src/int.rs | 4 ++-- crates/stdlib/src/json.rs | 16 ++++++++-------- crates/vm/src/builtins/bytes.rs | 13 +++++++++++++ 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 41432a98bb5..0f7591e820b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -369,6 +369,7 @@ redundant_clone = "warn" search_is_some = "warn" significant_drop_in_scrutinee = "warn" single_option_map = "warn" +string_lit_as_bytes = "warn" trait_duplication_in_bounds = "warn" type_repetition_in_bounds = "warn" unnecessary_struct_initialization = "warn" diff --git a/crates/common/src/int.rs b/crates/common/src/int.rs index 0a8f054bf1a..8efbef69840 100644 --- a/crates/common/src/int.rs +++ b/crates/common/src/int.rs @@ -195,7 +195,7 @@ mod tests { fn bytes_to_int_invalid_base() { for base in [1, 37] { assert_eq!( - bytes_to_int("012345".as_bytes(), base, DIGIT_LIMIT), + bytes_to_int(b"012345", base, DIGIT_LIMIT), Err(BytesToIntError::InvalidBase) ) } @@ -204,7 +204,7 @@ mod tests { #[test] fn bytes_to_int_digit_limit() { assert_eq!( - bytes_to_int("012345".as_bytes(), 10, 5), + bytes_to_int(b"012345", 10, 5), Err(BytesToIntError::DigitLimit { got: 6, limit: 5 }) ); } diff --git a/crates/stdlib/src/json.rs b/crates/stdlib/src/json.rs index dc2fbbc8892..b3b70acc906 100644 --- a/crates/stdlib/src/json.rs +++ b/crates/stdlib/src/json.rs @@ -146,7 +146,7 @@ mod _json { macro_rules! parse_const { ($s:literal, $val:expr) => { - if rest.starts_with($s.as_bytes()) { + if rest.starts_with($s) { return Ok(PyIterReturn::Return( vm.new_tuple(($val, char_idx + $s.len())).into(), )); @@ -154,9 +154,9 @@ mod _json { }; } - parse_const!("null", vm.ctx.none()); - parse_const!("true", true); - parse_const!("false", false); + parse_const!(b"null", vm.ctx.none()); + parse_const!(b"true", true); + parse_const!(b"false", false); if let Some((res, len)) = self.parse_number(rest, vm) { return Ok(PyIterReturn::Return( @@ -166,7 +166,7 @@ mod _json { macro_rules! parse_constant { ($s:literal) => { - if rest.starts_with($s.as_bytes()) { + if rest.starts_with($s) { return Ok(PyIterReturn::Return( vm.new_tuple(( self.parse_constant.call(($s,), vm)?, @@ -178,9 +178,9 @@ mod _json { }; } - parse_constant!("NaN"); - parse_constant!("Infinity"); - parse_constant!("-Infinity"); + parse_constant!(b"NaN"); + parse_constant!(b"Infinity"); + parse_constant!(b"-Infinity"); Ok(PyIterReturn::StopIteration(Some( vm.ctx.new_int(char_idx).into(), diff --git a/crates/vm/src/builtins/bytes.rs b/crates/vm/src/builtins/bytes.rs index f28e8ddbbd8..00a5e95f4cc 100644 --- a/crates/vm/src/builtins/bytes.rs +++ b/crates/vm/src/builtins/bytes.rs @@ -60,6 +60,18 @@ impl ToPyObject for Vec { } } +impl ToPyObject for [u8; N] { + fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef { + vm.ctx.new_bytes(self.into()).into() + } +} + +impl ToPyObject for &[u8; N] { + fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef { + vm.ctx.new_bytes(self.into()).into() + } +} + impl Deref for PyBytes { type Target = [u8]; @@ -73,6 +85,7 @@ impl AsRef<[u8]> for PyBytes { self.as_bytes() } } + impl AsRef<[u8]> for PyBytesRef { fn as_ref(&self) -> &[u8] { self.as_bytes() From 49d697b14c23f998ccb96004710bdc6a638259bc Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Sat, 27 Jun 2026 13:21:24 +0300 Subject: [PATCH 3/7] tuple_array_conversions --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index 0f7591e820b..6669f709c8a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -371,6 +371,7 @@ significant_drop_in_scrutinee = "warn" single_option_map = "warn" string_lit_as_bytes = "warn" trait_duplication_in_bounds = "warn" +tuple_array_conversions = "warn" type_repetition_in_bounds = "warn" unnecessary_struct_initialization = "warn" unused_peekable = "warn" From f7163ee4abf1be56da252cdc23f4092a6ef6af9a Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Sat, 27 Jun 2026 13:50:06 +0300 Subject: [PATCH 4/7] while_float --- Cargo.toml | 1 + crates/common/src/float_ops.rs | 4 ++-- crates/common/src/hash.rs | 19 ++++++++++--------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 6669f709c8a..3166dc958e1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -378,6 +378,7 @@ unused_peekable = "warn" unused_rounding = "warn" use_self = "warn" useless_let_if_seq = "warn" +while_float = "warn" # pedantic lints to enforce gradually assigning_clones = "warn" diff --git a/crates/common/src/float_ops.rs b/crates/common/src/float_ops.rs index fed080dcec8..f643961534a 100644 --- a/crates/common/src/float_ops.rs +++ b/crates/common/src/float_ops.rs @@ -4,8 +4,8 @@ use num_traits::{Signed, ToPrimitive}; #[must_use] pub const fn decompose_float(value: f64) -> (f64, i32) { - if 0.0 == value { - (0.0, 0i32) + if value == 0.0 { + (0.0, 0) } else { let bits = value.to_bits(); let exponent: i32 = ((bits >> 52) & 0x7ff) as i32 - 1022; diff --git a/crates/common/src/hash.rs b/crates/common/src/hash.rs index 5b16c89e7bc..91fd5e1cba0 100644 --- a/crates/common/src/hash.rs +++ b/crates/common/src/hash.rs @@ -49,9 +49,7 @@ impl HashSecret { let k1 = u64::from_le_bytes(right.try_into().unwrap()); Self { k0, k1 } } -} -impl HashSecret { pub fn hash_value(&self, data: &T) -> PyHash { fix_sentinel(mod_int(self.hash_one(data) as _)) } @@ -94,7 +92,7 @@ pub const fn hash_pointer(value: usize) -> PyHash { #[inline] #[must_use] -pub fn hash_float(value: f64) -> Option { +pub const fn hash_float(value: f64) -> Option { // cpython _Py_HashDouble if !value.is_finite() { return if value.is_infinite() { @@ -111,6 +109,8 @@ pub fn hash_float(value: f64) -> Option { let mut m = frexp.0; let mut e = frexp.1; let mut x: PyUHash = 0; + + #[expect(clippy::while_float, reason = "keep this loop like CPython does it")] while m != 0.0 { x = ((x << 28) & MODULUS) | (x >> (BITS - 28)); m *= 268_435_456.0; // 2**28 @@ -137,13 +137,14 @@ pub fn hash_float(value: f64) -> Option { #[must_use] pub fn hash_bigint(value: &BigInt) -> PyHash { - let ret = match value.to_i64() { - Some(i) => mod_int(i), - None => (value % MODULUS).to_i64().unwrap_or_else(|| unsafe { - // SAFETY: MODULUS < i64::MAX, so value % MODULUS is guaranteed to be in the range of i64 - core::hint::unreachable_unchecked() - }), + let ret = if let Some(v) = value.to_i64() { + mod_int(v) + } else { + // SAFETY: + // MODULUS < i64::MAX, so value % MODULUS is guaranteed to be in the range of i64 + unsafe { (value % MODULUS).to_i64().unwrap_unchecked() } }; + fix_sentinel(ret) } From e1d133163b637c2e393982ee8e064355dd2d4acd Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Sat, 27 Jun 2026 13:55:37 +0300 Subject: [PATCH 5/7] manual_assert --- Cargo.toml | 1 + crates/vm/src/function/builtin.rs | 7 ++++--- crates/vm/src/types/slot.rs | 9 ++++----- crates/vm/src/vm/mod.rs | 4 +--- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 3166dc958e1..105ce4b763d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -407,6 +407,7 @@ iter_filter_is_ok = "warn" iter_filter_is_some = "warn" large_futures = "warn" large_types_passed_by_value = "warn" +manual_assert = "warn" manual_instant_elapsed = "warn" manual_is_variant_and = "warn" map_unwrap_or = "warn" diff --git a/crates/vm/src/function/builtin.rs b/crates/vm/src/function/builtin.rs index 47cb8dfcb64..a2753bdf145 100644 --- a/crates/vm/src/function/builtin.rs +++ b/crates/vm/src/function/builtin.rs @@ -57,9 +57,10 @@ const fn zst_ref_out_of_thin_air(x: T) -> &'static T { // operation. if T isn't zero-sized, we don't have to worry about it because we'll fail to compile. core::mem::forget(x); const { - if core::mem::size_of::() != 0 { - panic!("can't use a non-zero-sized type here") - } + assert!( + core::mem::size_of::() == 0, + "can't use a non-zero-sized type here" + ); // SAFETY: we just confirmed that T is zero-sized, so we can // pull a value of it out of thin air. unsafe { core::ptr::NonNull::::dangling().as_ref() } diff --git a/crates/vm/src/types/slot.rs b/crates/vm/src/types/slot.rs index 4197e1554aa..83d9706cb33 100644 --- a/crates/vm/src/types/slot.rs +++ b/crates/vm/src/types/slot.rs @@ -1667,11 +1667,10 @@ pub trait Initializer: PyPayload { .matches(&class_name_for_debug as &str) .count() == 2; - if double_appearance { - panic!( - "This type `{class_name_for_debug}` doesn't seem to support `init`. Override `slot_init` instead: {msg}" - ); - } + assert!( + !double_appearance, + "This type `{class_name_for_debug}` doesn't seem to support `init`. Override `slot_init` instead: {msg}" + ) } } return Err(err); diff --git a/crates/vm/src/vm/mod.rs b/crates/vm/src/vm/mod.rs index 32a2906fa84..3ca5a083783 100644 --- a/crates/vm/src/vm/mod.rs +++ b/crates/vm/src/vm/mod.rs @@ -883,9 +883,7 @@ impl VirtualMachine { fn initialize(&mut self) { flame_guard!("init VirtualMachine"); - if self.initialized { - panic!("Double Initialize Error"); - } + assert!(!self.initialized, "Double Initialize Error"); // Initialize main thread ident before any threading operations #[cfg(feature = "threading")] From 8fe18a2c32781be7ef1cf0fc3261034a79c64118 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Sun, 28 Jun 2026 10:07:23 +0300 Subject: [PATCH 6/7] Revert "string_lit_as_bytes" This reverts commit f40f7564407c1378e0118a621eff782666536fc2. --- Cargo.toml | 1 - crates/common/src/int.rs | 4 ++-- crates/stdlib/src/json.rs | 16 ++++++++-------- crates/vm/src/builtins/bytes.rs | 13 ------------- 4 files changed, 10 insertions(+), 24 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 105ce4b763d..ca034e8dc54 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -369,7 +369,6 @@ redundant_clone = "warn" search_is_some = "warn" significant_drop_in_scrutinee = "warn" single_option_map = "warn" -string_lit_as_bytes = "warn" trait_duplication_in_bounds = "warn" tuple_array_conversions = "warn" type_repetition_in_bounds = "warn" diff --git a/crates/common/src/int.rs b/crates/common/src/int.rs index 8efbef69840..0a8f054bf1a 100644 --- a/crates/common/src/int.rs +++ b/crates/common/src/int.rs @@ -195,7 +195,7 @@ mod tests { fn bytes_to_int_invalid_base() { for base in [1, 37] { assert_eq!( - bytes_to_int(b"012345", base, DIGIT_LIMIT), + bytes_to_int("012345".as_bytes(), base, DIGIT_LIMIT), Err(BytesToIntError::InvalidBase) ) } @@ -204,7 +204,7 @@ mod tests { #[test] fn bytes_to_int_digit_limit() { assert_eq!( - bytes_to_int(b"012345", 10, 5), + bytes_to_int("012345".as_bytes(), 10, 5), Err(BytesToIntError::DigitLimit { got: 6, limit: 5 }) ); } diff --git a/crates/stdlib/src/json.rs b/crates/stdlib/src/json.rs index b3b70acc906..dc2fbbc8892 100644 --- a/crates/stdlib/src/json.rs +++ b/crates/stdlib/src/json.rs @@ -146,7 +146,7 @@ mod _json { macro_rules! parse_const { ($s:literal, $val:expr) => { - if rest.starts_with($s) { + if rest.starts_with($s.as_bytes()) { return Ok(PyIterReturn::Return( vm.new_tuple(($val, char_idx + $s.len())).into(), )); @@ -154,9 +154,9 @@ mod _json { }; } - parse_const!(b"null", vm.ctx.none()); - parse_const!(b"true", true); - parse_const!(b"false", false); + parse_const!("null", vm.ctx.none()); + parse_const!("true", true); + parse_const!("false", false); if let Some((res, len)) = self.parse_number(rest, vm) { return Ok(PyIterReturn::Return( @@ -166,7 +166,7 @@ mod _json { macro_rules! parse_constant { ($s:literal) => { - if rest.starts_with($s) { + if rest.starts_with($s.as_bytes()) { return Ok(PyIterReturn::Return( vm.new_tuple(( self.parse_constant.call(($s,), vm)?, @@ -178,9 +178,9 @@ mod _json { }; } - parse_constant!(b"NaN"); - parse_constant!(b"Infinity"); - parse_constant!(b"-Infinity"); + parse_constant!("NaN"); + parse_constant!("Infinity"); + parse_constant!("-Infinity"); Ok(PyIterReturn::StopIteration(Some( vm.ctx.new_int(char_idx).into(), diff --git a/crates/vm/src/builtins/bytes.rs b/crates/vm/src/builtins/bytes.rs index 00a5e95f4cc..f28e8ddbbd8 100644 --- a/crates/vm/src/builtins/bytes.rs +++ b/crates/vm/src/builtins/bytes.rs @@ -60,18 +60,6 @@ impl ToPyObject for Vec { } } -impl ToPyObject for [u8; N] { - fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef { - vm.ctx.new_bytes(self.into()).into() - } -} - -impl ToPyObject for &[u8; N] { - fn to_pyobject(self, vm: &VirtualMachine) -> PyObjectRef { - vm.ctx.new_bytes(self.into()).into() - } -} - impl Deref for PyBytes { type Target = [u8]; @@ -85,7 +73,6 @@ impl AsRef<[u8]> for PyBytes { self.as_bytes() } } - impl AsRef<[u8]> for PyBytesRef { fn as_ref(&self) -> &[u8] { self.as_bytes() From 5bf2a0c0cb34102506327cb08bb3d6cdb1011db0 Mon Sep 17 00:00:00 2001 From: ShaharNaveh <50263213+ShaharNaveh@users.noreply.github.com> Date: Sun, 28 Jun 2026 10:18:15 +0300 Subject: [PATCH 7/7] fix jit --- crates/jit/src/instructions.rs | 5 +++++ crates/vm/src/stdlib/os.rs | 7 +++---- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/crates/jit/src/instructions.rs b/crates/jit/src/instructions.rs index 6aff9f093e5..9b4656da5ad 100644 --- a/crates/jit/src/instructions.rs +++ b/crates/jit/src/instructions.rs @@ -666,6 +666,11 @@ impl<'a, 'b> FunctionCompiler<'a, 'b> { | Instruction::LoadFastBorrowLoadFastBorrow { var_nums } => { let oparg = var_nums.get(arg); let (idx1, idx2) = oparg.indexes(); + + #[expect( + clippy::tuple_array_conversions, + reason = "Seems like a false positive" + )] for idx in [idx1, idx2] { let local = self.variables[idx] .as_ref() diff --git a/crates/vm/src/stdlib/os.rs b/crates/vm/src/stdlib/os.rs index 4a1cbe2aecd..3c216168f3f 100644 --- a/crates/vm/src/stdlib/os.rs +++ b/crates/vm/src/stdlib/os.rs @@ -1795,9 +1795,9 @@ pub(super) mod _os { #[cfg(all(unix, not(any(target_os = "redox", target_os = "android"))))] #[pyfunction] fn getloadavg(vm: &VirtualMachine) -> PyResult<(f64, f64, f64)> { - let loadavg = crate::host_env::time::getloadavg() - .map_err(|_| vm.new_os_error("Load averages are unobtainable"))?; - Ok((loadavg[0], loadavg[1], loadavg[2])) + crate::host_env::time::getloadavg() + .map(Into::into) + .map_err(|_| vm.new_os_error("Load averages are unobtainable")) } #[cfg(unix)] @@ -1918,7 +1918,6 @@ pub(super) mod _os { } } - /// Perform a statvfs system call on the given path. #[cfg(all(unix, not(target_os = "redox")))] #[pyfunction] #[pyfunction(name = "fstatvfs")]