[dynamo] Fix functools.reduce polyfill signature mismatch on Python 3.15#185682
[dynamo] Fix functools.reduce polyfill signature mismatch on Python 3.15#185682joaopedroassad wants to merge 2 commits into
Conversation
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/185682
Note: Links to docs will display an error until the docs builds have been completed. ⏳ 1 Pending, 2 Unrelated FailuresAs of commit 382a377 with merge base 9082cdc ( BROKEN TRUNK - The following jobs failed but were present on the merge base:👉 Rebase onto the `viable/strict` branch to avoid these failures
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
|
|
|
|
|
The following ciflow label(s) have been added but CI has not been triggered yet because the workflows are awaiting approval:
Once a maintainer approves the workflows (scroll to the bottom of the PR page), the corresponding CI jobs will be triggered automatically. Please ping one of the reviewers if you do not have access to approve and run workflows. |
|
@claude explain those CI failures, check if they are related, and review the changes in this PR |
|
Claude finished @jansel's task in 2m 4s —— View job CI Failures Analysis & Code Review
CI Failures1. NEW FAILURE: This test failed with "Unexpected success" — meaning the test is marked as 2. BROKEN TRUNK: The job was interrupted mid-execution (tests were passing at ~57% completion) when the container was forcibly terminated. The log shows Neither failure is related to this PR. Code ReviewThe change is minimal and correct: +from functools import _initial_missing # type: ignore[attr-defined]
...
-_initial_missing = object()Correctness: The fix imports Backwards compatibility: The No issues found. This is a clean, minimal, well-motivated fix. LGTM. |
|
@pytorchbot rebase |
|
@pytorchbot started a rebase job onto refs/remotes/origin/viable/strict. Check the current status here |
|
@pytorchbot merge -i |
Merge startedYour change will be merged while ignoring the following 2 checks: pull / linux-jammy-py3.10-gcc11 / test-osdc (distributed, 1, 3, mt-l-x86iamx-8-64), inductor / unit-test / inductor-test / test-osdc (inductor, 2, 2, mt-l-x86aavx2-29-113-a10g) Learn more about merging in the wiki. Questions? Feedback? Please reach out to the PyTorch DevX Team |
Merge failedReason: 1 mandatory check(s) failed. The first few are: Dig deeper by viewing the failures on hud |
|
@pytorchbot rebase -b main |
|
You don't have permissions to rebase this PR since you are a first time contributor. If you think this is a mistake, please contact PyTorch Dev Infra. |
Clean merge with origin/main; no conflicts.
|
@pytorchbot merge |
Merge startedYour change will be merged once all checks pass (ETA 0-4 Hours). Learn more about merging in the wiki. Questions? Feedback? Please reach out to the PyTorch DevX Team |
mergedog handoffAll CI is green (or skipped). Ready for human review and Current PR head: CI notes at handoffmergedog is treating these still-failing checks as unrelated/spurious. Please verify before merging:
Warning: mergedog's suppressed check list differs from the latest Dr. CI summary. Suppressed by mergedog but not listed by Dr. CI:
Latest Dr. CI summary<!-- drci-comment-start -->
## :link: Helpful Links
### :test_tube: See artifacts and rendered test results at [hud.pytorch.org/pr/185682](https://hud.pytorch.org/pr/185682)
* :page_facing_up: Preview [Python docs built from this PR](https://docs-preview.pytorch.org/pytorch/pytorch/185682/index.html)
* :page_facing_up: Preview [C++ docs built from this PR](https://docs-preview.pytorch.org/pytorch/pytorch/185682/cppdocs/index.html)
* :question: Need help or want to give feedback on the CI? Visit the [bot commands wiki](https://github.com/pytorch/pytorch/wiki/Bot-commands)
Note: Links to docs will display an error until the docs builds have been completed.
## :hourglass_flowing_sand: 1 Pending, 2 Unrelated Failures
As of commit 382a377e8e558d1510ec0440d7057ba568df900a with merge base 9082cdc0be87044a0debd91ef1c67a340dace78f (<sub><sub><img alt="image" width=70 src="https://img.shields.io/date/1780252558?label=&color=FFFFFF&style=flat-square"></sub></sub>):
<details ><summary><b>BROKEN TRUNK</b> - The following jobs failed but were present on the merge base:</summary><p>👉 <b>Rebase onto the `viable/strict` branch to avoid these failures</b></p><p>
* [torchtitan-test / torchtitan-x-pytorch-test / test-osdc (torchtitan_features_integration, 1, 1, mt-l-x86aavx2-189-704-a10g-8)](https://hud.pytorch.org/pr/pytorch/pytorch/185682#78777184211) ([gh](https://github.com/pytorch/pytorch/actions/runs/26731570695/job/78777184211)) ([trunk failure](https://hud.pytorch.org/pytorch/pytorch/commit/9082cdc0be87044a0debd91ef1c67a340dace78f#78748449674))
`[OSDC] Step script exited with code 1. This is a script/workflow error, not an infrastructure issue. Check the step logs above for the actual failure.`
* [torchtitan-test / torchtitan-x-pytorch-test / test-osdc (torchtitan_models_integration, 1, 1, mt-l-x86aavx2-189-704-a10g-8)](https://hud.pytorch.org/pr/pytorch/pytorch/185682#78777184200) ([gh](https://github.com/pytorch/pytorch/actions/runs/26731570695/job/78777184200)) ([trunk failure](https://hud.pytorch.org/pytorch/pytorch/commit/9082cdc0be87044a0debd91ef1c67a340dace78f#78748449677))
`[OSDC] Step script exited with code 1. This is a script/workflow error, not an infrastructure issue. Check the step logs above for the actual failure.`
</p></details>
This comment was automatically generated by Dr. CI and updates every 15 minutes.
<!-- drci-comment-end -->No LLM was invoked during this run. |
🔗 Helpful Links🧪 See artifacts and rendered test results at hud.pytorch.org/pr/185682
Note: Links to docs will display an error until the docs builds have been completed. ✅ You can merge normally! (2 Unrelated Failures)As of commit 382a377 with merge base 9082cdc ( BROKEN TRUNK - The following jobs failed but were present on the merge base:👉 Rebase onto the `viable/strict` branch to avoid these failures
This comment was automatically generated by Dr. CI and updates every 15 minutes. |
….15 (pytorch#185682) ## Summary Python 3.15 will expose an introspectable signature for `functools.reduce` using a PEP 661 sentinel default: `(function, iterable, /, initial=functools._initial_missing)`. The CPython change is [pytorch#149591](python/cpython#149591), which merged into CPython main on 2026-05-10, after 3.15.0b1 was tagged. So on 3.15.0b1 the default is still `<unrepresentable>` and `inspect.signature()` raises `ValueError`, which `substitute_in_graph` swallows and skips the check. From 3.15.0b2 the check will run. When it runs, it compares positional parameter names, keyword-only names, and default values. The polyfill declares its own local sentinel: ```python _initial_missing = object() @substitute_in_graph(functools.reduce) def reduce(function, iterable, initial=_initial_missing, /): ... ``` That local `object()` is a different instance from `functools._initial_missing`, so the defaults dict compares unequal and `substitute_in_graph` raises: ``` File ".../torch/_dynamo/polyfills/functools.py", line N, in <module> @substitute_in_graph(functools.reduce) TypeError: Signature mismatch between <built-in function reduce> and <function reduce at 0x...>: (function, iterable, /, initial=_initial_missing) != (function, iterable, initial=<object object at 0x...>, /) ``` The polyfills loader imports every polyfill module, so this will break `import torch._dynamo` entirely on Python 3.15.0b2+. Same failure mode as pytorch#185403's `struct.pack` fix, just one step ahead of the next beta. The fix imports `functools._initial_missing` instead of declaring a local one. The polyfill's internal `if initial is _initial_missing` identity check still works because both sides now reference the same object. No behavior change on any Python version. `functools._initial_missing` has existed in `functools` since well before 3.10 (it's used by the pure-Python `functools.reduce` fallback), so the import is safe on every supported version. Part of pytorch#184352 (Python 3.15 support). Similar to pytorch#185403. ## Test plan Verified on a locally-built Python 3.15-dev (CPython main at `heads/3.15:863c7e0`, which includes [pytorch#149591](python/cpython#149591)). The upstream signature is exposed natively: ``` $ python3.15 -c "import functools, inspect; print(inspect.signature(functools.reduce))" (function, iterable, /, initial=_initial_missing) $ python3.15 -c "import functools, inspect; sig = inspect.signature(functools.reduce); print(sig.parameters['initial'].default is functools._initial_missing)" True ``` Extracted the actual `substitute_in_graph` from `torch/_dynamo/decorators.py` and ran it against both polyfill versions with no monkey-patching. Unmodified polyfill (`_initial_missing = object()` declared locally): ``` TypeError: Signature mismatch between <built-in function reduce> and <function unmodified_reduce at 0x...>: (function, iterable, /, initial=_initial_missing) != (function, iterable, initial=<object object at 0x...>, /) ``` Fixed polyfill (`from functools import _initial_missing`): no `TypeError` at the signature check. Regression on Python 3.12.13 (oldest currently supported): ``` $ python3 -c "import inspect, functools; inspect.signature(functools.reduce)" ValueError: no signature found for builtin <built-in function reduce> ``` The signature check is silently skipped on Python <= 3.14, so the fix is a no-op there. `functools._initial_missing` is confirmed present on 3.12.13. Eager-vs-polyfill parity verified on every input shape: ``` reduce(lambda a, b: a+b, [1,2,3,4]) == 10 (matches functools.reduce) reduce(lambda a, b: a+b, [1,2,3], 100) == 106 (matches) reduce(lambda a, b: a+b, []) -> TypeError("reduce() of empty iterable with no initial value") (matches) reduce(lambda a, b: a+b, [], 99) == 99 (matches) ``` Pre-commit checks: `python3 -m py_compile torch/_dynamo/polyfills/functools.py` and `git diff --staged --check` both clean. Pull Request resolved: pytorch#185682 Approved by: https://github.com/ezyang Co-authored-by: Edward Z. Yang via mergedog <ezyang@meta.com>
Summary
Python 3.15 will expose an introspectable signature for
functools.reduceusing a PEP 661 sentinel default:(function, iterable, /, initial=functools._initial_missing). The CPython change is #149591, which merged into CPython main on 2026-05-10, after 3.15.0b1 was tagged. So on 3.15.0b1 the default is still<unrepresentable>andinspect.signature()raisesValueError, whichsubstitute_in_graphswallows and skips the check. From 3.15.0b2 the check will run.When it runs, it compares positional parameter names, keyword-only names, and default values. The polyfill declares its own local sentinel:
That local
object()is a different instance fromfunctools._initial_missing, so the defaults dict compares unequal andsubstitute_in_graphraises:The polyfills loader imports every polyfill module, so this will break
import torch._dynamoentirely on Python 3.15.0b2+. Same failure mode as #185403'sstruct.packfix, just one step ahead of the next beta.The fix imports
functools._initial_missinginstead of declaring a local one. The polyfill's internalif initial is _initial_missingidentity check still works because both sides now reference the same object. No behavior change on any Python version.functools._initial_missinghas existed infunctoolssince well before 3.10 (it's used by the pure-Pythonfunctools.reducefallback), so the import is safe on every supported version.Part of #184352 (Python 3.15 support). Similar to #185403.
Test plan
Verified on a locally-built Python 3.15-dev (CPython main at
heads/3.15:863c7e0, which includes #149591). The upstream signature is exposed natively:Extracted the actual
substitute_in_graphfromtorch/_dynamo/decorators.pyand ran it against both polyfill versions with no monkey-patching.Unmodified polyfill (
_initial_missing = object()declared locally):Fixed polyfill (
from functools import _initial_missing): noTypeErrorat the signature check.Regression on Python 3.12.13 (oldest currently supported):
The signature check is silently skipped on Python <= 3.14, so the fix is a no-op there.
functools._initial_missingis confirmed present on 3.12.13. Eager-vs-polyfill parity verified on every input shape:Pre-commit checks:
python3 -m py_compile torch/_dynamo/polyfills/functools.pyandgit diff --staged --checkboth clean.cc @voznesenskym @penguinwu @EikanWang @jgong5 @Guobing-Chen @XiaobingSuper @zhuhaozhe @blzheng @wenzhe-nrv @jiayisunx @kadeng @chauhang @amjames @jataylo @azahed98