-
Notifications
You must be signed in to change notification settings - Fork 219
Description
Summary
While reading astral-sh/ruff#21172 , I wanted to try using the changes that PR made, but found a bug. With this code:
from typing import reveal_type
def foo[T: (list[int], None)](x: T) -> T:
match x:
case list():
reveal_type(x) # Revealed type: `Top[list[Unknown]]`
if isinstance(x, list):
reveal_type(x) # Revealed type: `Top[list[Unknown]]`
return xThe two xs should be narrowed to list[int], not Top[list[Unknown]]. From what I understand reading astral-sh/ruff#21172 , the code now converts the constraint to the union of the top of it's members in the narrowing, so T becomes Top[list[int]] | Top[None], but since list[int] is a fully static type, Top[list[int]] should just be list[int]. So it looks like the generic information is getting discarded somewhere along the way.
Edit:
I did some messing around with ty versions, and I found some interesting things:
In <=alpha.21 both reveal T@foo & list[Unknown]
In alpha.22 - alpha.25 only the isinstance gives Top[list[Unknown]], the match is still T@foo & list[Unknown]
In the playground (and presumably in the future alpha.26) the above behavior happens.
So it looks like this is not a new issue, at least for isinstance narrowing.
Version
playground (3c8fb6876)