Although the method signature in Sub is compatible with Super, mypy rejects the override: Signature of "method" incompatible with supertype "Super". I'm using  python 3.13.1 mypy 1.14.0  First, I made following test.pyi. from typing import overload class Super: def method(self, arg:Other|Super)->Super: pass class Sub(Super): @overload def method(self, arg:Other|Sub)->Sub: pass @overload def method(self, arg:Super)->Super: pass class Other: pass  Then, when I ran mypy test.pyi in command line, mypy produced the following diagnostic: test.pyi:7: error: Signature of "method" incompatible with supertype "Super" [override] test.pyi:7: note: Superclass: test.pyi:7: note: def method(self, arg: Other | Super) -> Super test.pyi:7: note: Subclass: test.pyi:7: note: @overload test.pyi:7: note: def method(self, arg: Other | Sub) -> Sub test.pyi:7: note: @overload test.pyi:7: note: def method(self, arg: Super) -> Super Found 1 error in 1 file (checked 1 source file)  I checked type of both Super.method and Sub.method's I/O, and found that there's no pattern that violates LSP (Liskov Substitution Principle). Overloaded Sub.method can  input arg of type Other|Super (= Other|Sub + Super) and output type Super (= Sub + Super ).  Above input and output type matches the signature of Super.method . So, I have no idea to be Signature of "method" incompatible with supertype "Super". Following is I/O table of method.    I\O Super.method Sub.method Compared to Super, Sub's return is: Adhering to LSP*     Other Super Sub narrower Yes   Sub Super Sub narrower Yes   Super Super Super the same Yes   Other|Sub Super Sub narrower Yes   Other|Super Super Super** the same Yes    *The LSP requires that the return type of a sub method be narrower or equal to the return type of the super method. **Sub.method returns  Sub when Other input and Super when Super input,  so it returns Sub|Super when Other|Super input. Sub|Super means Super. As you can see from the table above, there are no patterns that violate LSP.  So, I think that mypy error message Signature of "method" incompatible with supertype "Super" is incorrect. Is my code wrong? Also, if my code is not wrong and mypy's error message is wrong, where can I ask?  P.S. Quick way to hide the error. Although it's not a complete solution, I found a simple way to hide the error. from typing import overload class Super: def method(self, arg:Other|Super)->Super: pass class Sub(Super): @overload def method(self, arg:Other|Sub)->Sub: pass @overload def method(self, arg:Super)->Super: pass # Start of hiding error @overload def method( # type: ignore[overload-cannot-match] self, arg:Other|Super)->Super: pass # End of hiding error class Other: pass  As a last overload, I added a Sub.method with the exact same signature as Super.method. However, when this issue is resolved in a future version, it will mean that the code I added will not be reached and we should get a [overload-cannot-match] error. Therefore, I added # type: ignore[overload-cannot-match] to ignore this error in advance. (At first glance, it may seem like I am simply silencing errors with type: ignore, but this is not relevant to mypy as of now. This is merely a deterrent against future error.)
As pointed out in a pyright ticket about this, the typing spec mentions this behaviour explicitly:  If a callable B is overloaded with two or more signatures, it is assignable to callable A if at least one of the overloaded signatures in B is assignable to A  There's a mypy ticket asking about the same problem. However, your code is in fact safe, and the table in your post proves that. That's just a limitation of the specification and/or typecheckers. As discussed in comments, it may seem like the problem is the union type itself (Other | Super can't be dispatched to either of overloads), but it isn't true: mypy uses union math in that case, and overloaded call return type is a union of return types of matched overloads if all union members can be dispatched to one of them. Here's the source where this magic happens, read the comments there if you're interested - the main checker path is documented well. Now, given that your code doesn't typecheck only due to a typechecker/spec issue, you have several options:  # type: ignore[override] - why not? Your override is safe, just tell mypy to STFU.  Add a signature to match the spec requirements as in your last paragraph. But please don't add an unused ignore comment - there's a --warn-unused-ignores flag for mypy which is really useful. Don't add such ignore, just add a free-text comment explaining the problem and linking here or to the mypy issue.  Just extend the second signature. That's safe - overloads are tried in order, the first match wins (well, not exactly, but in simple cases without *args/**kwargs and ParamSpec that's true): class Sub(Super): @overload def method(self, arg: Other | Sub) -> Sub: ... @overload def method(self, arg: Other | Super) -> Super: ...    But I'd just go with an ignore comment and explain the problem: class Sub(Super): # The override is safe, but doesn't conform to the spec. # https://github.com/python/mypy/issues/12379 @overload # type: ignore[override] def method(self, arg: Other | Sub) -> Sub: ... @overload def method(self, arg: Super) -> Super: ... 