Tuesday, 31 March 2026

Mypy 1.20 Released

We’ve just uploaded mypy 1.20.0 to the Python Package Index (PyPI). Mypy is a static type checker for Python. This release includes new features, performance improvements and bug fixes. You can install it as follows:

python3 -m pip install -U mypy

You can read the full documentation for this release on Read the Docs.

Planned Changes to Defaults and Flags in Mypy 2.0

As a reminder, we are planning to enable --local-partial-types by default in mypy 2.0, which will likely be the next feature release. This will often require at least minor code changes. This option is implicitly enabled by mypy daemon, so this makes the behavior of daemon and non-daemon modes consistent.

Note that this release improves the compatibility of --local-partial-types significantly to make the switch easier (see below for more).

This can also be configured in a mypy configuration file (use False to disable):

local_partial_types = True

For more information, refer to the documentation.

We will also enable --strict-bytes by default in mypy 2.0. This usually requires at most minor code changes to adopt. For more information, refer to the documentation.

Finally, --allow-redefinition-new will be renamed to --allow-redefinition. If you want to continue using the older --allow-redefinition semantics which are less flexible (e.g. limited support for conditional redefinitions), you can switch to --allow-redefinition-old, which is currently supported as an alias to the legacy --allow-redefinition behavior. To use --allow-redefinition in the upcoming mypy 2.0, you can't use --no-local-partial-types. For more information, refer to the documentation.

Better Type Narrowing

Mypy's implementation of narrowing has been substantially reworked. Mypy will now narrow more aggressively, more consistently, and more correctly. In particular, you are likely to notice new narrowing behavior in equality expressions (==), containment expressions (in), match statements, and additional expressions providing type guards.

Note that mypy (and other Python type checkers) do not model the potential for various non-local operations to invalidate narrowing assumptions. This means mypy may conclude that some of your code is unreachable and avoid further checking of it. The --warn-unreachable flag is useful for highlighting these cases. To reset narrowing, you can insert dummy reassignments, for instance var = var will reset all narrowing of var.attr.

Future work includes better narrowing on initial assignments, more narrowing to Literal types, and better checking of unreachable code.

Contributed by Shantanu Jain.

  • Rework narrowing logic for equality and identity (Shantanu, PR 20492)
  • Refactor equality and identity narrowing for clarity (Shantanu, PR 20595)
  • Treat NotImplemented as a singleton type (Shantanu, PR 20601)
  • Improve narrowing logic for Enum int and str subclasses (Shantanu, PR 20609)
  • Narrow types based on collection containment (Shantanu, PR 20602)
  • Refactor and improve narrowing for type(x) == t checks (Shantanu, PR 20634)
  • Narrow for type expr comparisons to type exprs (Shantanu, PR 20639)
  • Narrowing for comparisons against x.__class__ (Shantanu, PR 20642)
  • Better narrowing with custom equality (Shantanu, PR 20643)
  • Use a single pass for core narrowing logic, add comments (Shantanu, PR 20659)
  • Narrowing for final type objects (Shantanu, PR 20661)
  • Avoid narrowing type[T] (Shantanu, PR 20662)
  • Avoid widening to Any for checks like type(x) is type(y: Any) (Shantanu, PR 20663)
  • Preserve some lost narrowing, cleanup (Shantanu, PR 20674)
  • Fix narrowing related code for types with overloaded __new__ (Shantanu, PR 20676)
  • Fix isinstance with unions of tuples (Shantanu, PR 20677)
  • Fix regression to chained containment (Shantanu, PR 20688)
  • Improve else handling with custom equality (Shantanu, PR 20692)
  • Better model runtime in isinstance and type checks (Shantanu, PR 20675)
  • Use --warn-unreachable and --strict-equality in more tests (Shantanu, PR 20707)
  • Model exact narrowing with type(x) checks (Shantanu, PR 20703)
  • Short term fix for bytes narrowing (Shantanu, PR 20704)
  • Preserve narrowing in unreachable code (Shantanu, PR 20710)
  • Fix bug when narrowing union containing custom eq against custom eq (Shantanu, PR 20754)
  • Fix narrowing for unions (Shantanu, PR 20728)
  • Unsoundly narrow away from None with custom eq (Shantanu, PR 20756)
  • Improve narrowing with numeric types (Shantanu, PR 20727)
  • Fix narrowing with final type objects (Shantanu, PR 20743)
  • Further improve match statement narrowing against unions (Shantanu, PR 20744)
  • Avoid narrowing to NewType (Shantanu, PR 20766)
  • Better match narrowing for irrefutable sequence patterns (Shantanu, PR 20782)
  • Remove prohibit_none_typevar_overlap (Shantanu, PR 20864)
  • Fix match statement narrowing reachability for tuples (Shantanu, PR 20896)
  • Better handling of generics when narrowing (Shantanu, PR 20863)
  • Better match narrowing for type objects (Shantanu, PR 20872)
  • Narrow Callable generic return types (Shantanu, PR 20868)
  • Better match narrowing for unions of type objects (Shantanu, PR 20905)
  • Improve reachability in narrowing logic (Shantanu, PR 20660)
  • Better match narrowing for irrefutable mapping patterns (Shantanu, PR 20906)
  • Fix match statement semantic reachability (Shantanu, PR 20968)
  • Add some additional narrowing test cases (Shantanu, PR 20598)
  • Move tests to check-narrowing , improve them slightly (Shantanu, PR 20637)
  • Add more tests for narrowing logic (Shantanu, PR 20672)
  • More testing related improvements and updates (Shantanu, PR 20709)
  • Add --warn-unreachable to more tests (Shantanu, PR 20977)

Drop Support for Python 3.9

Mypy no longer supports running with Python 3.9, which has reached end of life. When running mypy with Python 3.10+, it is still possible to type check code that needs to support Python 3.9 with the --python-version 3.9 argument. Support for this will be dropped in the first half of 2026!

Contributed by Marc Mueller (PR 20156).

Mypyc Accelerated Mypy Wheels for ARM Windows and Free Threading

For best performance, mypy can be compiled to C extension modules using mypyc. This makes mypy 3-5x faster than when interpreted with pure Python. We now build and upload mypyc accelerated mypy wheels for win_arm64 and cp314t-... to PyPI, making it easy for Windows users on ARM and those using the free theading builds for Python 3.14 to realise this speedup -- just pip install the latest mypy.

