Skip to content

Commit c37d972

Browse files
picnixzhauntsaninja
authored andcommitted
Fix type comments crash inside generic definitions (#16849)
Closes #16649 It's the first time I am contributing to mypy so I am not very familiar with how it works entirely behind the scene. The issue that I had is that a crash happens when using tuple type comments inside functions/classes that depend on a *constrained* type variable. After investigation, the reason is that the type checker generates all possible definitions (since constraints are known) and expands the functions definitions and bodies accordingly. However, by doing so, a tuple type comment ('# type: (int, float)') would have a FakeInfo, so `ExpandTypeVisitor` would fail since it queries `t.type.fullname`. By the way, feel free to change where my test should lie.
1 parent d39f023 commit c37d972

File tree

2 files changed

+37
-1
lines changed

2 files changed

+37
-1
lines changed

mypy/expandtype.py

+11-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
from typing import Final, Iterable, Mapping, Sequence, TypeVar, cast, overload
44

5-
from mypy.nodes import ARG_STAR, Var
5+
from mypy.nodes import ARG_STAR, FakeInfo, Var
66
from mypy.state import state
77
from mypy.types import (
88
ANY_STRATEGY,
@@ -208,6 +208,16 @@ def visit_erased_type(self, t: ErasedType) -> Type:
208208

209209
def visit_instance(self, t: Instance) -> Type:
210210
args = self.expand_types_with_unpack(list(t.args))
211+
212+
if isinstance(t.type, FakeInfo):
213+
# The type checker expands function definitions and bodies
214+
# if they depend on constrained type variables but the body
215+
# might contain a tuple type comment (e.g., # type: (int, float)),
216+
# in which case 't.type' is not yet available.
217+
#
218+
# See: https://github.com/python/mypy/issues/16649
219+
return t.copy_modified(args=args)
220+
211221
if t.type.fullname == "builtins.tuple":
212222
# Normalize Tuple[*Tuple[X, ...], ...] -> Tuple[X, ...]
213223
arg = args[0]

test-data/unit/check-typevar-values.test

+26
Original file line numberDiff line numberDiff line change
@@ -706,3 +706,29 @@ Func = Callable[[], T]
706706

707707
class A: ...
708708
class B: ...
709+
710+
[case testTypeCommentInGenericTypeWithConstrainedTypeVar]
711+
from typing import Generic, TypeVar
712+
713+
NT = TypeVar("NT", int, float)
714+
715+
class Foo1(Generic[NT]):
716+
p = 1 # type: int
717+
718+
class Foo2(Generic[NT]):
719+
p, q = 1, 2.0 # type: (int, float)
720+
721+
class Foo3(Generic[NT]):
722+
def bar(self) -> None:
723+
p = 1 # type: int
724+
725+
class Foo4(Generic[NT]):
726+
def bar(self) -> None:
727+
p, q = 1, 2.0 # type: (int, float)
728+
729+
def foo3(x: NT) -> None:
730+
p = 1 # type: int
731+
732+
def foo4(x: NT) -> None:
733+
p, q = 1, 2.0 # type: (int, float)
734+
[builtins fixtures/tuple.pyi]

0 commit comments

Comments
 (0)