mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-29 03:04:38 +08:00
24 files changed
+75
-108
No files matched your search
@@ -229,6 +229,7 @@ jobs:
|
||||
uses: coolreader18/redoxer-action@v1
|
||||
with:
|
||||
command: check
|
||||
args: --ignore-rust-version
|
||||
|
||||
snippets_cpython:
|
||||
if: ${{ !contains(github.event.pull_request.labels.*.name, 'skip:ci') }}
|
||||
@@ -407,7 +408,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: dtolnay/rust-toolchain@stable
|
||||
with:
|
||||
target: wasm32-wasi
|
||||
target: wasm32-wasip1
|
||||
|
||||
- uses: Swatinem/rust-cache@v2
|
||||
- name: Setup Wasmer
|
||||
@@ -415,8 +416,8 @@ jobs:
|
||||
- name: Install clang
|
||||
run: sudo apt-get update && sudo apt-get install clang -y
|
||||
- name: build rustpython
|
||||
run: cargo build --release --target wasm32-wasi --features freeze-stdlib,stdlib --verbose
|
||||
run: cargo build --release --target wasm32-wasip1 --features freeze-stdlib,stdlib --verbose
|
||||
- name: run snippets
|
||||
run: wasmer run --dir `pwd` target/wasm32-wasi/release/rustpython.wasm -- `pwd`/extra_tests/snippets/stdlib_random.py
|
||||
run: wasmer run --dir `pwd` target/wasm32-wasip1/release/rustpython.wasm -- `pwd`/extra_tests/snippets/stdlib_random.py
|
||||
- name: run cpython unittest
|
||||
run: wasmer run --dir `pwd` target/wasm32-wasi/release/rustpython.wasm -- `pwd`/Lib/test/test_int.py
|
||||
run: wasmer run --dir `pwd` target/wasm32-wasip1/release/rustpython.wasm -- `pwd`/Lib/test/test_int.py
|
||||
+1
-1
@@ -104,7 +104,7 @@ members = [
|
||||
version = "0.4.0"
|
||||
authors = ["RustPython Team"]
|
||||
edition = "2021"
|
||||
rust-version = "1.80.0"
|
||||
rust-version = "1.83.0"
|
||||
repository = "https://github.com/RustPython/RustPython"
|
||||
license = "MIT"
|
||||
|
||||
|
||||
@@ -91,13 +91,13 @@ You can compile RustPython to a standalone WebAssembly WASI module so it can run
|
||||
Build
|
||||
|
||||
```bash
|
||||
cargo build --target wasm32-wasi --no-default-features --features freeze-stdlib,stdlib --release
|
||||
cargo build --target wasm32-wasip1 --no-default-features --features freeze-stdlib,stdlib --release
|
||||
```
|
||||
|
||||
Run by wasmer
|
||||
|
||||
```bash
|
||||
wasmer run --dir `pwd` -- target/wasm32-wasi/release/rustpython.wasm `pwd`/extra_tests/snippets/stdlib_random.py
|
||||
wasmer run --dir `pwd` -- target/wasm32-wasip1/release/rustpython.wasm `pwd`/extra_tests/snippets/stdlib_random.py
|
||||
```
|
||||
|
||||
Run by wapm
|
||||
@@ -114,10 +114,10 @@ $ wapm run rustpython
|
||||
You can build the WebAssembly WASI file with:
|
||||
|
||||
```bash
|
||||
cargo build --release --target wasm32-wasi --features="freeze-stdlib"
|
||||
cargo build --release --target wasm32-wasip1 --features="freeze-stdlib"
|
||||
```
|
||||
|
||||
> Note: we use the `freeze-stdlib` to include the standard library inside the binary. You also have to run once `rustup target add wasm32-wasi`.
|
||||
> Note: we use the `freeze-stdlib` to include the standard library inside the binary. You also have to run once `rustup target add wasm32-wasip1`.
|
||||
|
||||
### JIT (Just in time) compiler
|
||||
|
||||
|
||||
+5
-22
@@ -1,7 +1,8 @@
|
||||
//! An unresizable vector backed by a `Box<[T]>`
|
||||
|
||||
#![allow(clippy::needless_lifetimes)]
|
||||
|
||||
use std::{
|
||||
alloc,
|
||||
borrow::{Borrow, BorrowMut},
|
||||
cmp, fmt,
|
||||
mem::{self, MaybeUninit},
|
||||
@@ -35,29 +36,11 @@ macro_rules! panic_oob {
|
||||
};
|
||||
}
|
||||
|
||||
fn capacity_overflow() -> ! {
|
||||
panic!("capacity overflow")
|
||||
}
|
||||
|
||||
impl<T> BoxVec<T> {
|
||||
pub fn new(n: usize) -> BoxVec<T> {
|
||||
unsafe {
|
||||
let layout = match alloc::Layout::array::<T>(n) {
|
||||
Ok(l) => l,
|
||||
Err(_) => capacity_overflow(),
|
||||
};
|
||||
let ptr = if mem::size_of::<T>() == 0 {
|
||||
ptr::NonNull::<MaybeUninit<T>>::dangling().as_ptr()
|
||||
} else {
|
||||
let ptr = alloc::alloc(layout);
|
||||
if ptr.is_null() {
|
||||
alloc::handle_alloc_error(layout)
|
||||
}
|
||||
ptr as *mut MaybeUninit<T>
|
||||
};
|
||||
let ptr = ptr::slice_from_raw_parts_mut(ptr, n);
|
||||
let xs = Box::from_raw(ptr);
|
||||
BoxVec { xs, len: 0 }
|
||||
BoxVec {
|
||||
xs: Box::new_uninit_slice(n),
|
||||
len: 0,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
//! A crate to hold types and functions common to all rustpython components.
|
||||
|
||||
#![cfg_attr(target_os = "redox", feature(byte_slice_trim_ascii))]
|
||||
#![cfg_attr(target_os = "redox", feature(byte_slice_trim_ascii, new_uninit))]
|
||||
|
||||
#[macro_use]
|
||||
mod macros;
|
||||
|
||||
@@ -2,7 +2,7 @@ use lock_api::{
|
||||
GetThreadId, RawMutex, RawRwLock, RawRwLockDowngrade, RawRwLockRecursive, RawRwLockUpgrade,
|
||||
RawRwLockUpgradeDowngrade,
|
||||
};
|
||||
use std::{cell::Cell, num::NonZeroUsize};
|
||||
use std::{cell::Cell, num::NonZero};
|
||||
|
||||
pub struct RawCellMutex {
|
||||
locked: Cell<bool>,
|
||||
@@ -203,7 +203,7 @@ fn deadlock(lock_kind: &str, ty: &str) -> ! {
|
||||
pub struct SingleThreadId(());
|
||||
unsafe impl GetThreadId for SingleThreadId {
|
||||
const INIT: Self = SingleThreadId(());
|
||||
fn nonzero_thread_id(&self) -> NonZeroUsize {
|
||||
NonZeroUsize::new(1).unwrap()
|
||||
fn nonzero_thread_id(&self) -> NonZero<usize> {
|
||||
NonZero::new(1).unwrap()
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
#![allow(clippy::needless_lifetimes)]
|
||||
|
||||
use lock_api::{MutexGuard, RawMutex};
|
||||
use std::{fmt, marker::PhantomData, ops::Deref};
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
#![allow(clippy::needless_lifetimes)]
|
||||
|
||||
use lock_api::{GetThreadId, GuardNoSend, RawMutex};
|
||||
use std::{
|
||||
cell::UnsafeCell,
|
||||
|
||||
+6
-5
@@ -331,12 +331,13 @@ pub mod levenshtein {
|
||||
/// ```
|
||||
#[macro_export]
|
||||
macro_rules! ascii {
|
||||
($x:literal) => {{
|
||||
const STR: &str = $x;
|
||||
const _: () = if !STR.is_ascii() {
|
||||
panic!("ascii!() argument is not an ascii string");
|
||||
($x:expr $(,)?) => {{
|
||||
let s = const {
|
||||
let s: &str = $x;
|
||||
assert!(s.is_ascii(), "ascii!() argument is not an ascii string");
|
||||
s
|
||||
};
|
||||
unsafe { $crate::vendored::ascii::AsciiStr::from_ascii_unchecked(STR.as_bytes()) }
|
||||
unsafe { $crate::vendored::ascii::AsciiStr::from_ascii_unchecked(s.as_bytes()) }
|
||||
}};
|
||||
}
|
||||
pub use ascii;
|
||||
|
||||
@@ -102,8 +102,7 @@ impl FrozenLib<Vec<u8>> {
|
||||
/// Encode the given iterator of frozen modules into a compressed vector of bytes
|
||||
pub fn encode<'a, I, B: AsRef<[u8]>>(lib: I) -> FrozenLib<Vec<u8>>
|
||||
where
|
||||
I: IntoIterator<Item = (&'a str, FrozenModule<B>)>,
|
||||
I::IntoIter: ExactSizeIterator + Clone,
|
||||
I: IntoIterator<Item = (&'a str, FrozenModule<B>), IntoIter: ExactSizeIterator + Clone>,
|
||||
{
|
||||
let iter = lib.into_iter();
|
||||
let mut bytes = Vec::new();
|
||||
|
||||
+1
-1
@@ -83,7 +83,7 @@ mod grp {
|
||||
#[pyfunction]
|
||||
fn getgrall(vm: &VirtualMachine) -> PyResult<Vec<PyObjectRef>> {
|
||||
// setgrent, getgrent, etc are not thread safe. Could use fgetgrent_r, but this is easier
|
||||
static GETGRALL: parking_lot::Mutex<()> = parking_lot::const_mutex(());
|
||||
static GETGRALL: parking_lot::Mutex<()> = parking_lot::Mutex::new(());
|
||||
let _guard = GETGRALL.lock();
|
||||
let mut list = Vec::new();
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// to allow `mod foo {}` in foo.rs; clippy thinks this is a mistake/misunderstanding of
|
||||
// how `mod` works, but we want this sometimes for pymodule declarations
|
||||
#![allow(clippy::module_inception)]
|
||||
#![cfg_attr(target_os = "redox", feature(raw_ref_op))]
|
||||
|
||||
#[macro_use]
|
||||
extern crate rustpython_derive;
|
||||
|
||||
@@ -36,7 +36,7 @@ mod platform {
|
||||
// based off winsock2.h: https://gist.github.com/piscisaureus/906386#file-winsock2-h-L128-L141
|
||||
|
||||
pub unsafe fn FD_SET(fd: RawFd, set: *mut fd_set) {
|
||||
let mut slot = std::ptr::addr_of_mut!((*set).fd_array).cast::<RawFd>();
|
||||
let mut slot = (&raw mut (*set).fd_array).cast::<RawFd>();
|
||||
let fd_count = (*set).fd_count;
|
||||
for _ in 0..fd_count {
|
||||
if *slot == fd {
|
||||
|
||||
@@ -2217,7 +2217,7 @@ mod _socket {
|
||||
fn as_slice(&self) -> &[netioapi::MIB_IF_ROW2] {
|
||||
unsafe {
|
||||
let p = self.ptr.as_ptr();
|
||||
let ptr = ptr::addr_of!((*p).Table) as *const netioapi::MIB_IF_ROW2;
|
||||
let ptr = &raw const (*p).Table as *const netioapi::MIB_IF_ROW2;
|
||||
std::slice::from_raw_parts(ptr, (*p).NumEntries as usize)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ mod _sqlite {
|
||||
ffi::{c_int, c_longlong, c_uint, c_void, CStr},
|
||||
fmt::Debug,
|
||||
ops::Deref,
|
||||
ptr::{addr_of_mut, null, null_mut},
|
||||
ptr::{null, null_mut},
|
||||
thread::ThreadId,
|
||||
};
|
||||
|
||||
@@ -1180,14 +1180,10 @@ mod _sqlite {
|
||||
)
|
||||
};
|
||||
|
||||
// TODO: replace with Result.inspect_err when stable
|
||||
if let Err(exc) = db.check(ret, vm) {
|
||||
db.check(ret, vm).inspect_err(|_| {
|
||||
// create_collation do not call destructor if error occur
|
||||
let _ = unsafe { Box::from_raw(data) };
|
||||
Err(exc)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
#[pymethod]
|
||||
@@ -2398,7 +2394,7 @@ mod _sqlite {
|
||||
let ret = unsafe {
|
||||
sqlite3_open_v2(
|
||||
path,
|
||||
addr_of_mut!(db),
|
||||
&raw mut db,
|
||||
SQLITE_OPEN_READWRITE
|
||||
| SQLITE_OPEN_CREATE
|
||||
| if uri { SQLITE_OPEN_URI } else { 0 },
|
||||
|
||||
@@ -728,11 +728,8 @@ impl ExactSizeIterator for DictIter<'_> {
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
trait DictView: PyPayload + PyClassDef + Iterable + Representable
|
||||
where
|
||||
Self::ReverseIter: PyPayload,
|
||||
{
|
||||
type ReverseIter;
|
||||
trait DictView: PyPayload + PyClassDef + Iterable + Representable {
|
||||
type ReverseIter: PyPayload;
|
||||
|
||||
fn dict(&self) -> &PyDictRef;
|
||||
fn item(vm: &VirtualMachine, key: PyObjectRef, value: PyObjectRef) -> PyObjectRef;
|
||||
|
||||
@@ -55,19 +55,14 @@ const fn zst_ref_out_of_thin_air<T: 'static>(x: T) -> &'static T {
|
||||
// would never get called anyway if we consider this semantically a Box::leak(Box::new(x))-type
|
||||
// operation. if T isn't zero-sized, we don't have to worry about it because we'll fail to compile.
|
||||
std::mem::forget(x);
|
||||
trait Zst: Sized + 'static {
|
||||
const THIN_AIR: &'static Self = {
|
||||
if std::mem::size_of::<Self>() == 0 {
|
||||
// SAFETY: we just confirmed that Self is zero-sized, so we can
|
||||
// pull a value of it out of thin air.
|
||||
unsafe { std::ptr::NonNull::<Self>::dangling().as_ref() }
|
||||
} else {
|
||||
panic!("can't use a non-zero-sized type here")
|
||||
}
|
||||
};
|
||||
const {
|
||||
if std::mem::size_of::<T>() != 0 {
|
||||
panic!("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 { std::ptr::NonNull::<T>::dangling().as_ref() }
|
||||
}
|
||||
impl<T: 'static> Zst for T {}
|
||||
<T as Zst>::THIN_AIR
|
||||
}
|
||||
|
||||
/// Get the [`STATIC_FUNC`](IntoPyNativeFn::STATIC_FUNC) of the passed function. The same
|
||||
|
||||
+2
-6
@@ -228,12 +228,8 @@ mod sealed {
|
||||
}
|
||||
|
||||
/// A sealed marker trait for `DictKey` types that always become an exact instance of `str`
|
||||
pub trait InternableString
|
||||
where
|
||||
Self: sealed::SealedInternable + ToPyObject + AsRef<Self::Interned>,
|
||||
Self::Interned: MaybeInternedString,
|
||||
{
|
||||
type Interned: ?Sized;
|
||||
pub trait InternableString: sealed::SealedInternable + ToPyObject + AsRef<Self::Interned> {
|
||||
type Interned: MaybeInternedString + ?Sized;
|
||||
fn into_pyref_exact(self, str_type: PyTypeRef) -> PyRefExact<PyStr>;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#![allow(clippy::upper_case_acronyms)]
|
||||
#![doc(html_logo_url = "https://raw.githubusercontent.com/RustPython/RustPython/main/logo.png")]
|
||||
#![doc(html_root_url = "https://docs.rs/rustpython-vm/")]
|
||||
#![cfg_attr(target_os = "redox", feature(raw_ref_op))]
|
||||
|
||||
#[cfg(feature = "flame-it")]
|
||||
#[macro_use]
|
||||
|
||||
@@ -322,7 +322,7 @@ unsafe impl Link for WeakLink {
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn pointers(target: NonNull<Self::Target>) -> NonNull<Pointers<Self::Target>> {
|
||||
NonNull::new_unchecked(ptr::addr_of_mut!((*target.as_ptr()).0.payload.pointers))
|
||||
NonNull::new_unchecked(&raw mut (*target.as_ptr()).0.payload.pointers)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,8 +364,11 @@ impl PyWeak {
|
||||
fn drop_inner(&self) {
|
||||
let dealloc = {
|
||||
let mut guard = unsafe { self.parent.as_ref().lock() };
|
||||
let offset = memoffset::offset_of!(PyInner<PyWeak>, payload);
|
||||
let pyinner = (self as *const Self as usize - offset) as *const PyInner<Self>;
|
||||
let offset = std::mem::offset_of!(PyInner<PyWeak>, payload);
|
||||
let pyinner = (self as *const Self)
|
||||
.cast::<u8>()
|
||||
.wrapping_sub(offset)
|
||||
.cast::<PyInner<Self>>();
|
||||
let node_ptr = unsafe { NonNull::new_unchecked(pyinner as *mut Py<Self>) };
|
||||
// the list doesn't have ownership over its PyRef<PyWeak>! we're being dropped
|
||||
// right now so that should be obvious!!
|
||||
@@ -1044,7 +1047,7 @@ impl<T: PyObjectPayload> PyRef<T> {
|
||||
pub fn leak(pyref: Self) -> &'static Py<T> {
|
||||
let ptr = pyref.ptr;
|
||||
std::mem::forget(pyref);
|
||||
unsafe { &*ptr.as_ptr() }
|
||||
unsafe { ptr.as_ref() }
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{fmt, marker::PhantomData};
|
||||
use std::fmt;
|
||||
|
||||
use crate::{
|
||||
object::{
|
||||
@@ -16,25 +16,18 @@ pub(in crate::object) struct PyObjVTable {
|
||||
}
|
||||
|
||||
impl PyObjVTable {
|
||||
pub fn of<T: PyObjectPayload>() -> &'static Self {
|
||||
struct Helper<T: PyObjectPayload>(PhantomData<T>);
|
||||
trait VtableHelper {
|
||||
const VTABLE: PyObjVTable;
|
||||
pub const fn of<T: PyObjectPayload>() -> &'static Self {
|
||||
&PyObjVTable {
|
||||
drop_dealloc: drop_dealloc_obj::<T>,
|
||||
debug: debug_obj::<T>,
|
||||
trace: const {
|
||||
if T::IS_TRACE {
|
||||
Some(try_trace_obj::<T>)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
}
|
||||
impl<T: PyObjectPayload> VtableHelper for Helper<T> {
|
||||
const VTABLE: PyObjVTable = PyObjVTable {
|
||||
drop_dealloc: drop_dealloc_obj::<T>,
|
||||
debug: debug_obj::<T>,
|
||||
trace: {
|
||||
if T::IS_TRACE {
|
||||
Some(try_trace_obj::<T>)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
},
|
||||
};
|
||||
}
|
||||
&Helper::<T>::VTABLE
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ mod pwd {
|
||||
#[pyfunction]
|
||||
fn getpwall(vm: &VirtualMachine) -> PyResult<Vec<PyObjectRef>> {
|
||||
// setpwent, getpwent, etc are not thread safe. Could use fgetpwent_r, but this is easier
|
||||
static GETPWALL: parking_lot::Mutex<()> = parking_lot::const_mutex(());
|
||||
static GETPWALL: parking_lot::Mutex<()> = parking_lot::Mutex::new(());
|
||||
let _guard = GETPWALL.lock();
|
||||
let mut list = Vec::new();
|
||||
|
||||
|
||||
+4
-7
@@ -133,13 +133,10 @@ impl VirtualMachine {
|
||||
let import_func = ctx.none();
|
||||
let profile_func = RefCell::new(ctx.none());
|
||||
let trace_func = RefCell::new(ctx.none());
|
||||
// hack to get around const array repeat expressions, rust issue #79270
|
||||
const NONE: Option<PyObjectRef> = None;
|
||||
// putting it in a const optimizes better, prevents linear initialization of the array
|
||||
#[allow(clippy::declare_interior_mutable_const)]
|
||||
const SIGNAL_HANDLERS: RefCell<[Option<PyObjectRef>; signal::NSIG]> =
|
||||
RefCell::new([NONE; signal::NSIG]);
|
||||
let signal_handlers = Some(Box::new(SIGNAL_HANDLERS));
|
||||
let signal_handlers = Some(Box::new(
|
||||
// putting it in a const optimizes better, prevents linear initialization of the array
|
||||
const { RefCell::new([const { None }; signal::NSIG]) },
|
||||
));
|
||||
|
||||
let module_inits = stdlib::get_module_inits();
|
||||
|
||||
|
||||
Reference in new issue
Block a user