Add more clippy rules (#8183)

* clippy `assigning_clones`

* string_lit_as_bytes

* tuple_array_conversions

* while_float

* manual_assert

* Revert "string_lit_as_bytes"

This reverts commit f40f756440.
This commit is contained in:
Shahar Naveh authored and GitHub committed 2026-06-30 23:40:29 +09:00
1 parent eae567ff33
commit 12b8305249
12 files changed
+43 -35

No files matched your search

+4
View File
@@ -371,14 +371,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"
@@ -404,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"
+1 -1
View File
@@ -2157,7 +2157,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");
}
}
+2 -1
View File
@@ -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 {
+2 -2
View File
@@ -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;
+10 -9
View File
@@ -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<T: Hash + ?Sized>(&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<PyHash> {
pub const fn hash_float(value: f64) -> Option<PyHash> {
// cpython _Py_HashDouble
if !value.is_finite() {
return if value.is_infinite() {
@@ -111,6 +109,8 @@ pub fn hash_float(value: f64) -> Option<PyHash> {
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<PyHash> {
#[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)
}
+5
View File
@@ -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()
+4 -3
View File
@@ -57,9 +57,10 @@ const fn zst_ref_out_of_thin_air<T: 'static>(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::<T>() != 0 {
panic!("can't use a non-zero-sized type here")
}
assert!(
core::mem::size_of::<T>() == 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::<T>::dangling().as_ref() }
+3 -3
View File
@@ -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() {
+3 -4
View File
@@ -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")]
+4 -5
View File
@@ -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);
+1 -3
View File
@@ -908,9 +908,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")]
+4 -4
View File
@@ -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;