microsoft / microsoft/pyright

Wrong (missing?) type inference on `{}` in match/case

Open
#11,133 0 comments 0 reactions 0 assignees View on GitHub
bug
Dominant language
Python
Stars
15.6k
Forks
1.8k
Avg merge
12h 13m
Merged PRs (30d)
52

Description

**Describe the bug**

A `case {}:` as a match branch does not cause the matched value to be inferred to be a dict.

**Code or Screenshots**

```python
from typing import reveal_type

def foo(x: tuple[str, str] | tuple[str, str, str] | dict[str, str] | None) -> None:
reveal_type(x)
match x:
case (a, b):
reveal_type(x)
print("pair")
case {"a": "1"}:
reveal_type(x)
print("a1 dict")
case {}:
reveal_type(x)
print("dict from {}")
case dict():
reveal_type(x)
print("dict from dict()")

foo(("a", "b"))
foo({"a": "1"})
foo({"a": "2"})
```

pyright 1.1.407 reports:
```
typecheck.py:4:17 - information: Type of "x" is "tuple[str, str] | tuple[str, str, str] | dict[str, str] | None"
typecheck.py:7:25 - information: Type of "x" is "tuple[str, str]"
typecheck.py:10:25 - information: Type of "x" is "dict[str, str]"
typecheck.py:13:25 - information: Type of "x" is "tuple[str, str, str] | dict[str, str] | None"
typecheck.py:16:25 - information: Type of "x" is "dict[str, str]"
```

Whereas running the script confirms that the `{}` branch is indeed taken by the 3rd call:
```
$ python3 src/a14y/typecheck.py
Runtime type is 'tuple'
Runtime type is 'tuple'
pair
Runtime type is 'dict'
Runtime type is 'dict'
a1 dict
Runtime type is 'dict'
Runtime type is 'dict'
dict from {}
```

Thus I expect we should see instead:
```
typecheck.py:4:17 - information: Type of "x" is "tuple[str, str] | tuple[str, str, str] | dict[str, str] | None"
typecheck.py:7:25 - information: Type of "x" is "tuple[str, str]"
typecheck.py:10:25 - information: Type of "x" is "dict[str, str]"
typecheck.py:13:25 - information: Type of "x" is "dict[str, str]"
```

(line 16 not being emitted, as is the case for other unreachable patterns)

Contributor guide

Open the contributing guide

Research direction

Start with the reproducer in src/a14y/typecheck.py and run it with pyright 1.1.407 to confirm the current narrowing and unreachable-pattern diagnostics. Trace the match/case type-inference behavior for the {} pattern, then verify that x narrows to dict[str, str] in that branch and that the later dict() branch is reported as unreachable.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
compilers
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.