Skip to content

Commit 583c5f7

Browse files
authored
Allow type parameters reusing the name missing from current module (#20081)
Fixes #18507. Fixes #19526. Fixes #19946 (already closed without reproducer, but star imports may cause such issues, `testPEP695TypeVarNameClashStarImport` fails on current master). Even if a type parameter is reusing the name from outer scope, it still cannot be a redefinition, so we can safely store it even in presence of unresolved star imports or variables that do not refer to a type.
1 parent c2a82b9 commit 583c5f7

File tree

2 files changed

+44
-2
lines changed

2 files changed

+44
-2
lines changed

mypy/semanal.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1794,7 +1794,9 @@ def push_type_args(
17941794
if self.is_defined_type_param(p.name):
17951795
self.fail(f'"{p.name}" already defined as a type parameter', context)
17961796
else:
1797-
self.add_symbol(p.name, tv, context, no_progress=True, type_param=True)
1797+
assert self.add_symbol(
1798+
p.name, tv, context, no_progress=True, type_param=True
1799+
), "Type parameter should not be discarded"
17981800

17991801
return tvs
18001802

@@ -6830,6 +6832,7 @@ def add_symbol_table_node(
68306832
else:
68316833
# see note in docstring describing None contexts
68326834
self.defer()
6835+
68336836
if (
68346837
existing is not None
68356838
and context is not None
@@ -6849,7 +6852,9 @@ def add_symbol_table_node(
68496852
self.add_redefinition(names, name, symbol)
68506853
if not (isinstance(new, (FuncDef, Decorator)) and self.set_original_def(old, new)):
68516854
self.name_already_defined(name, context, existing)
6852-
elif name not in self.missing_names[-1] and "*" not in self.missing_names[-1]:
6855+
elif type_param or (
6856+
name not in self.missing_names[-1] and "*" not in self.missing_names[-1]
6857+
):
68536858
names[name] = symbol
68546859
if not no_progress:
68556860
self.progress = True

test-data/unit/check-python312.test

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1228,6 +1228,43 @@ class C[T]:
12281228
def f[S, S](x: S) -> S: # E: "S" already defined as a type parameter
12291229
return x
12301230

1231+
[case testPEP695TypeVarNameClashNoCrashForwardReference]
1232+
# https://github.com/python/mypy/issues/18507
1233+
from typing import TypeVar
1234+
T = TypeVar("T", bound=Foo) # E: Name "Foo" is used before definition
1235+
1236+
class Foo: ...
1237+
class Bar[T]: ...
1238+
1239+
[case testPEP695TypeVarNameClashNoCrashDeferredSymbol]
1240+
# https://github.com/python/mypy/issues/19526
1241+
T = Unknown # E: Name "Unknown" is not defined
1242+
1243+
class Foo[T]: ...
1244+
class Bar[*T]: ...
1245+
class Baz[**T]: ...
1246+
[builtins fixtures/tuple.pyi]
1247+
1248+
[case testPEP695TypeVarNameClashTypeAlias]
1249+
type Tb = object
1250+
type Ta[Tb] = 'B[Tb]'
1251+
class A[Ta]: ...
1252+
class B[Tb](A[Ta]): ...
1253+
1254+
[case testPEP695TypeVarNameClashStarImport]
1255+
# Similar to
1256+
# https://github.com/python/mypy/issues/19946
1257+
import a
1258+
1259+
[file a.py]
1260+
from b import *
1261+
class Foo[T]: ...
1262+
1263+
[file b.py]
1264+
from a import *
1265+
class Bar[T]: ...
1266+
[builtins fixtures/tuple.pyi]
1267+
12311268
[case testPEP695ClassDecorator]
12321269
from typing import Any
12331270

0 commit comments

Comments
 (0)