Skip to content

UnboundLocalError is not returned #1454

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
dralley opened this issue Oct 2, 2019 · 3 comments
Closed

UnboundLocalError is not returned #1454

dralley opened this issue Oct 2, 2019 · 3 comments
Labels
C-compat A discrepancy between RustPython and CPython

Comments

@dralley
Copy link
Contributor

dralley commented Oct 2, 2019

x = 10
def foo():
    x += 1
    print(x)
foo()

Expected

Traceback (most recent call last):
  File "test3.py", line 5, in <module>
    foo()
  File "test3.py", line 3, in foo
    x += 1
UnboundLocalError: local variable 'x' referenced before assignment

Actual

11

This might be related to #1333

@dralley dralley added the C-compat A discrepancy between RustPython and CPython label Oct 2, 2019
@sanxiyn
Copy link
Contributor

sanxiyn commented Oct 11, 2019

In fact, there is no UnboundLocalError defined at all.

@Lynskylate
Copy link
Contributor

Lynskylate commented Oct 19, 2019

In fact this is because the generated bytecode isn't compact for python.

def foo():
    x += 1

dis(foo)
# RustPython bytecode
""""
                 0 LoadName             (x, Free)
                 1 LoadConst            (1)
                 2 BinaryOperation      (Add, true)
                 3 StoreName            (x, Free)
""""
# Python bytecode
"""
            0 LOAD_FAST                0 (x)
              2 LOAD_CONST               1 (1)
              4 INPLACE_ADD
              6 STORE_FAST               0 (x)

"""

RusyPython bytecode Load x from free scope, it means that load variables globally when reading from a local scope fails.
In cpython, it just load variable from locals.

//ceval.c 1329
        case TARGET(LOAD_FAST): {
            PyObject *value = GETLOCAL(oparg);
            if (value == NULL) {
                format_exc_check_arg(tstate, PyExc_UnboundLocalError,
                                     UNBOUNDLOCAL_ERROR_MSG,
                                     PyTuple_GetItem(co->co_varnames, oparg));
                goto error;
            }

@dralley
Copy link
Contributor Author

dralley commented Dec 6, 2020

This seems to be fixed now

@dralley dralley closed this as completed Dec 6, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-compat A discrepancy between RustPython and CPython
Projects
None yet
Development

No branches or pull requests

3 participants