Repository navigation
Conversation
This comment has been minimized.
This comment has been minimized.
|
Thanks for the primer run — it caught a real regression, and I have fixed it. mkdocs (real regression, fixed in 4532b6d): pywin32 (pre-existing, not caused by this PR): the |
|
Diff from mypy_primer, showing the effect of this PR on open source code: pywin32 (https://github.com/mhammond/pywin32)
./pythonwin/pywin/test/_dbgscript.py: error: INTERNAL ERROR -- Please try using mypy master on GitHub:
- version: 2.5.0+dev.b83696ea8099ef3772a5a2bc2c49f2b05340c37a
+ version: 2.5.0+dev.9ba5f4332381ac1f4146c954b30ea83cf2d19493
|
Fixes #22395.
An
__init__overload with an explicitselfannotation solved the typeparameters of the class that declares it, but not those of a generic subclass
that inherits the overload:
Sub(null=True)was inferred asSub[Never, Never]instead of
Sub[int | None, int | None].The typing spec requires the class being constructed to be bound to the
self parameter
(https://typing.python.org/en/latest/spec/constructors.html#init-method).
The class being constructed here is
Sub[_S, _G], and binding it toBase[int | None, int | None]solves_Sand_G.This is the
__init__counterpart of the__new__fix in #21441. That PRmade the explicit
__new__return type actually be used, but only for theclass where it is defined; a generic subclass had the same gap
(
E()forclass E(D[_S])wasE[Never]), so this PR fixes both pathsin the same place.
The fix is in
mypy/typeops.py::class_callable: when the explicit selfannotation (for
__init__) or return annotation (for__new__) is aninstance of a superclass of the class being constructed, solve the
constructed class's type variables from it (new helper
map_explicit_type_to_class), and validate the solution by mapping it backup to the annotated class. If the annotation cannot be mapped (for example
the subclass fixes a type variable to a different type), the previous
behavior is kept. For
__new__, the mapping is only attempted when theannotation refers to the class where
__new__is defined, so the behaviorintroduced in #21441 for explicit return types naming other classes is
unchanged.
This also resolves the known limitation documented in
testSelfTypeRestrictedMethodOverloadInit, where the test noted there was"no way to map the overloaded
__init__to subtype":SubP(use_str=True)is now
SubP[str]instead ofSubP[Any]. That test's expectations areupdated accordingly.
Tests run locally:
pytest mypy/test/testcheck.py -k "testSelfAnnotatedInitOverloadGenericSubclass or testNewReturnTypeGenericSubclass or testOverloadedGenericInit or testNewReturnType9 or testNewReturnType5": 5 passed. The two new tests fail without the fix and pass with it.pytest mypy/test/testcheck.py::TypeCheckSuite::check-generics.test mypy/test/testcheck.py::TypeCheckSuite::check-classes.test: 818 passed, 2 skipped, 1 xfailed.pytest mypy/test/testcheck.py: 8318 passed, 27 skipped, 7 xfailed.ruff checkandruff format --checkpass on the changed file;blackapplied per repo config.mypy --config-file mypy_self_check.ini mypy/typeops.py: no errors.Disclosure: this contribution was developed with the assistance of an LLM
code assistant; the fix, the tests, and the results above were verified by
running them locally.