Skip to content

Call __instancecheck__ and __subclasscheck__ #554

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Feb 28, 2019

Conversation

BenLewis-Seequent
Copy link

These magic methods are called as part of isinstance and issubclass to override their behavior. This means objtype::{isinstance, issubclass} require the vm, but in cases where the second argument is known to not override the associated magic method(i.e. most built in types), a version objtype::{real_isinstance, real_issubclass} can be used that doesn't require the vm.

@codecov-io
Copy link

codecov-io commented Feb 26, 2019

Codecov Report

Merging #554 into master will increase coverage by 0.13%.
The diff coverage is 25.37%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #554      +/-   ##
==========================================
+ Coverage   42.02%   42.15%   +0.13%     
==========================================
  Files          73       73              
  Lines       16425    16443      +18     
  Branches     4308     4316       +8     
==========================================
+ Hits         6902     6931      +29     
+ Misses       7561     7542      -19     
- Partials     1962     1970       +8
Impacted Files Coverage Δ
vm/src/macros.rs 14.28% <ø> (ø) ⬆️
vm/src/pyobject.rs 60.17% <0%> (ø) ⬆️
vm/src/obj/objsuper.rs 42.85% <0%> (-7.15%) ⬇️
vm/src/obj/objtype.rs 41.07% <32.65%> (+3.89%) ⬆️
vm/src/builtins.rs 36.05% <7.69%> (+1.44%) ⬆️
vm/src/stdlib/math.rs 30.66% <0%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update b0ee194...5779124. Read the comment docs.

@windelbouwman
Copy link
Contributor

There appear some files in conflict. Could you have a look at those?

@BenLewis-Seequent
Copy link
Author

Swapped the names over and resolved the conflicts.

@windelbouwman windelbouwman merged commit eaaafac into RustPython:master Feb 28, 2019
@@ -18,7 +18,8 @@ macro_rules! type_check {
// None indicates that we have no type requirement (i.e. we accept any type)
if let Some(expected_type) = $arg_type {
let arg = &$args.args[$arg_count];
if !$crate::obj::objtype::isinstance(arg, &expected_type) {

if !$crate::obj::objtype::real_isinstance($vm, arg, &expected_type)? {
Copy link
Contributor

@adrian17 adrian17 Feb 28, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know I'm late, but... do we need it here? type checking is already one of the slowest part of code, and I'd expect most, if not all, of types used for builtin functions' typechecks to not overload _instancecheck_.

(CPython builtin functions actually completely skip isinstance and directly check types with eg PyLong_CheckExact and PyType_FastSubclass macros)

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

for base in bases.clone() {
if objtype::issubclass(&base.typ(), &metaclass) {
if objtype::real_issubclass(vm, &base.typ(), &metaclass)? {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also here, pretty sure we shouldn't use the overloaded __subclasscheck__ and just call issubclass() directly.

With this contrived code:


class AlwaysGood(type):
	def __subclasscheck__(self, x):
		return True

class M(type): pass
class A(metaclass=M): pass

class M2(type, metaclass=AlwaysGood): pass
class C(A, metaclass=M2): pass

RustPython after this patch accepts this code, but CPython seems to have ignored overloaded method and still reports the metaclass conflict - which IMO is the correct behavior.

In general, looks like it'll be tricky to manage which calls should use builtin method, and which accept the overloaded method. Probably the best bet will be to hope that probably-imported-in-the-future CPython test suite will catch the inconsistencies :/

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are correct this shouldn't use the real version, I will create a PR soon to fix this.

@cthulahoops
Copy link
Collaborator

I'm also late to this one. I don't like the real_ naming (I do prefer the merged version to the original.)

I think the convention we've gone with is that there should be a method on VirtualMachine for the full magic method powered version, and a simple function for the low level implementation.

Ie. vm.issubclass(...) and objtype::issubclass.

@BenLewis-Seequent
Copy link
Author

I will make another PR to move the real_ version to the vm.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants