ruff/crates/ty_python_semantic/resources/mdtest/scopes/global.md
2025-05-03 19:49:15 +02:00

3.7 KiB

global references

Implicit global in function

A name reference to a never-defined symbol in a function is implicitly a global lookup.

x = 1

def f():
    reveal_type(x)  # revealed: Unknown | Literal[1]

Explicit global in function

x = 1

def f():
    global x
    reveal_type(x)  # revealed: Unknown | Literal[1]

Unassignable type in function

x: int = 1

def f():
    y: int = 1
    # error: [invalid-assignment] "Object of type `Literal[""]` is not assignable to `int`"
    y = ""

    global x
    # TODO: error: [invalid-assignment] "Object of type `Literal[""]` is not assignable to `int`"
    x = ""

Nested intervening scope

A global statement causes lookup to skip any bindings in intervening scopes:

x: int = 1

def outer():
    x: str = ""

    def inner():
        global x
        # TODO: revealed: int
        reveal_type(x)  # revealed: str

Narrowing

An assignment following a global statement should narrow the type in the local scope after the assignment.

x: int | None

def f():
    global x
    x = 1
    reveal_type(x)  # revealed: Literal[1]

nonlocal and global

A binding cannot be both nonlocal and global. This should emit a semantic syntax error. CPython marks the nonlocal line, while mypy, pyright, and ruff (PLE0115) mark the global line.

x = 1

def f():
    x = 1
    def g() -> None:
        nonlocal x
        global x  # TODO: error: [invalid-syntax] "name 'x' is nonlocal and global"
        x = None

Global declaration after global statement

def f():
    global x
    # TODO this should also not be an error
    y = x  # error: [unresolved-reference] "Name `x` used when not defined"
    x = 1  # No error.

x = 2

Semantic syntax errors

Using a name prior to its global declaration in the same scope is a syntax error.

x = 1

def f():
    print(x)  # TODO: error: [invalid-syntax] name `x` is used prior to global declaration
    global x
    print(x)

def f():
    global x
    print(x)  # TODO: error: [invalid-syntax] name `x` is used prior to global declaration
    global x
    print(x)

def f():
    print(x)  # TODO: error: [invalid-syntax] name `x` is used prior to global declaration
    global x, y
    print(x)

def f():
    global x, y
    print(x)  # TODO: error: [invalid-syntax] name `x` is used prior to global declaration
    global x, y
    print(x)

def f():
    x = 1  # TODO: error: [invalid-syntax] name `x` is used prior to global declaration
    global x
    x = 1

def f():
    global x
    x = 1  # TODO: error: [invalid-syntax] name `x` is used prior to global declaration
    global x
    x = 1

def f():
    del x  # TODO: error: [invalid-syntax] name `x` is used prior to global declaration
    global x, y
    del x

def f():
    global x, y
    del x  # TODO: error: [invalid-syntax] name `x` is used prior to global declaration
    global x, y
    del x

def f():
    del x  # TODO: error: [invalid-syntax] name `x` is used prior to global declaration
    global x
    del x

def f():
    global x
    del x  # TODO: error: [invalid-syntax] name `x` is used prior to global declaration
    global x
    del x

def f():
    del x  # TODO: error: [invalid-syntax] name `x` is used prior to global declaration
    global x, y
    del x

def f():
    global x, y
    del x  # TODO: error: [invalid-syntax] name `x` is used prior to global declaration
    global x, y
    del x

def f():
    print(f"{x=}")  # TODO: error: [invalid-syntax] name `x` is used prior to global declaration
    global x

# still an error in module scope
x = None  # TODO: error: [invalid-syntax] name `x` is used prior to global declaration
global x