Skip to content

Narrow nonlocal type based on position of inner scope #710

Open
@sharkdp

Description

@sharkdp

With astral-sh/ruff#18750 merged, we now consider all reachable bindings for nonlocal types. This can cause overly wide union types in cases where the inner scope is only executed after narrowing the type in the outer scope through an assignment. For example:

def outer(x=None):
    # …

    x = 1

    def inner():
        reveal_type(x)  # Unknown | None | Literal[1], should not contain `None`
    
    inner()

This should be fixed by considering the position of the inner scope within the enclosing scope. Only bindings that appear after the definition of the inner scope should be considered.

A similar problem appears with type narrowing through conditions.

def outer(x: int | None):
    if x is not None:
        def inner():
            reveal_type(x)  # int | None, should be int
        
        inner()

Fixing this as well might follow a similar strategy, if we implement the "treat every new narrowing of a definition as a new definition" strategy proposed in #690.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions