Skip to content
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

Make Type[T] comparisons work #1806

Merged
merged 9 commits into from
Jul 8, 2016

Conversation

Michael0x2a
Copy link
Collaborator

This commit introduces a workaround to fix the bug discussed in #1787

Previously, code where you compared two types (eg int == int or int != int) would cause mypy to incorrectly report a "too few arguments" error.

This commit introduces a workaround to fix the bug discussed in
python#1787

Previously, code where you compared two types (eg `int == int`) would
cause mypy to incorrectly report a "too few arguments" error.
@gvanrossum
Copy link
Member

@JukkaL What do you think of this? It works but it feels a bit ad-hoc. The same behavior applies to all operators (everything in nodes.op_methods and nearby variables) but it feels the key problem is happening because of some confusion between the class and the metaclass (or between the instance and the class) -- it's just only apparent for __eq__ because that's the only interesting operator defined on both type and object. I've got a feeling that maybe there's something that check_op() or check_op_local() could do better?

@gvanrossum
Copy link
Member

More background: for operators, the method name (in this case __eq__) is never looked up on the instance, only on the class; in the case of class objects, the "instance" is the class and the "class" is the metaclass. Without this rule we wouldn't be able to compare class objects using == at all, at least not for classes that override equality for their instances...

@JukkaL
Copy link
Collaborator

JukkaL commented Jul 6, 2016

Yeah, this feels a little ad hoc. It seems that __eq__ isn't really special -- for example, type(1) < type('x') works in Python 2, and arguably should be accepted by mypy. Maybe we should have the same logic for all operators if the left operand has type Type[x]?

This commit introduces a workaround to fix the bug discussed in
python#1787

Previously, code where you compared two types (eg `int == int`) would
cause mypy to incorrectly report a "too few arguments" error.
After talking with Guido, I realized Python special-cases literally the
operators (==, +, etc), NOT the magic methods themselves. So, that means
we need to special-case "a == b", but not "a.__eq__(b)".

As a result, checking to see if the method name was a magic method or
not was the wrong thing to do -- if the name of the method is "__eq__",
there's no way to know if the code was originally "foo == bar" or
"foo.__eq__(bar)".

So, rather then trying to do something with the operator name, I can
instead check and see if the node is an OpExpr or ComparisonExpr node vs
a CallExpr node.
builtin_type, not_ready_callback, msg)
if result:
return result
if not isinstance(node, (OpExpr, ComparisonExpr)):
Copy link
Collaborator

@ddfisher ddfisher Jul 8, 2016

Choose a reason for hiding this comment

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

node is just used as a context for errors, and isn't necessarily reliable. I don't think it probably shouldn't be used for this purpose.

Copy link
Collaborator

@ddfisher ddfisher Jul 8, 2016

Choose a reason for hiding this comment

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

Also, this doesn't catch all cases, e.g. __getitem__.

Copy link
Collaborator

Choose a reason for hiding this comment

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

I'd consider adding an optional bool parameter to this function instead and setting it in check_op (in checkexpr.py).

@ddfisher
Copy link
Collaborator

ddfisher commented Jul 8, 2016

Can you fix the problems surfaced by CI? This looks good otherwise.

@Michael0x2a
Copy link
Collaborator Author

Oh, whoops -- I forgot to test after merging. Doing that now.

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.

5 participants