Skip to content

gh-151321: Fix opcode metadata flags for LOAD_DEREF and LOAD_CLOSURE - #151386

Closed
harjothkhara wants to merge 2 commits into
python:mainfrom
harjothkhara:fix/opcode-deref-free-flags-151321
Closed

gh-151321: Fix opcode metadata flags for LOAD_DEREF and LOAD_CLOSURE#151386
harjothkhara wants to merge 2 commits into
python:mainfrom
harjothkhara:fix/opcode-deref-free-flags-151321

Conversation

@harjothkhara

@harjothkhara harjothkhara commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

LOAD_DEREF and LOAD_CLOSURE were missing HAS_FREE_FLAG in the generated opcode metadata, and both also carried HAS_LOCAL_FLAG. As a result dis.hasfree stopped reporting them and dis.haslocal wrongly included them, breaking the documented dis.hasfree/dis.haslocal contract. LOAD_CLOSURE regressed in 3.13 (it became a pseudo-op inheriting LOAD_FAST's flags); LOAD_DEREF regressed in 3.14 (it started using _PyCell_GetStackRef, which the cases generator's has_free heuristic didn't recognize). This restores the 3.12 classification.

The fix teaches the cases generator that _PyCell_GetStackRef is a free-variable access, and gives the LOAD_CLOSURE pseudo an explicit HAS_FREE. A pseudo that explicitly accesses a free variable now suppresses the inherited HAS_LOCAL, mirroring the existing uses_locals and not has_free rule. Only introspection metadata changes — the generated interpreter/optimizer code is unchanged.

After the fix dis.hasfree contains both ops and dis.haslocal contains neither. make regen-all produces no other churn, and test__opcode test_dis test_compile pass.

Backport note: this won't cherry-pick cleanly to 3.13 — there LOAD_DEREF still uses PyCell_GetRef (already detected correctly), so 3.13 needs a LOAD_CLOSURE-only manual backport. 3.14 takes the full diff. Requesting backport to 3.14 and 3.13.

Disclosure: I used AI assistance on this; I've reviewed it and can walk through the generator change.

…OSURE

LOAD_DEREF and LOAD_CLOSURE were missing HAS_FREE_FLAG in the generated
opcode metadata, and both also carried HAS_LOCAL_FLAG, so dis.hasfree no
longer reported them while dis.haslocal wrongly included them. This
regressed the documented dis.hasfree / dis.haslocal contract: LOAD_CLOSURE
broke in 3.13 (when it became a pseudo-op inheriting LOAD_FAST's flags) and
LOAD_DEREF broke in 3.14 (when it started using _PyCell_GetStackRef, which
the cases generator's has_free heuristic did not recognize).

Teach the cases generator to treat _PyCell_GetStackRef as a free-variable
access, and give the LOAD_CLOSURE pseudo an explicit HAS_FREE flag. A pseudo
that explicitly accesses a free variable now suppresses the inherited
HAS_LOCAL, mirroring the existing "uses_locals and not has_free" rule for
real instructions, so HAS_FREE and HAS_LOCAL are never both set. The change
is to introspection metadata only; the generated interpreter and optimizer
code are unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@harjothkhara
harjothkhara force-pushed the fix/opcode-deref-free-flags-151321 branch from a0a2d2f to 9ea5992 Compare June 11, 2026 23:38
@harjothkhara

Copy link
Copy Markdown
Contributor Author

The remaining CI failure appears unrelated to this PR.

The failing job is Windows (free-threading) / Build and test (x64, switch-case):
https://github.com/python/cpython/actions/runs/27384430583/job/80928389704

It failed in:
test_logging.TimedRotatingFileHandlerTest.test_rollover_at_midnight

This PR only changes opcode metadata/generation and test__opcode. I also reran the focused test locally after updating the branch onto current main, and it passed 6/6 times on my local macOS debug build.

Could someone with Actions permissions rerun the failed Windows job?

@harjothkhara
harjothkhara marked this pull request as ready for review June 12, 2026 03:32
@Wulian233

Copy link
Copy Markdown
Contributor

CI often fails, and it is generally unnecessary to deal with the failure that ensure unrelated

@harjothkhara

harjothkhara commented Jun 17, 2026

Copy link
Copy Markdown
Contributor Author

@markshannon, this PR has been open about a week. Would you mind taking a look when you get a chance?

@harjothkhara

harjothkhara commented Jun 27, 2026

Copy link
Copy Markdown
Contributor Author

@iritkatriel would you mind taking a look at this one? gh-151321: on main LOAD_DEREF and LOAD_CLOSURE are tagged HAS_LOCAL instead of HAS_FREE (so they show up in dis.haslocal rather than dis.hasfree). Root cause is the analyzer's has_free detector not recognizing _PyCell_GetStackRef. Fix plus a regression test and NEWS are here. (markshannon I believe owns this area)

@StanFromIreland

Copy link
Copy Markdown
Member

Closing in favour of #154778.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants