Skip to content

Selftype - fallback to type(x) for classmethods #3633

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 1 commit into from
Jun 30, 2017

Conversation

elazarg
Copy link
Contributor

@elazarg elazarg commented Jun 29, 2017

Fix #3630

@elazarg elazarg changed the title Fallback to type(x) for classmethods Selftype - fallback to type(x) for classmethods Jun 29, 2017
@elazarg elazarg force-pushed the selftype-classmethod-instance branch from c5b7109 to 398f520 Compare June 29, 2017 13:25
@@ -472,7 +472,7 @@ class B(A): pass
tvars = [TypeVarDef(n, i + 1, [], builtin_type('builtins.object'), tv.variance)
for (i, n), tv in zip(enumerate(info.type_vars), info.defn.type_vars)]
if is_classmethod:
t = bind_self(t, original_type)
t = bind_self(t, original_type, is_classmethod=True)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This path is not tested

@elazarg elazarg force-pushed the selftype-classmethod-instance branch from 398f520 to b369ca8 Compare June 29, 2017 13:48
Copy link
Member

@ilevkivskyi ilevkivskyi left a comment

Choose a reason for hiding this comment

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

Thanks! Just few comments.

self_param_type, original_type)[0]
ids = [x.id for x in func.variables]
typearg = infer_type_arguments(ids, self_param_type, original_type)[0]
if (is_classmethod and isinstance(typearg, UninhabitedType)
Copy link
Member

Choose a reason for hiding this comment

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

Do you really need this additional test for UninhabitedType? It looks a bit suspicious.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Even if it is a classmethod, if the inference is successful with the original type, then it's fine; this is the normal case, calling the method on a class. We only "delegate" to the type if we are not successful.

Copy link
Member

Choose a reason for hiding this comment

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

OK, this seems reasonable. If there will be no objections, then I am going to merge this.

and isinstance(original_type, (Instance, TypeVarType, TupleType))):
# In case we call a classmethod through an instance x, fallback to type(x)
# TODO: handle Union
typearg = infer_type_arguments(ids, self_param_type, TypeType(original_type))[0]
Copy link
Member

Choose a reason for hiding this comment

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

Does actually Type[] accepts Tuple as an argument? I thought it works with unions, but not with tuple types. Please correct me if I am wrong. (Or is this only to cover self types in named tuples?)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I basically mirrored the restriction on the type of the parameters :) but yes, I think it is needed for namedtuples.

def make(cls: Type[Q]) -> Q:
reveal_type(cls.new) # E: Revealed type is 'def () -> Q`-1'
reveal_type(cls().new) # E: Revealed type is 'def () -> Q`-1'
reveal_type(cls().new()) # E: Revealed type is 'Q`-1'
Copy link
Member

Choose a reason for hiding this comment

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

I would add more tests like in the original issue, i.e. with classes and @classmethod.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm not sure I understand. Can you elaborate? I thought the test for D above (line 226) is exactly the same as in the original issue.

Copy link
Member

Choose a reason for hiding this comment

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

Yes, sorry, GitHub just cut @classmethod for me.

def make(cls: Type[Q]) -> Q:
reveal_type(cls.new) # E: Revealed type is 'def () -> Q`-1'
reveal_type(cls().new) # E: Revealed type is 'def () -> Q`-1'
reveal_type(cls().new()) # E: Revealed type is 'Q`-1'
Copy link
Member

Choose a reason for hiding this comment

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

Yes, sorry, GitHub just cut @classmethod for me.

self_param_type, original_type)[0]
ids = [x.id for x in func.variables]
typearg = infer_type_arguments(ids, self_param_type, original_type)[0]
if (is_classmethod and isinstance(typearg, UninhabitedType)
Copy link
Member

Choose a reason for hiding this comment

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

OK, this seems reasonable. If there will be no objections, then I am going to merge this.

@ilevkivskyi ilevkivskyi merged commit e78768b into python:master Jun 30, 2017
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.

2 participants