Skip to content

Nonlocal float | None variable asserted to not be None still has None in its type #2649

@dscorbett

Description

@dscorbett

Summary

When a nonlocal variable of inferred type float | None is known (by control flow) not to be an int and is known (by assertion) not to be None, ty detects its type as int | float | None, ignoring the assertion. Example:

$ cat >bug.py <<'# EOF'
def _(maybe_float: float | None, certain_int: int, flag: bool) -> None:
    if isinstance(maybe_float, int):
        return
    x = maybe_float
    def _() -> None:
        nonlocal x
        if flag:
            x = certain_int
        assert x is not None
        +x
# EOF

$ ty check bug.py
error[unsupported-operator]: Unary operator `+` is not supported for object of type `int | float | None`
  --> bug.py:10:9
   |
 8 |             x = certain_int
 9 |         assert x is not None
10 |         +x
   |         ^^
   |
info: rule `unsupported-operator` is enabled by default

Found 1 diagnostic

Version

ty 0.0.14 (16597f5 2026-01-26)

Metadata

Metadata

Assignees

Labels

narrowingrelated to flow-sensitive type narrowing

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions