Skip to content

[red-knot] Add understanding of terminal statements to control-flow analysis #14014

@AlexWaygood

Description

@AlexWaygood

red-knot currently issues false positives on the following snippets:

def str_instance() -> str:
    return "foo"

some_string = str_instance()


try:
    x = some_string[5]
except IndexError:
    raise ValueError("no")
print(x)  # false positive 'possibly not defined' error here


def f():
    try:
        y = some_string[5]
    except IndexError:
        return
    print(y)  # false positive 'possibly not defined' error here


while True:
    try:
        z = some_string[5]
    except IndexError:
        continue
    print(z)  # false positive 'possibly not defined' error here

    try:
        aa = some_string[5]
    except IndexError:
        break
    print(aa)  # false positive 'possibly not defined' error here

In all of these situations, we see that a variable is declared in the try branch but not the except branch of the try/except block. We realise that either branch could be taken, so we union together the boundedness of the two branches to conclude that the variable is possibly unbound at the point where it is read later in the same scope.

What we're missing is special understanding of the return, raise, break and continue statements. When we union together the boundedness of the branches, we need to exclude all branches that always end in one of these statements, because we can determine that later statements in the same scope will be unreachable by branches that always end in one of those statements.

Metadata

Metadata

Assignees

Labels

tyMulti-file analysis & type inference

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions