Skip to content

Commit caae69f

Browse files
Merge pull request #658 from RustPython/mro
Cleaner type_type declaration, and faster instance checking.
2 parents b8aa38d + d7e1d69 commit caae69f

File tree

2 files changed

+24
-38
lines changed

2 files changed

+24
-38
lines changed

vm/src/obj/objtype.rs

Lines changed: 16 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -41,39 +41,23 @@ pub fn create_type(type_type: PyObjectRef, object_type: PyObjectRef, _dict_type:
4141
}
4242
}
4343

44-
pub fn init(context: &PyContext) {
45-
let type_type = &context.type_type;
46-
44+
pub fn init(ctx: &PyContext) {
4745
let type_doc = "type(object_or_name, bases, dict)\n\
4846
type(object) -> the object's type\n\
4947
type(name, bases, dict) -> a new type";
5048

51-
context.set_attr(&type_type, "__call__", context.new_rustfunc(type_call));
52-
context.set_attr(&type_type, "__new__", context.new_rustfunc(type_new));
53-
context.set_attr(&type_type, "__mro__", context.new_property(type_mro));
54-
context.set_attr(&type_type, "__repr__", context.new_rustfunc(type_repr));
55-
context.set_attr(
56-
&type_type,
57-
"__prepare__",
58-
context.new_rustfunc(type_prepare),
59-
);
60-
context.set_attr(
61-
&type_type,
62-
"__getattribute__",
63-
context.new_rustfunc(type_getattribute),
64-
);
65-
context.set_attr(
66-
&type_type,
67-
"__instancecheck__",
68-
context.new_rustfunc(type_instance_check),
69-
);
70-
context.set_attr(
71-
&type_type,
72-
"__subclasscheck__",
73-
context.new_rustfunc(type_subclass_check),
74-
);
75-
context.set_attr(&type_type, "__doc__", context.new_str(type_doc.to_string()));
76-
context.set_attr(&type_type, "__dir__", context.new_rustfunc(type_dir));
49+
extend_class!(&ctx, &ctx.type_type, {
50+
"__call__" => ctx.new_rustfunc(type_call),
51+
"__new__" => ctx.new_rustfunc(type_new),
52+
"__mro__" => ctx.new_property(type_mro),
53+
"__repr__" => ctx.new_rustfunc(type_repr),
54+
"__prepare__" => ctx.new_rustfunc(type_prepare),
55+
"__getattribute__" => ctx.new_rustfunc(type_getattribute),
56+
"__instancecheck__" => ctx.new_rustfunc(type_instance_check),
57+
"__subclasscheck__" => ctx.new_rustfunc(type_subclass_check),
58+
"__doc__" => ctx.new_str(type_doc.to_string()),
59+
"__dir__" => ctx.new_rustfunc(type_dir),
60+
});
7761
}
7862

7963
fn type_mro(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -97,8 +81,7 @@ fn _mro(cls: PyObjectRef) -> Option<Vec<PyObjectRef>> {
9781
/// Determines if `obj` actually an instance of `cls`, this doesn't call __instancecheck__, so only
9882
/// use this if `cls` is known to have not overridden the base __instancecheck__ magic method.
9983
pub fn isinstance(obj: &PyObjectRef, cls: &PyObjectRef) -> bool {
100-
let mro = _mro(obj.typ()).unwrap();
101-
mro.into_iter().any(|c| c.is(&cls))
84+
issubclass(obj.type_ref(), &cls)
10285
}
10386

10487
fn type_instance_check(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
@@ -114,8 +97,8 @@ fn type_instance_check(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
11497
/// so only use this if `cls` is known to have not overridden the base __subclasscheck__ magic
11598
/// method.
11699
pub fn issubclass(subclass: &PyObjectRef, cls: &PyObjectRef) -> bool {
117-
let mro = _mro(subclass.clone()).unwrap();
118-
mro.into_iter().any(|c| c.is(&cls))
100+
let ref mro = subclass.payload::<PyClass>().unwrap().mro;
101+
subclass.is(&cls) || mro.iter().any(|c| c.is(&cls))
119102
}
120103

121104
fn type_subclass_check(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {

vm/src/pyobject.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -788,19 +788,22 @@ pub trait FromPyObjectRef {
788788
}
789789

790790
pub trait TypeProtocol {
791-
fn typ(&self) -> PyObjectRef;
791+
fn typ(&self) -> PyObjectRef {
792+
self.type_ref().clone()
793+
}
794+
fn type_ref(&self) -> &PyObjectRef;
792795
}
793796

794797
impl TypeProtocol for PyObjectRef {
795-
fn typ(&self) -> PyObjectRef {
796-
(**self).typ()
798+
fn type_ref(&self) -> &PyObjectRef {
799+
(**self).type_ref()
797800
}
798801
}
799802

800803
impl TypeProtocol for PyObject {
801-
fn typ(&self) -> PyObjectRef {
804+
fn type_ref(&self) -> &PyObjectRef {
802805
match self.typ {
803-
Some(ref typ) => typ.clone(),
806+
Some(ref typ) => &typ,
804807
None => panic!("Object {:?} doesn't have a type!", self),
805808
}
806809
}

0 commit comments

Comments
 (0)