You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
member field + lambda results unexpected UnboundLocalError #3934
Traceback (most recent call last):
File "test_lambda_scope.py", line 3, in <module>
f = lambda x=v: x
File "test_lambda_scope.py", line 3, in X
f = lambda x=v: x
UnboundLocalError: local variable 'v' referenced before assignment
Since I am interested in how the RustPython compiler works, I want to try this! Is there any starting point in the codebase I could start poking around that might be relevant to this issue??
To be honest, I am not understand this problem very well.
The first step will be checking if it is a bytecode problem or not. dis module will be helpful.
The second step depends on the result of first step, but I would dig around LoadClassDeref generation and execution.
The v variable is stored through StoreLocal, but loaded through LoadFast. (and also the index mismatch too.)
While in cpython, the v variable is stored and loaded through LOAD_NAME, STORE_NAME.
I think it makes the LOAD_FAST fail by UnboundLocalError.
In the example code, compile_name with v is called twice when v is stored, and loaded.
The problem here is when v is stored, it is not function scope, so its op_typ is resolved as Local type,
but when the v is accessed, because it is in function scope, its op_typ is resolved as a Fast type.
So, I think maybe the problem here is the default argument v's scope is evaluated as in the function's scope in the only lambda expression, which is not correct.
>>>>> f = lambda x=v:x
name: v
self.ctx.in_func(): true
>>>>> def f(x=v): x
name: v
self.ctx.in_func(): false
Activity
jirheee commentedon Jul 31, 2022
Since I am interested in how the RustPython compiler works, I want to try this! Is there any starting point in the codebase I could start poking around that might be relevant to this issue??
youknowone commentedon Aug 1, 2022
To be honest, I am not understand this problem very well.
The first step will be checking if it is a bytecode problem or not.
dismodule will be helpful.The second step depends on the result of first step, but I would dig around
LoadClassDerefgeneration and execution.jirheee commentedon Aug 1, 2022
Thanks! I will start from the points you've mentioned 👍
youknowone commentedon Sep 21, 2022
@jirheee since it's been a while, do you need any help?
jopemachine commentedon Oct 15, 2022
I'm looking into this issue using
dismodule to the example code.RustPython's bytecodes of the example code are as follows.
But cpython's bytecodes are as follow.
I don't know about these bytecodes very much, but it seems the
UnboundLocalErroroccurs because of the below bytecodes.The
vvariable is stored throughStoreLocal, but loaded throughLoadFast. (and also the index mismatch too.)While in cpython, the
vvariable is stored and loaded throughLOAD_NAME,STORE_NAME.I think it makes the LOAD_FAST fail by
UnboundLocalError.Ref: Maybe the below function might be related
https://github.com/RustPython/RustPython/blob/main/compiler/codegen/src/compile.rs#L461-L534
jopemachine commentedon Oct 15, 2022
In the example code,
compile_namewithvis called twice whenvis stored, and loaded.The problem here is when
vis stored, it is not function scope, so itsop_typis resolved asLocaltype,but when the
vis accessed, because it is in function scope, itsop_typis resolved as aFasttype.(Related: https://github.com/RustPython/RustPython/blob/main/compiler/codegen/src/compile.rs#L479)
I think maybe using
LoadNameAnylike usingSTORE_NAMEandLOAD_NAMEin cpython might be a method to fix this.For example, below code does not occur this
UnboundLocalErrorThe above code's bytecodes are as follows and use
LoadNameAnyjopemachine commentedon Oct 16, 2022
So, I think maybe the problem here is the default argument
v's scope is evaluated as in the function's scope in the only lambda expression, which is not correct.Fix RustPython#3934
Fix RustPython#3934