Skip to content

Commit 5d28f9b

Browse files
authored
Merge pull request RustPython#594 from skinny121/isinstance_2
Only use real isinstance/issubclass for built-ins
2 parents 9b7c0f7 + b1a070a commit 5d28f9b

File tree

6 files changed

+27
-45
lines changed

6 files changed

+27
-45
lines changed

vm/src/builtins.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -347,7 +347,7 @@ fn builtin_isinstance(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
347347
required = [(obj, None), (typ, Some(vm.get_type()))]
348348
);
349349

350-
let isinstance = objtype::real_isinstance(vm, obj, typ)?;
350+
let isinstance = vm.isinstance(obj, typ)?;
351351
Ok(vm.new_bool(isinstance))
352352
}
353353

@@ -358,7 +358,7 @@ fn builtin_issubclass(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
358358
required = [(subclass, Some(vm.get_type())), (cls, Some(vm.get_type()))]
359359
);
360360

361-
let issubclass = objtype::real_issubclass(vm, subclass, cls)?;
361+
let issubclass = vm.issubclass(subclass, cls)?;
362362
Ok(vm.context().new_bool(issubclass))
363363
}
364364

@@ -814,7 +814,7 @@ pub fn builtin_build_class_(vm: &mut VirtualMachine, mut args: PyFuncArgs) -> Py
814814
let mut metaclass = args.get_kwarg("metaclass", vm.get_type());
815815

