Skip to content

Commit 1ed18c0

Browse files
qingshi163youknowone
authored andcommitted
fix vm.to_index now use number protocol
1 parent 3e6e348 commit 1ed18c0

File tree

3 files changed

+26
-32
lines changed

3 files changed

+26
-32
lines changed

Lib/test/test_index.py

-2
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,6 @@ def __index__(self):
7171
self.assertIs(type(direct_index), int)
7272
#self.assertIs(type(operator_index), int)
7373

74-
# TODO: RUSTPYTHON
75-
@unittest.expectedFailure
7674
def test_index_returns_int_subclass(self):
7775
class BadInt:
7876
def __index__(self):

vm/src/protocol/number.rs

+23-9
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,11 @@ impl PyNumber<'_> {
134134
),
135135
1,
136136
vm,
137-
)?
137+
)?;
138+
Ok(vm.ctx.new_int(ret.as_bigint().clone()))
139+
} else {
140+
Ok(ret)
138141
}
139-
Ok(ret)
140142
} else if self.methods(vm).index.is_some() {
141143
self.index(vm)
142144
} else if let Ok(Ok(f)) =
@@ -173,9 +175,13 @@ impl PyNumber<'_> {
173175
}
174176
}
175177

176-
pub fn index(&self, vm: &VirtualMachine) -> PyResult<PyIntRef> {
178+
pub fn index_opt(&self, vm: &VirtualMachine) -> PyResult<Option<PyIntRef>> {
177179
if self.obj.class().is(PyInt::class(vm)) {
178-
Ok(unsafe { self.obj.to_owned().downcast_unchecked::<PyInt>() })
180+
Ok(Some(unsafe {
181+
self.obj.to_owned().downcast_unchecked::<PyInt>()
182+
}))
183+
} else if let Some(i) = self.obj.downcast_ref::<PyInt>() {
184+
Ok(Some(i.to_owned()))
179185
} else if let Some(f) = self.methods(vm).index {
180186
let ret = f(self, vm)?;
181187
if !ret.class().is(PyInt::class(vm)) {
@@ -189,15 +195,23 @@ impl PyNumber<'_> {
189195
),
190196
1,
191197
vm,
192-
)?
198+
)?;
199+
Ok(Some(vm.ctx.new_int(ret.as_bigint().clone())))
200+
} else {
201+
Ok(Some(ret))
193202
}
194-
Ok(ret)
195203
} else {
196-
Err(vm.new_type_error(format!(
204+
Ok(None)
205+
}
206+
}
207+
208+
pub fn index(&self, vm: &VirtualMachine) -> PyResult<PyIntRef> {
209+
self.index_opt(vm)?.ok_or_else(|| {
210+
vm.new_type_error(format!(
197211
"'{}' object cannot be interpreted as an integer",
198212
self.obj.class()
199-
)))
200-
}
213+
))
214+
})
201215
}
202216

203217
pub fn float_opt(&self, vm: &VirtualMachine) -> PyResult<Option<PyRef<PyFloat>>> {

vm/src/vm/vm_ops.rs

+3-21
Original file line numberDiff line numberDiff line change
@@ -3,36 +3,18 @@ use crate::{
33
builtins::{PyInt, PyIntRef, PyStrInterned},
44
function::PyArithmeticValue,
55
object::{AsObject, PyObject, PyObjectRef, PyResult},
6-
protocol::PyIterReturn,
6+
protocol::{PyIterReturn, PyNumber},
77
types::PyComparisonOp,
88
};
99

1010
/// Collection of operators
1111
impl VirtualMachine {
1212
pub fn to_index_opt(&self, obj: PyObjectRef) -> Option<PyResult<PyIntRef>> {
13-
match obj.downcast() {
14-
Ok(val) => Some(Ok(val)),
15-
Err(obj) => self
16-
.get_method(obj, identifier!(self, __index__))
17-
.map(|index| {
18-
// TODO: returning strict subclasses of int in __index__ is deprecated
19-
self.invoke(&index?, ())?.downcast().map_err(|bad| {
20-
self.new_type_error(format!(
21-
"__index__ returned non-int (type {})",
22-
bad.class().name()
23-
))
24-
})
25-
}),
26-
}
13+
PyNumber::from(obj.as_ref()).index_opt(self).transpose()
2714
}
2815

2916
pub fn to_index(&self, obj: &PyObject) -> PyResult<PyIntRef> {
30-
self.to_index_opt(obj.to_owned()).unwrap_or_else(|| {
31-
Err(self.new_type_error(format!(
32-
"'{}' object cannot be interpreted as an integer",
33-
obj.class().name()
34-
)))
35-
})
17+
PyNumber::from(obj).index(self)
3618
}
3719

3820
#[inline]

0 commit comments

Comments
 (0)