clippy significant_drop_in_scrutinee & explicit_deref_methods (#8104)

This commit is contained in:
Shahar Naveh authored and GitHub committed 2026-06-15 11:21:13 +09:00
1 parent 7da696661b
commit 72052484ca
22 files changed
+124 -71

No files matched your search

+2
View File
@@ -373,6 +373,7 @@ needless_collect = "warn"
or_fun_call = "warn"
redundant_clone = "warn"
search_is_some = "warn"
significant_drop_in_scrutinee = "warn"
single_option_map = "warn"
trait_duplication_in_bounds = "warn"
unused_peekable = "warn"
@@ -386,6 +387,7 @@ cloned_instead_of_copied = "warn"
collapsible_else_if = "warn"
comparison_chain = "warn"
duration_suboptimal_units = "warn"
explicit_deref_methods = "warn"
explicit_into_iter_loop = "warn"
explicit_iter_loop = "warn"
filter_map_next = "warn"
+1 -1
View File
@@ -68,7 +68,7 @@ impl<T: ?Sized> Deref for BorrowedValue<'_, T> {
impl fmt::Display for BorrowedValue<'_, str> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
fmt::Display::fmt(self.deref(), f)
fmt::Display::fmt(&**self, f)
}
}
+1 -1
View File
@@ -1054,7 +1054,7 @@ impl FormatSpec {
cmp::max(0, (w as i32) - (num_chars as i32) - (sign_str.len() as i32))
});
let magnitude_str = magnitude_str.deref();
let magnitude_str = &**magnitude_str;
match align {
FormatAlign::Left => format!(
"{}{}{}",
+30 -19
View File
@@ -224,10 +224,12 @@ pub(crate) mod _asyncio {
}
FutureState::Finished => {
self.fut_log_tb.store(false, Ordering::Relaxed);
if let Some(exc) = self.fut_exception.read().clone() {
let fut_exception = self.fut_exception.read().clone();
if let Some(exc) = fut_exception {
let exc: PyBaseExceptionRef = exc.downcast().unwrap();
// Restore the original traceback to prevent traceback accumulation
if let Some(tb) = self.fut_exception_tb.read().clone() {
let fut_exception_tb = self.fut_exception_tb.read().clone();
if let Some(tb) = fut_exception_tb {
let _ = exc.set___traceback__(tb, vm);
}
Err(exc)
@@ -612,7 +614,8 @@ pub(crate) mod _asyncio {
fn _callbacks(&self, vm: &VirtualMachine) -> PyObjectRef {
let mut result = Vec::new();
if let Some(cb0) = self.fut_callback0.read().clone() {
let fut_callback0 = self.fut_callback0.read().clone();
if let Some(cb0) = fut_callback0 {
let ctx0 = self
.fut_context0
.read()
@@ -621,7 +624,8 @@ pub(crate) mod _asyncio {
result.push(vm.ctx.new_tuple(vec![cb0, ctx0]).into());
}
if let Some(callbacks) = self.fut_callbacks.read().clone() {
let fut_callbacks = self.fut_callbacks.read().clone();
if let Some(callbacks) = fut_callbacks {
let list: PyListRef = callbacks.downcast().unwrap();
for item in list.borrow_vec().iter() {
result.push(item.clone());
@@ -792,16 +796,12 @@ pub(crate) mod _asyncio {
return Ok(());
}
let exc = zelf.fut_exception.read().clone();
let exc = match exc {
Some(e) => e,
None => return Ok(()),
let Some(exc) = zelf.fut_exception.read().clone() else {
return Ok(());
};
let loop_obj = zelf.fut_loop.read().clone();
let loop_obj = match loop_obj {
Some(l) => l,
None => return Ok(()),
let Some(loop_obj) = zelf.fut_loop.read().clone() else {
return Ok(());
};
// Create context dict for call_exception_handler
@@ -816,7 +816,8 @@ pub(crate) mod _asyncio {
context.set_item(vm.ctx.intern_str("exception"), exc, vm)?;
context.set_item(vm.ctx.intern_str("future"), zelf.to_owned().into(), vm)?;
if let Some(tb) = zelf.fut_source_tb.read().clone() {
let fut_source_tb = zelf.fut_source_tb.read().clone();
if let Some(tb) = fut_source_tb {
context.set_item(vm.ctx.intern_str("source_traceback"), tb, vm)?;
}
@@ -1248,12 +1249,15 @@ pub(crate) mod _asyncio {
FutureState::Cancelled => Err(self.make_cancelled_error_impl(vm)),
FutureState::Finished => {
self.base.fut_log_tb.store(false, Ordering::Relaxed);
if let Some(exc) = self.base.fut_exception.read().clone() {
let fut_exception = self.base.fut_exception.read().clone();
if let Some(exc) = fut_exception {
let exc: PyBaseExceptionRef = exc.downcast().unwrap();
// Restore the original traceback to prevent traceback accumulation
if let Some(tb) = self.base.fut_exception_tb.read().clone() {
let fut_exception_tb = self.base.fut_exception_tb.read().clone();
if let Some(tb) = fut_exception_tb {
let _ = exc.set___traceback__(tb, vm);
}
Err(exc)
} else {
Ok(self
@@ -1517,7 +1521,8 @@ pub(crate) mod _asyncio {
let msg_value = args.msg.flatten();
if let Some(fut_waiter) = self.task_fut_waiter.read().clone() {
let task_fut_waiter = self.task_fut_waiter.read().clone();
if let Some(fut_waiter) = task_fut_waiter {
// Call cancel with msg=msg keyword argument
let cancel_args = if let Some(ref m) = msg_value {
FuncArgs::new(
@@ -1795,7 +1800,9 @@ pub(crate) mod _asyncio {
#[pygetset]
fn _callbacks(&self, vm: &VirtualMachine) -> PyObjectRef {
let mut result: Vec<PyObjectRef> = Vec::new();
if let Some(cb) = self.base.fut_callback0.read().clone() {
let fut_callback0 = self.base.fut_callback0.read().clone();
if let Some(cb) = fut_callback0 {
let ctx = self
.base
.fut_context0
@@ -1804,6 +1811,7 @@ pub(crate) mod _asyncio {
.unwrap_or_else(|| vm.ctx.none());
result.push(vm.ctx.new_tuple(vec![cb, ctx]).into());
}
if let Some(callbacks) = self.base.fut_callbacks.read().clone()
&& let Ok(list) = callbacks.downcast::<PyList>()
{
@@ -1811,6 +1819,7 @@ pub(crate) mod _asyncio {
result.push(item.clone());
}
}
// Return None if no callbacks
if result.is_empty() {
vm.ctx.none()
@@ -1859,7 +1868,8 @@ pub(crate) mod _asyncio {
)?;
context.set_item(vm.ctx.intern_str("task"), zelf.to_owned().into(), vm)?;
if let Some(tb) = zelf.base.fut_source_tb.read().clone() {
let fut_source_tb = zelf.base.fut_source_tb.read().clone();
if let Some(tb) = fut_source_tb {
context.set_item(vm.ctx.intern_str("source_traceback"), tb, vm)?;
}
@@ -1896,7 +1906,8 @@ pub(crate) mod _asyncio {
context.set_item(vm.ctx.intern_str("exception"), exc, vm)?;
context.set_item(vm.ctx.intern_str("future"), zelf.to_owned().into(), vm)?;
if let Some(tb) = zelf.base.fut_source_tb.read().clone() {
let fut_source_tb = zelf.base.fut_source_tb.read().clone();
if let Some(tb) = fut_source_tb {
context.set_item(vm.ctx.intern_str("source_traceback"), tb, vm)?;
}
+2 -1
View File
@@ -1520,7 +1520,8 @@ mod _sqlite3 {
#[pygetset]
fn autocommit(&self, vm: &VirtualMachine) -> PyObjectRef {
match *self.autocommit.lock() {
let mode = *self.autocommit.lock();
match mode {
AutocommitMode::Enabled => vm.ctx.true_value.clone().into(),
AutocommitMode::Disabled => vm.ctx.false_value.clone().into(),
AutocommitMode::Legacy => vm.ctx.new_int(LEGACY_TRANSACTION_CONTROL).into(),
+8 -4
View File
@@ -660,7 +660,8 @@ pub mod array {
if let OptionalArg::Present(init) = init {
if let Some(init) = init.downcast_ref::<Self>() {
match (spec, init.read().typecode()) {
let value = init.read().typecode();
match (spec, value) {
(spec, ch) if spec == ch => array.frombytes(&init.get_bytes()),
(spec, 'u') => {
return Err(vm.new_type_error(format!(
@@ -1406,12 +1407,15 @@ pub mod array {
}
impl SelfIter for PyArrayIter {}
impl IterNext for PyArrayIter {
fn next(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
zelf.internal.lock().next(|array, pos| {
Ok(match array.read().get(pos, vm) {
Some(item) => PyIterReturn::Return(item?),
None => PyIterReturn::StopIteration(None),
let value = array.read().get(pos, vm);
Ok(if let Some(item) = value {
PyIterReturn::Return(item?)
} else {
PyIterReturn::StopIteration(None)
})
})
}
+2 -1
View File
@@ -3413,7 +3413,8 @@ mod _ssl {
// Initialize connection if not already done
if conn_guard.is_none() {
// Check for pending context change (from SNI callback)
if let Some(new_ctx) = self.pending_context.write().take() {
let pending_context = self.pending_context.write().take();
if let Some(new_ctx) = pending_context {
*self.context.write() = new_ctx;
}
+5 -3
View File
@@ -170,9 +170,11 @@ impl PyClassMethod {
#[pygetset]
fn __isabstractmethod__(&self, vm: &VirtualMachine) -> PyObjectRef {
match vm.get_attribute_opt(self.callable.lock().clone(), "__isabstractmethod__") {
Ok(Some(is_abstract)) => is_abstract,
_ => vm.ctx.new_bool(false).into(),
let callable = self.callable.lock().clone();
if let Ok(Some(is_abstract)) = vm.get_attribute_opt(callable, "__isabstractmethod__") {
is_abstract
} else {
vm.ctx.new_bool(false).into()
}
}
+2 -2
View File
@@ -398,13 +398,13 @@ impl PyList {
let (mut elements, version_before) = {
let mut guard = self.elements.write();
let version_before = self.mutation_counter.load(Ordering::Relaxed);
(core::mem::take(guard.deref_mut()), version_before)
(core::mem::take(&mut *guard), version_before)
};
let res = do_sort(vm, &mut elements, options.key, options.reverse);
let mutated = {
let mut guard = self.elements.write();
let mutated = self.mutation_counter.load(Ordering::Relaxed) != version_before;
core::mem::swap(guard.deref_mut(), &mut elements);
core::mem::swap(&mut *guard, &mut elements);
mutated
};
res?;
+16 -8
View File
@@ -54,9 +54,12 @@ impl GetDescriptor for PyProperty {
) -> PyResult {
let (zelf, obj) = Self::_unwrap(&zelf_obj, obj, vm)?;
if vm.is_none(&obj) {
Ok(zelf_obj)
} else if let Some(getter) = zelf.getter.read().clone() {
// Clone and release lock before calling Python code to prevent deadlock
return Ok(zelf_obj);
}
// Clone and release lock before calling Python code to prevent deadlock
let value = zelf.getter.read().clone();
if let Some(getter) = value {
getter.call((obj,), vm)
} else {
let error_msg = zelf.format_property_error(&obj, "getter", vm)?;
@@ -74,7 +77,8 @@ impl PyProperty {
// Returns the name if available, None if not found, or propagates errors
fn get_property_name(&self, vm: &VirtualMachine) -> PyResult<Option<PyObjectRef>> {
// First check if name was set via __set_name__
if let Some(name) = self.name.read().clone() {
let value = self.name.read().clone();
if let Some(name) = value {
return Ok(Some(name));
}
@@ -110,7 +114,8 @@ impl PyProperty {
match value {
PySetterValue::Assign(value) => {
// Clone and release lock before calling Python code to prevent deadlock
if let Some(setter) = zelf.setter.read().clone() {
let set = zelf.setter.read().clone();
if let Some(setter) = set {
setter.call((obj, value), vm).map(drop)
} else {
let error_msg = zelf.format_property_error(&obj, "setter", vm)?;
@@ -119,7 +124,8 @@ impl PyProperty {
}
PySetterValue::Delete => {
// Clone and release lock before calling Python code to prevent deadlock
if let Some(deleter) = zelf.deleter.read().clone() {
let del = zelf.deleter.read().clone();
if let Some(deleter) = del {
deleter.call((obj,), vm).map(drop)
} else {
let error_msg = zelf.format_property_error(&obj, "deleter", vm)?;
@@ -224,7 +230,8 @@ impl PyProperty {
Self::init(new_prop_ref.clone(), args, vm)?;
// Copy the name if it exists
if let Some(name) = zelf.name.read().clone() {
let value = zelf.name.read().clone();
if let Some(name) = value {
*new_prop_ref.name.write() = Some(name);
}
@@ -296,7 +303,8 @@ impl PyProperty {
#[pygetset(setter)]
fn set___isabstractmethod__(&self, value: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
// Clone and release lock before calling Python code to prevent deadlock
if let Some(getter) = self.getter.read().clone() {
let maybe_getter = self.getter.read().clone();
if let Some(getter) = maybe_getter {
getter.set_attr("__isabstractmethod__", value, vm)?;
}
Ok(())
+11 -6
View File
@@ -5,12 +5,17 @@ use super::{
IterStatus, PositionIterInternal, PyDict, PyDictRef, PyGenericAlias, PyTupleRef, PyType,
PyTypeRef, builtins_iter,
};
use crate::common::lock::LazyLock;
use crate::{
AsObject, Context, Py, PyObject, PyObjectRef, PyPayload, PyRef, PyResult, TryFromObject,
atomic_func,
class::PyClassImpl,
common::{ascii, hash::PyHash, lock::PyMutex, rc::PyRc, wtf8::Wtf8Buf},
common::{
ascii,
hash::PyHash,
lock::{LazyLock, PyMutex},
rc::PyRc,
wtf8::Wtf8Buf,
},
convert::ToPyResult,
dict_inner::{self, DictSize},
function::{ArgIterable, FuncArgs, OptionalArg, PosArgs, PyArithmeticValue, PyComparisonValue},
@@ -24,9 +29,7 @@ use crate::{
utils::collection_repr,
vm::VirtualMachine,
};
use alloc::fmt;
use core::borrow::Borrow;
use core::ops::Deref;
use core::{borrow::Borrow, fmt};
use rustpython_common::{
atomic::{Ordering, PyAtomic, Radium},
hash,
@@ -924,10 +927,12 @@ impl Representable for PySet {
fn repr_wtf8(zelf: &crate::Py<Self>, vm: &VirtualMachine) -> PyResult<Wtf8Buf> {
let class = zelf.class();
let borrowed_name = class.name();
let class_name = borrowed_name.deref();
let class_name = &*borrowed_name;
if zelf.inner.len() == 0 {
return Ok(Wtf8Buf::from(format!("{class_name}()")));
}
if let Some(_guard) = ReprGuard::enter(vm, zelf.as_object()) {
let name = (class_name != "set").then_some(class_name);
zelf.inner.repr(name, vm)
+6 -3
View File
@@ -144,9 +144,12 @@ impl PyStaticMethod {
#[pygetset]
fn __isabstractmethod__(&self, vm: &VirtualMachine) -> PyObjectRef {
match vm.get_attribute_opt(self.callable.lock().clone(), "__isabstractmethod__") {
Ok(Some(is_abstract)) => is_abstract,
_ => vm.ctx.new_bool(false).into(),
let callable = self.callable.lock().clone();
if let Ok(Some(is_abstract)) = vm.get_attribute_opt(callable, "__isabstractmethod__") {
is_abstract
} else {
vm.ctx.new_bool(false).into()
}
}
+4 -4
View File
@@ -1281,14 +1281,14 @@ impl Py<PyType> {
where
F: Fn(&Self) -> R,
{
self.mro.read().iter().map(|x| x.deref()).map(f).collect()
self.mro.read().iter().map(|x| &**x).map(f).collect()
}
pub fn mro_collect(&self) -> Vec<PyRef<PyType>> {
self.mro
.read()
.iter()
.map(|x| x.deref())
.map(|x| &**x)
.map(|x| x.to_owned())
.collect()
}
@@ -2926,12 +2926,12 @@ fn best_base<'a>(bases: &'a [PyTypeRef], vm: &VirtualMachine) -> PyResult<&'a Py
let candidate = solid_base(base_i, vm);
if winner.is_none() {
winner = Some(candidate);
base = Some(base_i.deref());
base = Some(&**base_i);
} else if winner.unwrap().fast_issubclass(candidate) {
// Do nothing
} else if candidate.fast_issubclass(winner.unwrap()) {
winner = Some(candidate);
base = Some(base_i.deref());
base = Some(&**base_i);
} else {
return Err(vm.new_type_error("multiple bases have instance layout conflict"));
}
+3 -2
View File
@@ -23,8 +23,9 @@ const MINIMUM_OVERHEAD: usize = 1000 * core::mem::size_of::<usize>();
/// Alignment for all data stack allocations.
const ALIGN: usize = 16;
/// Header for a data stack chunk. The usable data region starts right after
/// this header (aligned to `ALIGN`).
/// Header for a data stack chunk.
///
/// The usable data region starts right after this header (aligned to [`ALIGN`]).
#[repr(C)]
struct DataStackChunk {
/// Previous chunk in the linked list (NULL for the root chunk).
+7 -4
View File
@@ -134,7 +134,9 @@ impl VirtualMachine {
exc: &Py<PyBaseException>,
) -> Result<(), W::Error> {
let vm = self;
if let Some(tb) = exc.traceback.read().clone() {
let traceback = exc.traceback.read().clone();
if let Some(tb) = traceback {
writeln!(output, "Traceback (most recent call last):")?;
for tb in tb.iter() {
write_traceback_entry(output, &tb)?;
@@ -162,9 +164,10 @@ impl VirtualMachine {
),
}?;
match offer_suggestions(exc, vm) {
Some(suggestions) => writeln!(output, ". Did you mean: '{suggestions}'?"),
None => writeln!(output),
if let Some(suggestions) = offer_suggestions(exc, vm) {
writeln!(output, ". Did you mean: '{suggestions}'?")
} else {
writeln!(output)
}
}
+6 -1
View File
@@ -151,7 +151,7 @@ impl PyInterned<PyStr> {
pub fn as_str(&self) -> &str {
self.inner
.to_str()
.unwrap_or_else(|| panic!("interned str is always valid UTF-8"))
.expect("interned str is always valid UTF-8")
}
}
@@ -257,6 +257,7 @@ mod sealed {
/// A sealed marker trait for `DictKey` types that always become an exact instance of `str`
pub trait InternableString: sealed::SealedInternable + ToPyObject + AsRef<Self::Interned> {
type Interned: MaybeInternedString + ?Sized;
fn into_pyref_exact(self, str_type: PyTypeRef) -> PyRefExact<PyStr>;
}
@@ -271,6 +272,7 @@ impl InternableString for String {
impl InternableString for &str {
type Interned = str;
#[inline]
fn into_pyref_exact(self, str_type: PyTypeRef) -> PyRefExact<PyStr> {
self.to_owned().into_pyref_exact(str_type)
@@ -279,6 +281,7 @@ impl InternableString for &str {
impl InternableString for Wtf8Buf {
type Interned = Wtf8;
fn into_pyref_exact(self, str_type: PyTypeRef) -> PyRefExact<PyStr> {
let obj = PyRef::new_ref(PyStr::from(self), str_type, None);
unsafe { PyRefExact::new_unchecked(obj) }
@@ -287,6 +290,7 @@ impl InternableString for Wtf8Buf {
impl InternableString for &Wtf8 {
type Interned = Wtf8;
fn into_pyref_exact(self, str_type: PyTypeRef) -> PyRefExact<PyStr> {
self.to_owned().into_pyref_exact(str_type)
}
@@ -294,6 +298,7 @@ impl InternableString for &Wtf8 {
impl InternableString for PyRefExact<PyStr> {
type Interned = Py<PyStr>;
#[inline]
fn into_pyref_exact(self, _str_type: PyTypeRef) -> PyRefExact<PyStr> {
self
+5 -4
View File
@@ -1489,7 +1489,7 @@ impl PyObject {
#[inline(always)]
pub fn class(&self) -> &Py<PyType> {
self.0.typ.deref()
&self.0.typ
}
pub fn set_class(&self, typ: PyTypeRef, vm: &VirtualMachine) {
@@ -1835,7 +1835,8 @@ impl PyObject {
result.push(dict_ref.into());
}
for slot in &ext.slots {
if let Some(val) = slot.write().take() {
let value = slot.write().take();
if let Some(val) = value {
result.push(val);
}
}
@@ -2130,7 +2131,7 @@ where
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.deref().eq(other.deref())
self.deref().eq(&**other)
}
}
@@ -2407,7 +2408,7 @@ where
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.deref().eq(other.deref())
self.deref().eq(&**other)
}
}
+1 -1
View File
@@ -17,7 +17,7 @@ impl fmt::Debug for Scope {
impl Scope {
#[inline]
#[must_use]
pub fn new(locals: Option<ArgMapping>, globals: PyDictRef) -> Self {
pub const fn new(locals: Option<ArgMapping>, globals: PyDictRef) -> Self {
Self { locals, globals }
}
+4 -2
View File
@@ -709,7 +709,8 @@ impl PyCData {
let key = self.unique_key(index);
// If we have a base object, find root and store there
if let Some(base_obj) = self.base.read().clone() {
let base = self.base.read().clone();
if let Some(base_obj) = base {
// Find root by walking up the base chain
let root_obj = Self::find_root_object(&base_obj);
Self::store_in_object(&root_obj, &key, keep, vm)?;
@@ -761,7 +762,8 @@ impl PyCData {
/// Uses unique_key (hierarchical) so nested fields don't collide.
pub fn keep_alive(&self, index: usize, obj: PyObjectRef) {
let key = self.unique_key(index);
if let Some(base_obj) = self.base.read().clone() {
let base = self.base.read().clone();
if let Some(base_obj) = base {
let root = Self::find_root_object(&base_obj);
if let Some(cdata) = root.downcast_ref::<Self>() {
cdata.kept_refs.write().insert(key, obj);
+2 -1
View File
@@ -373,7 +373,8 @@ impl PyCPointer {
zelf.0.keep_ref(1, value.clone(), vm)?;
// KeepRef: store GetKeepedObjects(dst) at index 0
if let Some(kept) = cdata.objects.read().clone() {
let objects = cdata.objects.read().clone();
if let Some(kept) = objects {
zelf.0.keep_ref(0, kept, vm)?;
}
+2 -1
View File
@@ -947,7 +947,8 @@ pub(crate) mod _thread {
let thread_id = current_thread_id();
// Fast path: check if dict exists under lock
if let Some(dict) = self.inner.data.lock().get(&thread_id).cloned() {
let value = self.inner.data.lock().get(&thread_id).cloned();
if let Some(dict) = value {
return dict;
}
+4 -2
View File
@@ -1552,7 +1552,8 @@ impl PyType {
let mro = self.mro.read();
// Look up in self's dict first
if let Some(attr) = self.attributes.read().get(name).cloned() {
let attr_name = self.attributes.read().get(name).cloned();
if let Some(attr) = attr_name {
if let Some(func) = try_extract(&attr, &mro) {
return SlotLookupResult::NativeSlot(func);
}
@@ -1561,7 +1562,8 @@ impl PyType {
// Look up in MRO (mro[0] is self, so skip it)
for (i, cls) in mro[1..].iter().enumerate() {
if let Some(attr) = cls.attributes.read().get(name).cloned() {
let attr_name = cls.attributes.read().get(name).cloned();
if let Some(attr) = attr_name {
// Use the slice starting from this class in MRO
if let Some(func) = try_extract(&attr, &mro[i + 1..]) {
return SlotLookupResult::NativeSlot(func);