Skip to content

Conversation

@randolf-scholz
Copy link
Contributor

Fixes #14014

Added an extra elif branch that checks if we are matching against typing.Callable, and uses callable_with_ellipsis to treat it as a Callable[..., Any].

Comment on lines +558 to +559
isinstance(type_info, Var)
and type_info.type is not None
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these two conditions are also checked in the elif before and below, but I did not bother to try to optimize them away.

):
# Consider as `Callable[..., Any]`
fallback = self.chk.named_type("builtins.function")
any_type = AnyType(TypeOfAny.unannotated)
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure if this is the right type of Any; I was guessing based on the description.

@github-actions

This comment has been minimized.

@randolf-scholz
Copy link
Contributor Author

randolf-scholz commented Jul 16, 2025

Hm, this probably can be improved quite a bit, since currently it always infers Callalbe[..., Any], but better would be to get the same inference as in a case fn if callable(fn) branch.

Comment on lines +565 to +567
fn_type = callable_with_ellipsis(any_type, ret_type=any_type, fallback=fallback)
# if typ is itself callable, use its own type, otherwise Callable[..,, Any]
typ = current_type if is_subtype(current_type, fn_type) else fn_type
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found a solution now to get more precise narrowing, e.g.

def int_fun(x: int) -> int: return x+1

match int_fun:
    case Callable() as fn:
        reveal_type(fn)  # N: Revealed type is "def (x: builtins.int) -> builtins.int"

I'm sure there's a more elegant way to do it, but this is the only thing I came up with.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hm, this doesn't work as desired when e.g. x: Callable[[int], int] | str, we get Callable[..., Any] and not Callable[[int], int].

I guess we need to patch the conditional_types_with_intersection function instead?

@randolf-scholz
Copy link
Contributor Author

randolf-scholz commented Jul 16, 2025

Closing temporarily to find a better solution that yields correct narrowing logic.

@github-actions
Copy link
Contributor

According to mypy_primer, this change doesn't affect type check results on a corpus of open source code. ✅

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

match-case class checking against collection.abc.Callable raises error [misc]

1 participant