Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
align PyNumber
  • Loading branch information
youknowone committed Dec 25, 2025
commit 6e6df1e7c14c305c509011678b8e1777849ee3ab
4 changes: 2 additions & 2 deletions crates/stdlib/src/sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ mod _sqlite {
let text2 = vm.ctx.new_str(text2);

let val = callable.call((text1, text2), vm)?;
let Some(val) = val.to_number().index(vm) else {
let Some(val) = val.number().index(vm) else {
return Ok(0);
};

Expand Down Expand Up @@ -2980,7 +2980,7 @@ mod _sqlite {
fn bind_parameters(self, parameters: &PyObject, vm: &VirtualMachine) -> PyResult<()> {
if let Some(dict) = parameters.downcast_ref::<PyDict>() {
self.bind_parameters_name(dict, vm)
} else if let Ok(seq) = PySequence::try_protocol(parameters, vm) {
} else if let Ok(seq) = parameters.try_sequence(vm) {
self.bind_parameters_sequence(seq, vm)
} else {
Err(new_programming_error(
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 @@ -43,7 +43,7 @@ impl PyObjectRef {
return Ok(false);
}
let rs_bool = if let Some(nb_bool) = self.class().slots.as_number.boolean.load() {
nb_bool(self.as_object().to_number(), vm)?
nb_bool(self.as_object().number(), vm)?
} else {
// TODO: Fully implement AsNumber and remove this block
match vm.get_method(self.clone(), identifier!(vm, __bool__)) {
Expand Down
4 changes: 2 additions & 2 deletions crates/vm/src/builtins/dict.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1145,7 +1145,7 @@ impl ViewSetOps for PyDictKeys {}
impl PyDictKeys {
#[pymethod]
fn __contains__(zelf: PyObjectRef, key: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
zelf.to_sequence().contains(&key, vm)
zelf.sequence_unchecked().contains(&key, vm)
}

#[pygetset]
Expand Down Expand Up @@ -1210,7 +1210,7 @@ impl ViewSetOps for PyDictItems {}
impl PyDictItems {
#[pymethod]
fn __contains__(zelf: PyObjectRef, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
zelf.to_sequence().contains(&needle, vm)
zelf.sequence_unchecked().contains(&needle, vm)
}
#[pygetset]
fn mapping(zelf: PyRef<Self>) -> PyMappingProxy {
Expand Down
8 changes: 4 additions & 4 deletions crates/vm/src/builtins/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use crate::{
class::PyClassImpl,
function::ArgCallable,
object::{Traverse, TraverseFn},
protocol::{PyIterReturn, PySequence},
protocol::PyIterReturn,
types::{IterNext, Iterable, SelfIter},
};
use rustpython_common::{
Expand Down Expand Up @@ -190,7 +190,7 @@ impl PyPayload for PySequenceIterator {
#[pyclass(with(IterNext, Iterable))]
impl PySequenceIterator {
pub fn new(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<Self> {
let _seq = PySequence::try_protocol(&obj, vm)?;
let _seq = obj.try_sequence(vm)?;
Ok(Self {
internal: PyMutex::new(PositionIterInternal::new(obj, 0)),
})
Expand All @@ -200,7 +200,7 @@ impl PySequenceIterator {
fn __length_hint__(&self, vm: &VirtualMachine) -> PyObjectRef {
let internal = self.internal.lock();
if let IterStatus::Active(obj) = &internal.status {
let seq = obj.to_sequence();
let seq = obj.sequence_unchecked();
seq.length(vm)
.map(|x| PyInt::from(x).into_pyobject(vm))
.unwrap_or_else(|_| vm.ctx.not_implemented())
Expand All @@ -224,7 +224,7 @@ impl SelfIter for PySequenceIterator {}
impl IterNext for PySequenceIterator {
fn next(zelf: &Py<Self>, vm: &VirtualMachine) -> PyResult<PyIterReturn> {
zelf.internal.lock().next(|obj, pos| {
let seq = obj.to_sequence();
let seq = obj.sequence_unchecked();
PyIterReturn::from_getitem_result(seq.get_item(pos as isize, vm), vm)
})
}
Expand Down
6 changes: 5 additions & 1 deletion crates/vm/src/builtins/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -354,7 +354,11 @@ where
} else {
let iter = obj.to_owned().get_iter(vm)?;
let iter = iter.iter::<PyObjectRef>(vm)?;
let len = obj.to_sequence().length_opt(vm).transpose()?.unwrap_or(0);
let len = obj
.sequence_unchecked()
.length_opt(vm)
.transpose()?
.unwrap_or(0);
let mut v = Vec::with_capacity(len);
for x in iter {
v.push(f(x?)?);
Expand Down
4 changes: 2 additions & 2 deletions crates/vm/src/builtins/mappingproxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ impl Constructor for PyMappingProxy {
type Args = PyObjectRef;

fn py_new(_cls: &Py<PyType>, mapping: Self::Args, vm: &VirtualMachine) -> PyResult<Self> {
if mapping.to_mapping().check()
if mapping.mapping_unchecked().check()
&& !mapping.downcastable::<PyList>()
&& !mapping.downcastable::<PyTuple>()
{
Expand Down Expand Up @@ -122,7 +122,7 @@ impl PyMappingProxy {
MappingProxyInner::Class(class) => Ok(key
.as_interned_str(vm)
.is_some_and(|key| class.attributes.read().contains_key(key))),
MappingProxyInner::Mapping(mapping) => mapping.to_sequence().contains(key, vm),
MappingProxyInner::Mapping(mapping) => mapping.sequence_unchecked().contains(key, vm),
}
}

Expand Down
4 changes: 3 additions & 1 deletion crates/vm/src/builtins/weakproxy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,9 @@ impl PyWeakProxy {
}
#[pymethod]
fn __contains__(&self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult<bool> {
self.try_upgrade(vm)?.to_sequence().contains(&needle, vm)
self.try_upgrade(vm)?
.sequence_unchecked()
.contains(&needle, vm)
}

fn getitem(&self, needle: PyObjectRef, vm: &VirtualMachine) -> PyResult {
Expand Down
4 changes: 2 additions & 2 deletions crates/vm/src/function/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ impl ArgMapping {

#[inline(always)]
pub fn mapping(&self) -> PyMapping<'_> {
self.obj.to_mapping()
self.obj.mapping_unchecked()
}
}

Expand Down Expand Up @@ -177,7 +177,7 @@ impl ToPyObject for ArgMapping {

impl TryFromObject for ArgMapping {
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
let _mapping = PyMapping::try_protocol(&obj, vm)?;
let _mapping = obj.try_mapping(vm)?;
Ok(Self { obj })
}
}
Expand Down
22 changes: 10 additions & 12 deletions crates/vm/src/protocol/mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,18 @@ impl PyMappingMethods {
}

impl PyObject {
pub fn to_mapping(&self) -> PyMapping<'_> {
pub fn mapping_unchecked(&self) -> PyMapping<'_> {
PyMapping { obj: self }
}

pub fn try_mapping(&self, vm: &VirtualMachine) -> PyResult<PyMapping<'_>> {
let mapping = self.mapping_unchecked();
if mapping.check() {
Ok(mapping)
} else {
Err(vm.new_type_error(format!("{} is not a mapping object", self.class())))
}
}
}

#[derive(Copy, Clone)]
Expand All @@ -96,17 +105,6 @@ impl AsRef<PyObject> for PyMapping<'_> {
}
}

impl<'a> PyMapping<'a> {
pub fn try_protocol(obj: &'a PyObject, vm: &VirtualMachine) -> PyResult<Self> {
let mapping = obj.to_mapping();
if mapping.check() {
Ok(mapping)
} else {
Err(vm.new_type_error(format!("{} is not a mapping object", obj.class())))
}
}
}

impl PyMapping<'_> {
#[inline]
pub fn slots(&self) -> &PyMappingSlots {
Expand Down
26 changes: 14 additions & 12 deletions crates/vm/src/protocol/number.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ pub type PyNumberTernaryFunc = fn(&PyObject, &PyObject, &PyObject, &VirtualMachi

impl PyObject {
#[inline]
pub const fn to_number(&self) -> PyNumber<'_> {
PyNumber(self)
pub const fn number(&self) -> PyNumber<'_> {
PyNumber { obj: self }
}

pub fn try_index_opt(&self, vm: &VirtualMachine) -> Option<PyResult<PyIntRef>> {
Expand All @@ -30,7 +30,7 @@ impl PyObject {
} else if let Some(i) = self.downcast_ref::<PyInt>() {
Some(Ok(vm.ctx.new_bigint(i.as_bigint())))
} else {
self.to_number().index(vm)
self.number().index(vm)
}
}

Expand All @@ -56,7 +56,11 @@ impl PyObject {

if let Some(i) = self.downcast_ref_if_exact::<PyInt>(vm) {
Ok(i.to_owned())
} else if let Some(i) = self.to_number().int(vm).or_else(|| self.try_index_opt(vm)) {
} else if let Some(i) = self
.number()
.int(vm)
.or_else(|| self.try_index_opt(vm))
{
i
} else if let Ok(Some(f)) = vm.get_special_method(self, identifier!(vm, __trunc__)) {
warnings::warn(
Expand Down Expand Up @@ -92,7 +96,7 @@ impl PyObject {
pub fn try_float_opt(&self, vm: &VirtualMachine) -> Option<PyResult<PyRef<PyFloat>>> {
if let Some(float) = self.downcast_ref_if_exact::<PyFloat>(vm) {
Some(Ok(float.to_owned()))
} else if let Some(f) = self.to_number().float(vm) {
} else if let Some(f) = self.number().float(vm) {
Some(f)
} else {
self.try_index_opt(vm)
Expand Down Expand Up @@ -420,27 +424,25 @@ impl PyNumberSlots {
}
}
#[derive(Copy, Clone)]
pub struct PyNumber<'a>(&'a PyObject);
pub struct PyNumber<'a> {
pub obj: &'a PyObject,
}

unsafe impl Traverse for PyNumber<'_> {
fn traverse(&self, tracer_fn: &mut TraverseFn<'_>) {
self.0.traverse(tracer_fn)
self.obj.traverse(tracer_fn)
}
}

impl Deref for PyNumber<'_> {
type Target = PyObject;

fn deref(&self) -> &Self::Target {
self.0
self.obj
}
}

impl<'a> PyNumber<'a> {
pub(crate) const fn obj(self) -> &'a PyObject {
self.0
}

// PyNumber_Check - slots are now inherited
pub fn check(obj: &PyObject) -> bool {
let methods = &obj.class().slots.as_number;
Expand Down
18 changes: 9 additions & 9 deletions crates/vm/src/protocol/object.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use crate::{
dict_inner::DictKey,
function::{Either, FuncArgs, PyArithmeticValue, PySetterValue},
object::PyPayload,
protocol::{PyIter, PyMapping, PySequence},
protocol::PyIter,
types::{Constructor, PyComparisonOp},
};

Expand Down Expand Up @@ -669,9 +669,9 @@ impl PyObject {
}

pub fn length_opt(&self, vm: &VirtualMachine) -> Option<PyResult<usize>> {
self.to_sequence()
self.sequence_unchecked()
.length_opt(vm)
.or_else(|| self.to_mapping().length_opt(vm))
.or_else(|| self.mapping_unchecked().length_opt(vm))
}

pub fn length(&self, vm: &VirtualMachine) -> PyResult<usize> {
Expand All @@ -690,9 +690,9 @@ impl PyObject {

let needle = needle.to_pyobject(vm);

if let Ok(mapping) = PyMapping::try_protocol(self, vm) {
if let Ok(mapping) = self.try_mapping(vm) {
mapping.subscript(&needle, vm)
} else if let Ok(seq) = PySequence::try_protocol(self, vm) {
} else if let Ok(seq) = self.try_sequence(vm) {
let i = needle.key_as_isize(vm)?;
seq.get_item(i, vm)
} else {
Expand Down Expand Up @@ -722,13 +722,13 @@ impl PyObject {
return dict.set_item(needle, value, vm);
}

let mapping = self.to_mapping();
let mapping = self.mapping_unchecked();
if let Some(f) = mapping.slots().ass_subscript.load() {
let needle = needle.to_pyobject(vm);
return f(mapping, &needle, Some(value), vm);
}

let seq = self.to_sequence();
let seq = self.sequence_unchecked();
if let Some(f) = seq.slots().ass_item.load() {
let i = needle.key_as_isize(vm)?;
return f(seq, i, Some(value), vm);
Expand All @@ -745,12 +745,12 @@ impl PyObject {
return dict.del_item(needle, vm);
}

let mapping = self.to_mapping();
let mapping = self.mapping_unchecked();
if let Some(f) = mapping.slots().ass_subscript.load() {
let needle = needle.to_pyobject(vm);
return f(mapping, &needle, None, vm);
}
let seq = self.to_sequence();
let seq = self.sequence_unchecked();
if let Some(f) = seq.slots().ass_item.load() {
let i = needle.key_as_isize(vm)?;
return f(seq, i, None, vm);
Expand Down
Loading