Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: python/mypy
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: master
Choose a base ref
...
head repository: python/mypy
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: release-2.1
Choose a head ref
Checking mergeability… Don’t worry, you can still create the pull request.
  • 6 commits
  • 30 files changed
  • 8 contributors

Commits on May 9, 2026

  1. [mypyc] Add librt.random module (#21433)

    The stdlib `random` module is fairly often used in performance critical
    code, and it's not super efficient. Add `librt.random` with a subset of
    the stdlib module interface that is optimized for performance when
    compiled.
    
    Use ChaCha8 as the algorithm. Based on some research, this is a modern,
    high-quality PRNG algorithm. It's used by Go `math/rand/v2`, among
    others.
    
    This is a non-cryptographic PRNG, similar to the stdlib `random` module
    (but this uses a different algorithm).
    
    I used Claude Code and Codex to write all the code, but I iterated on it
    quite a lot and did a bunch of manual validation and code review. I also
    asked Codex to explicitly check that the ChaCha8 implementation is
    correct by comparing it to a reference implementation.
    
    Use thread-local RNG state for module-level functions to enable good
    scaling in free-threaded builds. There's some extra complexity from
    having to free the state at thread exit.
    
    I asked a LLM to generate and run a benchmark, and here are the results
    on 3.14:
    ```
        │  Function   │ vs stdlib(compiled) │ vs stdlib(interpreted) │
        │ random()    │        3.2x         │          4.8x          │
        │ randint()   │        16.6x        │         18.0x          │
        │ randrange() │        14.5x        │         16.2x          │
        │ choice()    │        12.9x        │         10.3x          │
    ```
    
    `choice()` was replaced with `randrange` when using `librt`, since we don't provide it as part of this fairly minimal API.
    JukkaL committed May 9, 2026
    Configuration menu
    Copy the full SHA
    4b8fdca View commit details
    Browse the repository at this point in the history

Commits on May 10, 2026

  1. Fix function call message change for small number of args (#21432)

    Refs #21427
    
    I used `2` as a magic number, because in my opinion it is easier to tell
    the difference when all errors show up for the small number of args.
    
    ---------
    
    Co-authored-by: hauntsaninja <hauntsaninja@gmail.com>
    2 people authored and JukkaL committed May 10, 2026
    Configuration menu
    Copy the full SHA
    6c4af8e View commit details
    Browse the repository at this point in the history
  2. Fix nondeterminism from nonassociativity of overload joins (#21455)

    Fixes #21445
    
    See also my previous PRs #19147 and #19158
    hauntsaninja authored and JukkaL committed May 10, 2026
    Configuration menu
    Copy the full SHA
    116d60b View commit details
    Browse the repository at this point in the history
  3. Respect file config comments for stale modules (#21444)

    In mypy 1.19, re-running `mypy` with a saved cache and a file containing
    an inline configuration comment (e.g. `# mypy:
    disable-error-code="import-not-found"`) acted 'correctly', i.e. the same
    behaviour on the first run vs subsequent runs.
    
    In mypy 1.20 and newer, this is no longer the case. Running `mypy` with
    a pre-existing cache fails to respect inline configuration comments for
    stale modules, leading to confusing false-positive errors that can be
    hard to debug.
    
    This PR introduces a failing test as at current master, and then a fix
    for the issue. I believe this is the right fix, though happy to change
    as suggested by the maintainers, I'm not nearly as familiar with mypy
    internals.
    
    Notably also from L2376-80, it's by design that file-level comments
    aren't cached:
    
    ```python
        # Note that the options we store in the cache are the options as
        # specified by the command line/config file and *don't* reflect
        # updates made by inline config directives in the file. This is
        # important, or otherwise the options would never match when
        # verifying the cache.
    ```
    
    I believe that this regression was introduced in #20773
    
    A
    
    Co-authored-by: Adam Turner <turner@hudson-trading.com>
    2 people authored and JukkaL committed May 10, 2026
    Configuration menu
    Copy the full SHA
    8152f4a View commit details
    Browse the repository at this point in the history
  4. [mypyc] Enable incremental self-compilation (#21369)

    Six fixes on top of #21299, all required to self-compile mypy or to
    install a `separate=True` wheel via pip.
    
    - `mypyc/build.py`: pip invokes `setup.py` twice when building a wheel.
    On the second invocation mypy's incremental cache is fully warm, so we
    generate no new C source for any group; the resulting extensions ship
    without their entry points and import as stubs.
    - **Fix**: when a group emits no C source, reuse the .c file from the
    previous pass.
    
    - `mypyc/codegen/{emit,emitfunc}.py`: when code in one compiled group
    reads an attribute on an object whose class lives in another group, the
    generated cast depends on that other group's struct definitions. We
    weren't recording the dependency, so the C compiler couldn't see the
    layout and the build failed.
      - **Fix**: register the dependency at the cast site.
    
    - `mypyc/codegen/emitmodule.py`: when mypy compiles itself, a generated
    shim file can share a basename with a runtime C file. The C compiler
    resolves the runtime include relative to the shim's directory and picks
    up the shim instead.
    - **Fix**: search the include path explicitly so shims can't shadow
    runtime files.
    
    - `mypyc/lib-rt/misc_ops.c`: each compiled module gets its own shared
    library next to it in the package tree. The runtime was computing the
    module's file path as if a single shared library sat above the whole
    package, which doubled the package prefix and broke submodule lookups.
    - **Fix**: detect the per-module case and use only the module's leaf
    name.
    
    - `mypyc/irbuild/prepare.py`: traits and builtin-derived classes don't
    get a real C constructor emitted. A clean build sidesteps that, but a
    fully cached rebuild was taking the direct-call path and producing C
    that referenced a constructor that doesn't exist.
      - **Fix**: skip the registration the same way a clean build does.
    
    - `mypyc/build.py`: on every build_ext, setuptools rewrites every
    compiled .so in the source tree even when nothing changed. On macOS this
    invalidates the OS signature cache, so every import on the next run pays
    a re-verification cost.
    - **Fix**: skip the copy when source and destination already match,
    taking a 1-line edit rebuild from ~72s to ~6s. This is really a `setup`
    tools limitation though (relevant [mypy
    issue](mypyc/mypyc#1068) ?)
    
    I also added a `MYPYC_SEPARATE` env knob so CI can exercise the codegen
    path against mypy itself.
    
    
    ## Benchmarks
    
    Mypy self-compile on macOS, `MYPYC_OPT_LEVEL=0`, `-j 11`. Three
    scenarios:
    
    | | monolithic | separate=True |
    |:---:|:---:|:---:|
    | Clean build | 180s | 108s |
    | No-op rebuild | 124s | 5s |
    | 1-line edit | 106s | 6s |
    VaggelisD authored and JukkaL committed May 10, 2026
    Configuration menu
    Copy the full SHA
    2b1eb58 View commit details
    Browse the repository at this point in the history
  5. Configuration menu
    Copy the full SHA
    3f4067b View commit details
    Browse the repository at this point in the history
Loading