From 79c4439f2b3c5b37df014b5fa703d703bdcb0218 Mon Sep 17 00:00:00 2001 From: Noa Date: Thu, 16 Apr 2026 16:48:00 -0500 Subject: [PATCH 1/2] Use cfg_select in a bunch more places --- crates/common/src/rc.rs | 13 +-- crates/common/src/refcount.rs | 8 +- crates/common/src/str.rs | 9 +- crates/host_env/src/crt_fd.rs | 36 ++++---- crates/stdlib/src/faulthandler.rs | 91 ++++++------------- crates/stdlib/src/openssl.rs | 107 ++++++++++------------- crates/stdlib/src/socket.rs | 2 +- crates/stdlib/src/ssl.rs | 21 ++--- crates/vm/src/buffer.rs | 8 +- crates/vm/src/codecs.rs | 18 ++-- crates/vm/src/exceptions.rs | 26 +++--- crates/vm/src/getpath.rs | 9 +- crates/vm/src/stdlib/_ctypes/function.rs | 72 +++++++-------- crates/vm/src/stdlib/_ctypes/simple.rs | 12 +-- crates/vm/src/stdlib/_io.rs | 32 +++---- crates/vm/src/stdlib/_signal.rs | 67 +++++++------- crates/vm/src/stdlib/os.rs | 8 +- crates/vm/src/stdlib/time.rs | 61 ++++++------- crates/vm/src/version.rs | 23 +++-- crates/vm/src/vm/mod.rs | 42 +++------ crates/vm/src/vm/vm_object.rs | 64 ++++++-------- src/interpreter.rs | 29 +++--- src/lib.rs | 22 +++-- 23 files changed, 338 insertions(+), 442 deletions(-) diff --git a/crates/common/src/rc.rs b/crates/common/src/rc.rs index 9e4cca228fd..347543851e7 100644 --- a/crates/common/src/rc.rs +++ b/crates/common/src/rc.rs @@ -1,12 +1,7 @@ -#[cfg(not(feature = "threading"))] -use alloc::rc::Rc; -#[cfg(feature = "threading")] -use alloc::sync::Arc; - // type aliases instead of new-types because you can't do `fn method(self: PyRc)` with a // newtype; requires the arbitrary_self_types unstable feature -#[cfg(feature = "threading")] -pub type PyRc = Arc; -#[cfg(not(feature = "threading"))] -pub type PyRc = Rc; +pub type PyRc = cfg_select! { + feature = "threading" => alloc::sync::Arc::, + _ => alloc::rc::Rc::, +}; diff --git a/crates/common/src/refcount.rs b/crates/common/src/refcount.rs index d17f5ccd9f3..c7970cb3d86 100644 --- a/crates/common/src/refcount.rs +++ b/crates/common/src/refcount.rs @@ -20,10 +20,10 @@ const WEAK_COUNT: usize = 1 << STRONG_WIDTH; reason = "refcount overflow must preserve upstream abort semantics" )] fn refcount_overflow() -> ! { - #[cfg(feature = "std")] - std::process::abort(); - #[cfg(not(feature = "std"))] - core::panic!("refcount overflow"); + cfg_select! { + feature = "std" => std::process::abort(), + _ => core::panic!("refcount overflow"), + } } /// State wraps reference count + flags in a single word (platform usize) diff --git a/crates/common/src/str.rs b/crates/common/src/str.rs index 38e73a683f2..5ea1b6a52b0 100644 --- a/crates/common/src/str.rs +++ b/crates/common/src/str.rs @@ -7,12 +7,11 @@ use core::fmt; use core::ops::{Bound, RangeBounds}; use core::sync::atomic::Ordering::Relaxed; -#[cfg(not(target_arch = "wasm32"))] #[allow(non_camel_case_types)] -pub type wchar_t = libc::wchar_t; -#[cfg(target_arch = "wasm32")] -#[allow(non_camel_case_types)] -pub type wchar_t = u32; +pub type wchar_t = cfg_select! { + target_arch = "wasm32" => u32, + _ => libc::wchar_t, +}; /// Utf8 + state.ascii (+ PyUnicode_Kind in future) #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)] diff --git a/crates/host_env/src/crt_fd.rs b/crates/host_env/src/crt_fd.rs index ab7c94f8b3b..811fd74fb1a 100644 --- a/crates/host_env/src/crt_fd.rs +++ b/crates/host_env/src/crt_fd.rs @@ -26,15 +26,15 @@ mod c { // this is basically what CPython has for Py_off_t; windows uses long long // for offsets, other platforms just use off_t -#[cfg(not(windows))] -pub type Offset = c::off_t; -#[cfg(windows)] -pub type Offset = c::c_longlong; +pub type Offset = cfg_select! { + windows => c::c_longlong, + _ => c::off_t, +}; -#[cfg(not(windows))] -pub type Raw = RawFd; -#[cfg(windows)] -pub type Raw = i32; +pub type Raw = cfg_select! { + windows => i32, + _ => RawFd, +}; #[inline] fn cvt(ret: I) -> io::Result { @@ -341,18 +341,16 @@ pub fn ftruncate(fd: Borrowed<'_>, len: Offset) -> io::Result<()> { let ret = unsafe { suppress_iph!(c::ftruncate(fd.as_raw(), len)) }; // On Windows, _chsize_s returns 0 on success, or a positive error code (errno value) on failure. // On other platforms, ftruncate returns 0 on success, or -1 on failure with errno set. - #[cfg(windows)] - { - if ret != 0 { - // _chsize_s returns errno directly, convert to Windows error code - let winerror = crate::os::errno_to_winerror(ret); - return Err(io::Error::from_raw_os_error(winerror)); + cfg_select! { + windows => { + if ret != 0 { + // _chsize_s returns errno directly, convert to Windows error code + let winerror = crate::os::errno_to_winerror(ret); + return Err(io::Error::from_raw_os_error(winerror)); + } } - } - #[cfg(not(windows))] - { - cvt(ret)?; - } + _ => cvt(ret)?, + }; Ok(()) } diff --git a/crates/stdlib/src/faulthandler.rs b/crates/stdlib/src/faulthandler.rs index e562a382345..f21ed115a34 100644 --- a/crates/stdlib/src/faulthandler.rs +++ b/crates/stdlib/src/faulthandler.rs @@ -119,29 +119,14 @@ mod decl { // PUTS macro #[cfg(any(unix, windows))] fn puts(fd: i32, s: &str) { - let _ = unsafe { - #[cfg(windows)] - { - libc::write(fd, s.as_ptr() as *const libc::c_void, s.len() as u32) - } - #[cfg(not(windows))] - { - libc::write(fd, s.as_ptr() as *const libc::c_void, s.len()) - } - }; + puts_bytes(fd, s.as_bytes()) } #[cfg(any(unix, windows))] fn puts_bytes(fd: i32, s: &[u8]) { - let _ = unsafe { - #[cfg(windows)] - { - libc::write(fd, s.as_ptr() as *const libc::c_void, s.len() as u32) - } - #[cfg(not(windows))] - { - libc::write(fd, s.as_ptr() as *const libc::c_void, s.len()) - } + let _ = cfg_select! { + windows => unsafe { libc::write(fd, s.as_ptr() as *const libc::c_void, s.len() as u32) }, + _ => unsafe { libc::write(fd, s.as_ptr() as *const libc::c_void, s.len()) }, }; } @@ -158,16 +143,7 @@ mod decl { buf[2 + i] = HEX_CHARS[digit]; } - let _ = unsafe { - #[cfg(windows)] - { - libc::write(fd, buf.as_ptr() as *const libc::c_void, (2 + width) as u32) - } - #[cfg(not(windows))] - { - libc::write(fd, buf.as_ptr() as *const libc::c_void, 2 + width) - } - }; + puts_bytes(fd, &buf[..2 + width]); } // _Py_DumpDecimal (traceback.c) @@ -188,17 +164,7 @@ mod decl { v /= 10; } - let len = buf.len() - i; - let _ = unsafe { - #[cfg(windows)] - { - libc::write(fd, buf[i..].as_ptr() as *const libc::c_void, len as u32) - } - #[cfg(not(windows))] - { - libc::write(fd, buf[i..].as_ptr() as *const libc::c_void, len) - } - }; + puts_bytes(fd, &buf[..buf.len() - i]); } /// Get current thread ID @@ -857,30 +823,31 @@ mod decl { drop(guard); // Release lock before I/O // Timeout occurred, dump traceback - #[cfg(target_arch = "wasm32")] - let _ = (exit, fd, &header); - - #[cfg(not(target_arch = "wasm32"))] - { - puts_bytes(fd, header.as_bytes()); - - // Use thread frame slots when threading is enabled (includes all threads). - // Fall back to live frame walking for non-threaded builds. - #[cfg(feature = "threading")] - { - for (tid, slot) in &thread_frame_slots { - let frames = slot.frames.lock(); - dump_traceback_thread_frames(fd, *tid, false, &frames); - } - } - #[cfg(not(feature = "threading"))] - { - write_thread_id(fd, current_thread_id(), false); - dump_live_frames(fd); + cfg_select! { + target_arch = "wasm32" => { + let _ = (exit, fd, &header); } + _ => { + puts_bytes(fd, header.as_bytes()); + + // Use thread frame slots when threading is enabled (includes all threads). + // Fall back to live frame walking for non-threaded builds. + cfg_select! { + feature = "threading" => { + for (tid, slot) in &thread_frame_slots { + let frames = slot.frames.lock(); + dump_traceback_thread_frames(fd, *tid, false, &frames); + } + } + _ => { + write_thread_id(fd, current_thread_id(), false); + dump_live_frames(fd); + } + } - if exit { - rustpython_host_env::os::exit(1); + if exit { + rustpython_host_env::os::exit(1); + } } } diff --git a/crates/stdlib/src/openssl.rs b/crates/stdlib/src/openssl.rs index fb6766ae939..2d1bf7c4aec 100644 --- a/crates/stdlib/src/openssl.rs +++ b/crates/stdlib/src/openssl.rs @@ -1307,15 +1307,13 @@ mod _ssl { #[pygetset] fn num_tickets(&self, _vm: &VirtualMachine) -> PyResult { // Only supported for TLS 1.3 - #[cfg(ossl110)] - { - let ctx = self.ctx(); - let num = unsafe { sys::SSL_CTX_get_num_tickets(ctx.as_ptr()) }; - Ok(num) - } - #[cfg(not(ossl110))] - { - Ok(0) + cfg_select! { + ossl110 => { + let ctx = self.ctx(); + let num = unsafe { sys::SSL_CTX_get_num_tickets(ctx.as_ptr()) }; + Ok(num) + } + _ => Ok(0), } } #[pygetset(setter)] @@ -1330,19 +1328,19 @@ mod _ssl { return Err(vm.new_value_error("SSLContext is not a server context.")); } - #[cfg(ossl110)] - { - let ctx = self.builder(); - let result = unsafe { sys::SSL_CTX_set_num_tickets(ctx.as_ptr(), value as usize) }; - if result != 1 { - return Err(vm.new_value_error("failed to set num tickets.")); + cfg_select! { + ossl110 => { + let ctx = self.builder(); + let result = unsafe { sys::SSL_CTX_set_num_tickets(ctx.as_ptr(), value as usize) }; + if result != 1 { + return Err(vm.new_value_error("failed to set num tickets.")); + } + Ok(()) + } + _ => { + let _ = (value, vm); + Ok(()) } - Ok(()) - } - #[cfg(not(ossl110))] - { - let _ = (value, vm); - Ok(()) } } @@ -1565,9 +1563,10 @@ mod _ssl { let binary_form = args.binary_form.unwrap_or(false); let ctx = self.ctx(); #[cfg(ossl300)] - let certs = ctx.cert_store().all_certificates(); - #[cfg(not(ossl300))] - let certs = ctx.cert_store().objects().iter().filter_map(|x| x.x509()); + let certs = cfg_select! { + ossl300 => ctx.cert_store().all_certificates(), + _ => ctx.cert_store().objects().iter().filter_map(|x| x.x509()), + }; // Filter to only include CA certificates (Basic Constraints: CA=TRUE) let certs = certs @@ -2792,21 +2791,21 @@ mod _ssl { #[pymethod] fn verify_client_post_handshake(&self, vm: &VirtualMachine) -> PyResult<()> { - #[cfg(ossl111)] - { - let stream = self.connection.read(); - let result = unsafe { SSL_verify_client_post_handshake(stream.ssl().as_ptr()) }; - if result == 0 { - Err(convert_openssl_error(vm, openssl::error::ErrorStack::get())) - } else { - Ok(()) + cfg_select! { + ossl111 => { + let stream = self.connection.read(); + let result = unsafe { SSL_verify_client_post_handshake(stream.ssl().as_ptr()) }; + if result == 0 { + Err(convert_openssl_error(vm, openssl::error::ErrorStack::get())) + } else { + Ok(()) + } + } + _ => { + Err(vm.new_not_implemented_error( + "Post-handshake auth is not supported by your OpenSSL version.", + )) } - } - #[cfg(not(ossl111))] - { - Err(vm.new_not_implemented_error( - "Post-handshake auth is not supported by your OpenSSL version.", - )) } } @@ -3681,15 +3680,9 @@ mod _ssl { impl PySslSession { #[pygetset] fn time(&self) -> i64 { - unsafe { - #[cfg(ossl330)] - { - sys::SSL_SESSION_get_time(self.session) as i64 - } - #[cfg(not(ossl330))] - { - sys::SSL_SESSION_get_time(self.session) as i64 - } + cfg_select! { + ossl330 => unsafe { sys::SSL_SESSION_get_time(self.session) as i64 }, + _ => unsafe { sys::SSL_SESSION_get_time(self.session) as i64 }, } } @@ -3701,14 +3694,10 @@ mod _ssl { #[pygetset] fn ticket_lifetime_hint(&self) -> u64 { // SSL_SESSION_get_ticket_lifetime_hint available in OpenSSL 1.1.0+ - #[cfg(ossl110)] - { - unsafe { SSL_SESSION_get_ticket_lifetime_hint(self.session) as u64 } - } - #[cfg(not(ossl110))] - { + cfg_select! { + ossl110 => unsafe { SSL_SESSION_get_ticket_lifetime_hint(self.session) as u64 }, // Not available in older OpenSSL versions - 0 + _ => 0, } } @@ -3725,14 +3714,10 @@ mod _ssl { #[pygetset] fn has_ticket(&self) -> bool { // SSL_SESSION_has_ticket available in OpenSSL 1.1.0+ - #[cfg(ossl110)] - { - unsafe { SSL_SESSION_has_ticket(self.session) != 0 } - } - #[cfg(not(ossl110))] - { + cfg_select! { + ossl110 => unsafe { SSL_SESSION_has_ticket(self.session) != 0 }, // Not available in older OpenSSL versions - false + _ => false, } } } diff --git a/crates/stdlib/src/socket.rs b/crates/stdlib/src/socket.rs index fed5019c1b7..ebd447f413c 100644 --- a/crates/stdlib/src/socket.rs +++ b/crates/stdlib/src/socket.rs @@ -3264,7 +3264,7 @@ mod _socket { fn sock_from_raw(fileno: RawSocket, vm: &VirtualMachine) -> PyResult { let invalid = cfg_select! { windows => fileno == INVALID_SOCKET, - _ => fileno < 0 + _ => fileno < 0, }; if invalid { return Err(vm.new_value_error("negative file descriptor")); diff --git a/crates/stdlib/src/ssl.rs b/crates/stdlib/src/ssl.rs index 51f5bc042f4..6ee39b2445d 100644 --- a/crates/stdlib/src/ssl.rs +++ b/crates/stdlib/src/ssl.rs @@ -4832,31 +4832,20 @@ mod _ssl { // Common default paths for different platforms // These match the first candidates that rustls-native-certs/openssl-probe checks - #[cfg(target_os = "macos")] - let (default_cafile, default_capath) = { + let (default_cafile, default_capath): (Option<&str>, Option<&str>) = cfg_select! { // macOS primarily uses Keychain API, but provides fallback paths // for compatibility and when Keychain access fails - (Some("/etc/ssl/cert.pem"), Some("/etc/ssl/certs")) - }; - - #[cfg(target_os = "linux")] - let (default_cafile, default_capath) = { + target_os = "macos" => (Some("/etc/ssl/cert.pem"), Some("/etc/ssl/certs")), // Linux: matches openssl-probe's first candidate (/etc/ssl/cert.pem) // openssl-probe checks multiple locations at runtime, but we return // OpenSSL's compile-time default - (Some("/etc/ssl/cert.pem"), Some("/etc/ssl/certs")) - }; - - #[cfg(windows)] - let (default_cafile, default_capath) = { + target_os = "linux" => (Some("/etc/ssl/cert.pem"), Some("/etc/ssl/certs")), // Windows uses certificate store, not file paths // Return empty strings to avoid None being passed to os.path.isfile() - (Some(""), Some("")) + windows => (Some(""), Some("")), + _ => (None, None), }; - #[cfg(not(any(target_os = "macos", target_os = "linux", windows)))] - let (default_cafile, default_capath): (Option<&str>, Option<&str>) = (None, None); - let tuple = vm.ctx.new_tuple(vec![ vm.ctx.new_str("SSL_CERT_FILE").into(), // openssl_cafile_env default_cafile diff --git a/crates/vm/src/buffer.rs b/crates/vm/src/buffer.rs index db58c909bca..40984493c30 100644 --- a/crates/vm/src/buffer.rs +++ b/crates/vm/src/buffer.rs @@ -61,10 +61,10 @@ impl ByteOrder for LittleEndian { } } -#[cfg(target_endian = "big")] -type NativeEndian = BigEndian; -#[cfg(target_endian = "little")] -type NativeEndian = LittleEndian; +type NativeEndian = cfg_select! { + target_endian = "big" => BigEndian, + target_endian = "little" => LittleEndian, +}; #[derive(Copy, Clone, num_enum::TryFromPrimitive)] #[repr(u8)] diff --git a/crates/vm/src/codecs.rs b/crates/vm/src/codecs.rs index e4e3faa5809..ea9f9b464ee 100644 --- a/crates/vm/src/codecs.rs +++ b/crates/vm/src/codecs.rs @@ -441,15 +441,15 @@ enum StandardEncoding { } impl StandardEncoding { - #[cfg(target_endian = "little")] - const UTF_16_NE: Self = Self::Utf16Le; - #[cfg(target_endian = "big")] - const UTF_16_NE: Self = Self::Utf16Be; - - #[cfg(target_endian = "little")] - const UTF_32_NE: Self = Self::Utf32Le; - #[cfg(target_endian = "big")] - const UTF_32_NE: Self = Self::Utf32Be; + const UTF_16_NE: Self = cfg_select! { + target_endian = "little" => Self::Utf16Le, + target_endian = "big" => Self::Utf16Be, + }; + + const UTF_32_NE: Self = cfg_select! { + target_endian = "little" => Self::Utf32Le, + target_endian = "big" => Self::Utf32Be, + }; fn parse(encoding: &str) -> Option { if let Some(encoding) = encoding.to_lowercase().strip_prefix("utf") { diff --git a/crates/vm/src/exceptions.rs b/crates/vm/src/exceptions.rs index ffab36bd01d..78d8c73cd1d 100644 --- a/crates/vm/src/exceptions.rs +++ b/crates/vm/src/exceptions.rs @@ -1354,10 +1354,10 @@ impl OSErrorBuilder { } = self; let args = if let Some(errno) = errno { - #[cfg(windows)] - let winerror = winerror.to_pyobject(vm); - #[cfg(not(windows))] - let winerror = vm.ctx.none(); + let winerror = cfg_select! { + windows => winerror.to_pyobject(vm), + _ => vm.ctx.none(), + }; vec![ errno.to_pyobject(vm), @@ -2085,21 +2085,19 @@ pub(super) mod types { .get_attr("filename2", vm) .ok() .filter(|f| !vm.is_none(f)); - #[cfg(windows)] - let winerror = obj.get_attr("winerror", vm).ok().filter(|w| !vm.is_none(w)); + + let winerror: Option = cfg_select! { + windows => obj.get_attr("winerror", vm).ok().filter(|w| !vm.is_none(w)), + _ => None, + }; if let Some(filename2) = filename2 { - #[cfg(windows)] - { - args_reduced.push(winerror.unwrap_or_else(|| vm.ctx.none())); - } - #[cfg(not(windows))] - args_reduced.push(vm.ctx.none()); - args_reduced.push(filename2); + #[allow(clippy::unnecessary_literal_unwrap)] + let winerror = winerror.unwrap_or_else(|| vm.ctx.none()); + args_reduced.extend([winerror, filename2]); } else { // Diverges from CPython: include winerror even without // filename2 so it survives pickle round-trips. - #[cfg(windows)] if let Some(winerror) = winerror { args_reduced.push(winerror); } diff --git a/crates/vm/src/getpath.rs b/crates/vm/src/getpath.rs index 789fc72f62a..5e3ea2e94b4 100644 --- a/crates/vm/src/getpath.rs +++ b/crates/vm/src/getpath.rs @@ -307,11 +307,10 @@ fn calculate_base_executable(executable: Option<&PathBuf>, home_dir: &Option Option { - #[cfg(not(windows))] - let stdlib_dir = PathBuf::from(prefix).join(platform::stdlib_subdir()); - - #[cfg(windows)] - let stdlib_dir = PathBuf::from(prefix).join(platform::STDLIB_SUBDIR); + let stdlib_dir = Path::new(prefix).join(cfg_select! { + windows => platform::STDLIB_SUBDIR, + _ => platform::stdlib_subdir(), + }); if stdlib_dir.is_dir() { Some(stdlib_dir.to_string_lossy().into_owned()) diff --git a/crates/vm/src/stdlib/_ctypes/function.rs b/crates/vm/src/stdlib/_ctypes/function.rs index 9136304c296..f9b61fa4caf 100644 --- a/crates/vm/src/stdlib/_ctypes/function.rs +++ b/crates/vm/src/stdlib/_ctypes/function.rs @@ -655,24 +655,24 @@ fn wstring_at_impl(ptr: usize, size: isize, vm: &VirtualMachine) -> PyResult { // Windows: wchar_t = u16 (UTF-16) -> use Wtf8Buf::from_wide // macOS/Linux: wchar_t = i32 (UTF-32) -> convert via char::from_u32 - #[cfg(windows)] - { - use rustpython_common::wtf8::Wtf8Buf; - let wide: Vec = wchars.to_vec(); - let wtf8 = Wtf8Buf::from_wide(&wide); - Ok(vm.ctx.new_str(wtf8).into()) - } - #[cfg(not(windows))] - { - #[allow( - clippy::useless_conversion, - reason = "wchar_t is i32 on some platforms and u32 on others" - )] - let s: String = wchars - .iter() - .filter_map(|&c| u32::try_from(c).ok().and_then(char::from_u32)) - .collect(); - Ok(vm.ctx.new_str(s).into()) + cfg_select! { + windows => { + use rustpython_common::wtf8::Wtf8Buf; + let wide: Vec = wchars.to_vec(); + let wtf8 = Wtf8Buf::from_wide(&wide); + Ok(vm.ctx.new_str(wtf8).into()) + } + _ => { + #[allow( + clippy::useless_conversion, + reason = "wchar_t is i32 on some platforms and u32 on others" + )] + let s: String = wchars + .iter() + .filter_map(|&c| u32::try_from(c).ok().and_then(char::from_u32)) + .collect(); + Ok(vm.ctx.new_str(s).into()) + } } } @@ -2030,24 +2030,24 @@ fn ffi_to_python(ty: &Py, ptr: *const c_void, vm: &VirtualMachine) -> Py let slice = core::slice::from_raw_parts(wstr_ptr, len); // Windows: wchar_t = u16 (UTF-16) -> use Wtf8Buf::from_wide // Unix: wchar_t = i32 (UTF-32) -> convert via char::from_u32 - #[cfg(windows)] - { - use rustpython_common::wtf8::Wtf8Buf; - let wide: Vec = slice.to_vec(); - let wtf8 = Wtf8Buf::from_wide(&wide); - vm.ctx.new_str(wtf8).into() - } - #[cfg(not(windows))] - { - #[allow( - clippy::useless_conversion, - reason = "wchar_t is i32 on some platforms and u32 on others" - )] - let s: String = slice - .iter() - .filter_map(|&c| u32::try_from(c).ok().and_then(char::from_u32)) - .collect(); - vm.ctx.new_str(s).into() + cfg_select! { + windows => { + use rustpython_common::wtf8::Wtf8Buf; + let wide: Vec = slice.to_vec(); + let wtf8 = Wtf8Buf::from_wide(&wide); + vm.ctx.new_str(wtf8).into() + } + _ => { + #[allow( + clippy::useless_conversion, + reason = "wchar_t is i32 on some platforms and u32 on others" + )] + let s: String = slice + .iter() + .filter_map(|&c| u32::try_from(c).ok().and_then(char::from_u32)) + .collect(); + vm.ctx.new_str(s).into() + } } } } diff --git a/crates/vm/src/stdlib/_ctypes/simple.rs b/crates/vm/src/stdlib/_ctypes/simple.rs index 3bf1f84fbc5..c51679421bf 100644 --- a/crates/vm/src/stdlib/_ctypes/simple.rs +++ b/crates/vm/src/stdlib/_ctypes/simple.rs @@ -18,12 +18,12 @@ use core::fmt::Debug; use num_traits::ToPrimitive; /// Valid type codes for ctypes simple types -#[cfg(windows)] -// spell-checker: disable-next-line -pub(super) const SIMPLE_TYPE_CHARS: &str = "cbBhHiIlLdfuzZqQPXOv?g"; -#[cfg(not(windows))] -// spell-checker: disable-next-line -pub(super) const SIMPLE_TYPE_CHARS: &str = "cbBhHiIlLdfuzZqQPOv?g"; +pub(super) const SIMPLE_TYPE_CHARS: &str = cfg_select! { + // spell-checker: disable-next-line + windows => "cbBhHiIlLdfuzZqQPXOv?g", + // spell-checker: disable-next-line + _ => "cbBhHiIlLdfuzZqQPOv?g", +}; /// Convert ctypes type code to PEP 3118 format code. /// Some ctypes codes need to be mapped to standard-size codes based on platform. diff --git a/crates/vm/src/stdlib/_io.rs b/crates/vm/src/stdlib/_io.rs index 418431a73ee..197bb077e06 100644 --- a/crates/vm/src/stdlib/_io.rs +++ b/crates/vm/src/stdlib/_io.rs @@ -152,7 +152,7 @@ mod _io { any(target_os = "dragonfly", target_os = "freebsd", target_os = "linux") => { x || matches!(whence, libc::SEEK_DATA | libc::SEEK_HOLE) } - _ => x + _ => x, } } @@ -5078,23 +5078,23 @@ mod _io { // Construct a RawIO (subclass of RawIOBase) // On Windows, use _WindowsConsoleIO for console handles. // This is subsequently consumed by a Buffered Class. - #[cfg(all(feature = "host_env", windows))] - let is_console = super::winconsoleio::pyio_get_console_type(&file, vm) != '\0'; - #[cfg(not(all(feature = "host_env", windows)))] - let is_console = false; - - let file_io_class: &Py = { - cfg_select! { - all(feature = "host_env", windows) => { - if is_console { - Some(super::winconsoleio::WindowsConsoleIO::static_type()) - } else { - Some(super::fileio::FileIO::static_type()) - } + let is_console = cfg_select! { + all(feature = "host_env", windows) => { + super::winconsoleio::pyio_get_console_type(&file, vm) != '\0' + } + _ => false, + }; + + let file_io_class: &Py = cfg_select! { + all(feature = "host_env", windows) => { + if is_console { + Some(super::winconsoleio::WindowsConsoleIO::static_type()) + } else { + Some(super::fileio::FileIO::static_type()) } - feature = "host_env" => Some(super::fileio::FileIO::static_type()), - _ => None, } + feature = "host_env" => Some(super::fileio::FileIO::static_type()), + _ => None, } .ok_or_else(|| { new_unsupported_operation( diff --git a/crates/vm/src/stdlib/_signal.rs b/crates/vm/src/stdlib/_signal.rs index e80386a670a..6ae0393dbcc 100644 --- a/crates/vm/src/stdlib/_signal.rs +++ b/crates/vm/src/stdlib/_signal.rs @@ -16,11 +16,11 @@ pub(crate) mod _signal { #[cfg(unix)] use rustpython_host_env::signal::{double_to_timeval, itimerval_to_tuple}; - #[cfg(any(unix, windows))] - use libc::sighandler_t; #[allow(non_camel_case_types)] - #[cfg(not(any(unix, windows)))] - type sighandler_t = usize; + type sighandler_t = cfg_select! { + any(unix, windows) => libc::sighandler_t, + _ => usize, + }; cfg_select! { windows => { @@ -552,41 +552,40 @@ pub(crate) mod _signal { use crate::PyPayload; use crate::builtins::PySet; let set = PySet::default().into_ref(&vm.ctx); - #[cfg(unix)] - { - // Use sigfillset to get all valid signals - let mut mask: libc::sigset_t = unsafe { core::mem::zeroed() }; - // SAFETY: mask is a valid pointer - if unsafe { libc::sigfillset(&mut mask) } != 0 { - return Err(vm.new_os_error("sigfillset failed".to_owned())); + cfg_select! { + unix => { + // Use sigfillset to get all valid signals + let mut mask: libc::sigset_t = unsafe { core::mem::zeroed() }; + // SAFETY: mask is a valid pointer + if unsafe { libc::sigfillset(&mut mask) } != 0 { + return Err(vm.new_os_error("sigfillset failed".to_owned())); + } + // Convert the filled mask to a Python set + for signum in 1..signal::NSIG { + if unsafe { libc::sigismember(&mask, signum as i32) } == 1 { + set.add(vm.ctx.new_int(signum as i32).into(), vm)?; + } + } } - // Convert the filled mask to a Python set - for signum in 1..signal::NSIG { - if unsafe { libc::sigismember(&mask, signum as i32) } == 1 { - set.add(vm.ctx.new_int(signum as i32).into(), vm)?; + windows => { + // Windows only supports a limited set of signals + for &signum in &[ + libc::SIGINT, + libc::SIGILL, + libc::SIGFPE, + libc::SIGSEGV, + libc::SIGTERM, + SIGBREAK, + libc::SIGABRT, + ] { + set.add(vm.ctx.new_int(signum).into(), vm)?; } } - } - #[cfg(windows)] - { - // Windows only supports a limited set of signals - for &signum in &[ - libc::SIGINT, - libc::SIGILL, - libc::SIGFPE, - libc::SIGSEGV, - libc::SIGTERM, - SIGBREAK, - libc::SIGABRT, - ] { - set.add(vm.ctx.new_int(signum).into(), vm)?; + _ => { + // Empty set for platforms without signal support (e.g., WASM) + let _ = &set; } } - #[cfg(not(any(unix, windows)))] - { - // Empty set for platforms without signal support (e.g., WASM) - let _ = &set; - } Ok(set.into()) } diff --git a/crates/vm/src/stdlib/os.rs b/crates/vm/src/stdlib/os.rs index da646c95411..53843994225 100644 --- a/crates/vm/src/stdlib/os.rs +++ b/crates/vm/src/stdlib/os.rs @@ -824,10 +824,10 @@ pub(super) mod _os { .map_err(|e| e.into_pyexception(vm))? .ok_or_else(|| crate::exceptions::cstring_error(vm))?; // On Windows, combine st_ino and st_ino_high into 128-bit value - #[cfg(windows)] - let ino: u128 = stat.st_ino as u128 | ((stat.st_ino_high as u128) << 64); - #[cfg(not(windows))] - let ino: u128 = stat.st_ino as u128; + let ino: u128 = cfg_select! { + windows => stat.st_ino as u128 | ((stat.st_ino_high as u128) << 64), + _ => stat.st_ino as u128, + }; // Err(T) means other thread set `ino` at the mean time which is safe to ignore let _ = self.ino.compare_exchange(None, Some(ino)); Ok(ino) diff --git a/crates/vm/src/stdlib/time.rs b/crates/vm/src/stdlib/time.rs index a630e3ac506..ec12ad0efaf 100644 --- a/crates/vm/src/stdlib/time.rs +++ b/crates/vm/src/stdlib/time.rs @@ -491,24 +491,23 @@ mod decl { secs: OptionalArg>>, vm: &VirtualMachine, ) -> PyResult { - #[cfg(any(unix, windows))] - { - let ts = match secs { - OptionalArg::Present(Some(value)) => pyobj_to_time_t(value, vm)?, - OptionalArg::Present(None) | OptionalArg::Missing => current_time_t(), - }; - gmtime_from_timestamp(ts, vm) - } - - #[cfg(not(any(unix, windows)))] - { - let instant = match secs { - OptionalArg::Present(Some(secs)) => pyobj_to_date_time(secs, vm)?.naive_utc(), - OptionalArg::Present(None) | OptionalArg::Missing => { - chrono::offset::Utc::now().naive_utc() - } - }; - Ok(StructTimeData::new_utc(vm, instant)) + cfg_select! { + any(unix, windows) => { + let ts = match secs { + OptionalArg::Present(Some(value)) => pyobj_to_time_t(value, vm)?, + OptionalArg::Present(None) | OptionalArg::Missing => current_time_t(), + }; + gmtime_from_timestamp(ts, vm) + } + _ => { + let instant = match secs { + OptionalArg::Present(Some(secs)) => pyobj_to_date_time(secs, vm)?.naive_utc(), + OptionalArg::Present(None) | OptionalArg::Missing => { + chrono::offset::Utc::now().naive_utc() + } + }; + Ok(StructTimeData::new_utc(vm, instant)) + } } } @@ -517,20 +516,18 @@ mod decl { secs: OptionalArg>>, vm: &VirtualMachine, ) -> PyResult { - #[cfg(any(unix, windows))] - { - let ts = match secs { - OptionalArg::Present(Some(value)) => pyobj_to_time_t(value, vm)?, - OptionalArg::Present(None) | OptionalArg::Missing => current_time_t(), - }; - localtime_from_timestamp(ts, vm) - } - - #[cfg(not(any(unix, windows)))] - let instant = secs.naive_or_local(vm)?; - #[cfg(not(any(unix, windows)))] - { - Ok(StructTimeData::new_local(vm, instant, 0)) + cfg_select! { + any(unix, windows) => { + let ts = match secs { + OptionalArg::Present(Some(value)) => pyobj_to_time_t(value, vm)?, + OptionalArg::Present(None) | OptionalArg::Missing => current_time_t(), + }; + localtime_from_timestamp(ts, vm) + } + _ => { + let instant = secs.naive_or_local(vm)?; + Ok(StructTimeData::new_local(vm, instant, 0)) + } } } diff --git a/crates/vm/src/version.rs b/crates/vm/src/version.rs index 5b80a33322b..4da22b12a33 100644 --- a/crates/vm/src/version.rs +++ b/crates/vm/src/version.rs @@ -18,20 +18,19 @@ pub const VERSION_HEX: usize = pub fn get_version() -> String { // Windows: include MSC v. for compatibility with ctypes.util.find_library // MSC v.1929 = VS 2019, version 14+ makes find_msvcrt() return None - #[cfg(windows)] - let msc_info = { - let arch = if cfg!(target_pointer_width = "64") { - "64 bit (AMD64)" - } else { - "32 bit (Intel)" - }; - // Include both RustPython identifier and MSC v. for compatibility - format!(" MSC v.1929 {arch}",) + let msc_info = cfg_select! { + windows => {{ + let arch = if cfg!(target_pointer_width = "64") { + "64 bit (AMD64)" + } else { + "32 bit (Intel)" + }; + // Include both RustPython identifier and MSC v. for compatibility + format!(" MSC v.1929 {arch}",) + }}, + _ => String::new(), }; - #[cfg(not(windows))] - let msc_info = String::new(); - format!( "{:.80} ({:.80}) \n[RustPython {} with {:.80}{}]", // \n is PyPy convention get_version_number(), diff --git a/crates/vm/src/vm/mod.rs b/crates/vm/src/vm/mod.rs index 267382ed34d..be43e575e3f 100644 --- a/crates/vm/src/vm/mod.rs +++ b/crates/vm/src/vm/mod.rs @@ -697,13 +697,11 @@ impl VirtualMachine { /// Mirrors `_Py_ThreadCanHandleSignals`. #[allow(dead_code)] pub(crate) fn is_main_thread(&self) -> bool { - #[cfg(feature = "threading")] - { - crate::stdlib::_thread::get_ident() == self.state.main_thread_ident.load() - } - #[cfg(not(feature = "threading"))] - { - true + cfg_select! { + feature = "threading" => { + crate::stdlib::_thread::get_ident() == self.state.main_thread_ident.load() + } + _ => true, } } @@ -2030,13 +2028,9 @@ impl VirtualMachine { thread::suspend_if_needed(&self.state.stop_the_world); #[cfg(not(target_arch = "wasm32"))] - { - crate::signal::check_signals(self) - } - #[cfg(target_arch = "wasm32")] - { - Ok(()) - } + crate::signal::check_signals(self)?; + + Ok(()) } /// Push a new exc_info slot (for generator/coroutine resume). @@ -2151,11 +2145,9 @@ impl VirtualMachine { } 1 } else if exc.fast_isinstance(self.ctx.exceptions.keyboard_interrupt) { - #[allow(clippy::if_same_then_else)] - { - self.print_exception(exc); - #[cfg(unix)] - { + self.print_exception(exc); + cfg_select! { + unix => { let action = SigAction::new( nix::sys::signal::SigHandler::SigDfl, SaFlags::SA_ONSTACK, @@ -2169,15 +2161,9 @@ impl VirtualMachine { (libc::SIGINT as u32) + 128 } - #[cfg(windows)] - { - // STATUS_CONTROL_C_EXIT - same as CPython - 0xC000013A - } - #[cfg(not(any(unix, windows)))] - { - 1 - } + // STATUS_CONTROL_C_EXIT - same as CPython + windows => 0xC000013A, + _ => 1, } } else { self.print_exception(exc); diff --git a/crates/vm/src/vm/vm_object.rs b/crates/vm/src/vm/vm_object.rs index 0c60be2c0ec..d599a781bde 100644 --- a/crates/vm/src/vm/vm_object.rs +++ b/crates/vm/src/vm/vm_object.rs @@ -12,43 +12,35 @@ impl VirtualMachine { #[track_caller] #[cold] fn _py_panic_failed(&self, exc: PyBaseExceptionRef, msg: &str) -> ! { - #[cfg(not(all( - target_arch = "wasm32", - not(any(target_os = "emscripten", target_os = "wasi")), - )))] - { - self.print_exception(exc); - self.flush_std(); - panic!("{msg}") - } - #[cfg(all( - target_arch = "wasm32", - feature = "wasmbind", - not(any(target_os = "emscripten", target_os = "wasi")), - ))] - #[cfg(all(target_arch = "wasm32", not(target_os = "wasi"), feature = "wasmbind"))] - { - use wasm_bindgen::prelude::*; - #[wasm_bindgen] - extern "C" { - #[wasm_bindgen(js_namespace = console)] - fn error(s: &str); + cfg_select! { + all( + target_arch = "wasm32", + not(any(target_os = "emscripten", target_os = "wasi")) + ) => cfg_select! { + feature = "wasmbind" => { + use wasm_bindgen::prelude::*; + #[wasm_bindgen] + extern "C" { + #[wasm_bindgen(js_namespace = console)] + fn error(s: &str); + } + let mut s = String::new(); + self.write_exception(&mut s, &exc).unwrap(); + error(&s); + panic!("{msg}; exception backtrace above") + } + _ => { + use crate::convert::ToPyObject; + let err_string: String = exc.to_pyobject(self).repr(self).unwrap().to_string(); + eprintln!("{err_string}"); + panic!("{msg}; python exception not available") + } + }, + _ => { + self.print_exception(exc); + self.flush_std(); + panic!("{msg}") } - let mut s = String::new(); - self.write_exception(&mut s, &exc).unwrap(); - error(&s); - panic!("{msg}; exception backtrace above") - } - #[cfg(all( - target_arch = "wasm32", - not(feature = "wasmbind"), - not(any(target_os = "emscripten", target_os = "wasi")), - ))] - { - use crate::convert::ToPyObject; - let err_string: String = exc.to_pyobject(self).repr(self).unwrap().to_string(); - eprintln!("{err_string}"); - panic!("{msg}; python exception not available") } } diff --git a/src/interpreter.rs b/src/interpreter.rs index b9ee2dbbc44..9060f3a7bec 100644 --- a/src/interpreter.rs +++ b/src/interpreter.rs @@ -15,15 +15,14 @@ impl InterpreterBuilderExt for InterpreterBuilder { let defs = rustpython_stdlib::stdlib_module_defs(&self.ctx); let builder = self.add_native_modules(&defs); - #[cfg(feature = "freeze-stdlib")] - let builder = builder - .add_frozen_modules(rustpython_pylib::FROZEN_STDLIB) - .init_hook(set_frozen_stdlib_dir); - - #[cfg(not(feature = "freeze-stdlib"))] - let builder = builder.init_hook(setup_dynamic_stdlib); - - builder + cfg_select! { + feature = "freeze-stdlib" => { + builder + .add_frozen_modules(rustpython_pylib::FROZEN_STDLIB) + .init_hook(set_frozen_stdlib_dir) + } + _ => builder.init_hook(setup_dynamic_stdlib), + } } } @@ -64,13 +63,9 @@ fn collect_stdlib_paths() -> Vec { .map(|path| path.into_os_string().into_string().unwrap()) .collect() } else { - #[cfg(feature = "rustpython-pylib")] - { - vec![rustpython_pylib::LIB_PATH.to_owned()] - } - #[cfg(not(feature = "rustpython-pylib"))] - { - vec![] - } + vec![ + #[cfg(feature = "rustpython-pylib")] + rustpython_pylib::LIB_PATH.to_owned(), + ] } } diff --git a/src/lib.rs b/src/lib.rs index b9ddcc3aeb0..0ce4a230e3a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -176,18 +176,16 @@ fn run_file(vm: &VirtualMachine, scope: Scope, path: &str) -> PyResult<()> { vm.insert_sys_path(vm.new_pyobj(dir))?; } - #[cfg(feature = "host_env")] - { - vm.run_any_file(scope, path) - } - #[cfg(not(feature = "host_env"))] - { - // In sandbox mode, the binary reads the file and feeds source to the VM. - // The VM itself has no filesystem access. - let path = if path.is_empty() { "???" } else { path }; - match std::fs::read_to_string(path) { - Ok(source) => vm.run_string(scope, &source, path.to_owned()).map(drop), - Err(err) => Err(vm.new_os_error(err.to_string())), + cfg_select! { + feature = "host_env" => vm.run_any_file(scope, path), + _ => { + // In sandbox mode, the binary reads the file and feeds source to the VM. + // The VM itself has no filesystem access. + let path = if path.is_empty() { "???" } else { path }; + match std::fs::read_to_string(path) { + Ok(source) => vm.run_string(scope, &source, path.to_owned()).map(drop), + Err(err) => Err(vm.new_os_error(err.to_string())), + } } } } From 615583d31c43b469e738e591189c2593843a3f17 Mon Sep 17 00:00:00 2001 From: Noa Date: Mon, 4 May 2026 14:47:49 -0500 Subject: [PATCH 2/2] Fix typos --- crates/stdlib/src/faulthandler.rs | 7 ++----- crates/stdlib/src/openssl.rs | 3 +-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/crates/stdlib/src/faulthandler.rs b/crates/stdlib/src/faulthandler.rs index f21ed115a34..6d27a77d4f2 100644 --- a/crates/stdlib/src/faulthandler.rs +++ b/crates/stdlib/src/faulthandler.rs @@ -124,10 +124,7 @@ mod decl { #[cfg(any(unix, windows))] fn puts_bytes(fd: i32, s: &[u8]) { - let _ = cfg_select! { - windows => unsafe { libc::write(fd, s.as_ptr() as *const libc::c_void, s.len() as u32) }, - _ => unsafe { libc::write(fd, s.as_ptr() as *const libc::c_void, s.len()) }, - }; + let _ = unsafe { libc::write(fd, s.as_ptr().cast::(), s.len() as _) }; } // _Py_DumpHexadecimal (traceback.c) @@ -164,7 +161,7 @@ mod decl { v /= 10; } - puts_bytes(fd, &buf[..buf.len() - i]); + puts_bytes(fd, &buf[i..]); } /// Get current thread ID diff --git a/crates/stdlib/src/openssl.rs b/crates/stdlib/src/openssl.rs index 2d1bf7c4aec..066f8516710 100644 --- a/crates/stdlib/src/openssl.rs +++ b/crates/stdlib/src/openssl.rs @@ -1308,7 +1308,7 @@ mod _ssl { fn num_tickets(&self, _vm: &VirtualMachine) -> PyResult { // Only supported for TLS 1.3 cfg_select! { - ossl110 => { + ossl111 => { let ctx = self.ctx(); let num = unsafe { sys::SSL_CTX_get_num_tickets(ctx.as_ptr()) }; Ok(num) @@ -1562,7 +1562,6 @@ mod _ssl { ) -> PyResult> { let binary_form = args.binary_form.unwrap_or(false); let ctx = self.ctx(); - #[cfg(ossl300)] let certs = cfg_select! { ossl300 => ctx.cert_store().all_certificates(), _ => ctx.cert_store().objects().iter().filter_map(|x| x.x509()),