Skip to content

Match statement + exception on default case doesn't narrow properly #1384

@drewbrew

Description

@drewbrew

Summary

Example function:

def do_something(interval: str, number_of_periods: int | None = None) -> None:
    match interval:
        case "monthly":
            if number_of_periods is None:
                number_of_periods = 12
            # do other stuff here
        case "daily":
            if number_of_periods is None:
                number_of_periods = 30
        case "hourly":
            if number_of_periods is None:
                number_of_periods = 24
        case _:
            raise ValueError(f"Unknown interval {interval}")
    if number_of_periods < 0 or number_of_periods > 50:
        raise ValueError(f"Invalid number of periods {number_of_periods}")
    # now fetch some data or something, IDK

Running ty check on this function returns two errors because ty does not catch that number_of_periods has to be an int at that point (each branch of the match either coerces that variable into an int or fails out with an exception).

error[unsupported-operator]: Operator `<` is not supported for types `None` and `int`, in comparing `int | None` with `Literal[0]`
  --> ty_fail.py:15:8
   |
13 |         case _:
14 |             raise ValueError(f"Unknown interval {interval}")
15 |     if number_of_periods < 0 or number_of_periods > 50:
   |        ^^^^^^^^^^^^^^^^^^^^^
16 |         raise ValueError(f"Invalid number of periods {number_of_periods}")
17 |     # now fetch some data or something, IDK
   |
info: rule `unsupported-operator` is enabled by default

error[unsupported-operator]: Operator `>` is not supported for types `None` and `int`, in comparing `int | None` with `Literal[50]`
  --> ty_fail.py:15:33
   |
13 |         case _:
14 |             raise ValueError(f"Unknown interval {interval}")
15 |     if number_of_periods < 0 or number_of_periods > 50:
   |                                 ^^^^^^^^^^^^^^^^^^^^^^
16 |         raise ValueError(f"Invalid number of periods {number_of_periods}")
17 |     # now fetch some data or something, IDK
   |
info: rule `unsupported-operator` is enabled by default

This may be related to #1349 but I'm not 100% sure.

Version

ty 0.0.1-alpha.23

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions