)]}'
{
  "commit": "2b1eb58a250c5f1eb4ef5fb1f312ff528c5a1d4e",
  "tree": "34094fb5541021961a74e33ae3cd327a8c834547",
  "parents": [
    "8152f4af3f6c03beaf2660026240f0fdce7feecc"
  ],
  "author": {
    "name": "Vaggelis Danias",
    "email": "daniasevangelos@gmail.com",
    "time": "Fri May 08 20:22:49 2026 +0300"
  },
  "committer": {
    "name": "Jukka Lehtosalo",
    "email": "jukka.lehtosalo@iki.fi",
    "time": "Sun May 10 12:22:05 2026 +0100"
  },
  "message": "[mypyc] Enable incremental self-compilation (#21369)\n\nSix fixes on top of #21299, all required to self-compile mypy or to\ninstall a `separate\u003dTrue` wheel via pip.\n\n- `mypyc/build.py`: pip invokes `setup.py` twice when building a wheel.\nOn the second invocation mypy\u0027s incremental cache is fully warm, so we\ngenerate no new C source for any group; the resulting extensions ship\nwithout their entry points and import as stubs.\n- **Fix**: when a group emits no C source, reuse the .c file from the\nprevious pass.\n\n- `mypyc/codegen/{emit,emitfunc}.py`: when code in one compiled group\nreads an attribute on an object whose class lives in another group, the\ngenerated cast depends on that other group\u0027s struct definitions. We\nweren\u0027t recording the dependency, so the C compiler couldn\u0027t see the\nlayout and the build failed.\n  - **Fix**: register the dependency at the cast site.\n\n- `mypyc/codegen/emitmodule.py`: when mypy compiles itself, a generated\nshim file can share a basename with a runtime C file. The C compiler\nresolves the runtime include relative to the shim\u0027s directory and picks\nup the shim instead.\n- **Fix**: search the include path explicitly so shims can\u0027t shadow\nruntime files.\n\n- `mypyc/lib-rt/misc_ops.c`: each compiled module gets its own shared\nlibrary next to it in the package tree. The runtime was computing the\nmodule\u0027s file path as if a single shared library sat above the whole\npackage, which doubled the package prefix and broke submodule lookups.\n- **Fix**: detect the per-module case and use only the module\u0027s leaf\nname.\n\n- `mypyc/irbuild/prepare.py`: traits and builtin-derived classes don\u0027t\nget a real C constructor emitted. A clean build sidesteps that, but a\nfully cached rebuild was taking the direct-call path and producing C\nthat referenced a constructor that doesn\u0027t exist.\n  - **Fix**: skip the registration the same way a clean build does.\n\n- `mypyc/build.py`: on every build_ext, setuptools rewrites every\ncompiled .so in the source tree even when nothing changed. On macOS this\ninvalidates the OS signature cache, so every import on the next run pays\na re-verification cost.\n- **Fix**: skip the copy when source and destination already match,\ntaking a 1-line edit rebuild from ~72s to ~6s. This is really a `setup`\ntools limitation though (relevant [mypy\nissue](https://github.com/mypyc/mypyc/issues/1068) ?)\n\nI also added a `MYPYC_SEPARATE` env knob so CI can exercise the codegen\npath against mypy itself.\n\n\n## Benchmarks\n\nMypy self-compile on macOS, `MYPYC_OPT_LEVEL\u003d0`, `-j 11`. Three\nscenarios:\n\n| | monolithic | separate\u003dTrue |\n|:---:|:---:|:---:|\n| Clean build | 180s | 108s |\n| No-op rebuild | 124s | 5s |\n| 1-line edit | 106s | 6s |",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "08eeb13c9175201e9037e6539c78b881caa612f7",
      "old_mode": 33188,
      "old_path": "mypyc/build.py",
      "new_id": "84633086d272450ffa52bb84e5db479ae6b78d89",
      "new_mode": 33188,
      "new_path": "mypyc/build.py"
    },
    {
      "type": "modify",
      "old_id": "45ff34ab045d5b972dadf788cc522bb789c7e74e",
      "old_mode": 33188,
      "old_path": "mypyc/codegen/emit.py",
      "new_id": "01cf3593a8d60cd1765fa52d1c54044144e06522",
      "new_mode": 33188,
      "new_path": "mypyc/codegen/emit.py"
    },
    {
      "type": "modify",
      "old_id": "e4a8922a103d424647ce76119aca6bc4d26aa273",
      "old_mode": 33188,
      "old_path": "mypyc/codegen/emitfunc.py",
      "new_id": "dcb606f6ab51bfb10185dd1c651a18ce3e1822a8",
      "new_mode": 33188,
      "new_path": "mypyc/codegen/emitfunc.py"
    },
    {
      "type": "modify",
      "old_id": "3f10df7fa8c98915feda1889dbdad1a46483ba7a",
      "old_mode": 33188,
      "old_path": "mypyc/codegen/emitmodule.py",
      "new_id": "fa0a4385f4fb571f9d97b1555206545189c24490",
      "new_mode": 33188,
      "new_path": "mypyc/codegen/emitmodule.py"
    },
    {
      "type": "modify",
      "old_id": "09bfc8339b4041d4140aedd47ae1fa65ba3a3a2b",
      "old_mode": 33188,
      "old_path": "mypyc/irbuild/prepare.py",
      "new_id": "f143ce1b4402520370a0bfb5338ab753e57a77e8",
      "new_mode": 33188,
      "new_path": "mypyc/irbuild/prepare.py"
    },
    {
      "type": "modify",
      "old_id": "2aaadb2ac47d2cf227739f4133fec94557eae6bc",
      "old_mode": 33188,
      "old_path": "mypyc/lib-rt/misc_ops.c",
      "new_id": "392dba0deca4c35c9f3cab0e940204a09c02bc40",
      "new_mode": 33188,
      "new_path": "mypyc/lib-rt/misc_ops.c"
    },
    {
      "type": "modify",
      "old_id": "d36a6bfa2c2dc8606e065233b26d96e0f6187623",
      "old_mode": 33188,
      "old_path": "setup.py",
      "new_id": "1879f6892ba8fcfe0d683a884809a2c2550f0dc4",
      "new_mode": 33188,
      "new_path": "setup.py"
    }
  ]
}
