Repository: python/mypy

Issue:
`name-defined` error lets Mypy forget `TypedDict` was wrapped in `Unpack`
```python
from typing import overload, TypedDict, Unpack

class TD(TypedDict, total=False):
    x: float
    y: str

@overload
def f(*, x: float) -> None: ...
@overload
def f(*, y: str) -> None: ...
def f(**kwargs: Unpack[TD]) -> None:  # error: Overloaded function implementation does not accept all possible arguments of signature 1 [misc]
                                      # error: Overloaded function implementation does not accept all possible arguments of signature 1 [misc]
    y  # error: Name "y" is not defined

class A:
    def f(self, *, x: float) -> None: ...
class B(A):
    def f(self, **kwargs: Unpack[TD]) -> None:  # error: Argument 1 of "f" is incompatible with supertype "A"; supertype defines the argument type as "float"  [override]
        y  # type: ignore[name-defined]
reveal_type(B.f)  # note: Revealed type is "def (self: temp.B, **kwargs: TypedDict('temp.TD', {'x'?: builtins.float, 'y'?: builtins.str}))"
B().f(x=1.0)  # error: Argument "x" to "f" of "B" has incompatible type "float"; expected "TD"  [arg-type]
```


Discussion:

Resolving patch:
diff --git a/mypy/typeanal.py b/mypy/typeanal.py
--- a/mypy/typeanal.py
+++ b/mypy/typeanal.py
@@ -1007,7 +1007,7 @@ def visit_parameters(self, t: Parameters) -> Type:
     def visit_callable_type(self, t: CallableType, nested: bool = True) -> Type:
         # Every Callable can bind its own type variables, if they're not in the outer scope
         with self.tvar_scope_frame():
-            unpacked_kwargs = False
+            unpacked_kwargs = t.unpack_kwargs
             if self.defining_alias:
                 variables = t.variables
             else:


Test patch:
diff --git a/test-data/unit/check-typeddict.test b/test-data/unit/check-typeddict.test
--- a/test-data/unit/check-typeddict.test
+++ b/test-data/unit/check-typeddict.test
@@ -3487,3 +3487,41 @@ class A(Generic[T]):
         return self.a(x=1)
 [typing fixtures/typing-full.pyi]
 [builtins fixtures/tuple.pyi]
+
+[case testNameUndefinedErrorDoesNotLoseUnpackedKWArgsInformation]
+from typing import overload
+from typing_extensions import TypedDict, Unpack
+
+class TD(TypedDict, total=False):
+    x: int
+    y: str
+
+@overload
+def f(self, *, x: int) -> None: ...
+@overload
+def f(self, *, y: str) -> None: ...
+def f(self, **kwargs: Unpack[TD]) -> None:
+    z  # E: Name "z" is not defined
+
+@overload
+def g(self, *, x: float) -> None: ...
+@overload
+def g(self, *, y: str) -> None: ...
+def g(self, **kwargs: Unpack[TD]) -> None:  # E: Overloaded function implementation does not accept all possible arguments of signature 1
+    z  # E: Name "z" is not defined
+
+class A:
+    def f(self, *, x: int) -> None: ...
+    def g(self, *, x: float) -> None: ...
+class B(A):
+    def f(self, **kwargs: Unpack[TD]) -> None:
+        z  # E: Name "z" is not defined
+    def g(self, **kwargs: Unpack[TD]) -> None:  # E: Signature of "g" incompatible with supertype "A" \
+                                                # N:      Superclass: \
+                                                # N:          def g(self, *, x: float) -> None \
+                                                # N:      Subclass: \
+                                                # N:          def g(*, x: int = ..., y: str = ...) -> None
+        z  # E: Name "z" is not defined
+reveal_type(B.f)  # N: Revealed type is "def (self: __main__.B, **kwargs: Unpack[TypedDict('__main__.TD', {'x'?: builtins.int, 'y'?: builtins.str})])"
+B().f(x=1.0)  # E: Argument "x" to "f" of "B" has incompatible type "float"; expected "int"
+[builtins fixtures/primitives.pyi]