facebook / facebook/pyrefly

Narrowing lost after excluding the only None case

Open
#3,374 2 comments 1 reaction 1 assignee Claimed by @asukaminato0721 View on GitHub
narrowing typechecking
Dominant language
Rust
Stars
7k
Forks
516
PR merge metrics
No merged PRs in 30d

Description

### Describe the Bug

## Summary

Pyrefly reports an unsupported operation on an optional value even after an earlier guard excludes the only `None` case that would make the operation invalid.

## Repro

```python
from datetime import date

def foo(x: float | None, y: date | None, z: date) -> float:
if x is None and y is None:
raise ValueError()

if x is None:
return (y - z).days / 365.25

return x
```

## What Pyrefly Reports

On `y - z`, Pyrefly reports:

```text
`-` is not supported between `None` and `date`
Cannot find `__sub__` or `__rsub__`
```

Hover/type info still shows:

```text
(parameter) y: date | None
```

even inside:

```python
if x is None:
```

## Expected

Inside `if x is None:`, `y` should be narrowed to `date`.

The earlier guard already excluded:

```python
x is None and y is None
```

so once control reaches:

```python
if x is None:
```

the `y is None` case should no longer be possible.

## Actual

Pyrefly continues to treat `y` as `date | None` and reports the subtraction as invalid.

## Environment

- pyrefly: `1.0.0`
- python: `3.14.4`
- platform: `Linux 6.17.0-1013-aws x86_64`
- reproduction context: `both`

### Sandbox Link

_No response_

### (Only applicable for extension issues) IDE Information

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.