Skip to content

Incorrectly narrows type from signature annotation to Never #20467

@RolandSaur

Description

@RolandSaur

Bug Report

When taking the parameter type from the signature, mypy incorrectly thinks that the annotation of type <class 'type'> is the actual type of the variable.

To Reproduce

In the following example, process_signature extracts the type of input from the signature of a function and then tries to match it to int or float. However the type of input_type is <class 'type'> not int or float. Therefore, when the code is run assert_never is reached.

from typing import Callable, assert_never, reveal_type
from inspect import signature


def takes_int(x: int) -> None:
    print(f"{x} is a int")

def process_signature(
        func: Callable[[int], None] | Callable[[float], None]
) -> None:
    input_type = signature(func).parameters['x'].annotation
    reveal_type(input_type)  # Runtime type is 'type' => should reach `case _:`
    match input_type:
        case int():
            print("This is an int")
        case float():
            print("This is a float")
        case _:
            assert_never(input_type)  # this is reached during runtime


process_signature(takes_int)

Expected Behavior

mypy to complain that input to assert_never is <class 'type'> but expected Never.

Actual Behavior

mypy does not complain.

Your Environment

  • Mypy version used: 1.19.1
  • Mypy command-line flags: None
  • Mypy configuration options from mypy.ini (and other config files): None
  • Python version used: 3.13.7

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugmypy got something wrong

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions