Skip to content

Inconsistent behavior on default value to generically typed method #9793

Closed
@cmekik

Description

@cmekik

Bug Report

I get an error when I add a default value to a generically typed argument for a method in a generic class. But, when I do the same thing in a slightly roundabout way, the error is not raised.

To Reproduce

In the code below, the error occurs on the default A to the argument constructor of the __init__ method for class B.

The error message is:
Incompatible default for argument "constructor" (default has type "Type[A]", argument has type "Type[T]")

Class B2, on the other hand, does not raise an error, even though I think it has essentially the same effect.

from typing import Hashable, Mapping, Generic, TypeVar, Type

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

class A:
    pass

class B(Generic[T]):

    mapping: Mapping[Hashable, T]
    constructor: Type[T]

    def __init__(
        self, 
        mapping: Mapping[Hashable, T], 
        constructor: Type[T] = A
    ) -> None:

        self.mapping = mapping
        self.constructor = constructor


class B2(Generic[T]):

    mapping: Mapping[Hashable, T]
    constructor: Type[T]

    def __init__(
        self, 
        mapping: Mapping[Hashable, T], 
        constructor: Type[T] = None
    ) -> None:

        self.mapping = mapping
        self.constructor = constructor if constructor is not None else A 

Expected Behavior

I expect A to be the default type for the type variable T while giving the user the option to subclass A if necessary. In my application, there are many possible variants of A and I would like to have one container class (represented by B/B2) that is aware of the specific mapping value type (which should not be changed after initialization). For instance, assuming A2 is a subclass of A, I expect the following not to raise an error (it does not, ignoring the issue with the default value).

a: A2 = B({1: A2}, A2).mapping[1]

Actual Behavior

I did not expect mypy to raise an error on the init method for class B. I also expected that if B raises an error so should B2, but it does not.

Your Environment

I am using mypy as my linter in visual studio code.

  • Mypy version used: 0.770
  • Mypy command-line flags: none/default
  • Mypy configuration options from mypy.ini (and other config files): default
  • Python version used: 3.7
  • Operating system and version: Ubuntu 20.04

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions