Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Should *args narrow in type guards? #14273

Open
A5rocks opened this issue Dec 10, 2022 · 3 comments
Open

Should *args narrow in type guards? #14273

A5rocks opened this issue Dec 10, 2022 · 3 comments

Comments

@A5rocks
Copy link
Contributor

A5rocks commented Dec 10, 2022

While making a PR I found a TODO that goes along the lines of "is *args support for TypeGuard even worth it?"

I want to approach this from a different perspective. Pyright supports this:

from typing_extensions import TypeGuard

def typeguard(*args: object) -> TypeGuard[int]:
  ...

def f(x: object, y: object) -> None:
  if typeguard(x, y):
    reveal_type(x)  # revealed `int`
    reveal_type(y)  # revealed `object`

I'm ... not quite sure that should be allowed. Going strictly by the specification:

Type checkers should assume that type narrowing should be applied to the expression that is passed as the first positional argument to a user-defined type guard.

(PEP 647, emphasis my own)

Notice how it says first and argument (no s). (and the "passed as" sets up that we're talking about function signature, not how the function is called)


Anyways, given that:

  • other type checkers support it
  • but it doesn't seem widely used (there's been no issue on here AFAICT about it)
  • it's not part of the specification
  • it's not clear how it should extend (first *args argument (like pyright)? all of them (which would allow more flexibility)?)

Should this even be attempted in the first place? I'm in favor of removing the TODO.

@A5rocks
Copy link
Contributor Author

A5rocks commented Dec 13, 2022

cc @erictraut as creator of pyright and typeguard PEP writer.

  1. Is this intended behavior on the part of pyright?
  2. And if it is, do you recommend mypy follow suit?

@erictraut
Copy link

I have to admit that I hadn't considered the use of an *args parameter in a user-defined type guard function when I wrote PEP 647. I think it's ill-advised to implement a type guard function that starts with an *args because it's ambiguous what the behavior should be — or what the intent of the function's author was.

Pyright's implementation happens to handle this case. If it's simple for this to be fixed in mypy, then it might be worth making the change. I think it's also fine for mypy's maintainers to say "this is undefined behavior, so don't use *args as the first parameter to a user-defined type guard function".

@A5rocks
Copy link
Contributor Author

A5rocks commented Dec 13, 2022

Alright. I suspect it would be somewhat simple to handle, but will have to check in a while -- it's very likely, though, that I'll end up leaving the TODO alone. I'll leave this issue open in case someone with actual say in mypy wants to leave their opinion :P

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

No branches or pull requests

2 participants