Contributed by Marc Mueller (PR mypy_mypyc-wheels#106, PR mypy_mypyc-wheels#110).

Improved Compatibility for Local Partial Types

Compatibility between mypy's default behavior and the --local-partial-types flag is now improved. This improves compatibility between mypy daemon and non-daemon modes, since the mypy daemon requires local partial types to be enabled.

In particular, code like this now behaves consistently independent of whether local partial types are enabled or not:

x = None

def foo() -> None:
    global x
    x = 1

# The inferred type of 'x' is always 'int | None'.

Also, we are planning to turn local partial types on by default in mypy 2.0 (to be released soon), and this makes the change much less disruptive. Explicitly disabling local partial types will continue to be supported, but the support will likely be deprecated and removed eventually, as the legacy behavior is hard to support together with some important changes we are working on, in addition to being incompatible with the mypy daemon.

This feature was contributed by Ivan Levkivskyi (PR 20938).

Python 3.14 T-String Support (PEP 750)

Mypy now supports t-strings that were introduced in Python 3.14.

  • Add support for Python 3.14 t-strings (PEP 750) (Neil Schemenauer and Brian Schubert, PR 20850)
  • Add implicit module dependency if using t-string (Jukka Lehtosalo, PR 20900)

Experimental New Parser

If you install mypy using pip install mypy[native-parser] and run mypy with --native-parser, you can experiment with a new Python parser. It is based on the Ruff parser, and it's more efficient than the default parser. It will also enable access to all Python syntax independent of which Python version you use to run mypy. The new parser is still not feature-complete and has known issues.

Related changes:

  • Add work-in-progress implementation of a new Python parser (Jukka Lehtosalo, PR 20856)
  • Skip redundant analysis pass when using the native parser (Ivan Levkivskyi, PR 21015)
  • Add t-string support to native parser (Ivan Levkivskyi, PR 21007)
  • Handle hex bigint literals in native parser (Ivan Levkivskyi, PR 20988)
  • Pass all relevant options to native parser (Ivan Levkivskyi, PR 20984)
  • Support @no_type_check with native parser (Ivan Levkivskyi, PR 20959)
  • Fix error code handling in native parser (Ivan Levkivskyi, PR 20952)
  • Add ast-serialize as an optional dependency (Ivan Levkivskyi, PR 21028)
  • Use native-parser instead of native-parse for optional dependency (Jukka Lehtosalo, PR 21115)

Performance Improvements

Mypy now uses a binary cache format (fixed-format cache) by default to speed up incremental checking. You can still use --no-fixed-format-cache to use the legacy JSON cache format, but we will remove the JSON cache format in a future release. Mypy includes a tool to convert individual fixed-format cache files (.ff) to the JSON format to make it possible to inspect cache contents:

python -m mypy.exportjson <path> ...

If the SQLite cache is enabled, you will first need to convert the SQLite cache into individual files using the misc/convert-cache.py tool available in the mypy GitHub repository. You can also disable the SQLite cache using --no-sqlite-cache.

The SQLite cache (--sqlite-cache) is now enabled by default. It improves mypy performance significantly in certain environments where slow file system operations used to be a bottleneck.

List of all performance improvements (for mypyc improvements there is a separate section below):

  • Flip fixed-format cache to on by default (Ivan Levkivskyi, PR 20758)
  • Enable --sqlite-cache by default (Shantanu, PR 21041)
  • Save work on emitting ignored diagnostics (Shantanu, PR 20621)
  • Skip logging and stats collection calls if they are no-ops (Jukka Lehtosalo, PR 20839)
  • Speed up large incremental builds by optimizing internal state construction (Jukka Lehtosalo, PR 20838)
  • Speed up suppressed dependencies options processing (Jukka Lehtosalo, PR 20806)
  • Avoid path operations that need syscalls (Jukka Lehtosalo, PR 20802)
  • Use faster algorithm for topological sort (Jukka Lehtosalo, PR 20790)
  • Replace old topological sort (Jukka Lehtosalo, PR 20805)
  • Fix quadratic performance in dependency graph loading for incremental builds (Jukka Lehtosalo, PR 20786)
  • Micro-optimize transitive dependency hash calculation (Jukka Lehtosalo, PR 20798)
  • Speed up options snapshot calculation (Jukka Lehtosalo, PR 20797)
  • Micro-optimize read buffering, metastore abspath, path joining (Shantanu, PR 20810)
  • Speed up type comparisons and hashing for literal types (Shantanu, PR 20423)
  • Optimize overloaded signatures check (asce, PR 20378)
  • Avoid unnecessary work when checking deferred functions (Ivan Levkivskyi, PR 20860)
  • Improve --allow-redefinition-new performance for code with loops (Ivan Levkivskyi, PR 20862)
  • Avoid setattr/getattr with fixed format cache (Ivan Levkivskyi, PR 20826)

Improvements to Allowing Redefinitions

Mypy now allows significantly more flexible variable redefinitions when using --allow-redefinition-new. In particular, function parameters can now be redefined with a different type:

# mypy: allow-redefinition-new, local-partial-types

def process(items: list[str]) -> None:
    # Reassign parameter to a completely different type.
    # Without --allow-redefinition-new, this is a type error 
    # because list[list[str]] is not compatible with 
    # list[str].
    items = [item.split() for item in items]
    ...

In mypy 2.0, we will update --allow-redefinition to mean --allow-redefinition-new. This release adds --allow-redefinition-old as an alias of --allow-redefinition, which can be used to continue using the old redefinition behavior in mypy 2.0 and later.

List of changes:

  • Add --allow-redefinition-old as an alias of --allow-redefinition (Ivan Levkivskyi, PR 20764)
  • Allow redefinitions for function arguments (Ivan Levkivskyi, PR 20853)
  • Fix regression on redefinition in deferred loop (Ivan Levkivskyi, PR 20879)
  • Fix loop convergence with redefinitions (Ivan Levkivskyi, PR 20865)
  • Make sure new redefinition semantics only apply to inferred variables (Ivan Levkivskyi, PR 20909)
  • Fix union edge case in function argument redefinition (Ivan Levkivskyi, PR 20908)
  • Show an error when old and new redefinition are enabled in a file (Ivan Levkivskyi, PR 20920)
  • --allow-redefinition-new is no longer experimental (Jukka Lehtosalo, PR 21110)
  • Fix type inference for nested union types (Ivan Levkivskyi, PR 20912)
  • Fix type inference regression for multiple variables in loops (Ivan Levkivskyi, PR 20892)
  • Improve type inference for empty collections in conditional contexts (Ivan Levkivskyi, PR 20851)

Incremental Checking Improvements

This release includes multiple fixes to incremental type checking:

  • Invalidate cache when --enable-incomplete-feature changes (kaushal trivedi, PR 20849)
  • Add back support for warn_unused_configs (Ivan Levkivskyi, PR 20801)
  • Recover from corrupted fixed-format cache meta file (Jukka Lehtosalo, PR 20780)
  • Distinguish not found versus skipped modules (Ivan Levkivskyi, PR 20812)
  • Fix undetected submodule deletion on warm run (Ivan Levkivskyi, PR 20784)
  • Fix staleness on changed follow-imports options (Ivan Levkivskyi, PR 20773)
  • Verify indirect dependencies reachable on incremental run (Ivan Levkivskyi, PR 20735)
  • Fix indirect dependencies for protocols (Ivan Levkivskyi, PR 20752)
  • Show error locations in other modules on warm runs (Ivan Levkivskyi, PR 20635)
  • Don't read errors from cache on silent import (Sjoerd Job Postmus, PR 20509)
  • More robust fix for re-export of __all__ (Ivan Levkivskyi, PR 20487)

Fixes to Crashes

  • Fix crash on partially typed namespace package (Ivan Levkivskyi, PR 20742)
  • Fix internal error caused by the generic type alias with an unpacked list (Kai (Kazuya Ito), PR 20689)
  • Fix crash when missing format character (Shantanu, PR 20524)
  • Fix crash when passing literal values as type arguments to variadic generics (Aaron Wieczorek, PR 20543)
  • Fix crash on circular star import in incremental mode (Ivan Levkivskyi, PR 20511)
  • Fix crash with tuple unpack inside TypeVar default (Marc Mueller, PR 20456)
  • Fix crash on typevar with forward reference used in other module (Ivan Levkivskyi, PR 20334)
  • Fix crash on star import of redefinition (Ivan Levkivskyi, PR 20333)
  • Fix crash involving Unpack-ed TypeVarTuple (Shantanu, PR 20323)
  • Fix crashes caused by type variable defaults in-place modifications (Stanislav Terliakov, PR 20139)
  • Fix crash when calling len() with no arguments (Jukka Lehtosalo, PR 20774)
  • Fix crash when checking async for inside nested comprehensions (A5rocks, PR 20540)
  • Fix ParamSpec related crash (Stanislav Terliakov, PR 20119)

Mypyc: Faster Imports on macOS

Imports in native (compiled) modules that target other native modules that are compiled together are now significantly faster on macOS, especially on the first run after a compiled package has been installed. This also speeds up the first mypy run after installation/update on macOS.

This was contributed by Jukka Lehtosalo (PR 21101).

librt: Mypyc Standard Library

Mypyc now has a dedicated standard library, librt, to provide basic features that are optimized for compiled code. They are faster than corresponding Python stdlib functionality. There is no plan to replace the Python stdlib, though. We'll only include a carefully selected set of features that help with common performance bottlenecks in compiled code.

Currently, we provide librt.base64 that has optimized SIMD (Single Instruction, Multiple Data) base64 encoding and decoding functions. In future mypyc releases we are planning to add efficient data structures, string/bytes utilities, and more.

Use python3 -m pip install librt to make librt available to compiled modules. Compiled modules don't require librt unless they explicitly import librt. If you install mypy, you will also get a compatible version of librt as a dependency. We will keep librt backward compatible, so you should always be able to update to a newer version of the library.

Related changes:

  • Add minimal, experimental librt.base64 module (Jukka Lehtosalo, PR 20226)
  • Use faster base64 encode implementation in librt.base64 (Jukka Lehtosalo, PR 20237)
  • Add efficient librt.base64.b64decode (Jukka Lehtosalo, PR 20263)
  • Enable SIMD for librt.base64 on x86-64 (Jukka Lehtosalo, PR 20244)
  • Add primitive for librt.base64.b64decode (Jukka Lehtosalo, PR 20272)
  • Add urlsafe_b64encode and urlsafe_b64decode to librt.base64 (Jukka Lehtosalo, PR 20274)
  • Make librt.base64 non-experimental (Ivan Levkivskyi, PR 20783)
  • Support pyodide for Python 3.12 (Michael R. Crusoe, PR 20342)
  • Support pyodide via the NEON intrinsics (Michael R. Crusoe, PR 20316)
  • Fix librt compilation on platforms with OpenMP (Ivan Levkivskyi, PR 20583)
  • Fix cross-compiling librt by enabling x86_64 optimizations with pragmas (James Le Cuirot, PR 20815)
  • Use existing SIMD CPU dispatch by customizing build flags (Michael R. Crusoe, PR 20253)
  • Document librt and librt.base64 (Jukka Lehtosalo, PR 21114)

Mypyc: Acyclic Classes

Mypyc now supports defining acyclic native classes that don't participate in the tracing garbage collection:

from mypy_extensions import mypyc_attr

@mypyc_attr(acyclic=True)
class Item:
    def __init__(self, key: str, value: str) -> None:
        self.key = key
        self.value = value

Allocating and freeing instances of acyclic classes is faster than regular native class instances, and they use less memory, but if they participate in reference cycles, there may be memory leaks.

This was contributed by Jukka Lehtosalo (PR 20795).

Additional Mypyc Fixes and Improvements

  • Fix range loop variable off-by-one after loop exit (Vaggelis Danias, PR 21098)
  • Fix memory leak on property setter call (Piotr Sawicki, PR 21095)
  • Fix ClassVar self-references in class bodies (Vaggelis Danias, PR 21011)
  • Fix cross-module class attribute defaults causing KeyError (Vaggelis Danias, PR 21012)
  • Fix shadow vtable misalignment for @property getters/setters (Vaggelis Danias, PR 21010)
  • Fix lambda inside comprehension (Vaggelis Danias, PR 21009)
  • Use cached ASCII characters in CPyStr_GetItem (Vaggelis Danias, PR 21035)
  • Speed up int to bytes conversion (Piotr Sawicki, PR 21036)
  • Add missing primitive documentation (Jukka Lehtosalo, PR 21037)
  • Fix undefined behavior in generated C (Jukka Lehtosalo, PR 21094)
  • Fix vtable construction for deep trait inheritance (Vaggelis Danias, PR 20917)
  • Fix __init_subclass__ running before ClassVar instantiations (Vaggelis Danias, PR 20916)
  • Add support for str.lower() and str.upper() (Vaggelis Danias, PR 20948)
  • Add str.isdigit() primitive (Vaggelis Danias, PR 20893)
  • Add str.isalnum() primitive (Vaggelis Danias, PR 20852)
  • Add str.isspace() primitive (Vaggelis Danias, PR 20842)
  • Reduce memory usage when compiling large files (Vaggelis Danias, PR 20897)
  • Generate error if using Python 3.14 t-string (Jukka Lehtosalo, PR 20899)
  • Fix undefined attribute in nested coroutines (Piotr Sawicki, PR 20654)
  • Do not emit tracebacks with negative line numbers (Piotr Sawicki, PR 20641)
  • Fix crash on multiple nested decorated functions with same name (Piotr Sawicki, PR 20666)
  • Fix Final load in unreachable branches (BobTheBuidler, PR 20617)
  • Add new primitive for int.to_bytes (BobTheBuidler, PR 19674)
  • Support constant folding in f-string to str conversion (BobTheBuidler, PR 19970)
  • Implement bytes.endswith (esarp, PR 20447)
  • Fix coercion from short tagged int to fixed-width int (Jukka Lehtosalo, PR 20587)
  • Fix generation of function wrappers for decorated functions (Piotr Sawicki, PR 20584)
  • Generate function wrappers for each callable class instance (Piotr Sawicki, PR 20575)
  • Speed up ord(str[n]) by inlining (Jukka Lehtosalo, PR 20578)
  • Add inline primitives for bytes.__getitem__ (Jukka Lehtosalo, PR 20552)
  • Add primitive type for bytearray (Jukka Lehtosalo, PR 20551)
  • Fix and clean up bytearray support in primitives (Jukka Lehtosalo, PR 20550)
  • Enable --strict-bytes by default in mypyc (and require it) (Jukka Lehtosalo, PR 20548)
  • Fix exception reraising when awaiting a future (Piotr Sawicki, PR 20547)
  • Add inline primitives for BytesBuilder get item and set item (Jukka Lehtosalo, PR 20546)
  • Optimize loops over enumerate, map, zip, range, and other builtins with known lengths (BobTheBuidler, PR 19927)
  • Raise ValueError if int too big for native int type (Jukka Lehtosalo, PR 20385)
  • Fix generator regression with empty tuple (BobTheBuidler, PR 20371)
  • Improve constant folding for len() of string literals and Final values (BobTheBuidler, PR 20074)
  • Add primitive for bytes.startswith (esarp, PR 20387)
  • Fix calling async methods through vectorcall (Piotr Sawicki, PR 20393)
  • Extend loop optimization to use constant folding for determining sequence lengths (BobTheBuidler, PR 19930)
  • Wrap async functions with function-like type (Piotr Sawicki, PR 20260)
  • Add a primitive for bytes translate method (Jukka Lehtosalo, PR 20305)
  • Add primitives for bytes and str multiply (Jukka Lehtosalo, PR 20303)
  • Match int arguments to primitives with native int parameters (Jukka Lehtosalo, PR 20299)
  • Allow disabling extra flags with MYPYC_NO_EXTRA_FLAGS environment variable (James Hilliard, PR 20507)
  • Fix unsupported imports for type annotations (Lukas Geiger, PR 20390)
  • Fix unaligned memory access in librt internal helper function (Gregor Riepl, PR 20474)
  • Fix build issue (James Hilliard, PR 20510)

Removed Flags --force-uppercase-builtins and --force-union-syntax

The --force-uppercase-builtins flag was deprecated and has been a no-op since mypy 1.17.0. Since mypy has dropped support for Python 3.9, the --force-union-syntax flag is no longer necessary.

Contributed by Marc Mueller (PR 20410) and (PR 20405).

Stubgen Improvements

  • Fix mis-parsing of double colon ("::") (Jeremy Nimmer, PR 20285)

Stubtest Improvements

  • Attempt to resolve decorators from their type (Shantanu, PR 20867)
  • Fix crash on instances with redefined __class__ (sobolevn, PR 20926)
  • Improve checking of positional-only parameters in dunder methods (Brian Schubert, PR 19593)
  • Check Final variables with literal values against runtime (Vikash Kumar, PR 20858)
  • Fix duplicate errors with invalid line numbers (Joren Hammudoglu, PR 20417)
  • Ignore __conditional_annotations__ (Joren Hammudoglu, PR 20392)
  • Transparent @type_check_only types (Joren Hammudoglu, PR 20352)
  • Check runtime availability of private types not marked @type_check_only (Brian Schubert, PR 19574)

Documentation Updates

  • Document semantics of function argument redefinition (Ivan Levkivskyi, PR 20910)
  • Update common issues: document how the type ignore must come first (wyattscarpenter, PR 20886)
  • Update "type inference and annotations" (Kai (Kazuya Ito), PR 20619)
  • Document unreachability handling of return NotImplemented (wyattscarpenter, PR 20561)

Changes to Messages

  • Simpler/cleaner reveal_type() (Ivan Levkivskyi, PR 20929)
  • Use "parameter" instead of "argument" in overload error (Kai (Kazuya Ito), PR 20994)
  • Use "parameter" instead of "argument" in unpacking error (Kai (Kazuya Ito), PR 20683)
  • Use "type arguments" instead of "type parameters" for bare generics (Kai (Kazuya Ito), PR 20494)
  • Update "arguments" to "parameters" (Kai (Kazuya Ito), PR 20711)
  • Use "parameter" instead of "argument" in default value error messages (Kai (Kazuya Ito), PR 20964)
  • Update error message for parameter overlap in TypedDict (Kai (Kazuya Ito), PR 20956)
  • Correct "Duplicate argument" error messages (Kai (Kazuya Ito), PR 20957)
  • Use standard formatting for note on unexpected keyword (Ivan Levkivskyi, PR 20808)
  • Fix edge cases in pretty formatting (Ivan Levkivskyi, PR 20809)
  • Add function definition notes for missing named argument errors (Kevin Kannammalil, PR 20794)
  • Make overloaded constructors consistent in error messages (Ivan Levkivskyi, PR 20483)
  • Improve error message for invalid Python package (Shantanu, PR 20482)
  • Emit end line/column in JSON format for span tracking (Adam Turner, PR 20734)
  • Wrap callable in union syntax (Marc Mueller, PR 20406)

Other Notable Fixes and Improvements

  • Unify handling of self attributes in daemon (Ivan Levkivskyi, PR 21025)
  • Improve support for hasattr() (Ivan Levkivskyi, PR 20914)
  • Warn when @disjoint_base is used on protocols or TypedDicts (Brian Schubert, PR 21029)
  • Model tuple type aliases better (Shantanu, PR 20967)
  • Fix incorrect type inference for container literals inside loops (Ivan Levkivskyi, PR 20875)
  • Fix edge case in type comparison for type variables with narrowed bounds (Ivan Levkivskyi, PR 20874)
  • Prohibit access via class for instance-only attributes (Ivan Levkivskyi, PR 20855)
  • Update JSON export tool to support binary meta cache files (Jukka Lehtosalo, PR 20096)
  • Better handling for uncaught top-level exceptions (Ivan Levkivskyi, PR 20749)
  • Attrs field level kw_only=False overrides kw_only=True at class level (getzze, PR 20949)
  • Fix __slots__ issue with deferred base (Shantanu, PR 20573)
  • Fix deferral logic for special types (Ivan Levkivskyi, PR 20678)
  • Fix false negatives in walrus versus inference fallback logic (Ivan Levkivskyi, PR 20622)
  • Fix enum value inference with user-defined data type mixin (E. M. Bray, PR 16320)
  • Fix incorrect classification of class attributes versus enum members (Stanislav Terliakov, PR 19687)
  • Improve type inference when finding common types for callable types (Shantanu, PR 18406)
  • Remove special case for Union type context (Shantanu, PR 20610)
  • Evaluate argument expressions in runtime evaluation order (Shantanu, PR 20491)
  • Allow empty type applications for ParamSpec (A5rocks, PR 20572)
  • Make X[()] count as a type application (A5rocks, PR 20568)
  • Accept value as keyword argument in TypeAliasType (Ali Hamdan, PR 20556)
  • Avoid treating pass and ... as no-op for reachability (Shantanu, PR 20488)
  • Fix specialization leak in generic TypedDict.update() (Aaron Wieczorek, PR 20517)
  • Fix false positive redundant expression warnings with isinstance() on Any | Protocol unions (Randolf Scholz, PR 20450)
  • Fix type checking of class-scope imports accessed via self or cls (bzoracler, PR 20480)
  • Prevent synthetic intersections from leaking to module public interfaces (bzoracler, PR 20459)
  • Fix package build failure when the compiler types are not defined (Steven Pitman, PR 20429)
  • Fix --strict-equality for iteratively visited code (Christoph Tyralla, PR 19635)
  • Allow literals as kwargs dict keys (Shantanu, PR 20416)
  • Error for invalid varargs and varkwargs to Any call (Shantanu, PR 20324)
  • Fix type inference for binary operators with tuple subclasses (Randolf Scholz, PR 19046)
  • Improve type inference for ternary expressions with literals and collections (Randolf Scholz, PR 19563)
  • Do not treat match value patterns as isinstance checks (Stanislav Terliakov, PR 20146)
  • Fix noncommutative joins with bounded TypeVars (Shantanu, PR 20345)
  • Fix error location reporting for **rest patterns in match statements (Marc Mueller, PR 20407)
  • Fix matching against union of tuples (Saul Shanabrook, PR 19600)
  • Allow types.NoneType in match cases (A5rocks, PR 20383)
  • Treat Literal["xyz"] as iterable (Shantanu, PR 20347)
  • Treat functions that return None as returning None (Shantanu, PR 20350)
  • Fix str unpack type propagation, use dedicated error code (Shantanu, PR 20325)
  • Unpack unions inside tuples in except handlers (asce, PR 17762)
  • Ignore empty error codes from type: ignore (Donghoon Nam, PR 20052)
  • Make NoneType annotation error use a new error code (wyattscarpenter, PR 20222)
  • Fail with an explicit error on PyPy (Ivan Levkivskyi, PR 20384)
  • Add hidden --overwrite-union-syntax option (Marc Mueller, PR 20332)
  • Fix possibly-undefined false-positive with nesting (grayjk, PR 20276)
  • Fix spurious possibly-undefined errors in for-else with break (Łukasz Langa, PR 19696)
  • Avoid false possibly-undefined errors due to omitted unrequired else statements (Christoph Tyralla, PR 20149)
  • Fix generator expression behavior for reveal_type (michaelm-openai, PR 20594)
  • Fix error on instance property and init-only variable with the same name in a dataclass (Roberto Fernández Iglesias, PR 17219)
  • Improve error messages when __module__ or __qualname__ are used as type annotations (A5rocks, PR 20288)
  • Check for multiple type var tuples for PEP 695 (A5rocks, PR 20289)
  • Improve interaction between --local-partial-types and hashability (Shantanu, PR 20719)
  • Stop looking for .gitignore at top level of working tree (Colin Watson, PR 20775)
  • Try fixing Cygwin build (Ivan Levkivskyi, PR 20830)
  • Fix daemon dependencies in diff-cache.py tool (Jukka Lehtosalo, PR 20837)
  • Support fixed-format cache in diff-cache.py tool (Jukka Lehtosalo, PR 20827)
  • Update convert-cache.py tool to work with fixed-format caches (Ivan Levkivskyi, PR 20761)
  • Write errors to a separate cache file (Ivan Levkivskyi, PR 21022)
  • Write ignored lines to cache meta (Ivan Levkivskyi, PR 20747)
  • Serialize raw errors in cache metas (Ivan Levkivskyi, PR 20372)
  • Include misc/{diff-cache,apply-cache-diff}.py in sdist (Michael R. Crusoe, PR 21096)

Typeshed updates

Please see git log for full list of standard library typeshed stub changes.

Acknowledgements

Thanks to all mypy contributors who contributed to this release:

  • A5rocks
  • Aaron Wieczorek
  • Adam Turner
  • Ali Hamdan
  • asce
  • BobTheBuidler
  • Brent Westbrook
  • Brian Schubert
  • bzoracler
  • Chris Burroughs
  • Christoph Tyralla
  • Colin Watson
  • Donghoon Nam
  • E. M. Bray
  • Emma Smith
  • Ethan Sarp
  • George Ogden
  • getzze
  • grayjk
  • Gregor Riepl
  • Ivan Levkivskyi
  • James Hilliard
  • James Le Cuirot
  • Jeremy Nimmer
  • Joren Hammudoglu
  • Kai (Kazuya Ito)
  • kaushal trivedi
  • Kevin Kannammalil
  • Lukas Geiger
  • Łukasz Langa
  • Marc Mueller
  • Michael R. Crusoe
  • michaelm-openai
  • Neil Schemenauer
  • Piotr Sawicki
  • Randolf Scholz
  • Roberto Fernández Iglesias
  • Saul Shanabrook
  • Shantanu Jain
  • Sjoerd Job Postmus
  • sobolevn
  • Stanislav Terliakov
  • Steven Pitman
  • Vaggelis Danias
  • Vikash Kumar
  • wyattscarpenter

I’d also like to thank my employer, Dropbox, for supporting mypy development.

Friday, 28 November 2025

Mypy 1.19 Released

We’ve just uploaded mypy 1.19.0 to the Python Package Index (PyPI). Mypy is a static type checker for Python. This release includes new features, performance improvements and bug fixes. You can install it as follows:

python3 -m pip install -U mypy

You can read the full documentation for this release on Read the Docs.

Python 3.9 Support Ending Soon

This is the last mypy feature release that supports Python 3.9, which reached end of life in October 2025.

Performance Improvements

  • Switch to a more dynamic SCC processing logic (Ivan Levkivskyi, PR 20053)
  • Speed up type aliases (Ivan Levkivskyi, PR 19810)

Fixed‑Format Cache Improvements

Mypy uses a cache by default to speed up incremental runs by reusing partial results from earlier runs. Mypy 1.18 added a new binary fixed-format cache representation as an experimental feature. The feature is no longer experimental, and we are planning to enable it by default in a future mypy release (possibly 1.20), since it's faster and uses less space than the original, JSON-based cache format. Use --fixed-format-cache to enable the fixed-format cache.

Mypy now has an extra dependency on the librt PyPI package, as it's needed for cache serialization and deserialization.

Mypy ships with a tool to convert fixed-format cache files to the old JSON format. Example of how to use this:

$ python -m mypy.exportjson .mypy_cache/.../my_module.data.ff

This way existing use cases that parse JSON cache files can be supported when using the new format, though an extra conversion step is needed.

This release includes these improvements:

  • Force-discard cache if cache format changed (Ivan Levkivskyi, PR 20152)
  • Add tool to convert binary cache files to JSON (Jukka Lehtosalo, PR 20071)
  • Use more efficient serialization format for long integers in cache files (Jukka Lehtosalo, PR 20151)
  • More robust packing of floats in fixed-format cache (Ivan Levkivskyi, PR 20150)
  • Use self-descriptive cache with type tags (Ivan Levkivskyi, PR 20137)
  • Use fixed format for cache metas (Ivan Levkivskyi, PR 20088)
  • Make metas more compact; fix indirect suppression (Ivan Levkivskyi, PR 20075)
  • Use dedicated tags for most common cached instances (Ivan Levkivskyi, PR 19762)

PEP 747: Annotating Type Forms

Mypy now recognizes TypeForm[T] as a type and implements PEP 747. The feature is still experimental, and it's disabled by default. Use --enable-incomplete-feature=TypeForm to enable type forms. A type form object captures the type information provided by a runtime type expression. Example:

from typing_extensions import TypeForm

def trycastT -> T | None: ...

def example(o: object) -> None:
    # 'int | str' below is an expression that represents a type.
    # Unlike type[T], TypeForm[T] can be used with all kinds of types,
    # including union types.
    x = trycast(int | str, o)
    if x is not None:
        # Type of 'x' is 'int | str' here
        ...

This feature was contributed by David Foster (PR 19596).

Fixes to Crashes

  • Do not push partial types to the binder (Stanislav Terliakov, PR 20202)
  • Fix crash on recursive tuple with Hashable (Ivan Levkivskyi, PR 20232)
  • Fix crash related to decorated functions (Stanislav Terliakov, PR 20203)
  • Do not abort constructing TypeAlias if only type parameters hold us back (Stanislav Terliakov, PR 20162)
  • Use the fallback for ModuleSpec early if it can never be resolved (Stanislav Terliakov, PR 20167)
  • Do not store deferred NamedTuple fields as redefinitions (Stanislav Terliakov, PR 20147)
  • Discard partial types remaining after inference failure (Stanislav Terliakov, PR 20126)
  • Fix an infinite recursion bug (Stanislav Terliakov, PR 20127)
  • Fix IsADirectoryError for namespace packages when using --linecoverage-report (wyattscarpenter, PR 20109)
  • Fix an internal error when creating cobertura output for namespace package (wyattscarpenter, PR 20112)
  • Allow type parameters reusing the name missing from current module (Stanislav Terliakov, PR 20081)
  • Prevent TypeGuardedType leak from narrowing declared type as part of type variable bound (Stanislav Terliakov, PR 20046)
  • Fix crash on invalid unpack in base class (Ivan Levkivskyi, PR 19962)
  • Traverse ParamSpec prefix where we should (Ivan Levkivskyi, PR 19800)
  • Fix daemon crash related to imports (Ivan Levkivskyi, PR 20271)

Mypyc: Support for __getattr__, __setattr__, and __delattr__

Mypyc now has partial support for __getattr__, __setattr__ and __delattr__ methods in native classes.

Note that native attributes are not stored using __dict__. Setting attributes directly while bypassing __setattr__ is possible by using super().__setattr__(...) or object.__setattr__(...), but not via __dict__.

Example:

class Demo:
    _data: dict[str, str]

    def __init__(self) -> None:
        # Initialize data dict without calling our __setattr__
        super().__setattr__("_data", {})

    def __setattr__(self, name: str, value: str) -> None:
        print(f"Setting {name} = {value!r}")

        if name == "_data":
            raise AttributeError("'_data' cannot be set")

        self._data[name] = value

    def __getattr__(self, name: str) -> str:
        print(f"Getting {name}")

        try:
            return self._data[name]
        except KeyError:
            raise AttributeError(name)

d = Demo()
d.x = "hello"
d.y = "world"

print(d.x)
print(d.y)

Related PRs:

  • Generate __setattr__ wrapper (Piotr Sawicki, PR 19937)
  • Generate __getattr__ wrapper (Piotr Sawicki, PR 19909)
  • Support deleting attributes in __setattr__ wrapper (Piotr Sawicki, PR 19997)

Miscellaneous Mypyc Improvements

  • Fix __new__ in native classes with inheritance (Piotr Sawicki, PR 20302)
  • Fix crash on super in generator (Ivan Levkivskyi, PR 20291)
  • Fix calling base class async method using super() (Jukka Lehtosalo, PR 20254)
  • Fix async or generator methods in traits (Jukka Lehtosalo, PR 20246)
  • Optimize equality check with string literals (BobTheBuidler, PR 19883)
  • Fix inheritance of async defs (Jukka Lehtosalo, PR 20044)
  • Reject invalid mypyc_attr args (BobTheBuidler, PR 19963)
  • Optimize isinstance with tuple of primitive types (BobTheBuidler, PR 19949)
  • Optimize away first index check in for loops if length > 1 (BobTheBuidler, PR 19933)
  • Fix broken exception/cancellation handling in async def (Jukka Lehtosalo, PR 19951)
  • Transform object.__new__ inside __new__ (Piotr Sawicki, PR 19866)
  • Fix crash with NewType and other non-class types in incremental builds (Jukka Lehtosalo, PR 19837)
  • Optimize container creation from expressions with length known at compile time (BobTheBuidler, PR 19503)
  • Allow per-class free list to be used with inheritance (Jukka Lehtosalo, PR 19790)
  • Fix object finalization (Marc Mueller, PR 19749)
  • Allow defining a single-item free "list" for a native class (Jukka Lehtosalo, PR 19785)
  • Speed up unary "not" (Jukka Lehtosalo, PR 19774)

Stubtest Improvements

  • Check _value_ for ellipsis-valued stub enum members (Stanislav Terliakov, PR 19760)
  • Include function name in overload assertion messages (Joren Hammudoglu, PR 20063)
  • Fix special case in analyzing function signature (iap, PR 19822)
  • Improve allowlist docs with better example (sobolevn, PR 20007)

Documentation Updates

  • Update duck type compatibility: mention strict-bytes and mypy 2.0 (wyattscarpenter, PR 20121)
  • Document --enable-incomplete-feature TypeForm (wyattscarpenter, PR 20173)
  • Change the inline TypedDict example (wyattscarpenter, PR 20172)
  • Replace List with built‑in list (PEP 585) (Thiago J. Barbalho, PR 20000)
  • Improve junit documentation (wyattscarpenter, PR 19867)

Other Notable Fixes and Improvements

  • Fix annotated with function as type keyword list parameter (KarelKenens, PR 20094)
  • Fix errors for raise NotImplemented (Shantanu, PR 20168)
  • Don't let help formatter line-wrap URLs (Frank Dana, PR 19825)
  • Do not cache fast container types inside lambdas (Stanislav Terliakov, PR 20166)
  • Respect force-union-syntax flag in error hint (Marc Mueller, PR 20165)
  • Fix type checking of dict type aliases (Shantanu, PR 20170)
  • Use pretty callable formatting more often for callable expressions (Theodore Ando, PR 20128)
  • Use dummy concrete type instead of Any when checking protocol variance (bzoracler, PR 20110)
  • PEP 696: Fix swapping TypeVars with defaults (Randolf Scholz, PR 19449)
  • Fix narrowing of class pattern with union type (Randolf Scholz, PR 19517)
  • Do not emit unreachable warnings for lines that return NotImplemented (Christoph Tyralla, PR 20083)
  • Fix matching against typing.Callable and Protocol types (Randolf Scholz, PR 19471)
  • Make --pretty work better on multi-line issues (A5rocks, PR 20056)
  • More precise return types for TypedDict.get (Randolf Scholz, PR 19897)
  • Prevent false unreachable warnings for @final instances that occur when strict optional checking is disabled (Christoph Tyralla, PR 20045)
  • Check class references to catch non-existent classes in match cases (A5rocks, PR 20042)
  • Do not sort unused error codes in unused error codes warning (wyattscarpenter, PR 20036)
  • Fix [name-defined] false positive in class A[X, Y=X]: case (sobolevn, PR 20021)
  • Filter SyntaxWarnings during AST parsing (Marc Mueller, PR 20023)
  • Make untyped decorator its own error code (wyattscarpenter, PR 19911)
  • Support error codes from plugins in options (Sigve Sebastian Farstad, PR 19719)
  • Allow returning Literals in __new__ (James Hilton-Balfe, PR 15687)
  • Inverse interface freshness logic (Ivan Levkivskyi, PR 19809)
  • Do not report exhaustive-match after deferral (Stanislav Terliakov, PR 19804)
  • Make untyped_calls_exclude invalidate cache (Ivan Levkivskyi, PR 19801)
  • Add await to empty context hack (Stanislav Terliakov, PR 19777)
  • Consider non-empty enums assignable to Self (Stanislav Terliakov, PR 19779)

Typeshed updates

Please see git log for full list of standard library typeshed stub changes.

Acknowledgements

Thanks to all mypy contributors who contributed to this release:

  • A5rocks
  • BobTheBuidler
  • bzoracler
  • Chainfire
  • Christoph Tyralla
  • David Foster
  • Frank Dana
  • Guo Ci
  • iap
  • Ivan Levkivskyi
  • James Hilton-Balfe
  • jhance
  • Joren Hammudoglu
  • Jukka Lehtosalo
  • KarelKenens
  • Kevin Kannammalil
  • Marc Mueller
  • Michael Carlstrom
  • Michael J. Sullivan
  • Piotr Sawicki
  • Randolf Scholz
  • Shantanu
  • Sigve Sebastian Farstad
  • sobolevn
  • Stanislav Terliakov
  • Stephen Morton
  • Theodore Ando
  • Thiago J. Barbalho
  • wyattscarpenter

I’d also like to thank Dropbox for supporting mypy development.

Thursday, 11 September 2025

Mypy 1.18.1 Released

We’ve just uploaded mypy 1.18.1 to the Python Package Index (PyPI). Mypy is a static type checker for Python. This release includes new features, performance improvements and bug fixes. You can install it as follows:

python3 -m pip install -U mypy

You can read the full documentation for this release on Read the Docs.

Mypy Performance Improvements

Mypy 1.18.1 includes numerous performance improvements, resulting in about 40% speedup compared to 1.17 when type checking mypy itself. In extreme cases, the improvement can be 10x or higher. The list below is an overview of the various mypy optimizations. Many mypyc improvements (discussed in a separate section below) also improve performance.

Type caching optimizations have a small risk of causing regressions. When reporting issues with unexpected inferred types, please also check if --disable-expression-cache will work around the issue, as it turns off some of these optimizations.

  • Improve self check performance by 1.8% (Jukka Lehtosalo, PR 19768, 19769, 19770)
  • Optimize fixed-format deserialization (Ivan Levkivskyi, PR 19765)
  • Use macros to optimize fixed-format deserialization (Ivan Levkivskyi, PR 19757)
  • Two additional micro‑optimizations (Ivan Levkivskyi, PR 19627)
  • Another set of micro‑optimizations (Ivan Levkivskyi, PR 19633)
  • Cache common types (Ivan Levkivskyi, PR 19621)
  • Skip more method bodies in third‑party libraries for speed (Ivan Levkivskyi, PR 19586)
  • Simplify the representation of callable types (Ivan Levkivskyi, PR 19580)
  • Add cache for types of some expressions (Ivan Levkivskyi, PR 19505)
  • Use cache for dictionary expressions (Ivan Levkivskyi, PR 19536)
  • Use cache for binary operations (Ivan Levkivskyi, PR 19523)
  • Cache types of type objects (Ivan Levkivskyi, PR 19514)
  • Avoid duplicate work when checking boolean operations (Ivan Levkivskyi, PR 19515)
  • Optimize generic inference passes (Ivan Levkivskyi, PR 19501)
  • Speed up the default plugin (Jukka Lehtosalo, PRs 19385 and 19462)
  • Remove nested imports from the default plugin (Ivan Levkivskyi, PR 19388)
  • Micro‑optimize type expansion (Jukka Lehtosalo, PR 19461)
  • Micro‑optimize type indirection (Jukka Lehtosalo, PR 19460)
  • Micro‑optimize the plugin framework (Jukka Lehtosalo, PR 19464)
  • Avoid temporary set creation in subtype checking (Jukka Lehtosalo, PR 19463)
  • Subtype checking micro‑optimization (Jukka Lehtosalo, PR 19384)
  • Return early where possible in subtype check (Stanislav Terliakov, PR 19400)
  • Deduplicate some types before joining (Stanislav Terliakov, PR 19409)
  • Speed up type checking by caching argument inference context (Jukka Lehtosalo, PR 19323)
  • Optimize binding method self argument type and deprecation checks (Ivan Levkivskyi, PR 19556)
  • Keep trivial instance types/aliases during expansion (Ivan Levkivskyi, PR 19543)

Fixed‑Format Cache (Experimental)

Mypy now supports a new cache format used for faster incremental builds. It makes incremental builds up to twice as fast. The feature is experimental and currently only supported when using a compiled version of mypy. Use --fixed-format-cache to enable the new format, or fixed_format_cache = True in a configuration file.

We plan to enable this by default in a future mypy release, and we'll eventually deprecate and remove support for the original JSON-based format.

Unlike the JSON-based cache format, the new binary format is currently not easy to parse and inspect by mypy users. We are planning to provide a tool to convert fixed-format cache files to JSON, but details of the output JSON may be different from the current JSON format. If you rely on being able to inspect mypy cache files, we recommend creating a GitHub issue and explaining your use case, so that we can more likely provide support for it. (Using MypyFile.read(binary_data) to inspect cache data may be sufficient to support some use cases.)

This feature was contributed by Ivan Levkivskyi (PR 19668, 19735, 19750, 19681, 19752, 19815).

Flexible Variable Definitions: Update

Mypy 1.16.0 introduced --allow-redefinition-new, which allows redefining variables with different types, and inferring union types for variables from multiple assignments. The feature is now documented in the --help output, but the feature is still experimental.

We are planning to enable this by default in mypy 2.0, and we will also deprecate the older --allow-redefinition flag. Since the new behavior differs significantly from the older flag, we encourage users of --allow-redefinition to experiment with --allow-redefinition-new and create a GitHub issue if the new functionality doesn't support some important use cases.

This feature was contributed by Jukka Lehtosalo.

Inferred Type for Bare ClassVar

A ClassVar without an explicit type annotation now causes the type of the variable to be inferred from the initializer:

from typing import ClassVar

class Item:
    # Type of 'next_id' is now 'int' (it was 'Any')
    next_id: ClassVar = 1

    ...

This feature was contributed by Ivan Levkivskyi (PR 19573).

Disjoint Base Classes (@disjoint_base, PEP 800)

Mypy now understands disjoint bases (PEP 800): it recognizes the @disjoint_base decorator, and rejects class definitions that combine mutually incompatible base classes, and takes advantage of the fact that such classes cannot exist in reachability and narrowing logic.

This class definition will now generate an error:

# Error: Class "Bad" has incompatible disjoint bases
class Bad(str, Exception):
    ...

This feature was contributed by Jelle Zijlstra (PR 19678).

Miscellaneous New Mypy Features

  • Add --strict-equality-for-none to flag non-overlapping comparisons involving None (Christoph Tyralla, PR 19718)
  • Don’t show import‑related errors after a module‑level assert such as assert sys.platform == "linux" that is always false (Stanislav Terliakov, PR 19347)

Improvements to Match Statements

  • Add temporary named expressions for match subjects (Stanislav Terliakov, PR 18446)
  • Fix unwrapping of assignment expressions in match subject (Marc Mueller, PR 19742)
  • Omit errors for class patterns against object (Marc Mueller, PR 19709)
  • Remove unnecessary error for certain match class patterns (Marc Mueller, PR 19708)
  • Use union type for captured vars in or pattern (Marc Mueller, PR 19710)
  • Prevent final reassignment inside match case (Omer Hadari, PR 19496)

Fixes to Crashes

  • Fix crash with variadic tuple arguments to a generic type (Randolf Scholz, PR 19705)
  • Fix crash when enable_error_code in pyproject.toml has wrong type (wyattscarpenter, PR 19494)
  • Prevent crash for dataclass with PEP 695 TypeVarTuple on Python 3.13+ (Stanislav Terliakov, PR 19565)
  • Fix crash on settable property alias (Ivan Levkivskyi, PR 19615)

Experimental Free-threading Support for Mypyc

All mypyc tests now pass on free-threading Python 3.14 release candidate builds. The performance of various micro-benchmarks scale well across multiple threads.

Free-threading support is still experimental. Note that native attribute access (get and set), list item access and certain other operations are still unsafe when there are race conditions. This will likely change in the future. You can follow the area-free-threading label in the mypyc issues tracker to follow progress.

Related PRs:

  • Enable free‑threading when compiling multiple modules (Jukka Lehtosalo, PR 19541)
  • Fix list.pop on free‑threaded builds (Jukka Lehtosalo, PR 19522)
  • Make type objects immortal under free‑threading (Jukka Lehtosalo, PR 19538)

Mypyc: Support __new__

Mypyc now has rudimentary support for user-defined __new__ methods.

This feature was contributed by Piotr Sawicki (PR 19739).

Mypyc: Faster Generators and Async Functions

Generators and calls of async functions are now faster, sometimes by 2x or more.

Related PRs:

  • Speed up for loops over native generators (Jukka Lehtosalo, PR 19415)
  • Speed up native‑to‑native calls using await (Jukka Lehtosalo, PR 19398)
  • Call generator helper directly in await expressions (Jukka Lehtosalo, PR 19376)
  • Speed up generator allocation with per‑type freelists (Jukka Lehtosalo, PR 19316)

Miscellaneous Mypyc Improvements

  • Special‑case certain Enum method calls for speed (Ivan Levkivskyi, PR 19634)
  • Fix issues related to subclassing and undefined attribute tracking (Chainfire, PR 19787)
  • Fix invalid C function signature (Jukka Lehtosalo, PR 19773)
  • Speed up implicit __ne__ (Jukka Lehtosalo, PR 19759)
  • Speed up equality with optional str/bytes types (Jukka Lehtosalo, PR 19758)
  • Speed up access to empty tuples (BobTheBuidler, PR 19654)
  • Speed up calls with *args (BobTheBuidler, PRs 19623 and 19631)
  • Speed up calls with **kwargs (BobTheBuidler, PR 19630)
  • Optimize type(x), x.__class__, and <type>.__name__ (Jukka Lehtosalo, PR 19691, 19683)
  • Specialize bytes.decode for common encodings (Jukka Lehtosalo, PR 19688)
  • Speed up in operations using final fixed‑length tuples (Jukka Lehtosalo, PR 19682)
  • Optimize f‑string building from final values (BobTheBuidler, PR 19611)
  • Add dictionary set item for exact dict instances (BobTheBuidler, PR 19657)
  • Cache length when iterating over immutable types (BobTheBuidler, PR 19656)
  • Fix name conflict related to attributes of generator classes (Piotr Sawicki, PR 19535)
  • Fix segfault from heap type objects with a static docstring (Brian Schubert, PR 19636)
  • Unwrap NewType to its base type for additional optimizations (BobTheBuidler, PR 19497)
  • Generate an export table only for separate compilation (Jukka Lehtosalo, PR 19521)
  • Speed up isinstance with built‑in types (Piotr Sawicki, PR 19435)
  • Use native integers for some sequence indexing (Jukka Lehtosalo, PR 19426)
  • Speed up isinstance(obj, list) (Piotr Sawicki, PR 19416)
  • Report error on reserved method names (Piotr Sawicki, PR 19407)
  • Speed up string equality (Jukka Lehtosalo, PR 19402)
  • Raise NameError on undefined names (Piotr Sawicki, PR 19395)
  • Use per‑type freelists for nested functions (Jukka Lehtosalo, PR 19390)
  • Simplify comparison of tuple elements (Piotr Sawicki, PR 19396)
  • Generate introspection signatures for compiled functions (Brian Schubert, PR 19307)
  • Fix undefined attribute checking special case (Jukka Lehtosalo, PR 19378)
  • Fix comparison of tuples with different lengths (Piotr Sawicki, PR 19372)
  • Speed up list.clear (Jahongir Qurbonov, PR 19344)
  • Speed up weakref.proxy (BobTheBuidler, PR 19217)
  • Speed up weakref.ref (BobTheBuidler, PR 19099)
  • Speed up str.count (BobTheBuidler, PR 19264)

Stubtest Improvements

  • Add temporary --ignore-disjoint-bases flag to ease PEP 800 migration (Joren Hammudoglu, PR 19740)
  • Flag redundant uses of @disjoint_base (Jelle Zijlstra, PR 19715)
  • Improve signatures for __init__ of C extension classes (Stephen Morton, PR 18259)
  • Handle overloads with mixed positional‑only parameters (Stephen Morton, PR 18287)
  • Use “parameter” (not “argument”) in error messages (PrinceNaroliya, PR 19707)
  • Don’t require @disjoint_base when __slots__ imply finality (Jelle Zijlstra, PR 19701)
  • Allow runtime‑existing aliases of @type_check_only types (Brian Schubert, PR 19568)
  • More detailed checking of type objects in stubtest (Stephen Morton, PR 18251)
  • Support running stubtest in non-UTF8 terminals (Stanislav Terliakov, PR 19085)

Documentation Updates

  • Add idlemypyextension to IDE integrations (CoolCat467, PR 18615)
  • Document that object is often preferable to Any in APIs (wyattscarpenter, PR 19103)
  • Include a detailed listing of flags enabled by --strict (wyattscarpenter, PR 19062)
  • Update “common issues” (reveal_type/reveal_locals; note on orjson) (wyattscarpenter, PR 19059, 19058)

Other Notable Fixes and Improvements

  • Remove deprecated --new-type-inference flag (the new algorithm has long been default) (Ivan Levkivskyi, PR 19570)
  • Use empty context as a fallback for return expressions when outer context misleads inference (Ivan Levkivskyi, PR 19767)
  • Fix forward references in type parameters of over‑parameterized PEP 695 aliases (Brian Schubert, PR 19725)
  • Don’t expand PEP 695 aliases when checking node fullnames (Brian Schubert, PR 19699)
  • Don’t use outer context for 'or' expression inference when LHS is Any (Stanislav Terliakov, PR 19748)
  • Recognize buffer protocol special methods (Brian Schubert, PR 19581)
  • Support attribute access on enum members correctly (Stanislav Terliakov, PR 19422)
  • Check __slots__ assignments on self types (Stanislav Terliakov, PR 19332)
  • Move self‑argument checks after decorator application (Stanislav Terliakov, PR 19490)
  • Infer empty list for __slots__ and module __all__ (Stanislav Terliakov, PR 19348)
  • Use normalized tuples for fallback calculation (Stanislav Terliakov, PR 19111)
  • Preserve literals when joining similar types (Stanislav Terliakov, PR 19279)
  • Allow adjacent conditionally‑defined overloads (Stanislav Terliakov, PR 19042)
  • Check property decorators more strictly (Stanislav Terliakov, PR 19313)
  • Support properties with generic setters (Ivan Levkivskyi, PR 19298)
  • Generalize class/static method and property alias support (Ivan Levkivskyi, PR 19297)
  • Re‑widen custom properties after narrowing (Ivan Levkivskyi, PR 19296)
  • Avoid erasing type objects when checking runtime cover (Shantanu, PR 19320)
  • Include tuple fallback in constraints built from tuple types (Stanislav Terliakov, PR 19100)
  • Somewhat better isinstance support on old‑style unions (Shantanu, PR 19714)
  • Improve promotions inside unions (Christoph Tyralla, PR 19245)
  • Treat uninhabited types as having all attributes (Ivan Levkivskyi, PR 19300)
  • Improve metaclass conflict checks (Robsdedude, PR 17682)
  • Fixes to metaclass resolution algorithm (Robsdedude, PR 17713)
  • PEP 702 @deprecated: handle “combined” overloads (Christoph Tyralla, PR 19626)
  • PEP 702 @deprecated: include overloads in snapshot descriptions (Christoph Tyralla, PR 19613)
  • Ignore overload implementation when checking __OP__ / __rOP__ compatibility (Stanislav Terliakov, PR 18502)
  • Support _value_ as a fallback for ellipsis Enum members (Stanislav Terliakov, PR 19352)
  • Sort arguments in TypedDict overlap messages (Marc Mueller, PR 19666)
  • Fix handling of implicit return in lambda (Stanislav Terliakov, PR 19642)
  • Improve behavior of uninhabited types (Stanislav Terliakov, PR 19648)
  • Fix overload diagnostics when *args and **kwargs both match (Shantanu, PR 19614)
  • Further fix overload diagnostics for *args/**kwargs (Shantanu, PR 19619)
  • Show type variable name in "Cannot infer type argument" (Brian Schubert, PR 19290)
  • Fail gracefully on unsupported template strings (PEP 750) (Brian Schubert, PR 19700)
  • Revert colored argparse help for Python 3.14 (Marc Mueller, PR 19721)
  • Update stubinfo for latest typeshed (Shantanu, PR 19771)
  • Fix dict assignment when an incompatible same‑shape TypedDict exists (Stanislav Terliakov, PR 19592)
  • Fix constructor type for subclasses of Any (Ivan Levkivskyi, PR 19295)
  • Fix TypeGuard/TypeIs being forgotten in some cases (Brian Schubert, PR 19325)
  • Fix TypeIs negative narrowing for unions of generics (Brian Schubert, PR 18193)
  • dmypy suggest: Fix incorrect signature suggestion when a type matches a module name (Brian Schubert, PR 18937)
  • dmypy suggest: Fix interaction with __new__ (Stanislav Terliakov, PR 18966)
  • dmypy suggest: Support Callable / callable Protocols in decorator unwrapping (Anthony Sottile, PR 19072)
  • Fix missing error when redeclaring a type variable in a nested generic class (Brian Schubert, PR 18883)
  • Fix for overloaded type object erasure (Shantanu, PR 19338)
  • Fix TypeGuard with call on temporary object (Saul Shanabrook, PR 19577)

Typeshed Updates

Please see git log for full list of standard library typeshed stub changes.

Acknowledgements

Thanks to all mypy contributors who contributed to this release:

  • Ali Hamdan
  • Anthony Sottile
  • BobTheBuidler
  • Brian Schubert
  • Chainfire
  • Charlie Denton
  • Christoph Tyralla
  • CoolCat467
  • Daniel Hnyk
  • Emily
  • Emma Smith
  • Ethan Sarp
  • Ivan Levkivskyi
  • Jahongir Qurbonov
  • Jelle Zijlstra
  • Joren Hammudoglu
  • Jukka Lehtosalo
  • Marc Mueller
  • Omer Hadari
  • Piotr Sawicki
  • PrinceNaroliya
  • Randolf Scholz
  • Robsdedude
  • Saul Shanabrook
  • Shantanu
  • Stanislav Terliakov
  • Stephen Morton
  • wyattscarpenter

I’d also like to thank my employer, Dropbox, for supporting mypy development.

Monday, 14 July 2025

Mypy 1.17 Released

We’ve just uploaded mypy 1.17 to the Python Package Index (PyPI). Mypy is a static type checker for Python. This release includes new features and bug fixes. You can install it as follows:

python3 -m pip install -U mypy

You can read the full documentation for this release on Read the Docs.

Optionally Check That Match Is Exhaustive

Mypy can now optionally generate an error if a match statement does not match exhaustively, without having to use assert_never(...). Enable this by using --enable-error-code exhaustive-match.

Example:

# mypy: enable-error-code=exhaustive-match

import enum

class Color(enum.Enum):
    RED = 1
    BLUE = 2

def show_color(val: Color) -> None:
    # error: Unhandled case for values of type "Literal[Color.BLUE]"
    match val:
        case Color.RED:
            print("red")

This feature was contributed by Donal Burns (PR 19144).

Further Improvements to Attribute Resolution

This release includes additional improvements to how attribute types and kinds are resolved. These fix many bugs and overall improve consistency.

  • Handle corner case: protocol/class variable/descriptor (Ivan Levkivskyi, PR 19277)
  • Fix a few inconsistencies in protocol/type object interactions (Ivan Levkivskyi, PR 19267)
  • Refactor/unify access to static attributes (Ivan Levkivskyi, PR 19254)
  • Remove inconsistencies in operator handling (Ivan Levkivskyi, PR 19250)
  • Make protocol subtyping more consistent (Ivan Levkivskyi, PR 18943)

Fixes to Nondeterministic Type Checking

Previous mypy versions could infer different types for certain expressions across different runs (typically depending on which order certain types were processed, and this order was nondeterministic). This release includes fixes to several such issues.

  • Fix nondeterministic type checking by making join with explicit Protocol and type promotion commute (Shantanu, PR 18402)
  • Fix nondeterministic type checking caused by nonassociative of None joins (Shantanu, PR 19158)
  • Fix nondeterministic type checking caused by nonassociativity of joins (Shantanu, PR 19147)
  • Fix nondeterministic type checking by making join between type and TypeVar commute (Shantanu, PR 19149)

Remove Support for Targeting Python 3.8

Mypy now requires --python-version 3.9 or greater. Support for targeting Python 3.8 is fully removed now. Since 3.8 is an unsupported version, mypy will default to the oldest supported version (currently 3.9) if you still try to target 3.8.

This change is necessary because typeshed stopped supporting Python 3.8 after it reached its End of Life in October 2024.

Contributed by Marc Mueller (PR 19157, PR 19162).

Initial Support for Python 3.14

Mypy is now tested on 3.14 and mypyc works with 3.14.0b3 and later. Binary wheels compiled with mypyc for mypy itself will be available for 3.14 some time after 3.14.0rc1 has been released.

Note that not all features are supported just yet.

Contributed by Marc Mueller (PR 19164)

Deprecated Flag: --force-uppercase-builtins

Mypy only supports Python 3.9+. The --force-uppercase-builtins flag is now deprecated as unnecessary, and a no-op. It will be removed in a future version.

Contributed by Marc Mueller (PR 19176)

Mypyc: Improvements to Generators and Async Functions

This release includes both performance improvements and bug fixes related to generators and async functions (these share many implementation details).

  • Fix exception swallowing in async try/finally blocks with await (Chainfire, PR 19353)
  • Fix AttributeError in async try/finally with mixed return paths (Chainfire, PR 19361)
  • Make generated generator helper method internal (Jukka Lehtosalo, PR 19268)
  • Free coroutine after await encounters StopIteration (Jukka Lehtosalo, PR 19231)
  • Use non-tagged integer for generator label (Jukka Lehtosalo, PR 19218)
  • Merge generator and environment classes in simple cases (Jukka Lehtosalo, PR 19207)

Mypyc: Partial, Unsafe Support for Free Threading

Mypyc has minimal, quite memory-unsafe support for the free threaded builds of 3.14. It is also only lightly tested. Bug reports and experience reports are welcome!

Here are some of the major limitations:

  • Free threading only works when compiling a single module at a time.
  • If there is concurrent access to an object while another thread is mutating the same
object, it's possible to encounter segfaults and memory corruption.

  • There are no efficient native primitives for thread synthronization, though the
regular threading module can be used.

  • Some workloads don't scale well to multiple threads for no clear reason.

Related PRs:

  • Enable partial, unsafe support for free-threading (Jukka Lehtosalo, PR 19167)
  • Fix incref/decref on free-threaded builds (Jukka Lehtosalo, PR 19127)

Other Mypyc Fixes and Improvements

  • Derive .c file name from full module name if using multi_file (Jukka Lehtosalo, PR 19278)
  • Support overriding the group name used in output files (Jukka Lehtosalo, PR 19272)
  • Add note about using non-native class to subclass built-in types (Jukka Lehtosalo, PR 19236)
  • Make some generated classes implicitly final (Jukka Lehtosalo, PR 19235)
  • Don't simplify module prefixes if using separate compilation (Jukka Lehtosalo, PR 19206)

Stubgen Improvements

  • Add import for types in __exit__ method signature (Alexey Makridenko, PR 19120)
  • Add support for including class and property docstrings (Chad Dombrova, PR 17964)
  • Don't generate Incomplete | None = None argument annotation (Sebastian Rittau, PR 19097)
  • Support several more constructs in stubgen's alias printer (Stanislav Terliakov, PR 18888)

Miscellaneous Fixes and Improvements

  • Combine the revealed types of multiple iteration steps in a more robust manner (Christoph Tyralla, PR 19324)
  • Improve the handling of "iteration dependent" errors and notes in finally clauses (Christoph Tyralla, PR 19270)
  • Lessen dmypy suggest path limitations for Windows machines (CoolCat467, PR 19337)
  • Fix type ignore comments erroneously marked as unused by dmypy (Charlie Denton, PR 15043)
  • Fix misspelled exhaustive-match error code (johnthagen, PR 19276)
  • Fix missing error context for unpacking assignment involving star expression (Brian Schubert, PR 19258)
  • Fix and simplify error de-duplication (Ivan Levkivskyi, PR 19247)
  • Disallow ClassVar in type aliases (Brian Schubert, PR 19263)
  • Add script that prints list of compiled files when compiling mypy (Jukka Lehtosalo, PR 19260)
  • Fix help message url for "None and Optional handling" section (Guy Wilson, PR 19252)
  • Display fully qualified name of imported base classes in errors about incompatible overrides (Mikhail Golubev, PR 19115)
  • Avoid false unreachable, redundant-expr, and redundant-casts warnings in loops more robustly and efficiently, and avoid multiple revealed type notes for the same line (Christoph Tyralla, PR 19118)
  • Fix type extraction from isinstance checks (Stanislav Terliakov, PR 19223)
  • Erase stray type variables in functools.partial (Stanislav Terliakov, PR 18954)
  • Make inferring condition value recognize the whole truth table (Stanislav Terliakov, PR 18944)
  • Support type aliases, NamedTuple and TypedDict in constrained TypeVar defaults (Stanislav Terliakov, PR 18884)
  • Move dataclass kw_only fields to the end of the signature (Stanislav Terliakov, PR 19018)
  • Provide a better fallback value for the python_version option (Marc Mueller, PR 19162)
  • Avoid spurious non-overlapping equality error with metaclass with __eq__ (Michael J. Sullivan, PR 19220)
  • Narrow type variable bounds (Ivan Levkivskyi, PR 19183)
  • Add classifier for Python 3.14 (Marc Mueller, PR 19199)
  • Capitalize syntax error messages (Charulata, PR 19114)
  • Infer constraints eagerly if actual is Any (Ivan Levkivskyi, PR 19190)
  • Include walrus assignments in conditional inference (Stanislav Terliakov, PR 19038)
  • Use PEP 604 syntax when converting types to strings (Marc Mueller, PR 19179)
  • Use more lower-case builtin types in error messages (Marc Mueller, PR 19177)
  • Fix example to use correct method of Stack (Łukasz Kwieciński, PR 19123)
  • Forbid .pop of Readonly NotRequired TypedDict items (Stanislav Terliakov, PR 19133)
  • Emit a friendlier warning on invalid exclude regex, instead of a stacktrace (wyattscarpenter, PR 19102)
  • Enable ANSI color codes for dmypy client in Windows (wyattscarpenter, PR 19088)
  • Extend special case for context-based type variable inference to unions in return position (Stanislav Terliakov, PR 18976)

Acknowledgements

Thanks to all mypy contributors who contributed to this release:

  • Alexey Makridenko
  • Brian Schubert
  • Chad Dombrova
  • Chainfire
  • Charlie Denton
  • Charulata
  • Christoph Tyralla
  • CoolCat467
  • Donal Burns
  • Guy Wilson
  • Ivan Levkivskyi
  • johnthagen
  • Jukka Lehtosalo
  • Łukasz Kwieciński
  • Marc Mueller
  • Michael J. Sullivan
  • Mikhail Golubev
  • Sebastian Rittau
  • Shantanu
  • Stanislav Terliakov
  • wyattscarpenter

I’d also like to thank my employer, Dropbox, for supporting mypy development.