Thanks to visit codestin.com
Credit goes to github.com

Skip to content

gh-121377: Fix closure with intervening comprehension - #124696

Draft
carljm wants to merge 4 commits into
python:mainfrom
carljm:inlinecompbug
Draft

gh-121377: Fix closure with intervening comprehension#124696
carljm wants to merge 4 commits into
python:mainfrom
carljm:inlinecompbug

Conversation

@carljm

@carljm carljm commented Sep 27, 2024

Copy link
Copy Markdown
Member

Fix the case where a comprehension iteration variable is inlined into a function that otherwise does not have a variable by that name, but the name should be a free variable from an enclosing scope passed through to other enclosed scopes.

Comment thread Python/symtable.c Outdated
@JelleZijlstra

Copy link
Copy Markdown
Member

Found this failure case:

>>> def f(x):
...     def g():
...         [(x, lambda: x) for x in []]
...         def h():
...             print(x)
...         h()
...     g()
...     
>>> f(1)
Traceback (most recent call last):
  File "<python-input-1>", line 1, in <module>
    f(1)
    ~^^^
  File "<python-input-0>", line 7, in f
    g()
    ~^^
  File "<python-input-0>", line 6, in g
    h()
    ~^^
  File "<python-input-0>", line 5, in h
    print(x)
          ^
NameError: cannot access free variable 'x' where it is not associated with a value in enclosing scope

@JelleZijlstra

Copy link
Copy Markdown
Member

Simpler repro:

def f(x):
    def g():
        [lambda: x for x in []]
        def h():
            assert x == 1
        h()
    g()
    
f(1)

Comment thread Lib/test/test_listcomps.py Outdated
code = """
x = 1
def f():
[lambda: x for x in [1]]

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
[lambda: x for x in [1]]
[lambda: x for x in [2]]

As discussed:

  • Use a different value (the test ran correctly but used the wrong 1)
  • Should change it to execute the lambda so we ensure the value of x inside the lambda is right

@carljm
carljm marked this pull request as draft September 27, 2024 23:14
@limwz01

limwz01 commented Nov 20, 2024

Copy link
Copy Markdown

@carljm I think the tests are not testing the exact situation in my original example. They already pass in Python 3.13. The intervening list comprehension needs to be in the innermost scope like my original example, which still fails.

@limwz01

limwz01 commented Nov 20, 2024

Copy link
Copy Markdown

oh, sorry ignore me, I was confused. apparently the tests passed because I ran it at module scope. they are also tested in function scope, so that is ok, I think

@limwz01

limwz01 commented Nov 20, 2024

Copy link
Copy Markdown

but maybe you should also add a test to also test a local in f() to be sure. (I keep getting confused by the change of the function names between our examples)

@github-actions

Copy link
Copy Markdown

This PR is stale because it has been open for 30 days with no activity.

@github-actions github-actions Bot added the stale Stale PR or inactive for long period of time. label Apr 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

stale Stale PR or inactive for long period of time.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants