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

dataclass with Generic parameter does not honor default value #12962

Closed
aha79 opened this issue Jun 9, 2022 · 4 comments
Closed

dataclass with Generic parameter does not honor default value #12962

aha79 opened this issue Jun 9, 2022 · 4 comments

Comments

@aha79
Copy link

aha79 commented Jun 9, 2022

Bug Report

A dataclass with generic field does not infer the generics type when a default is provided.

To Reproduce

@dataclass
class Data(Generic[T]):
    field: T = 1
# -> "Incompatible types in assignment (expression has type "int", variable has type "T")"  (INCORRECT, should be accepted w/o error)

reveal_type( Data(17.5).field )
#  -> Revealed type is "builtins.float*"    (CORRECT)
reveal_type( Data().field )
#  -> Revealed type is "<nothing>"    (FAILED, should be int)

Expected Behavior

The default value supplied in the dataclass should be honored. Semantically the construct is not an assignment, but a default value
in the __init__ function:

Under the hood the (autogenerated) dataclass constructor looks like this

def __init__(self, field = 1):
     self.field = field 

So when field is not provided during construction of Data instance the field is passed as an int, so the generic type T should be inferred as int (if field is omitted in constructor). In the exactly same way as T is inferred as float when the field is given explicitly in the constructor (e.g. Data(17.5).field)

Concluding, what should happen:

  • Data() -> infer T as int (from the default in dataclass) (does not work)
  • Data(val) -> infer T as same type as val (this works)

Actual Behavior

Default argument is ignored

Your Environment

  • Mypy version used: 0.960
  • Mypy command-line flags:
  • Mypy configuration options from mypy.ini (and other config files):
  • Python version used: 3.9.7
  • Operating system and version: Windows 10
@aha79 aha79 added the bug mypy got something wrong label Jun 9, 2022
@aha79
Copy link
Author

aha79 commented Jun 9, 2022

#11923 seems to be a related issue

@erictraut
Copy link

I would not expect this to work. A dataclass decorator effectively adds a synthesized __init__ method to the class. For your sample, that method would look like the following:

def __init__(self, field: T = 1) -> None: ...

If you were to explicitly create a generic class with this __init__ method, mypy would similarly reject it because concrete default argument values are not supported for generic parameters.

@aha79
Copy link
Author

aha79 commented Jun 9, 2022

I see. So the real issue is that concrete default arguments are not allowed for generic parameters. However, after looking around on this site I found that this feature seems to meet some interest and has been requested several times so far (#4236, #3737, #10854, #10504, #5802, #5273, #5464, and perhaps more)

The issue is that the proposed workaround or solution with @overload (as in #4236 (comment)) does not work for dataclasses (or at least I cannot see how this would work in my case). With dataclasses the __init__ is autogenerated and manually overwriting __init__would undermine the purpose of using dataclasses in the first place.

The things is that when writing code with generics one arrives quickly at the point where the built-in default (T=Any) is not adequate.

@AlexWaygood
Copy link
Member

This isn't supported by the current type system, so I'm closing for now; but it sounds like you may be interested in python/peps#2717

@AlexWaygood AlexWaygood closed this as not planned Won't fix, can't repro, duplicate, stale Jul 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants