Skip to content

Commit

Permalink
[PEP 695] Generate error if new-style type alias used as base class
Browse files Browse the repository at this point in the history
  • Loading branch information
JukkaL committed Sep 19, 2024
1 parent 4554bd0 commit 25c0ea7
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 3 deletions.
15 changes: 15 additions & 0 deletions mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -1824,6 +1824,8 @@ def analyze_class(self, defn: ClassDef) -> None:
defn, bases, context=defn
)

self.check_type_alias_bases(bases)

for tvd in tvar_defs:
if isinstance(tvd, TypeVarType) and any(
has_placeholder(t) for t in [tvd.upper_bound] + tvd.values
Expand Down Expand Up @@ -1895,6 +1897,19 @@ def analyze_class(self, defn: ClassDef) -> None:

self.analyze_class_body_common(defn)

def check_type_alias_bases(self, bases: list[Expression]) -> None:
for base in bases:
if isinstance(base, IndexExpr):
base = base.base
if (
isinstance(base, RefExpr)
and isinstance(base.node, TypeAlias)
and base.node.python_3_12_type_alias
):
self.fail(
'Type alias defined using "type" statement not valid as base class', base
)

def setup_type_vars(self, defn: ClassDef, tvar_defs: list[TypeVarLikeType]) -> None:
defn.type_vars = tvar_defs
defn.info.type_vars = []
Expand Down
38 changes: 35 additions & 3 deletions test-data/unit/check-python312.test
Original file line number Diff line number Diff line change
Expand Up @@ -591,6 +591,40 @@ a4: A4
reveal_type(a4) # N: Revealed type is "Union[builtins.int, builtins.str]"
[builtins fixtures/type.pyi]

[case testPEP695TypeAliasNotValidAsBaseClass]
# flags: --enable-incomplete-feature=NewGenericSyntax
from typing import TypeAlias

import m

type A1 = int
class Bad1(A1): # E: Type alias defined using "type" statement not valid as base class
pass

type A2[T] = list[T]
class Bad2(A2[int]): # E: Type alias defined using "type" statement not valid as base class
pass

class Bad3(m.A1): # E: Type alias defined using "type" statement not valid as base class
pass

class Bad4(m.A2[int]): # E: Type alias defined using "type" statement not valid as base class
pass

B1 = int
B2 = list
B3: TypeAlias = int
class Good1(B1): pass
class Good2(B2[int]): pass
class Good3(list[A1]): pass
class Good4(list[A2[int]]): pass
class Good5(B3): pass

[file m.py]
type A1 = str
type A2[T] = list[T]
[typing fixtures/typing-medium.pyi]

[case testPEP695TypeAliasWithUnusedTypeParams]
# flags: --enable-incomplete-feature=NewGenericSyntax
type A[T] = int
Expand Down Expand Up @@ -637,9 +671,7 @@ class D: pass

type A = C

# Note that this doesn't actually work at runtime, but we currently don't
# keep track whether a type alias is valid in various runtime type contexts.
class D(A):
class D(A): # E: Type alias defined using "type" statement not valid as base class
pass

class C: pass
Expand Down

0 comments on commit 25c0ea7

Please sign in to comment.