Skip to content

Commit

Permalink
Fix type inference of positional parameter in class pattern involving…
Browse files Browse the repository at this point in the history
… builtin subtype (#18141)

Fixes #18140

### Demo
```python
from typing import reveal_type

class A(str):
    pass

class B(str):
    __match_args__ = ("b",)
    
    @Property
    def b(self) -> int: return 1


match A("a"):
    case A(a):
        reveal_type(a)  # before: Revealed type is "__main__.A"
                        # after:  Revealed type is "__main__.A"
        print(type(a))  # output: <class '__main__.A'>

match B("b"):
    case B(b):
        reveal_type(b)  # before: Revealed type is "__main__.B"
                        # after:  Revealed type is "builtins.int"
        print(type(b))  # output: <class 'int'>
```
  • Loading branch information
brianschubert authored Nov 11, 2024
1 parent 3b00002 commit 54a2c6d
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 1 deletion.
4 changes: 3 additions & 1 deletion mypy/checkpattern.py
Original file line number Diff line number Diff line change
Expand Up @@ -693,7 +693,9 @@ def visit_class_pattern(self, o: ClassPattern) -> PatternType:

def should_self_match(self, typ: Type) -> bool:
typ = get_proper_type(typ)
if isinstance(typ, Instance) and typ.type.is_named_tuple:
if isinstance(typ, Instance) and typ.type.get("__match_args__") is not None:
# Named tuples and other subtypes of builtins that define __match_args__
# should not self match.
return False
for other in self.self_match_types:
if is_subtype(typ, other):
Expand Down
19 changes: 19 additions & 0 deletions test-data/unit/check-python310.test
Original file line number Diff line number Diff line change
Expand Up @@ -648,6 +648,25 @@ match m:
reveal_type(m) # N: Revealed type is "builtins.tuple[Any, ...]"
[builtins fixtures/primitives.pyi]

[case testMatchClassPatternCaptureSelfSubtype]
class A(str):
pass

class B(str):
__match_args__ = ("b",)
b: int

def f1(x: A):
match x:
case A(a):
reveal_type(a) # N: Revealed type is "__main__.A"

def f2(x: B):
match x:
case B(b):
reveal_type(b) # N: Revealed type is "builtins.int"
[builtins fixtures/tuple.pyi]

[case testMatchInvalidClassPattern]
m: object

Expand Down

0 comments on commit 54a2c6d

Please sign in to comment.