Skip to content

Commit 6a3dff6

Browse files
authored
Downcastable (#5986)
* simplify int power * downcastasble * deprecate payload*
1 parent 177bfb7 commit 6a3dff6

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+210
-222
lines changed

.cspell.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@
6060
"dedentations",
6161
"dedents",
6262
"deduped",
63+
"downcastable",
6364
"downcasted",
6465
"dumpable",
6566
"emscripten",

stdlib/src/array.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -667,7 +667,7 @@ mod array {
667667
ArrayContentType::from_char(spec).map_err(|err| vm.new_value_error(err))?;
668668

669669
if let OptionalArg::Present(init) = init {
670-
if let Some(init) = init.payload::<Self>() {
670+
if let Some(init) = init.downcast_ref::<Self>() {
671671
match (spec, init.read().typecode()) {
672672
(spec, ch) if spec == ch => array.frombytes(&init.get_bytes()),
673673
(spec, 'u') => {
@@ -681,7 +681,7 @@ mod array {
681681
}
682682
}
683683
}
684-
} else if let Some(wtf8) = init.payload::<PyStr>() {
684+
} else if let Some(wtf8) = init.downcast_ref::<PyStr>() {
685685
if spec == 'u' {
686686
let bytes = Self::_unicode_to_wchar_bytes(wtf8.as_wtf8(), array.itemsize());
687687
array.frombytes_move(bytes);
@@ -690,7 +690,7 @@ mod array {
690690
"cannot use a str to initialize an array with typecode '{spec}'"
691691
)));
692692
}
693-
} else if init.payload_is::<PyBytes>() || init.payload_is::<PyByteArray>() {
693+
} else if init.downcastable::<PyBytes>() || init.downcastable::<PyByteArray>() {
694694
init.try_bytes_like(vm, |x| array.frombytes(x))?;
695695
} else if let Ok(iter) = ArgIterable::try_from_object(vm, init.clone()) {
696696
for obj in iter.iter(vm)? {
@@ -765,7 +765,7 @@ mod array {
765765
let mut w = zelf.try_resizable(vm)?;
766766
if zelf.is(&obj) {
767767
w.imul(2, vm)
768-
} else if let Some(array) = obj.payload::<Self>() {
768+
} else if let Some(array) = obj.downcast_ref::<Self>() {
769769
w.iadd(&array.read(), vm)
770770
} else {
771771
let iter = ArgIterable::try_from_object(vm, obj)?;
@@ -1013,7 +1013,7 @@ mod array {
10131013
cloned = zelf.read().clone();
10141014
&cloned
10151015
} else {
1016-
match value.payload::<Self>() {
1016+
match value.downcast_ref::<Self>() {
10171017
Some(array) => {
10181018
guard = array.read();
10191019
&*guard
@@ -1059,7 +1059,7 @@ mod array {
10591059

10601060
#[pymethod]
10611061
fn __add__(&self, other: PyObjectRef, vm: &VirtualMachine) -> PyResult<PyRef<Self>> {
1062-
if let Some(other) = other.payload::<Self>() {
1062+
if let Some(other) = other.downcast_ref::<Self>() {
10631063
self.read()
10641064
.add(&other.read(), vm)
10651065
.map(|array| Self::from(array).into_ref(&vm.ctx))
@@ -1079,7 +1079,7 @@ mod array {
10791079
) -> PyResult<PyRef<Self>> {
10801080
if zelf.is(&other) {
10811081
zelf.try_resizable(vm)?.imul(2, vm)?;
1082-
} else if let Some(other) = other.payload::<Self>() {
1082+
} else if let Some(other) = other.downcast_ref::<Self>() {
10831083
zelf.try_resizable(vm)?.iadd(&other.read(), vm)?;
10841084
} else {
10851085
return Err(vm.new_type_error(format!(

stdlib/src/csv.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ mod _csv {
269269
mut _rest: FuncArgs,
270270
vm: &VirtualMachine,
271271
) -> PyResult<()> {
272-
let Some(name) = name.payload_if_subclass::<PyStr>(vm) else {
272+
let Some(name) = name.downcast_ref::<PyStr>() else {
273273
return Err(vm.new_type_error("argument 0 must be a string"));
274274
};
275275
let dialect = match dialect {
@@ -290,7 +290,7 @@ mod _csv {
290290
mut _rest: FuncArgs,
291291
vm: &VirtualMachine,
292292
) -> PyResult<PyDialect> {
293-
let Some(name) = name.payload_if_subclass::<PyStr>(vm) else {
293+
let Some(name) = name.downcast_ref::<PyStr>() else {
294294
return Err(vm.new_exception_msg(
295295
super::_csv::error(vm),
296296
format!("argument 0 must be a string, not '{}'", name.class()),
@@ -309,7 +309,7 @@ mod _csv {
309309
mut _rest: FuncArgs,
310310
vm: &VirtualMachine,
311311
) -> PyResult<()> {
312-
let Some(name) = name.payload_if_subclass::<PyStr>(vm) else {
312+
let Some(name) = name.downcast_ref::<PyStr>() else {
313313
return Err(vm.new_exception_msg(
314314
super::_csv::error(vm),
315315
format!("argument 0 must be a string, not '{}'", name.class()),

stdlib/src/select.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -350,7 +350,7 @@ mod decl {
350350
fn try_from_object(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<Self> {
351351
let timeout = if vm.is_none(&obj) {
352352
None
353-
} else if let Some(float) = obj.payload::<PyFloat>() {
353+
} else if let Some(float) = obj.downcast_ref::<PyFloat>() {
354354
let float = float.to_f64();
355355
if float.is_nan() {
356356
return Err(vm.new_value_error("Invalid value NaN (not a number)"));

stdlib/src/sqlite.rs

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -535,7 +535,7 @@ mod _sqlite {
535535
let access = ptr_to_str(access, vm)?;
536536

537537
let val = callable.call((action, arg1, arg2, db_name, access), vm)?;
538-
let Some(val) = val.payload::<PyInt>() else {
538+
let Some(val) = val.downcast_ref::<PyInt>() else {
539539
return Ok(SQLITE_DENY);
540540
};
541541
val.try_to_primitive::<c_int>(vm)
@@ -1897,18 +1897,18 @@ mod _sqlite {
18971897
Ok(self
18981898
.description
18991899
.iter()
1900-
.map(|x| x.payload::<PyTuple>().unwrap().as_slice()[0].clone())
1900+
.map(|x| x.downcast_ref::<PyTuple>().unwrap().as_slice()[0].clone())
19011901
.collect())
19021902
}
19031903

19041904
fn subscript(&self, needle: &PyObject, vm: &VirtualMachine) -> PyResult {
1905-
if let Some(i) = needle.payload::<PyInt>() {
1905+
if let Some(i) = needle.downcast_ref::<PyInt>() {
19061906
let i = i.try_to_primitive::<isize>(vm)?;
19071907
self.data.getitem_by_index(vm, i)
1908-
} else if let Some(name) = needle.payload::<PyStr>() {
1908+
} else if let Some(name) = needle.downcast_ref::<PyStr>() {
19091909
for (obj, i) in self.description.iter().zip(0..) {
1910-
let obj = &obj.payload::<PyTuple>().unwrap().as_slice()[0];
1911-
let Some(obj) = obj.payload::<PyStr>() else {
1910+
let obj = &obj.downcast_ref::<PyTuple>().unwrap().as_slice()[0];
1911+
let Some(obj) = obj.downcast_ref::<PyStr>() else {
19121912
break;
19131913
};
19141914
let a_iter = name.as_str().chars().flat_map(|x| x.to_uppercase());
@@ -1919,7 +1919,7 @@ mod _sqlite {
19191919
}
19201920
}
19211921
Err(vm.new_index_error("No item with that key"))
1922-
} else if let Some(slice) = needle.payload::<PySlice>() {
1922+
} else if let Some(slice) = needle.downcast_ref::<PySlice>() {
19231923
let list = self.data.getitem_by_slice(vm, slice.to_saturated(vm)?)?;
19241924
Ok(vm.ctx.new_tuple(list).into())
19251925
} else {
@@ -1962,7 +1962,7 @@ mod _sqlite {
19621962
vm: &VirtualMachine,
19631963
) -> PyResult<PyComparisonValue> {
19641964
op.eq_only(|| {
1965-
if let Some(other) = other.payload::<Self>() {
1965+
if let Some(other) = other.downcast_ref::<Self>() {
19661966
let eq = vm
19671967
.bool_eq(zelf.description.as_object(), other.description.as_object())?
19681968
&& vm.bool_eq(zelf.data.as_object(), other.data.as_object())?;
@@ -2179,7 +2179,7 @@ mod _sqlite {
21792179
let mut byte: u8 = 0;
21802180
let ret = inner.blob.read_single(&mut byte, index);
21812181
self.check(ret, vm).map(|_| vm.ctx.new_int(byte).into())
2182-
} else if let Some(slice) = needle.payload::<PySlice>() {
2182+
} else if let Some(slice) = needle.downcast_ref::<PySlice>() {
21832183
let blob_len = inner.blob.bytes();
21842184
let slice = slice.to_saturated(vm)?;
21852185
let (range, step, length) = slice.adjust_indices(blob_len as usize);
@@ -2220,7 +2220,7 @@ mod _sqlite {
22202220
let inner = self.inner(vm)?;
22212221

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

26462646
let ret = if vm.is_none(obj) {
26472647
unsafe { sqlite3_bind_null(self.st, pos) }
2648-
} else if let Some(val) = obj.payload::<PyInt>() {
2648+
} else if let Some(val) = obj.downcast_ref::<PyInt>() {
26492649
let val = val.try_to_primitive::<i64>(vm).map_err(|_| {
26502650
vm.new_overflow_error("Python int too large to convert to SQLite INTEGER")
26512651
})?;
26522652
unsafe { sqlite3_bind_int64(self.st, pos, val) }
2653-
} else if let Some(val) = obj.payload::<PyFloat>() {
2653+
} else if let Some(val) = obj.downcast_ref::<PyFloat>() {
26542654
let val = val.to_f64();
26552655
unsafe { sqlite3_bind_double(self.st, pos, val) }
2656-
} else if let Some(val) = obj.payload::<PyStr>() {
2656+
} else if let Some(val) = obj.downcast_ref::<PyStr>() {
26572657
let (ptr, len) = str_to_ptr_len(val, vm)?;
26582658
unsafe { sqlite3_bind_text(self.st, pos, ptr, len, SQLITE_TRANSIENT()) }
26592659
} else if let Ok(buffer) = PyBuffer::try_from_borrowed_object(vm, obj) {
@@ -2900,11 +2900,11 @@ mod _sqlite {
29002900
unsafe {
29012901
if vm.is_none(val) {
29022902
sqlite3_result_null(self.ctx)
2903-
} else if let Some(val) = val.payload::<PyInt>() {
2903+
} else if let Some(val) = val.downcast_ref::<PyInt>() {
29042904
sqlite3_result_int64(self.ctx, val.try_to_primitive(vm)?)
2905-
} else if let Some(val) = val.payload::<PyFloat>() {
2905+
} else if let Some(val) = val.downcast_ref::<PyFloat>() {
29062906
sqlite3_result_double(self.ctx, val.to_f64())
2907-
} else if let Some(val) = val.payload::<PyStr>() {
2907+
} else if let Some(val) = val.downcast_ref::<PyStr>() {
29082908
let (ptr, len) = str_to_ptr_len(val, vm)?;
29092909
sqlite3_result_text(self.ctx, ptr, len, SQLITE_TRANSIENT())
29102910
} else if let Ok(buffer) = PyBuffer::try_from_borrowed_object(vm, val) {

stdlib/src/termios.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -217,9 +217,12 @@ mod termios {
217217
))
218218
})?;
219219
for (cc, x) in termios.c_cc.iter_mut().zip(cc.iter()) {
220-
*cc = if let Some(c) = x.payload::<PyBytes>().filter(|b| b.as_bytes().len() == 1) {
220+
*cc = if let Some(c) = x
221+
.downcast_ref::<PyBytes>()
222+
.filter(|b| b.as_bytes().len() == 1)
223+
{
221224
c.as_bytes()[0] as _
222-
} else if let Some(i) = x.payload::<PyInt>() {
225+
} else if let Some(i) = x.downcast_ref::<PyInt>() {
223226
i.try_to_primitive(vm)?
224227
} else {
225228
return Err(vm.new_type_error(

vm/src/builtins/asyncgenerator.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -344,7 +344,9 @@ impl PyAsyncGenAThrow {
344344
let ret = self.ag.inner.send(self.ag.as_object(), val, vm);
345345
if self.aclose {
346346
match ret {
347-
Ok(PyIterReturn::Return(v)) if v.payload_is::<PyAsyncGenWrappedValue>() => {
347+
Ok(PyIterReturn::Return(v))
348+
if v.downcastable::<PyAsyncGenWrappedValue>() =>
349+
{
348350
Err(self.yield_close(vm))
349351
}
350352
other => other
@@ -392,7 +394,7 @@ impl PyAsyncGenAThrow {
392394

393395
fn ignored_close(&self, res: &PyResult<PyIterReturn>) -> bool {
394396
res.as_ref().is_ok_and(|v| match v {
395-
PyIterReturn::Return(obj) => obj.payload_is::<PyAsyncGenWrappedValue>(),
397+
PyIterReturn::Return(obj) => obj.downcastable::<PyAsyncGenWrappedValue>(),
396398
PyIterReturn::StopIteration(_) => false,
397399
})
398400
}

vm/src/builtins/bool.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ impl PyObjectRef {
5757
Some(method_or_err) => {
5858
let method = method_or_err?;
5959
let bool_obj = method.call((), vm)?;
60-
let int_obj = bool_obj.payload::<PyInt>().ok_or_else(|| {
60+
let int_obj = bool_obj.downcast_ref::<PyInt>().ok_or_else(|| {
6161
vm.new_type_error(format!(
6262
"'{}' object cannot be interpreted as an integer",
6363
bool_obj.class().name()
@@ -128,8 +128,8 @@ impl PyBool {
128128
let lhs = get_value(&lhs);
129129
let rhs = get_value(&rhs);
130130
(lhs || rhs).to_pyobject(vm)
131-
} else if let Some(lhs) = lhs.payload::<PyInt>() {
132-
lhs.__or__(rhs, vm).to_pyobject(vm)
131+
} else if let Some(lhs) = lhs.downcast_ref::<PyInt>() {
132+
lhs.__or__(rhs).to_pyobject(vm)
133133
} else {
134134
vm.ctx.not_implemented()
135135
}
@@ -144,8 +144,8 @@ impl PyBool {
144144
let lhs = get_value(&lhs);
145145
let rhs = get_value(&rhs);
146146
(lhs && rhs).to_pyobject(vm)
147-
} else if let Some(lhs) = lhs.payload::<PyInt>() {
148-
lhs.__and__(rhs, vm).to_pyobject(vm)
147+
} else if let Some(lhs) = lhs.downcast_ref::<PyInt>() {
148+
lhs.__and__(rhs).to_pyobject(vm)
149149
} else {
150150
vm.ctx.not_implemented()
151151
}
@@ -160,8 +160,8 @@ impl PyBool {
160160
let lhs = get_value(&lhs);
161161
let rhs = get_value(&rhs);
162162
(lhs ^ rhs).to_pyobject(vm)
163-
} else if let Some(lhs) = lhs.payload::<PyInt>() {
164-
lhs.__xor__(rhs, vm).to_pyobject(vm)
163+
} else if let Some(lhs) = lhs.downcast_ref::<PyInt>() {
164+
lhs.__xor__(rhs).to_pyobject(vm)
165165
} else {
166166
vm.ctx.not_implemented()
167167
}
@@ -212,5 +212,5 @@ pub(crate) fn init(context: &Context) {
212212

213213
// Retrieve inner int value:
214214
pub(crate) fn get_value(obj: &PyObject) -> bool {
215-
!obj.payload::<PyInt>().unwrap().as_bigint().is_zero()
215+
!obj.downcast_ref::<PyInt>().unwrap().as_bigint().is_zero()
216216
}

vm/src/builtins/builtin_func.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ impl Comparable for PyNativeMethod {
213213
_vm: &VirtualMachine,
214214
) -> PyResult<PyComparisonValue> {
215215
op.eq_only(|| {
216-
if let Some(other) = other.payload::<Self>() {
216+
if let Some(other) = other.downcast_ref::<Self>() {
217217
let eq = match (zelf.func.zelf.as_ref(), other.func.zelf.as_ref()) {
218218
(Some(z), Some(o)) => z.is(o),
219219
(None, None) => true,

vm/src/builtins/complex.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ impl PyObjectRef {
5858
/// Tries converting a python object into a complex, returns an option of whether the complex
5959
/// and whether the object was a complex originally or coerced into one
6060
pub fn try_complex(&self, vm: &VirtualMachine) -> PyResult<Option<(Complex64, bool)>> {
61-
if let Some(complex) = self.payload_if_exact::<PyComplex>(vm) {
61+
if let Some(complex) = self.downcast_ref_if_exact::<PyComplex>(vm) {
6262
return Ok(Some((complex.value, true)));
6363
}
6464
if let Some(method) = vm.get_method(self.clone(), identifier!(vm, __complex__)) {
@@ -79,7 +79,7 @@ impl PyObjectRef {
7979

8080
return Ok(Some((ret.value, true)));
8181
} else {
82-
return match result.payload::<PyComplex>() {
82+
return match result.downcast_ref::<PyComplex>() {
8383
Some(complex_obj) => Ok(Some((complex_obj.value, true))),
8484
None => Err(vm.new_type_error(format!(
8585
"__complex__ returned non-complex (type '{}')",
@@ -90,7 +90,7 @@ impl PyObjectRef {
9090
}
9191
// `complex` does not have a `__complex__` by default, so subclasses might not either,
9292
// use the actual stored value in this case
93-
if let Some(complex) = self.payload_if_subclass::<PyComplex>(vm) {
93+
if let Some(complex) = self.downcast_ref::<PyComplex>() {
9494
return Ok(Some((complex.value, true)));
9595
}
9696
if let Some(float) = self.try_float_opt(vm) {
@@ -105,7 +105,7 @@ pub fn init(context: &Context) {
105105
}
106106

107107
fn to_op_complex(value: &PyObject, vm: &VirtualMachine) -> PyResult<Option<Complex64>> {
108-
let r = if let Some(complex) = value.payload_if_subclass::<PyComplex>(vm) {
108+
let r = if let Some(complex) = value.downcast_ref::<PyComplex>() {
109109
Some(complex.value)
110110
} else {
111111
float::to_op_float(value, vm)?.map(|float| Complex64::new(float, 0.0))
@@ -175,7 +175,7 @@ impl Constructor for PyComplex {
175175

176176
if let Some(c) = val.try_complex(vm)? {
177177
c
178-
} else if let Some(s) = val.payload_if_subclass::<PyStr>(vm) {
178+
} else if let Some(s) = val.downcast_ref::<PyStr>() {
179179
if args.imag.is_present() {
180180
return Err(vm.new_type_error(
181181
"complex() can't take second arg if first is a string",
@@ -419,7 +419,7 @@ impl Comparable for PyComplex {
419419
vm: &VirtualMachine,
420420
) -> PyResult<PyComparisonValue> {
421421
op.eq_only(|| {
422-
let result = if let Some(other) = other.payload_if_subclass::<Self>(vm) {
422+
let result = if let Some(other) = other.downcast_ref::<Self>() {
423423
if zelf.value.re.is_nan()
424424
&& zelf.value.im.is_nan()
425425
&& other.value.re.is_nan()

0 commit comments

Comments
 (0)