DEV Community

Dex
Dex

Posted on

mypy rejected subclassing an inferred-Any variable. The fix is deferred, not special-cased.

mypy accepted this:

from typing import Any

def f(x: Any):
    class Sub(x): pass
Enter fullscreen mode Exit fullscreen mode

It rejected this:

def f(*args: *tuple[int, Any]) -> Any:
    x = args[1]
    class Sub(x): pass
Enter fullscreen mode Exit fullscreen mode

Same variable, same Any. The difference is when the type is known. Semantic analysis runs before type inference. When a base class is a variable with no inferred type yet, the analyser saw Var.type is None and reported it invalid, early, before inference ever got a say.
The fix does not special-case Any. It defers the verdict. A new DeferredBaseClassVar exception fires when a base-class variable has no inferred type yet, on the base-class analysis path only. analyze_base_classes catches it, treats the base as Any provisionally so MRO computation proceeds, and records it for the checker to settle once inference is done. The premature --disallow-subclassing-any error is skipped for provisional bases for the same reason: you cannot grade a type that does not exist yet.
The general point is the one that keeps showing up in type checkers: an error raised in the wrong phase is a false positive, even when the check itself is correct. Fix the phase, not the check.
Since the first version, the deferred-base handling gained support for a second subscript and for string subscripts, pushed 2026-10-29. The PR is still open, not merged.
PR: python/mypy#22037. Fixes #21998.

Top comments (0)