Open RenDelaCruz opened 8 months ago
I poked at it a little and there is a bug here but I wanted to clarify that this is not influenced by the scope: it has to do with the type of the match
"subject".
In your global scope example the subject has type A
but in the function, the subject, obj
has type object
.
If we remove the match statement:
python3 -c 'o = object(); o.id'
you'll get an AttributeError
. ✅python3 -m mypy -c 'o = object(); o.id'
: ✅error: "object" has no attribute "id" [attr-defined]
However, with a match statment it's a bit different
match object():
case object(id=object_id):
print("match")
case _:
print("no match")
error: Class "builtins.object" has no attribute "id"
The match
statement is more like a hasattr()
check, which mypy does have the ability to handle. But changing the behaviour to do that then opens up false negatives where mypy fails to warn you about typos etc.
A similar question was recently posted to the pyright issue tracker. From my perspective, this is a legitimate use of pattern matching. Pyright therefore does not generate a type error for the code at the top of this thread. As @TeamSpen210 notes, this comes at the expense of some potential false negatives.
I agree, using object()
in this case is a legitimate use of pattern matching. Since this works with regular Python, and reduces excessive use of hasattr
checks.
Perhaps mypy should make an exception for subjects with an object
type, when used in match case statements only
Bug Report
In the global scope, mypy allows destructuring any object in
match case
withobject(x=y)
:However, in a method, mypy errors out trying to use
object(x=y)
inmatch case
:Edit: Turns out, it is not due to scoping, but due to the type of the
match <subject>
. See https://github.com/python/mypy/issues/16912#issuecomment-1939638659To Reproduce
mypy playground: https://mypy-play.net/?mypy=latest&python=3.12&gist=c5799b1b128c52894f2879f9fc8d0115
Expected Behavior
Should allow using
case object(x=y)
inmatch case
syntax.Actual Behavior
Errors out trying
case object(x=y)
inmatch case
syntax, inside a method. Does not error out in global scope.Your Environment
mypy.ini
(and other config files):