Skip to content

isinstance(value, type) on Union with type[T] as possible type narrows to type instead of type[T] #3435

Description

@Keymasterer44

Describe the Bug

On code like the following (code can also be seen in the attached sandbox link):

from typing import *

T = TypeVar("T")


def generic_list_function(value: T | list[T]) -> None:
    if isinstance(value, list):
        reveal_type(value)


def generic_type_function(value: T | type[T]) -> None:
    if isinstance(value, type):
        reveal_type(value)

I would expect the reveal_type(value) of both functions to respectively provide list[T] and type[T] based on the union type that's being narrowed, the same behaviour as what Pyright would infer.
While the list[T] narrowing works as expected, Pyrefly narrows the T | type[T] to just type instead of type[T] after the isinstance check, completely discarding the generic type parameter.

This behaviour is particularly inconvenient when migrating a larger project from Pyright to Pyrefly since there's no way I can think of to easily change the check to one that Pyrefire interprets correctly.
If needed, I can also provide samples of the real production code where I noticed this issue.

Sandbox Link

https://pyrefly.org/sandbox/?project=N4IgZglgNgpgziAXKOBDAdgEwEYHsAeAdAA4CeS4ATrgLYAEALqcROgOZ0Q3G6UN0AqADroRAFToBeOmOYwAaqkoAKISDFqAlCJ1YYYOmxjoYlCAGMA%2BlAhwGlsAFd05hhFzplAN1RRHMRBk6AB86GzsAbTEAXU06AFoAPjoAOQ8AkToszgNbVjsMcxhvX38AGjDbBk1ETOz6yhgvGF9LJmJinz8YOLoAYjpG5t84SsiYulRRmHwO1xhMXRFMfUNjUws2uQdnV3dPLv9AiVD2mCjYhOS0k1r0eohcuHyGQs7SmAqzmrr6rKGWlAth0St1egMAO64RxQTB0GZzfhnC4VAEjRhyTjoOwtRboEBlEBkRpgKCkQgMWhQCgDAAKpBJZLoaCweHwdHMHkgbEclFQbg8hBEAwAyjAYHQABYMBjEOCIAD0CuJ%2BjJhF4bAVxgVmFw5jgCs56G5vP5%2BwVdDAvEmPmgqGwsA5XIgPL5AvuuGI7rgQvQZAYko88WalGeHikdDUAGZCABGABMahEEVM1FD0REzi4PD4C3imAgjT2zQjAHIXeheDBSyJKwx4o0AI6OQt5gDWMFI8VQ5iKcFG0lLEKU6Br%2BIAvoSe25mgAxaAwCgsnAEEjkcdAA

(Only applicable for extension issues) IDE Information

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    narrowingIssues with narrowing - root cause is usually narrowing, flow handling, or bothtypechecking

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions