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
downcastasble
  • Loading branch information
youknowone committed Jul 16, 2025
commit bbf980828282d09e5e5cf5f83b79b6f1cf2d81a4
1 change: 1 addition & 0 deletions .cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@
"dedentations",
"dedents",
"deduped",
"downcastable",
"downcasted",
"dumpable",
"emscripten",
Expand Down
14 changes: 7 additions & 7 deletions stdlib/src/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ mod array {
ArrayContentType::from_char(spec).map_err(|err| vm.new_value_error(err))?;

if let OptionalArg::Present(init) = init {
if let Some(init) = init.payload::<Self>() {
if let Some(init) = init.downcast_ref::<Self>() {
match (spec, init.read().typecode()) {
(spec, ch) if spec == ch => array.frombytes(&init.get_bytes()),
(spec, 'u') => {
Expand All @@ -681,7 +681,7 @@ mod array {
}
}
}
} else if let Some(wtf8) = init.payload::<PyStr>() {
} else if let Some(wtf8) = init.downcast_ref::<PyStr>() {
if spec == 'u' {
let bytes = Self::_unicode_to_wchar_bytes(wtf8.as_wtf8(), array.itemsize());
array.frombytes_move(bytes);
Expand All @@ -690,7 +690,7 @@ mod array {
"cannot use a str to initialize an array with typecode '{spec}'"
)));
}
} else if init.payload_is::<PyBytes>() || init.payload_is::<PyByteArray>() {
} else if init.downcastable::<PyBytes>() || init.downcastable::<PyByteArray>() {
init.try_bytes_like(vm, |x| array.frombytes(x))?;
} else if let Ok(iter) = ArgIterable::try_from_object(vm, init.clone()) {
for obj in iter.iter(vm)? {
Expand Down Expand Up @@ -765,7 +765,7 @@ mod array {
let mut w = zelf.try_resizable(vm)?;
if zelf.is(&obj) {
w.imul(2, vm)
} else if let Some(array) = obj.payload::<Self>() {
} else if let Some(array) = obj.downcast_ref::<Self>() {
w.iadd(&array.read(), vm)
} else {
let iter = ArgIterable::try_from_object(vm, obj)?;
Expand Down Expand Up @@ -1013,7 +1013,7 @@ mod array {
cloned = zelf.read().clone();
&cloned
} else {
match value.payload::<Self>() {
match value.downcast_ref::<Self>() {
Some(array) => {
guard = array.read();
&*guard
Expand Down Expand Up @@ -1059,7 +1059,7 @@ mod array {

#[pymethod]
fn __add__(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
if let Some(other) = other.payload::<Self>() {
if let Some(other) = other.downcast_ref::<Self>() {
self.read()
.add(&other.read(), vm)
.map(|array| Self::from(array).into_ref(&vm.ctx))
Expand All @@ -1079,7 +1079,7 @@ mod array {
) -> PyResult<PyRef<Self>> {
if zelf.is(&other) {
zelf.try_resizable(vm)?.imul(2, vm)?;
} else if let Some(other) = other.payload::<Self>() {
} else if let Some(other) = other.downcast_ref::<Self>() {
zelf.try_resizable(vm)?.iadd(&other.read(), vm)?;
} else {
return Err(vm.new_type_error(format!(
Expand Down
2 changes: 1 addition & 1 deletion stdlib/src/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ mod decl {
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
let timeout = if vm.is_none(&obj) {
None
} else if let Some(float) = obj.payload::<PyFloat>() {
} else if let Some(float) = obj.downcast_ref::<PyFloat>() {
let float = float.to_f64();
if float.is_nan() {
return Err(vm.new_value_error("Invalid value NaN (not a number)"));
Expand Down
34 changes: 17 additions & 17 deletions stdlib/src/sqlite.rs
Original file line number Diff line number Diff line change
Expand Up @@ -535,7 +535,7 @@ mod _sqlite {
let access = ptr_to_str(access, vm)?;

let val = callable.call((action, arg1, arg2, db_name, access), vm)?;
let Some(val) = val.payload::<PyInt>() else {
let Some(val) = val.downcast_ref::<PyInt>() else {
return Ok(SQLITE_DENY);
};
val.try_to_primitive::<c_int>(vm)
Expand Down Expand Up @@ -1897,18 +1897,18 @@ mod _sqlite {
Ok(self
.description
.iter()
.map(|x| x.payload::<PyTuple>().unwrap().as_slice()[0].clone())
.map(|x| x.downcast_ref::<PyTuple>().unwrap().as_slice()[0].clone())
.collect())
}

fn subscript(&self, needle: &PyObject, vm: &VirtualMachine) -> PyResult {
if let Some(i) = needle.payload::<PyInt>() {
if let Some(i) = needle.downcast_ref::<PyInt>() {
let i = i.try_to_primitive::<isize>(vm)?;
self.data.getitem_by_index(vm, i)
} else if let Some(name) = needle.payload::<PyStr>() {
} else if let Some(name) = needle.downcast_ref::<PyStr>() {
for (obj, i) in self.description.iter().zip(0..) {
let obj = &obj.payload::<PyTuple>().unwrap().as_slice()[0];
let Some(obj) = obj.payload::<PyStr>() else {
let obj = &obj.downcast_ref::<PyTuple>().unwrap().as_slice()[0];
let Some(obj) = obj.downcast_ref::<PyStr>() else {
break;
};
let a_iter = name.as_str().chars().flat_map(|x| x.to_uppercase());
Expand All @@ -1919,7 +1919,7 @@ mod _sqlite {
}
}
Err(vm.new_index_error("No item with that key"))
} else if let Some(slice) = needle.payload::<PySlice>() {
} else if let Some(slice) = needle.downcast_ref::<PySlice>() {
let list = self.data.getitem_by_slice(vm, slice.to_saturated(vm)?)?;
Ok(vm.ctx.new_tuple(list).into())
} else {
Expand Down Expand Up @@ -1962,7 +1962,7 @@ mod _sqlite {
vm: &VirtualMachine,
) -> PyResult<PyComparisonValue> {
op.eq_only(|| {
if let Some(other) = other.payload::<Self>() {
if let Some(other) = other.downcast_ref::<Self>() {
let eq = vm
.bool_eq(zelf.description.as_object(), other.description.as_object())?
&& vm.bool_eq(zelf.data.as_object(), other.data.as_object())?;
Expand Down Expand Up @@ -2179,7 +2179,7 @@ mod _sqlite {
let mut byte: u8 = 0;
let ret = inner.blob.read_single(&mut byte, index);
self.check(ret, vm).map(|_| vm.ctx.new_int(byte).into())
} else if let Some(slice) = needle.payload::<PySlice>() {
} else if let Some(slice) = needle.downcast_ref::<PySlice>() {
let blob_len = inner.blob.bytes();
let slice = slice.to_saturated(vm)?;
let (range, step, length) = slice.adjust_indices(blob_len as usize);
Expand Down Expand Up @@ -2220,7 +2220,7 @@ mod _sqlite {
let inner = self.inner(vm)?;

if let Some(index) = needle.try_index_opt(vm) {
let Some(value) = value.payload::<PyInt>() else {
let Some(value) = value.downcast_ref::<PyInt>() else {
return Err(vm.new_type_error(format!(
"'{}' object cannot be interpreted as an integer",
value.class()
Expand All @@ -2232,7 +2232,7 @@ mod _sqlite {
Self::expect_write(blob_len, 1, index, vm)?;
let ret = inner.blob.write_single(value, index);
self.check(ret, vm)
} else if let Some(_slice) = needle.payload::<PySlice>() {
} else if let Some(_slice) = needle.downcast_ref::<PySlice>() {
Err(vm.new_not_implemented_error("Blob slice assignment is not implemented"))
// let blob_len = inner.blob.bytes();
// let slice = slice.to_saturated(vm)?;
Expand Down Expand Up @@ -2645,15 +2645,15 @@ mod _sqlite {

let ret = if vm.is_none(obj) {
unsafe { sqlite3_bind_null(self.st, pos) }
} else if let Some(val) = obj.payload::<PyInt>() {
} else if let Some(val) = obj.downcast_ref::<PyInt>() {
let val = val.try_to_primitive::<i64>(vm).map_err(|_| {
vm.new_overflow_error("Python int too large to convert to SQLite INTEGER")
})?;
unsafe { sqlite3_bind_int64(self.st, pos, val) }
} else if let Some(val) = obj.payload::<PyFloat>() {
} else if let Some(val) = obj.downcast_ref::<PyFloat>() {
let val = val.to_f64();
unsafe { sqlite3_bind_double(self.st, pos, val) }
} else if let Some(val) = obj.payload::<PyStr>() {
} else if let Some(val) = obj.downcast_ref::<PyStr>() {
let (ptr, len) = str_to_ptr_len(val, vm)?;
unsafe { sqlite3_bind_text(self.st, pos, ptr, len, SQLITE_TRANSIENT()) }
} else if let Ok(buffer) = PyBuffer::try_from_borrowed_object(vm, obj) {
Expand Down Expand Up @@ -2900,11 +2900,11 @@ mod _sqlite {
unsafe {
if vm.is_none(val) {
sqlite3_result_null(self.ctx)
} else if let Some(val) = val.payload::<PyInt>() {
} else if let Some(val) = val.downcast_ref::<PyInt>() {
sqlite3_result_int64(self.ctx, val.try_to_primitive(vm)?)
} else if let Some(val) = val.payload::<PyFloat>() {
} else if let Some(val) = val.downcast_ref::<PyFloat>() {
sqlite3_result_double(self.ctx, val.to_f64())
} else if let Some(val) = val.payload::<PyStr>() {
} else if let Some(val) = val.downcast_ref::<PyStr>() {
let (ptr, len) = str_to_ptr_len(val, vm)?;
sqlite3_result_text(self.ctx, ptr, len, SQLITE_TRANSIENT())
} else if let Ok(buffer) = PyBuffer::try_from_borrowed_object(vm, val) {
Expand Down
7 changes: 5 additions & 2 deletions stdlib/src/termios.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,9 +217,12 @@ mod termios {
))
})?;
for (cc, x) in termios.c_cc.iter_mut().zip(cc.iter()) {
*cc = if let Some(c) = x.payload::<PyBytes>().filter(|b| b.as_bytes().len() == 1) {
*cc = if let Some(c) = x
.downcast_ref::<PyBytes>()
.filter(|b| b.as_bytes().len() == 1)
{
c.as_bytes()[0] as _
} else if let Some(i) = x.payload::<PyInt>() {
} else if let Some(i) = x.downcast_ref::<PyInt>() {
i.try_to_primitive(vm)?
} else {
return Err(vm.new_type_error(
Expand Down
6 changes: 4 additions & 2 deletions vm/src/builtins/asyncgenerator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,9 @@ impl PyAsyncGenAThrow {
let ret = self.ag.inner.send(self.ag.as_object(), val, vm);
if self.aclose {
match ret {
Ok(PyIterReturn::Return(v)) if v.payload_is::<PyAsyncGenWrappedValue>() => {
Ok(PyIterReturn::Return(v))
if v.downcastable::<PyAsyncGenWrappedValue>() =>
{
Err(self.yield_close(vm))
}
other => other
Expand Down Expand Up @@ -392,7 +394,7 @@ impl PyAsyncGenAThrow {

fn ignored_close(&self, res: &PyResult<PyIterReturn>) -> bool {
res.as_ref().is_ok_and(|v| match v {
PyIterReturn::Return(obj) => obj.payload_is::<PyAsyncGenWrappedValue>(),
PyIterReturn::Return(obj) => obj.downcastable::<PyAsyncGenWrappedValue>(),
PyIterReturn::StopIteration(_) => false,
})
}
Expand Down
10 changes: 5 additions & 5 deletions vm/src/builtins/bool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ impl PyObjectRef {
Some(method_or_err) => {
let method = method_or_err?;
let bool_obj = method.call((), vm)?;
let int_obj = bool_obj.payload::<PyInt>().ok_or_else(|| {
let int_obj = bool_obj.downcast_ref::<PyInt>().ok_or_else(|| {
vm.new_type_error(format!(
"'{}' object cannot be interpreted as an integer",
bool_obj.class().name()
Expand Down Expand Up @@ -128,7 +128,7 @@ impl PyBool {
let lhs = get_value(&lhs);
let rhs = get_value(&rhs);
(lhs || rhs).to_pyobject(vm)
} else if let Some(lhs) = lhs.payload::<PyInt>() {
} else if let Some(lhs) = lhs.downcast_ref::<PyInt>() {
lhs.__or__(rhs, vm).to_pyobject(vm)
} else {
vm.ctx.not_implemented()
Expand All @@ -144,7 +144,7 @@ impl PyBool {
let lhs = get_value(&lhs);
let rhs = get_value(&rhs);
(lhs && rhs).to_pyobject(vm)
} else if let Some(lhs) = lhs.payload::<PyInt>() {
} else if let Some(lhs) = lhs.downcast_ref::<PyInt>() {
lhs.__and__(rhs, vm).to_pyobject(vm)
} else {
vm.ctx.not_implemented()
Expand All @@ -160,7 +160,7 @@ impl PyBool {
let lhs = get_value(&lhs);
let rhs = get_value(&rhs);
(lhs ^ rhs).to_pyobject(vm)
} else if let Some(lhs) = lhs.payload::<PyInt>() {
} else if let Some(lhs) = lhs.downcast_ref::<PyInt>() {
lhs.__xor__(rhs, vm).to_pyobject(vm)
} else {
vm.ctx.not_implemented()
Expand Down Expand Up @@ -212,5 +212,5 @@ pub(crate) fn init(context: &Context) {

// Retrieve inner int value:
pub(crate) fn get_value(obj: &PyObject) -> bool {
!obj.payload::<PyInt>().unwrap().as_bigint().is_zero()
!obj.downcast_ref::<PyInt>().unwrap().as_bigint().is_zero()
}
2 changes: 1 addition & 1 deletion vm/src/builtins/builtin_func.rs
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ impl Comparable for PyNativeMethod {
_vm: &VirtualMachine,
) -> PyResult<PyComparisonValue> {
op.eq_only(|| {
if let Some(other) = other.payload::<Self>() {
if let Some(other) = other.downcast_ref::<Self>() {
let eq = match (zelf.func.zelf.as_ref(), other.func.zelf.as_ref()) {
(Some(z), Some(o)) => z.is(o),
(None, None) => true,
Expand Down
2 changes: 1 addition & 1 deletion vm/src/builtins/complex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ impl PyObjectRef {

return Ok(Some((ret.value, true)));
} else {
return match result.payload::<PyComplex>() {
return match result.downcast_ref::<PyComplex>() {
Some(complex_obj) => Ok(Some((complex_obj.value, true))),
None => Err(vm.new_type_error(format!(
"__complex__ returned non-complex (type '{}')",
Expand Down
2 changes: 1 addition & 1 deletion vm/src/builtins/float.rs
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ impl PyFloat {
// Retrieve inner float value:
#[cfg(feature = "serde")]
pub(crate) fn get_value(obj: &PyObject) -> f64 {
obj.payload::<PyFloat>().unwrap().value
obj.downcast_ref::<PyFloat>().unwrap().value
}

#[rustfmt::skip] // to avoid line splitting
Expand Down
4 changes: 2 additions & 2 deletions vm/src/builtins/int.rs
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,7 @@ impl PyInt {
F: FnOnce(&BigInt, &BigInt, &VirtualMachine) -> R,
R: ToPyResult,
{
if let (Some(a), Some(b)) = (a.payload::<Self>(), b.payload::<Self>()) {
if let (Some(a), Some(b)) = (a.downcast_ref::<Self>(), b.downcast_ref::<Self>()) {
op(&a.value, &b.value, vm).to_pyresult(vm)
} else {
Ok(vm.ctx.not_implemented())
Expand Down Expand Up @@ -860,7 +860,7 @@ fn try_int_radix(obj: &PyObject, base: u32, vm: &VirtualMachine) -> PyResult<Big

// Retrieve inner int value:
pub(crate) fn get_value(obj: &PyObject) -> &BigInt {
&obj.payload::<PyInt>().unwrap().value
&obj.downcast_ref::<PyInt>().unwrap().value
}

pub fn try_to_float(int: &BigInt, vm: &VirtualMachine) -> PyResult<f64> {
Expand Down
2 changes: 1 addition & 1 deletion vm/src/builtins/iter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ impl<T> PositionIterInternal<T> {
F: FnOnce(&T, usize) -> usize,
{
if let IterStatus::Active(obj) = &self.status {
if let Some(i) = state.payload::<PyInt>() {
if let Some(i) = state.downcast_ref::<PyInt>() {
let i = i.try_to_primitive(vm).unwrap_or(0);
self.position = f(obj, i);
Ok(())
Expand Down
18 changes: 9 additions & 9 deletions vm/src/builtins/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ impl PyMemoryView {
/// this should be the main entrance to create the memoryview
/// to avoid the chained memoryview
pub fn from_object(obj: &PyObject, vm: &VirtualMachine) -> PyResult<Self> {
if let Some(other) = obj.payload::<Self>() {
if let Some(other) = obj.downcast_ref::<Self>() {
Ok(other.new_view())
} else {
let buffer = PyBuffer::try_from_borrowed_object(vm, obj)?;
Expand Down Expand Up @@ -330,7 +330,7 @@ impl PyMemoryView {
return Ok(false);
}

if let Some(other) = other.payload::<Self>() {
if let Some(other) = other.downcast_ref::<Self>() {
if other.released.load() {
return Ok(false);
}
Expand Down Expand Up @@ -665,7 +665,7 @@ impl PyMemoryView {
if needle.is(&vm.ctx.ellipsis) {
return Ok(zelf.into());
}
if let Some(tuple) = needle.payload::<PyTuple>() {
if let Some(tuple) = needle.downcast_ref::<PyTuple>() {
if tuple.is_empty() {
return zelf.unpack_single(0, vm);
}
Expand Down Expand Up @@ -864,7 +864,7 @@ impl Py<PyMemoryView> {
// TODO: merge branches when we got conditional if let
if needle.is(&vm.ctx.ellipsis) {
return self.pack_single(0, value, vm);
} else if let Some(tuple) = needle.payload::<PyTuple>() {
} else if let Some(tuple) = needle.downcast_ref::<PyTuple>() {
if tuple.is_empty() {
return self.pack_single(0, value, vm);
}
Expand Down Expand Up @@ -907,15 +907,15 @@ enum SubscriptNeedle {
impl TryFromObject for SubscriptNeedle {
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
// TODO: number protocol
if let Some(i) = obj.payload::<PyInt>() {
if let Some(i) = obj.downcast_ref::<PyInt>() {
Ok(Self::Index(i.try_to_primitive(vm)?))
} else if obj.payload_is::<PySlice>() {
} else if obj.downcastable::<PySlice>() {
Ok(Self::Slice(unsafe { obj.downcast_unchecked::<PySlice>() }))
} else if let Ok(i) = obj.try_index(vm) {
Ok(Self::Index(i.try_to_primitive(vm)?))
} else {
if let Some(tuple) = obj.payload::<PyTuple>() {
if tuple.iter().all(|x| x.payload_is::<PyInt>()) {
if let Some(tuple) = obj.downcast_ref::<PyTuple>() {
if tuple.iter().all(|x| x.downcastable::<PyInt>()) {
let v = tuple
.iter()
.map(|x| {
Expand All @@ -924,7 +924,7 @@ impl TryFromObject for SubscriptNeedle {
})
.try_collect()?;
return Ok(Self::MultiIndex(v));
} else if tuple.iter().all(|x| x.payload_is::<PySlice>()) {
} else if tuple.iter().all(|x| x.downcastable::<PySlice>()) {
return Err(vm.new_not_implemented_error(
"multi-dimensional slicing is not implemented",
));
Expand Down
Loading
Loading