816816
for base in bases.clone() {
817-
if objtype::real_issubclass(vm, &base.typ(), &metaclass)? {
817+
if objtype::issubclass(&base.typ(), &metaclass) {
818818
metaclass = base.typ();
819819
} else if !objtype::issubclass(&metaclass, &base.typ()) {
820820
return Err(vm.new_type_error("metaclass conflict: the metaclass of a derived class must be a (non-strict) subclass of the metaclasses of all its bases".to_string()));

vm/src/macros.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ macro_rules! type_check {
1919
if let Some(expected_type) = $arg_type {
2020
let arg = &$args.args[$arg_count];
2121

22-
if !$crate::obj::objtype::real_isinstance($vm, arg, &expected_type)? {
22+
if !$crate::obj::objtype::isinstance(arg, &expected_type) {
2323
let arg_typ = arg.typ();
2424
let expected_type_name = $vm.to_pystr(&expected_type)?;
2525
let actual_type = $vm.to_pystr(&arg_typ)?;

vm/src/obj/objsuper.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,7 @@ fn super_init(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
7272
};
7373

7474
// Check obj type:
75-
if !(objtype::real_isinstance(vm, &py_obj, &py_type)?
76-
|| objtype::real_issubclass(vm, &py_obj, &py_type)?)
77-
{
75+
if !(objtype::isinstance(&py_obj, &py_type) || objtype::issubclass(&py_obj, &py_type)) {
7876
return Err(vm.new_type_error(
7977
"super(type, obj): obj must be an instance or subtype of type".to_string(),
8078
));

vm/src/obj/objtype.rs

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use super::objbool;
21
use super::objdict;
32
use super::objstr;
43
use super::objtype; // Required for arg_check! to use isinstance
@@ -9,7 +8,6 @@ use crate::pyobject::{
98
use crate::vm::VirtualMachine;
109
use std::cell::RefCell;
1110
use std::collections::HashMap;
12-
use std::rc::Rc;
1311

1412
/*
1513
* The magical type type
@@ -108,23 +106,6 @@ pub fn isinstance(obj: &PyObjectRef, cls: &PyObjectRef) -> bool {
108106
mro.into_iter().any(|c| c.is(&cls))
109107
}
110108

111-
/// Determines if `obj` is an instance of `cls`, either directly, indirectly or virtually via the
112-
/// __instancecheck__ magic method.
113-
pub fn real_isinstance(
114-
vm: &mut VirtualMachine,
115-
obj: &PyObjectRef,
116-
cls: &PyObjectRef,
117-
) -> PyResult<bool> {
118-
// cpython first does an exact check on the type, although documentation doesn't state that
119-
// https://github.com/python/cpython/blob/a24107b04c1277e3c1105f98aff5bfa3a98b33a0/Objects/abstract.c#L2408
120-
if Rc::ptr_eq(&obj.typ(), cls) {
121-
Ok(true)
122-
} else {
123-
let ret = vm.call_method(cls, "__instancecheck__", vec![obj.clone()])?;
124-
objbool::boolval(vm, ret)
125-
}
126-
}
127-
128109
fn type_instance_check(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
129110
arg_check!(
130111
vm,
@@ -142,17 +123,6 @@ pub fn issubclass(subclass: &PyObjectRef, cls: &PyObjectRef) -> bool {
142123
mro.into_iter().any(|c| c.is(&cls))
143124
}
144125

145-
/// Determines if `subclass` is a subclass of `cls`, either directly, indirectly or virtually via
146-
/// the __subclasscheck__ magic method.
147-
pub fn real_issubclass(
148-
vm: &mut VirtualMachine,
149-
subclass: &PyObjectRef,
150-
cls: &PyObjectRef,
151-
) -> PyResult<bool> {
152-
let ret = vm.call_method(cls, "__subclasscheck__", vec![subclass.clone()])?;
153-
objbool::boolval(vm, ret)
154-
}
155-
156126
fn type_subclass_check(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
157127
arg_check!(
158128
vm,

vm/src/pyobject.rs

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -922,7 +922,7 @@ impl PyFuncArgs {
922922
) -> Result<Option<PyObjectRef>, PyObjectRef> {
923923
match self.get_optional_kwarg(key) {
924924
Some(kwarg) => {
925-
if objtype::real_isinstance(vm, &kwarg, &ty)? {
925+
if objtype::isinstance(&kwarg, &ty) {
926926
Ok(Some(kwarg))
927927
} else {
928928
let expected_ty_name = vm.to_pystr(&ty)?;
@@ -1003,13 +1003,7 @@ where
10031003
Ok(value) => Some(T::try_from_object(self.vm, value)),
10041004
Err(err) => {
10051005
let stop_ex = self.vm.ctx.exceptions.stop_iteration.clone();
1006-
let stop = match objtype::real_isinstance(self.vm, &err, &stop_ex) {
1007-
Ok(stop) => stop,
1008-
Err(e) => {
1009-
return Some(Err(e));
1010-
}
1011-
};
1012-
if stop {
1006+
if objtype::isinstance(&err, &stop_ex) {
10131007
None
10141008
} else {
10151009
Some(Err(err))

vm/src/vm.rs

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,26 @@ impl VirtualMachine {
242242
self.call_method(obj, "__repr__", vec![])
243243
}
244244

245+
/// Determines if `obj` is an instance of `cls`, either directly, indirectly or virtually via
246+
/// the __instancecheck__ magic method.
247+
pub fn isinstance(&mut self, obj: &PyObjectRef, cls: &PyObjectRef) -> PyResult<bool> {
248+
// cpython first does an exact check on the type, although documentation doesn't state that
249+
// https://github.com/python/cpython/blob/a24107b04c1277e3c1105f98aff5bfa3a98b33a0/Objects/abstract.c#L2408
250+
if Rc::ptr_eq(&obj.typ(), cls) {
251+
Ok(true)
252+
} else {
253+
let ret = self.call_method(cls, "__instancecheck__", vec![obj.clone()])?;
254+
objbool::boolval(self, ret)
255+
}
256+
}
257+
258+
/// Determines if `subclass` is a subclass of `cls`, either directly, indirectly or virtually
259+
/// via the __subclasscheck__ magic method.
260+
pub fn issubclass(&mut self, subclass: &PyObjectRef, cls: &PyObjectRef) -> PyResult<bool> {
261+
let ret = self.call_method(cls, "__subclasscheck__", vec![subclass.clone()])?;
262+
objbool::boolval(self, ret)
263+
}
264+
245265
pub fn call_get_descriptor(&mut self, attr: PyObjectRef, obj: PyObjectRef) -> PyResult {
246266
let attr_class = attr.typ();
247267
if let Some(descriptor) = attr_class.get_attr("__get__") {

0 commit comments

Comments
 (0)