Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion crates/capi/src/pyerrors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ pub unsafe extern "C" fn PyException_GetTraceback(exc: *mut PyObject) -> *mut Py
with_vm(|vm| {
let exc = unsafe { &*exc }.try_downcast_ref::<PyBaseException>(vm)?;
let tb = exc
.__traceback__()
.traceback()
.map(|tb| tb.into_object().into_raw().as_ptr())
.unwrap_or_default();
Ok(tb)
Expand Down
2 changes: 1 addition & 1 deletion crates/derive-impl/src/pyclass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -764,7 +764,7 @@ pub(crate) fn impl_pyclass(attr: PunctuatedNestedMeta, item: Item) -> Result<Tok

#[inline]
unsafe fn validate_downcastable_from(obj: &::rustpython_vm::PyObject) -> bool {
<Self as ::rustpython_vm::class::PyClassDef>::BASICSIZE <= obj.class().slots.basicsize && obj.class().fast_issubclass(<Self as ::rustpython_vm::class::StaticType>::static_type())
<Self as ::rustpython_vm::class::PyClassDef>::BASICSIZE <= obj.class().payload().slots.basicsize && obj.class().fast_issubclass(<Self as ::rustpython_vm::class::StaticType>::static_type())
}

fn class(ctx: &::rustpython_vm::vm::Context) -> &'static ::rustpython_vm::Py<::rustpython_vm::builtins::PyType> {
Expand Down
4 changes: 2 additions & 2 deletions crates/derive-impl/src/pymodule.rs
Original file line number Diff line number Diff line change
Expand Up @@ -755,7 +755,7 @@ impl ModuleItem for ClassItem {
// module resolution, e.g. TypeAliasType)
{
let module_key = rustpython_vm::identifier!(ctx, __module__);
let has_module_getset = new_class.attributes
let has_module_getset = new_class.payload().attributes
.get(module_key)
.is_some_and(|v| v.downcastable::<rustpython_vm::builtins::PyGetSet>());
if !has_module_getset {
Expand Down Expand Up @@ -849,7 +849,7 @@ impl ModuleItem for StructSequenceItem {
let new_class = <#pytype_ident as ::rustpython_vm::class::PyClassImpl>::make_static_type();
{
let module_key = rustpython_vm::identifier!(ctx, __module__);
let has_module_getset = new_class.attributes
let has_module_getset = new_class.payload().attributes
.get(module_key)
.is_some_and(|v| v.downcastable::<rustpython_vm::builtins::PyGetSet>());
if !has_module_getset {
Expand Down
4 changes: 2 additions & 2 deletions crates/stdlib/src/_asyncio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ pub(crate) mod _asyncio {

// Save the original traceback for later restoration
if let Ok(exc_ref) = exc.clone().downcast::<PyBaseException>() {
let tb = exc_ref.__traceback__().map(|tb| tb.into());
let tb = exc_ref.traceback().map(|tb| tb.into());
*zelf.fut_exception_tb.write() = tb;
}

Expand Down Expand Up @@ -2296,7 +2296,7 @@ pub(crate) mod _asyncio {
} else {
task.base.fut_state.store(FutureState::Finished);
// Save the original traceback for later restoration
let tb = exc.__traceback__().map(|tb| tb.into());
let tb = exc.traceback().map(|tb| tb.into());
*task.base.fut_exception_tb.write() = tb;
*task.base.fut_exception.write() = Some(exc.clone().into());
task.base.fut_log_tb.store(true, Ordering::Relaxed);
Expand Down
6 changes: 5 additions & 1 deletion crates/stdlib/src/elementtree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,10 @@ pub(crate) mod _elementtree {
self.inner.read().children.len()
}

fn is_empty(&self) -> bool {
self.len() == 0
}

fn child(&self, index: usize) -> Option<PyObjectRef> {
self.inner.read().children.get(index).cloned()
}
Expand Down Expand Up @@ -1209,7 +1213,7 @@ pub(crate) mod _elementtree {
None,
vm,
)?;
Ok(zelf.len() != 0)
Ok(!zelf.is_empty())
}),
..PyNumberMethods::NOT_IMPLEMENTED
};
Expand Down
2 changes: 1 addition & 1 deletion crates/vm/src/builtins/bool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ impl PyObject {
#[cold]
#[inline(never)]
fn try_to_bool_slow(&self, vm: &VirtualMachine) -> PyResult<bool> {
let slots = &self.class().slots;
let slots = self.class().slots();

// 1. Try nb_bool slot first
if let Some(nb_bool) = slots.as_number.boolean.load() {
Expand Down
17 changes: 12 additions & 5 deletions crates/vm/src/builtins/bytes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,6 +550,11 @@ impl PyBytes {

#[pyclass]
impl Py<PyBytes> {
#[inline]
pub fn as_bytes(&self) -> &[u8] {
self.payload().as_bytes()
}

#[pymethod]
fn __reduce_ex__(
&self,
Expand Down Expand Up @@ -637,7 +642,7 @@ impl AsBuffer for PyBytes {
fn as_buffer(zelf: &Py<Self>, _vm: &VirtualMachine) -> PyResult<PyBuffer> {
let buf = PyBuffer::new(
zelf.to_owned().into(),
BufferDescriptor::simple(zelf.len(), true),
BufferDescriptor::simple(zelf.as_bytes().len(), true),
&BUFFER_METHODS,
);
Ok(buf)
Expand All @@ -647,7 +652,9 @@ impl AsBuffer for PyBytes {
impl AsMapping for PyBytes {
fn as_mapping() -> &'static PyMappingMethods {
static AS_MAPPING: LazyLock<PyMappingMethods> = LazyLock::new(|| PyMappingMethods {
length: atomic_func!(|mapping, _vm| Ok(PyBytes::mapping_downcast(mapping).len())),
length: atomic_func!(|mapping, _vm| {
Ok(PyBytes::mapping_downcast(mapping).as_bytes().len())
}),
subscript: atomic_func!(
|mapping, needle, vm| PyBytes::mapping_downcast(mapping)._getitem(needle, vm)
),
Expand All @@ -660,7 +667,7 @@ impl AsMapping for PyBytes {
impl AsSequence for PyBytes {
fn as_sequence() -> &'static PySequenceMethods {
static AS_SEQUENCE: LazyLock<PySequenceMethods> = LazyLock::new(|| PySequenceMethods {
length: atomic_func!(|seq, _vm| Ok(PyBytes::sequence_downcast(seq).len())),
length: atomic_func!(|seq, _vm| Ok(PyBytes::sequence_downcast(seq).as_bytes().len())),
concat: atomic_func!(|seq, other, vm| {
PyBytes::sequence_downcast(seq)
.inner
Expand Down Expand Up @@ -769,7 +776,7 @@ impl PyPayload for PyBytesIterator {
impl PyBytesIterator {
#[pymethod]
fn __length_hint__(&self) -> usize {
self.internal.lock().length_hint(|obj| obj.len())
self.internal.lock().length_hint(|obj| obj.as_bytes().len())
}

#[pymethod]
Expand All @@ -787,7 +794,7 @@ impl PyBytesIterator {
fn __setstate__(&self, state: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
self.internal
.lock()
.set_state(&state, |obj, pos| pos.min(obj.len()), vm)
.set_state(&state, |obj, pos| pos.min(obj.as_bytes().len()), vm)
}
}

Expand Down
2 changes: 1 addition & 1 deletion crates/vm/src/builtins/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -560,5 +560,5 @@ fn vectorcall_float(
#[rustfmt::skip] // to avoid line splitting
pub(crate) fn init(context: &'static Context) {
PyFloat::extend_class(context, context.types.float_type);
context.types.float_type.slots.vectorcall.store(Some(vectorcall_float));
context.types.float_type.slots().vectorcall.store(Some(vectorcall_float));
}
4 changes: 2 additions & 2 deletions crates/vm/src/builtins/genericalias.rs
Original file line number Diff line number Diff line change
Expand Up @@ -369,11 +369,11 @@ fn subs_tvars(

for arg in sub_params.iter() {
if let Some(idx) = tuple_index(params.as_slice(), arg) {
let param = &params[idx];
let param = &params.as_slice()[idx];
let substituted_arg = &arg_items[idx];

// Check if this is a TypeVarTuple (has tp_iter)
if param.class().slots.iter.load().is_some()
if param.class().slots().iter.load().is_some()
&& substituted_arg.try_to_ref::<PyTuple>(vm).is_ok()
{
// TypeVarTuple case - extend with tuple elements
Expand Down
14 changes: 13 additions & 1 deletion crates/vm/src/builtins/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,18 @@ impl ToPyObject for Vec<PyObjectRef> {
}
}

impl Py<PyList> {
#[inline]
pub fn borrow_vec(&self) -> PyMappedRwLockReadGuard<'_, [PyObjectRef]> {
self.payload().borrow_vec()
}

#[inline]
pub fn borrow_vec_mut(&self) -> PyRwLockWriteGuard<'_, Vec<PyObjectRef>> {
self.payload().borrow_vec_mut()
}
}

impl PyList {
#[deprecated(note = "use PyList::from(...).into_ref() instead")]
pub fn new_ref(elements: Vec<PyObjectRef>, ctx: &Context) -> PyRef<Self> {
Expand Down Expand Up @@ -792,7 +804,7 @@ fn object_lt(
vm: &VirtualMachine,
) -> PyResult<bool> {
#[allow(unpredictable_function_pointer_comparisons)]
if a.class().slots.richcompare.load() != Some(cmp) {
if a.class().slots().richcompare.load() != Some(cmp) {
return a.rich_compare_bool(b, PyComparisonOp::Lt, vm);
}
match cmp(a, b, PyComparisonOp::Lt, vm)? {
Expand Down
7 changes: 6 additions & 1 deletion crates/vm/src/builtins/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1474,7 +1474,12 @@ static BUFFER_WRAPPER_METHODS: BufferMethods = BufferMethods {
// A native release runs when the memoryview itself is torn down; only a
// Python-level hook on a foreign exporter has to be called here.
if !mv.buffer.obj.is(&wrapper.exporter)
&& wrapper.exporter.class().slots.python_release_buffer.load()
&& wrapper
.exporter
.class()
.slots()
.python_release_buffer
.load()
{
call_python_release_buffer(&wrapper.exporter, mv.clone());
}
Expand Down
22 changes: 13 additions & 9 deletions crates/vm/src/builtins/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ fn type_slot_names(typ: &Py<PyType>, vm: &VirtualMachine) -> PyResult<Option<sup
// object_getstate_default
fn object_getstate_default(obj: &PyObject, required: bool, vm: &VirtualMachine) -> PyResult {
// Check itemsize
if required && obj.class().slots.itemsize > 0 {
if required && obj.class().slots().itemsize > 0 {
return Err(vm.new_type_error(format!("cannot pickle {:.200} objects", obj.class().name())));
}

Expand All @@ -205,22 +205,22 @@ fn object_getstate_default(obj: &PyObject, required: bool, vm: &VirtualMachine)

if required {
// Start with PyBaseObject_Type's basicsize
let mut basicsize = vm.ctx.types.object_type.slots.basicsize;
let mut basicsize = vm.ctx.types.object_type.slots().basicsize;

// Add __dict__ size if type has dict
if obj.class().slots.flags.has_feature(PyTypeFlags::HAS_DICT) {
if obj.class().slots().flags.has_feature(PyTypeFlags::HAS_DICT) {
basicsize += core::mem::size_of::<PyObjectRef>();
}

// Add __weakref__ size if type has weakref support
let has_weakref = if let Some(ref ext) = obj.class().heaptype_ext {
let has_weakref = if let Some(ext) = obj.class().heaptype_ext() {
match &ext.slots {
None => true, // Heap type without __slots__ has automatic weakref
Some(slots) => slots.iter().any(|s| s.as_bytes() == b"__weakref__"),
}
} else {
let weakref_name = vm.ctx.intern_str("__weakref__");
obj.class().attributes.contains(weakref_name)
obj.class().attributes().contains(weakref_name)
};
if has_weakref {
basicsize += core::mem::size_of::<PyObjectRef>();
Expand All @@ -232,7 +232,7 @@ fn object_getstate_default(obj: &PyObject, required: bool, vm: &VirtualMachine)
}

// Fail if actual type's basicsize > expected basicsize
if obj.class().slots.basicsize > basicsize {
if obj.class().slots().basicsize > basicsize {
return Err(vm.new_type_error(format!("cannot pickle '{}' object", obj.class().name())));
}
}
Expand Down Expand Up @@ -326,7 +326,7 @@ impl PyBaseObject {
}
}
PyComparisonOp::Ne => {
let cmp = zelf.class().slots.richcompare.load().unwrap();
let cmp = zelf.class().slots().richcompare.load().unwrap();
let value = match cmp(zelf, other, PyComparisonOp::Eq, vm)? {
Either::A(obj) => PyArithmeticValue::from_object(vm, obj)
.map(|obj| obj.try_to_bool(vm))
Expand Down Expand Up @@ -524,7 +524,7 @@ impl PyBaseObject {

#[pymethod]
fn __sizeof__(zelf: PyObjectRef) -> usize {
zelf.class().slots.basicsize
zelf.class().slots().basicsize
}
}

Expand Down Expand Up @@ -580,7 +580,11 @@ pub fn object_generic_set_dict(
pub(crate) fn init(ctx: &'static Context) {
// Manually set alloc/init slots - derive macro doesn't generate extend_slots
// for trait impl that overrides #[pyslot] method
ctx.types.object_type.slots.alloc.store(Some(generic_alloc));
ctx.types
.object_type
.slots()
.alloc
.store(Some(generic_alloc));
ctx.types
.object_type
.slots
Expand Down
10 changes: 10 additions & 0 deletions crates/vm/src/builtins/str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,16 @@ impl PyStr {
}

impl Py<PyStr> {
#[inline]
pub fn as_wtf8(&self) -> &Wtf8 {
self.payload().as_wtf8()
}

#[inline]
pub fn as_bytes(&self) -> &[u8] {
self.payload().as_bytes()
}

pub fn as_utf8(&self) -> Option<&Py<PyUtf8Str>> {
if self.is_utf8() {
// SAFETY: is_utf8() guarantees the PyUtf8Str invariant.
Expand Down
Loading
Loading