# Exhaustive Checks with Mypy

If you want to exhaustively check an enum (or a literal) and have Mypy tell you when you forgot a case, you can [write yourself a tiny utility function](https://mypy.readthedocs.io/en/latest/literal_types.html#exhaustiveness-checking):

```python
from typing import NoReturn

def unreachable(v: NoReturn) -> NoReturn:
    raise AssertionError()
```

You can then use it with `match` (on Python 3.10) or `is`:

```python

import enum

from .utils import unreachable

class Fruit(enum.Enum):
    APPLE = enum.auto()
    BANANA = enum.auto()

def using_match(fruit: Fruit) -> int:
    match fruit:
        case Fruit.APPLE:
            return 1
        case Fruit.BANANA:
            return 2
        case _:
            unreachable(fruit)
        
def using_is(fruit: Fruit) -> int:
    if fruit is Fruit.APPLE:
        return 1
    elif fruit is Fruit.BANANA:
        return 2
    else:
        unreachable(fruit)
```

But beware that [this won't work for enums](https://github.com/python/mypy/issues/6366) when using `==` as Mypy can't know whether the operator has been overridden:

```python
def using_eq(fruit: Fruit) -> int:
    if fruit == Fruit.APPLE:
        return 1
    elif fruit == Fruit.BANANA:
        return 2
    else:
        # error: Argument 1 to "unreachable" has incompatible
        #   type "Fruit"; expected "NoReturn"  [arg-type]
        unreachable(fruit)
```
