Repository navigation
mypy rejects subclassing Any typed *args entries within a function #21998
Description
(No AI or LLMs were used in finding or writing up this issue.)
In Python and passing other type checkers (e.g. pyright 1.1.414 and pyrefly 1.3.1) it is ok to subclass a type passed within the *args variadic argument which is typed as Any, but mypy 2.3.1 and recent master seems to reject this.
E.g. the following Python program runs fine and typechecks via pyright 1.1.414 and pyrefly 1.3.1
(btw if you have an objection to this on the basis of the intermediate x variable, please also see the example pair at the end of the issue showing mypy will allow a keyword arg for a type to subclass but not an element of *args without an intermediate variable)
https://mypy-play.net/?gist=caa19ef606afd2b352e2e5e3fa608bca
from typing import Any
def fun_varargs_element_to_type_used_for_inherit(
*args: *tuple[int, Any],
) -> Any:
# not allowed by mypy but allowed by pyright and others
x = args[1]
class Sub(x): pass
return Sub()
s = fun_varargs_element_to_type_used_for_inherit(1, str)
print('isinstance(s, str): ', isinstance(s, str))
Per pyright 1.1.414 and pyrefly 1.3.1 it typechecks and in python 3.13.2 (and 3.12 see gist above) runs and produces valid output:
(venv) [liveuser@localhost-live mypy]$ pyright ~/examplecomplex2.py
0 errors, 0 warnings, 0 informations
(venv) [liveuser@localhost-live mypy]$ python ~/examplecomplex2.py
isinstance(s, str): True
But mypy 2.3.1 rejects it (see mypy playground link and associated gist https://mypy-play.net/?gist=caa19ef606afd2b352e2e5e3fa608bca ) .
Here are some unit test cases showing this behavior as well:
[case testVarargsArgumentTypeCheckingUsingArgumentTypeFromVarArgsForInheritanceExplicitCastOk]
# flags: --python-version 3.12
from typing import Any
def fun_explicit_cast_varargs_element_to_type_used_for_inherit(
*args: *tuple[int, Any],
):
# allowed
x : type = args[1]
class Sub(x): pass
fun_explicit_cast_varargs_element_to_type_used_for_inherit(1, str)
[builtins fixtures/tuple.pyi]
[case testVarargsArgumentTypeCheckingUsingArgumentTypeFromVarArgsForInheritance-xfail]
# flags: --python-version 3.12
from typing import Any
def fun_varargs_element_to_type_used_for_inherit(
*args: *tuple[int, Any],
):
# not allowed by mypy but allowed by pyright and others
x = args[1]
class Sub(x): pass
fun_varargs_element_to_type_used_for_inherit(1, str)
[builtins fixtures/tuple.pyi]
The first case passes, the second xfails (I marked it expected fail for now per current behavior) when it should pass it seems.
Note that passing a type via an Any typed keyword parameter is OK-ed by mypy:
https://mypy-play.net/?gist=9ff16e8bc2f873f3fe5d0dcb4ff8baeb
[liveuser@localhost-live mypy]$ cat ~/examplecomplex3.py
from typing import Any
def fun_keyword_parameter_to_type_used_for_inherit(
*args: *tuple[int, Any],
keywordarg: Any
) -> Any:
class Sub(keywordarg): pass
return Sub()
s = fun_keyword_parameter_to_type_used_for_inherit(1, 1, keywordarg=str)
print('isinstance(s, str): ', isinstance(s, str))
[liveuser@localhost-live mypy]$ python ~/examplecomplex3.py
isinstance(s, str): True
[liveuser@localhost-live mypy]$ mypy ~/examplecomplex3.py
Success: no issues found in 1 source file
But using args[1] (an element of the *args tuple directly) when Any typed to pass a type for subclassing is not allowed by mypy, while it is allowed by pyright 1.1.414 and pyrefly 1.3.1 and python:
https://mypy-play.net/?gist=d12a1ef7f71677f150d09200fadf1958
[liveuser@localhost-live mypy]$ cat ~/examplecomplex4.py
from typing import Any
def fun_varargs_element_to_type_used_for_inherit(
*args: *tuple[int, Any],
) -> Any:
# not allowed by mypy but allowed by pyright and others
class Sub(args[1]): pass
return Sub()
s = fun_varargs_element_to_type_used_for_inherit(1, str)
print('isinstance(s, str): ', isinstance(s, str))
[liveuser@localhost-live mypy]$ python ~/examplecomplex4.py
isinstance(s, str): True
[liveuser@localhost-live mypy]$ pyright ~/examplecomplex4.py
0 errors, 0 warnings, 0 informations
[liveuser@localhost-live mypy]$ mypy ~/examplecomplex4.py
/home/liveuser/examplecomplex4.py:7: error: Variable "args" is not valid as a type [valid-type]
/home/liveuser/examplecomplex4.py:7: note: See https://mypy.readthedocs.io/en/stable/common_issues.html#variables-vs-type-aliases
/home/liveuser/examplecomplex4.py:7: error: Invalid base class "args" [misc]
/home/liveuser/examplecomplex4.py:7: error: Invalid type: try using Literal[1] instead? [valid-type]
Found 3 errors in 1 file (checked 1 source file)
(Note the above typechecks fine in pyright 1.1.414 and pyrefly 1.3.1 )
- Mypy version used: 2.3.1 (and recent master)
- Mypy command-line flags: None
- Mypy configuration options from
mypy.ini(and other config files): defaults - Python version used: 3.12 and 3.13.2
Thanks so much for building this tool!
Activity
willy-b commentedon Sep 16, 2026
See as related #5865 .
willy-b commentedon Sep 21, 2026
(This came up when writing unit tests around a fix for an outright crash of MyPy reported at #21907 3 weeks ago.)
[-]Possible bug - mypy rejects subclassing `Any` typed `*args` entries within a function (OK in python; pyright and pyrefly say OK) though allowing the same from keyword parameters[/-][+]mypy rejects subclassing `Any` typed `*args` entries within a function[/+]Restore mypy core modules deleted by bad push
Restore python#21998 implementation lost in bad merge
willy-b commentedon Sep 27, 2026
anyone working on this is advised to please review #22002 to see items that came up within the review there.
@dibrinsofor , @Dextheking1 not my call on who takes this but I have separated this from #21907 (working on that revealed this to me) and will put out a fix for that first.
I would be happy to review PRs for this though as the issue reporter if someone sends them.
willy-b commentedon Oct 5, 2026
I think @ilevkivskyi is working on this area fwiw and will likely get to it. He just landed a PR with something very close to what I was testing in my fork to fix the crash I reported earlier at #21907 .
willy-b commentedon Oct 26, 2026
BTW, in Pyrefly with preset
basicdisabled (presetbasicis the default for the CLI tool), pyrefly also complains about subclassing explicitAnyfrom within*argsbut not for normal parameters, e.g.:Without preset basic, with https://pyrefly.org/en/docs/error-kinds/#invalid-inheritance enabled,
subclassing variables whose
reveal_typeisAnyis allowed by pyrefly (an explicitlyAnytyped parameter, as they could contain atype):https://pyrefly.org/sandbox/?project=v2.pZRBCsMgEEWvMpCFoZS6zykK3QbENpJ0oyFqobfvd7TFUAgt2SVDxuj85_tDmYcKUKXtU816QWDQh4reDAqxYBMTtBlaHpPuWLO9ZQzwyNOrdNVqBEWUr-UlXvHelVg--KUyp57O_8OfE8S9zSiIinF4ivkmcazRL2W0fOfZ0DkXqIwGJgMIY4QvEfCptw1UaWgKYfadlO92t4zSWDm4m5erDkkJXf3Qd7bwejlyzJ_HsntAEpkjsYWRSBThi00yXg
where the Pyrefly output (WITHOUT preset basic) is:
with no errors.
However, WITHOUT preset basic (with preset
basicthis is still OK), subclassing an explicitlyAnytyped*argsentry is marked with "Invalid base class:tuple[int, Any][invalid-inheritance]" (runs fine in Python), even though it also shows asAnybyreveal_typeand was explicitly typed asAnyby the user:https://pyrefly.org/sandbox/?project=v2.pZRBCoMwEEWvMtBFRKTBracodKkSbA1aaJNiEs_fn8RKpCBIdzJmQph5_x1QZp4AKuZuArJGyKd8SQU16SAg4YzsBRaE54wQqM3CwHJ_tqLcOgSvxpYKL-C2aFQgBN9hsInJMt9Rly02SRRze3W3tVot21sp9T8DHH5Mhx5YRvAbFfFhSS7gtpAJYkUal6WMll8GTnSJBVrGCfsBnsHBsYDi3KgT9CpptPZtKs6_7XoauFS813fDNx2cPO7d3D2CubfXkQ7MGlz7D3wsssf20GOePJzYpekD
above runs fine in Python and outputs
but pyrefly analysis (without preset basic), gives:
I will ask the Pyrefly team about that as well since these are two cases where
reveal_typeshows the same type (Any) and in both cases theAnywas typed explicitly, but the checker is saying one is valid to inherit from and not the other.willy-b commentedon Oct 27, 2026
For the record, here is a Pyright playground demonstration of Pyright allowing subclassing an Any typed
*argsentry (by index) without any typechecking errors (I showed above on commandline but did not produce a reproducible playground link):Code sample in https://pyright-play.net/?code=GYJw9gtgBALgngBwJYDsDmUkQWEMoCCKcAUCQCYCmwUwArigPoBuAhiO2gM6OUA2lCJRQxGMMGMSVGdLpXKNguRqgAWlEEhgAKElH0AqTlwBcUAzDoIBAbVQwANIWIBdByQCUUALQA%2BZ3AmelAglMyUrHySCJTaxjYAjC4ewQDGfKxcXFAAynQARnEg3InJZgiZXMGhliAouQXaKSTZALy0DCzsxrwCQiJiEvAxMnIKSiAqKOqaOglOXDAgKQiaItoA5EhcqIusKKmxXAtLHmYbTtu7MPuH2sdQi8seQA
As to pyrefly, they may disallow it when the basic preset is disabled (I think also unintentionally as they allow subclassing explicit Anys in other contexts),
why I re-confirmed above in the pyright playground that it is checking for valid inheritance AND specifically allowing this (behavior I think MyPy also should have (purpose of this ticket) since MyPy allows explicitly Any typed variables to be subclassed, just not when indexed into
*args, which seems to be a bug).Thanks