Add some clippy lints#7755
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughAdds nine Clippy lints to workspace config and performs widespread micro-refactors: consolidates match patterns, replaces eager fallbacks with lazy closures, and eliminates redundant clones across many crates without changing public APIs or core control flow. Changes
Sequence Diagram(s)(Skipped — changes are refactors/ownership and do not introduce new multi-component control flows.) Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🧹 Nitpick comments (2)
crates/vm/src/ospath.rs (1)
128-135: ⚡ Quick winConsider removing the clone here for consistency.
Similar to the optimization on line 113, the clone on line 128 can be eliminated by using the
PyObjectRefreturned from theErrvariant.♻️ Proposed refactor
- self.try_match_str_bytes(result.clone(), vm)?.map_err(|_| { + self.try_match_str_bytes(result, vm)?.map_err(|result_obj| { vm.new_type_error(format!( "{}expected {}.__fspath__() to return str or bytes, not {}", self.error_prefix(), obj.class().name(), - result.class().name(), + result_obj.class().name(), )) })🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/vm/src/ospath.rs` around lines 128 - 135, The clone of result is unnecessary: remove the .clone() passed to self.try_match_str_bytes and instead capture the Err value inside map_err’s closure (e.g., .map_err(|obj| { ... })) so you can use that PyObjectRef’s class name in the error message (use obj.class().name() instead of result.class().name()); update the closure parameter name accordingly while keeping vm.new_type_error and the existing format string.crates/stdlib/src/csv.rs (1)
98-99: Pass string literals and char values directly tonew_strinstead of allocating unnecessarily.The
new_strmethod acceptsimpl Into<pystr::PyStr>, which includes&strandchar. Line 98 can pass the string literal directly without.to_string(). For line 99, sincetis au8, cast it tocharand pass it directly instead of usingformat!.Suggested changes
Terminator::CRLF => vm.ctx.new_str("\r\n"), Terminator::Any(t) => vm.ctx.new_str(t as char),🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@crates/stdlib/src/csv.rs` around lines 98 - 99, In crates/stdlib/src/csv.rs, the Terminator match allocates unnecessarily by calling .to_string() and format!; update the Terminator::CRLF and Terminator::Any arms to pass literals and char values directly into vm.ctx.new_str (use the string literal "\r\n" and cast the u8 t to char) so new_str receives &str/char instead of an owned String, eliminating the extra allocations.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@crates/stdlib/src/csv.rs`:
- Around line 1028-1030: Replace the redundant and panicking UTF-8 conversion by
using the already-validated string `s`: instead of calling
String::from_utf8(...).unwrap().parse::<i64>(), trim and parse the slice of `s`
(e.g., `s[range].trim().parse::<i64>()`) and match on the parse Result (e.g.,
`if let Ok(t) = ...`) so you never call `.unwrap()`; ensure you drop the extra
conversion of `buffer` and only operate on `s`, keeping error handling via the
parse result.
In `@crates/vm/src/format.rs`:
- Around line 59-61: The loop is pushing a libc::c_char into a Vec<u8> causing
portability/compile issues on platforms where c_char = i8; update the push to
cast the dereferenced pointer to the Vec element type using a generic cast (use
as _) so the compiler infers the correct unsigned type—i.e., change the use of
result.push(*ptr) to result.push(*ptr as _) and keep the existing sentinel check
using libc::c_char::MAX; this touches the variables result and ptr in the loop
in format.rs.
In `@crates/vm/src/stdlib/_ctypes/function.rs`:
- Around line 2111-2119: The current match arm incorrectly groups "l"/"L" with
"q"/"Q" and always writes 8-byte i64/u64 values, causing buffer overruns on
32-bit targets; update the match in the callback writer so "l" and "L" are
handled separately from "q"/"Q": for "l" write into the result as the
platform-dependent c_long type (use the module's c_long type and convert the
BigInt to an i64 then cast to c_long with a safe fallback), for "L" write as
c_ulong (convert via to_u64 then cast to c_ulong with fallback), and keep
"q"/"Q" writing i64/u64 as before; reference the existing match arms for ("l" |
"q"), ("L" | "Q"), get_ffi_type, and the result pointer handling so you change
the pointer casts to *mut c_long/*mut c_ulong for "l"/"L" respectively instead
of *mut i64/*mut u64.
---
Nitpick comments:
In `@crates/stdlib/src/csv.rs`:
- Around line 98-99: In crates/stdlib/src/csv.rs, the Terminator match allocates
unnecessarily by calling .to_string() and format!; update the Terminator::CRLF
and Terminator::Any arms to pass literals and char values directly into
vm.ctx.new_str (use the string literal "\r\n" and cast the u8 t to char) so
new_str receives &str/char instead of an owned String, eliminating the extra
allocations.
In `@crates/vm/src/ospath.rs`:
- Around line 128-135: The clone of result is unnecessary: remove the .clone()
passed to self.try_match_str_bytes and instead capture the Err value inside
map_err’s closure (e.g., .map_err(|obj| { ... })) so you can use that
PyObjectRef’s class name in the error message (use obj.class().name() instead of
result.class().name()); update the closure parameter name accordingly while
keeping vm.new_type_error and the existing format string.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yml
Review profile: CHILL
Plan: Pro
Run ID: 03445c0b-9f46-44f5-90bd-ab60824e0bf5
📒 Files selected for processing (55)
Cargo.tomlcrates/codegen/src/compile.rscrates/codegen/src/ir.rscrates/codegen/src/symboltable.rscrates/common/src/format.rscrates/common/src/str.rscrates/derive-impl/src/pyclass.rscrates/derive-impl/src/pystructseq.rscrates/stdlib/src/_asyncio.rscrates/stdlib/src/contextvars.rscrates/stdlib/src/csv.rscrates/stdlib/src/mmap.rscrates/stdlib/src/posixsubprocess.rscrates/stdlib/src/socket.rscrates/stdlib/src/ssl.rscrates/stdlib/src/ssl/cert.rscrates/stdlib/src/ssl/compat.rscrates/stdlib/src/unicodedata.rscrates/vm/src/buffer.rscrates/vm/src/builtins/builtin_func.rscrates/vm/src/builtins/code.rscrates/vm/src/builtins/function.rscrates/vm/src/builtins/interpolation.rscrates/vm/src/builtins/range.rscrates/vm/src/builtins/set.rscrates/vm/src/builtins/type.rscrates/vm/src/codecs.rscrates/vm/src/exception_group.rscrates/vm/src/exceptions.rscrates/vm/src/format.rscrates/vm/src/frame.rscrates/vm/src/getpath.rscrates/vm/src/import.rscrates/vm/src/ospath.rscrates/vm/src/stdlib/_abc.rscrates/vm/src/stdlib/_ast/python.rscrates/vm/src/stdlib/_ctypes.rscrates/vm/src/stdlib/_ctypes/array.rscrates/vm/src/stdlib/_ctypes/base.rscrates/vm/src/stdlib/_ctypes/function.rscrates/vm/src/stdlib/_ctypes/pointer.rscrates/vm/src/stdlib/_ctypes/simple.rscrates/vm/src/stdlib/_ctypes/structure.rscrates/vm/src/stdlib/_ctypes/union.rscrates/vm/src/stdlib/_io.rscrates/vm/src/stdlib/_sre.rscrates/vm/src/stdlib/_sysconfigdata.rscrates/vm/src/stdlib/_thread.rscrates/vm/src/stdlib/builtins.rscrates/vm/src/stdlib/itertools.rscrates/vm/src/stdlib/sys.rscrates/vm/src/stdlib/time.rscrates/vm/src/types/structseq.rscrates/vm/src/vm/mod.rscrates/vm/src/warn.rs
| if let Ok(t) = String::from_utf8(trim_spaces(&buffer[range]).to_vec()) | ||
| .unwrap() | ||
| .parse::<i64>() |
There was a problem hiding this comment.
Fix panic risk from .unwrap() and avoid redundant UTF-8 conversion.
Line 1029 contains an .unwrap() call that can panic if UTF-8 conversion fails, violating Rust error handling best practices. Additionally, the code converts the buffer slice to UTF-8 twice: once on line 1022 (producing s) and again on lines 1028-1029. Since s is already a validated UTF-8 string, you can trim and parse it directly.
🔧 Proposed fix
let s = core::str::from_utf8(&buffer[range.clone()])
// not sure if this is possible - the input was all strings
.map_err(|_e| vm.new_unicode_decode_error("csv not utf8"))?;
// Rustpython TODO!
// Incomplete implementation
if let QuoteStyle::Nonnumeric = zelf.dialect.quoting {
- if let Ok(t) = String::from_utf8(trim_spaces(&buffer[range]).to_vec())
- .unwrap()
- .parse::<i64>()
- {
+ if let Ok(t) = s.trim().parse::<i64>() {
Ok(vm.ctx.new_int(t).into())
} else {
Ok(vm.ctx.new_str(s).into())Based on learnings: Follow Rust best practices for error handling and memory management.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@crates/stdlib/src/csv.rs` around lines 1028 - 1030, Replace the redundant and
panicking UTF-8 conversion by using the already-validated string `s`: instead of
calling String::from_utf8(...).unwrap().parse::<i64>(), trim and parse the slice
of `s` (e.g., `s[range].trim().parse::<i64>()`) and match on the parse Result
(e.g., `if let Ok(t) = ...`) so you never call `.unwrap()`; ensure you drop the
extra conversion of `buffer` and only operate on `s`, keeping error handling via
the parse result.
| Some("l" | "q") => { | ||
| if let Ok(i) = obj.try_int(vm) { | ||
| *(result as *mut i64) = i.as_bigint().to_i64().unwrap_or(0); | ||
| } | ||
| } | ||
| Some("L") | Some("Q") => { | ||
| Some("L" | "Q") => { | ||
| if let Ok(i) = obj.try_int(vm) { | ||
| *(result as *mut u64) = i.as_bigint().to_u64().unwrap_or(0); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== get_ffi_type width mapping for l/L =="
rg -n -C3 '"l" =>|\"L\" =>' crates/vm/src/stdlib/_ctypes.rs
echo
echo "== python_to_ffi write targets for l/L/q/Q =="
rg -n -C4 'Some\("l" \| "q"\)|Some\("L" \| "Q"\)|Some\("l"\)|Some\("L"\)|Some\("q"\)|Some\("Q"\)' crates/vm/src/stdlib/_ctypes/function.rsRepository: RustPython/RustPython
Length of output: 213
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Code at lines 2111-2119 in function.rs ==="
sed -n '2108,2122p' crates/vm/src/stdlib/_ctypes/function.rs
echo
echo "=== Search for get_ffi_type l/L mappings ==="
rg -n '"l"|"L"' crates/vm/src/stdlib/_ctypes.rs | head -20Repository: RustPython/RustPython
Length of output: 809
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== get_ffi_type mappings for l and L (lines 165-185) ==="
sed -n '165,185p' crates/vm/src/stdlib/_ctypes.rs
echo
echo "=== Check libc crate for c_long/c_ulong definitions ==="
rg -n 'c_long|c_ulong' crates/vm/src/stdlib/_ctypes.rs | head -10Repository: RustPython/RustPython
Length of output: 1357
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "=== Check for other pointer cast patterns in python_to_ffi ==="
sed -n '2050,2150p' crates/vm/src/stdlib/_ctypes/function.rs | grep -n -E 'Some\(|as \*mut|=>|^\s*}'Repository: RustPython/RustPython
Length of output: 2404
Fix platform-width regression for 'l'/'L' callback writes.
Lines 2111 and 2116 incorrectly write i64/u64 for both ("l" | "q") and ("L" | "Q"). The get_ffi_type function maps "l" to c_long (4 bytes on 32-bit platforms, 8 on 64-bit) and "L" to c_ulong. Grouping them with "q"/"Q" (always 8 bytes) causes buffer overruns: writing 8 bytes into a 4-byte result slot corrupts memory on 32-bit targets.
Separate the cases and write to the correct platform-dependent types:
Suggested fix
- Some("l" | "q") => {
+ Some("l") => {
+ if let Ok(i) = obj.try_int(vm) {
+ *(result as *mut libc::c_long) =
+ i.as_bigint().to_i64().unwrap_or(0) as libc::c_long;
+ }
+ }
+ Some("q") => {
if let Ok(i) = obj.try_int(vm) {
*(result as *mut i64) = i.as_bigint().to_i64().unwrap_or(0);
}
}
- Some("L" | "Q") => {
+ Some("L") => {
+ if let Ok(i) = obj.try_int(vm) {
+ *(result as *mut libc::c_ulong) =
+ i.as_bigint().to_u64().unwrap_or(0) as libc::c_ulong;
+ }
+ }
+ Some("Q") => {
if let Ok(i) = obj.try_int(vm) {
*(result as *mut u64) = i.as_bigint().to_u64().unwrap_or(0);
}
}🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@crates/vm/src/stdlib/_ctypes/function.rs` around lines 2111 - 2119, The
current match arm incorrectly groups "l"/"L" with "q"/"Q" and always writes
8-byte i64/u64 values, causing buffer overruns on 32-bit targets; update the
match in the callback writer so "l" and "L" are handled separately from "q"/"Q":
for "l" write into the result as the platform-dependent c_long type (use the
module's c_long type and convert the BigInt to an i64 then cast to c_long with a
safe fallback), for "L" write as c_ulong (convert via to_u64 then cast to
c_ulong with fallback), and keep "q"/"Q" writing i64/u64 as before; reference
the existing match arms for ("l" | "q"), ("L" | "Q"), get_ffi_type, and the
result pointer handling so you change the pointer casts to *mut c_long/*mut
c_ulong for "l"/"L" respectively instead of *mut i64/*mut u64.
Summary by CodeRabbit
Chores
Refactor