Skip to content

Incorrect error in factory function on a dataclass #5263

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

Closed
wkschwartz opened this issue Jun 21, 2018 · 3 comments · Fixed by #5646
Closed

Incorrect error in factory function on a dataclass #5263

wkschwartz opened this issue Jun 21, 2018 · 3 comments · Fixed by #5646
Assignees
Labels
bug mypy got something wrong priority-1-normal topic-plugins The plugin API and ideas for new plugins

Comments

@wkschwartz
Copy link
Contributor

wkschwartz commented Jun 21, 2018

In Python 3.7.0rc1 and mypy 0.620+dev-5dc7454b1acb47dcbb3361c849e6113efcdbaaf2, if I save the following code to dc_test.py

from typing import Type, TypeVar
from dataclasses import dataclass

T = TypeVar('T', bound='A')

@dataclass
class A:
	@classmethod
	def make(cls: Type[T]) -> T:
		return cls()

I get the following mypy output

$ mypy dc_test.py 
dc_test.py:10: error: Incompatible return value type (got "A", expected "T")

If I comment out the @dataclass line, I get no error. I would expect to get no error with or without the @dataclass line.

@gvanrossum gvanrossum added the bug mypy got something wrong label Jun 22, 2018
@gvanrossum
Copy link
Member

Confirmed. All I can think of is that something's wrong with how class decorators are implemented in mypy.

@ilevkivskyi ilevkivskyi added priority-1-normal topic-plugins The plugin API and ideas for new plugins labels Jun 22, 2018
@ilevkivskyi
Copy link
Member

ilevkivskyi commented Jun 22, 2018

The type first argument of class methods is patched by plugins for attrs and dataclasses (because __init__ is auto-generated). It looks like this patching is not done carefully (it needs to interact well with bind_self).

@wkschwartz
Copy link
Contributor Author

Workaround until this issue is fixed

Casting the result to type T silences mypy's false positive error.

-from typing import Type, TypeVar
+from typing import Type, TypeVar, cast
 from dataclasses import dataclass

 T = TypeVar('T', bound='A')

 @dataclass
 class A:
 	@classmethod
 	def make(cls: Type[T]) -> T:
-		return cls()
+		return cast(T, cls())

@msullivan msullivan self-assigned this Sep 19, 2018
msullivan added a commit that referenced this issue Sep 19, 2018
Currently the first argument to `__new__` and classmethods is a
callable type that is constructed during semantic analysis by
typechecker code (!) that looks for the `__init__`/`__new__` methods.

This causes a number of problems, including not being able to call
`object.__new__` in a subclass's `__new__` if it took arguments
(#4190) and giving the wrong type if `__init__` appeared after the
class method (#1727).

Taking a `Type` instead lets us solve those problems, and postpone
computing the callable version of the type until typechecking if it is
needed.

This also lets us drop a bunch of plugin code that tries to fix up the
types of its cls arguments post-hoc, sometimes incorrectly (#5263).

Fixes #1727.
Fixes #4190.
Fixes #5263.
msullivan added a commit that referenced this issue Sep 21, 2018
Currently the first argument to `__new__` and classmethods is a
callable type that is constructed during semantic analysis by
typechecker code (!) that looks for the `__init__`/`__new__` methods.

This causes a number of problems, including not being able to call
`object.__new__` in a subclass's `__new__` if it took arguments
(#4190) and giving the wrong type if `__init__` appeared after the
class method (#1727).

Taking a `Type` instead lets us solve those problems, and postpone
computing the callable version of the type until typechecking if it is
needed.

This also lets us drop a bunch of plugin code that tries to fix up the
types of its cls arguments post-hoc, sometimes incorrectly (#5263).

Fixes #1727.
Fixes #4190.
Fixes #5263.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug mypy got something wrong priority-1-normal topic-plugins The plugin API and ideas for new plugins
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants