Skip to content

Commit 8f8584f

Browse files
committed
[GR-21351] free var not registered for code constructor if not refed in the function
1 parent c63d37e commit 8f8584f

File tree

5 files changed

+169
-0
lines changed

5 files changed

+169
-0
lines changed

graalpython/com.oracle.graal.python.test/src/com/oracle/graal/python/test/parser/FuncDefTests.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,12 @@ public void positionalOnlyArg46() throws Exception {
474474
public void positionalOnlyArg47() throws Exception {
475475
checkSyntaxError("async def f(a, *, c, /, d, e): pass");
476476
}
477+
478+
@Test
479+
public void issue21351() throws Exception {
480+
// parser test for GR-21351
481+
checkScopeAndTree();
482+
}
477483

478484
private void checkScopeAndTree() throws Exception {
479485
File testFile = getTestFileFromTestAndTestMethod();
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
def outer():
2+
var = None
3+
def toInternal(obj):
4+
nonlocal var
5+
x = 10
6+
return toInternal
7+
8+
fnc = outer()
9+
c = fnc.__code__
10+
11+
print("free > ", c.co_freevars)
12+
print("cell > ", c.co_cellvars)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
Scope: []
2+
Kind: Module
3+
FrameDescriptor: Empty
4+
CellVars: Empty
5+
FreeVars: Empty
6+
Scope: outer
7+
Kind: Function
8+
FrameDescriptor: [toInternal, var, <return_val>]
9+
CellVars: [var]
10+
FreeVars: Empty
11+
Scope: toInternal
12+
Kind: Function
13+
FrameDescriptor: [obj, var, x, <return_val>]
14+
CellVars: Empty
15+
FreeVars: [var]
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
ModuleRootNode Name: <module 'issue21351'> SourceSection: [0,208]`def outer():↵ var...`
2+
Signature: varArgs=False, varKeywordArgs=False, noArguments=True, positionalOnly=True, requiresKeywordArgs=False
3+
FreeVars: None
4+
NeedsCellFrame: False
5+
FrameDescriptor: Empty
6+
Documentation: None
7+
InnerRootNode SourceSection: [0,208]`def outer():↵ var...`
8+
ExpressionWithSideEffects SourceSection: [0,207]`def outer():↵ var...`
9+
WriteNameNodeGen SourceSection: [0,112]`def outer():↵ var...`
10+
Identifier: outer
11+
FunctionDefinitionNode Name: outer SourceSection: None
12+
Arguments: None
13+
KwArguments: None
14+
Documentation: StringLiteralNode: Empty
15+
FreeVarSlots: None
16+
ExecutionSlots:
17+
FreeVarsSlots: None
18+
CellVarsSlots: var,
19+
FunctionRootNode SourceSection: [0,112]`def outer():↵ var...`
20+
Name: outer
21+
Signature: varArgs=False, varKeywordArgs=False, noArguments=True, positionalOnly=True, requiresKeywordArgs=False
22+
CelVars: var
23+
FreeVars: None
24+
NeedsCellFrame: False
25+
FrameDescriptor: 3 slots [var, toInternal, <return_val>]
26+
ExecutionSlots:
27+
FreeVarsSlots: None
28+
CellVarsSlots: var,
29+
InnerRootNode SourceSection: [0,112]`def outer():↵ var...`
30+
ReturnTargetNode SourceSection: [0,112]`def outer():↵ var...`
31+
Body: BlockNode SourceSection: None
32+
BlockNode SourceSection: None
33+
FunctionBodyNode SourceSection: [17,110]`var = None↵ def t...`
34+
WriteLocalCellNodeGen SourceSection: [17,27]`var = None`
35+
Identifier: var
36+
ReadLocalVariableNode SourceSection: None
37+
Frame: [0,var,Illegal]
38+
ReadVariableFromFrameNodeGen SourceSection: None
39+
ObjectLiteralNode SourceSection: [23,27]`None`
40+
WriteLocalVariableNodeGen SourceSection: [32,93]`def toInternal(obj):...`
41+
Identifier: toInternal
42+
WriteLocalFrameSlotNodeGen SourceSection: None
43+
Frame: [1,toInternal,Illegal]
44+
FunctionDefinitionNode Name: toInternal SourceSection: None
45+
Arguments: None
46+
KwArguments: None
47+
Documentation: StringLiteralNode: Empty
48+
FreeVarSlots: var,
49+
ExecutionSlots:
50+
FreeVarsSlots: var,
51+
CellVarsSlots: None
52+
FunctionRootNode SourceSection: [32,93]`def toInternal(obj):...`
53+
Name: toInternal
54+
Signature: varArgs=False, varKeywordArgs=False, noArguments=False, positionalOnly=True, requiresKeywordArgs=False
55+
Param Names: obj
56+
CelVars: None
57+
FreeVars: var
58+
NeedsCellFrame: False
59+
FrameDescriptor: 4 slots [obj, x, var, <return_val>]
60+
ExecutionSlots:
61+
FreeVarsSlots: var,
62+
CellVarsSlots: None
63+
InnerRootNode SourceSection: [32,93]`def toInternal(obj):...`
64+
ReturnTargetNode SourceSection: [32,93]`def toInternal(obj):...`
65+
Body: BlockNode SourceSection: None
66+
WriteLocalVariableNodeGen SourceSection: None
67+
Identifier: obj
68+
WriteLocalFrameSlotNodeGen SourceSection: None
69+
Frame: [0,obj,Illegal]
70+
ArgumentExpressionNode SourceSection: None
71+
ReadIndexedArgumentNodeGen SourceSection: None
72+
Index: 0
73+
FunctionBodyNode SourceSection: [61,88]`nonlocal var↵ ...`
74+
ExpressionStatementNode SourceSection: [61,73]`nonlocal var`
75+
EmptyNode SourceSection: [61,73]`nonlocal var`
76+
WriteLocalVariableNodeGen SourceSection: [82,88]`x = 10`
77+
Identifier: x
78+
WriteLocalFrameSlotNodeGen SourceSection: None
79+
Frame: [1,x,Illegal]
80+
IntegerLiteralNode SourceSection: [86,88]`10`
81+
Value: 10
82+
Return Expresssion: ReadLocalVariableNode SourceSection: None
83+
Frame: [3,<return_val>,Illegal]
84+
ReadVariableFromFrameNodeGen SourceSection: None
85+
FrameReturnNode SourceSection: [93,110]`return toInternal`
86+
WriteLocalVariableNodeGen SourceSection: None
87+
Identifier: <return_val>
88+
WriteLocalFrameSlotNodeGen SourceSection: None
89+
Frame: [2,<return_val>,Illegal]
90+
ReadLocalVariableNode SourceSection: [100,110]`toInternal`
91+
Frame: [1,toInternal,Illegal]
92+
ReadVariableFromFrameNodeGen SourceSection: None
93+
Return Expresssion: ReadLocalVariableNode SourceSection: None
94+
Frame: [2,<return_val>,Illegal]
95+
ReadVariableFromFrameNodeGen SourceSection: None
96+
WriteNameNodeGen SourceSection: [112,125]`fnc = outer()`
97+
Identifier: fnc
98+
PythonCallNodeGen SourceSection: [118,125]`outer()`
99+
CallNodeGen SourceSection: None
100+
ReadNameNodeGen SourceSection: [118,123]`outer`
101+
Identifier: outer
102+
WriteNameNodeGen SourceSection: [126,142]`c = fnc.__code__`
103+
Identifier: c
104+
GetAttributeNodeGen SourceSection: [130,142]`fnc.__code__`
105+
GetFixedAttributeNodeGen SourceSection: None
106+
Key: __code__
107+
LookupAndCallBinaryNodeGen SourceSection: None
108+
Op: __getattribute__
109+
ReadNameNodeGen SourceSection: [130,133]`fnc`
110+
Identifier: fnc
111+
ExpressionStatementNode SourceSection: [144,175]`print("free > ", c.c...`
112+
PythonCallNodeGen SourceSection: [144,175]`print("free > ", c.c...`
113+
CallNodeGen SourceSection: None
114+
StringLiteralNode SourceSection: [150,159]`"free > "`
115+
GetAttributeNodeGen SourceSection: [161,174]`c.co_freevars`
116+
GetFixedAttributeNodeGen SourceSection: None
117+
Key: co_freevars
118+
LookupAndCallBinaryNodeGen SourceSection: None
119+
Op: __getattribute__
120+
ReadNameNodeGen SourceSection: [161,162]`c`
121+
Identifier: c
122+
ReadNameNodeGen SourceSection: [144,149]`print`
123+
Identifier: print
124+
PythonCallNodeGen SourceSection: [176,207]`print("cell > ", c.c...`
125+
CallNodeGen SourceSection: None
126+
StringLiteralNode SourceSection: [182,191]`"cell > "`
127+
GetAttributeNodeGen SourceSection: [193,206]`c.co_cellvars`
128+
GetFixedAttributeNodeGen SourceSection: None
129+
Key: co_cellvars
130+
LookupAndCallBinaryNodeGen SourceSection: None
131+
Op: __getattribute__
132+
ReadNameNodeGen SourceSection: [193,194]`c`
133+
Identifier: c
134+
ReadNameNodeGen SourceSection: [176,181]`print`
135+
Identifier: print

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/parser/ScopeInfo.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ public void addExplicitNonlocalVariable(String identifier) {
193193
if (explicitNonlocalVariables == null) {
194194
explicitNonlocalVariables = new HashSet<>();
195195
}
196+
addSeenVar(identifier);
196197
explicitNonlocalVariables.add(identifier);
197198
}
198199

0 commit comments

Comments
 (0)