diff --git a/Cargo.toml b/Cargo.toml index 4781c95e101..ca034e8dc54 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -370,14 +370,17 @@ search_is_some = "warn" significant_drop_in_scrutinee = "warn" single_option_map = "warn" trait_duplication_in_bounds = "warn" +tuple_array_conversions = "warn" type_repetition_in_bounds = "warn" unnecessary_struct_initialization = "warn" 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" bool_to_int_with_if = "warn" checked_conversions = "warn" cloned_instead_of_copied = "warn" @@ -403,6 +406,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/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/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) } 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/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/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/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")] 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")] 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;