Skip to content

Protocol with __call__ method hides type errors #377

@ojii

Description

@ojii

Summary

Callable is very restricted in what it can express (no kwargs, no optional arguments, etc) and the official Python typing documentation instructs you to use a Protocol subclass with a __call__ method instead. However with ty this does not work as expected.

Given the following code:

from typing import Protocol


class MyCallable(Protocol):
    def __call__(self, arg: int) -> int: ...


def func(mc: MyCallable) -> int:
    return mc(1)


# expect to type check
func(lambda n: 1)

# expect to fail check
func(lambda: None)


def x(arg: int) -> int:
    return 1


# expect to type check
func(x)


def y(arg: str) -> str:
    return "a"


# expect to fail check
func(y)


# expect to type check, but fails with call-non-callable on F
def func2[F: MyCallable](f: F) -> int:
    return f(1)

Running ty check file.py everything passes but the check on func2, it is happy with all the calls to func even though half the arguments passed in should fail the type check.

Version

ty 0.0.1-alpha.1 (12f466e 2025-05-13)

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions