Repository: python/mypy

Issue:
Regression with generic TypeVar inheritance
**Bug Report**
Regression added with #12590. Currently also part of the v0.950 release branch.
/CC: @JukkaL

**To Reproduce**

```py
from dataclasses import dataclass
from typing import Any, Callable, Generic, TypeVar


T = TypeVar("T")

@dataclass
class Parent(Generic[T]):
    f: Callable[[T], Any]

@dataclass
class Child(Parent[T]): ...


class A: ...
def func(obj: A) -> bool: ...

reveal_type(Child[A](func).f)
```

**Expected Behavior**

```
test.py:18: note: Revealed type is "def (test.A) -> Any"
```

**Actual Behavior**

```
test.py:18: note: Revealed type is "def (T`1) -> Any"
test.py:18: error: Argument 1 to "Child" has incompatible type "Callable[[A], bool]"; expected "Callable[[T], Any]"
```

**Your Environment**

- Mypy version used: mypy 0.960+dev.50213b520b131fc1dd037dfcc1938beba1f4e177


Discussion:

Resolving patch:
diff --git a/mypy/plugins/dataclasses.py b/mypy/plugins/dataclasses.py
--- a/mypy/plugins/dataclasses.py
+++ b/mypy/plugins/dataclasses.py
@@ -19,6 +19,7 @@
     get_proper_type, AnyType, TypeOfAny,
 )
 from mypy.server.trigger import make_wildcard_trigger
+from mypy.state import state
 
 # The set of decorators that generate dataclasses.
 dataclass_makers: Final = {
@@ -101,10 +102,8 @@ def deserialize(
     def expand_typevar_from_subtype(self, sub_type: TypeInfo) -> None:
         """Expands type vars in the context of a subtype when an attribute is inherited
         from a generic super type."""
-        if not isinstance(self.type, TypeVarType):
-            return
-
-        self.type = map_type_from_supertype(self.type, sub_type, self.info)
+        if self.type is not None:
+            self.type = map_type_from_supertype(self.type, sub_type, self.info)
 
 
 class DataclassTransformer:
@@ -402,7 +401,11 @@ def collect_attributes(self) -> Optional[List[DataclassAttribute]]:
                 name: str = data["name"]
                 if name not in known_attrs:
                     attr = DataclassAttribute.deserialize(info, data, ctx.api)
-                    attr.expand_typevar_from_subtype(ctx.cls.info)
+                    # TODO: We shouldn't be performing type operations during the main
+                    #       semantic analysis pass, since some TypeInfo attributes might
+                    #       still be in flux. This should be performed in a later phase.
+                    with state.strict_optional_set(ctx.api.options.strict_optional):
+                        attr.expand_typevar_from_subtype(ctx.cls.info)
                     known_attrs.add(name)
                     super_attrs.append(attr)
                 elif all_attrs:


Test patch:
diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test
--- a/test-data/unit/check-dataclasses.test
+++ b/test-data/unit/check-dataclasses.test
@@ -1568,3 +1568,54 @@ class B:
 class Derived(A, B):
     pass
 [builtins fixtures/dataclasses.pyi]
+
+[case testDataclassGenericInheritance2]
+# flags: --python-version 3.7
+from dataclasses import dataclass
+from typing import Any, Callable, Generic, TypeVar, List
+
+T = TypeVar("T")
+S = TypeVar("S")
+
+@dataclass
+class Parent(Generic[T]):
+    f: Callable[[T], Any]
+
+@dataclass
+class Child(Parent[T]): ...
+
+class A: ...
+def func(obj: A) -> bool: ...
+
+reveal_type(Child[A](func).f)  # N: Revealed type is "def (__main__.A) -> Any"
+
+@dataclass
+class Parent2(Generic[T]):
+    a: List[T]
+
+@dataclass
+class Child2(Generic[T, S], Parent2[S]):
+    b: List[T]
+
+reveal_type(Child2([A()], [1]).a)  # N: Revealed type is "builtins.list[__main__.A]"
+reveal_type(Child2[int, A]([A()], [1]).b)  # N: Revealed type is "builtins.list[builtins.int]"
+[builtins fixtures/dataclasses.pyi]
+
+[case testDataclassInheritOptionalType]
+# flags: --python-version 3.7 --strict-optional
+from dataclasses import dataclass
+from typing import Any, Callable, Generic, TypeVar, List, Optional
+
+T = TypeVar("T")
+
+@dataclass
+class Parent(Generic[T]):
+    x: Optional[str]
+@dataclass
+class Child(Parent):
+    y: Optional[int]
+Child(x=1, y=1)  # E: Argument "x" to "Child" has incompatible type "int"; expected "Optional[str]"
+Child(x='', y='')  # E: Argument "y" to "Child" has incompatible type "str"; expected "Optional[int]"
+Child(x='', y=1)
+Child(x=None, y=None)
+[builtins fixtures/dataclasses.pyi]