Repository: python/mypy
Pull request: Added error code for overlapping function signatures
Closes #17570. This is my first contribution to mypy! 🐍 
Added an error code for overlapping function signatures.
Test in check-errorcodes.test is a derivative of this post: https://stackoverflow.com/q/69341607




Problem statement:
Use a more specific error code for overlapping function signatures
Hi, would it be possible to add a more specific error code for the `Overloaded function signature x will never be matched` error?

I want to be able to disable it in the config without also disabling every other `misc` error.

Hints from issue discussion:
Seems reasonable. In general we should minimize use of the `misc` code.

Commit message: [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

Patch to review:
diff --git a/docs/source/error_code_list.rst b/docs/source/error_code_list.rst
index 64d9a1d03287..31c2a27f8954 100644
--- a/docs/source/error_code_list.rst
+++ b/docs/source/error_code_list.rst
@@ -1149,6 +1149,32 @@ types you expect.
 
 See :ref:`overloading <function-overloading>` for more explanation.
 
+
+.. _code-overload-cannot-match:
+
+Check error code of overload function signature match
+--------------------------------------------------------------------------
+
+In the case of an overloaded function, if one of the signatures is never accessible, this error may occur.
+An example where this can occur is with the utilization of floats and int types, due to the behavior of integers matching floats in mypy.
+Consider swapping the declaration of the two types so that the narrower signature is declared before the broader signature.
+
+Example:
+
+.. code-block:: python
+
+    from typing import overload, Union
+
+    @overload
+    def process(response1: float,response2: float) -> float:
+        ...
+    @overload
+    def process(response1: int,response2: int) -> int: # E: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader  [overload-cannot-match]
+        ...
+
+    def process(response1,response2)-> Union[float,int]:
+    return response1 + response2
+
 .. _code-annotation-unchecked:
 
 Notify about an annotation in an unchecked function [annotation-unchecked]
diff --git a/mypy/errorcodes.py b/mypy/errorcodes.py
index 6e8763264ddd..9f7b340f43f0 100644
--- a/mypy/errorcodes.py
+++ b/mypy/errorcodes.py
@@ -273,6 +273,14 @@ def __hash__(self) -> int:
 # This is a catch-all for remaining uncategorized errors.
 MISC: Final[ErrorCode] = ErrorCode("misc", "Miscellaneous other checks", "General")
 
+OVERLOAD_CANNOT_MATCH: Final[ErrorCode] = ErrorCode(
+    "overload-cannot-match",
+    "Warn user about signature matching for overloaded functions.",
+    "General",
+    sub_code_of=MISC,
+)
+
+
 OVERLOAD_OVERLAP: Final[ErrorCode] = ErrorCode(
     "overload-overlap",
     "Warn if multiple @overload variants overlap in unsafe ways",
diff --git a/mypy/message_registry.py b/mypy/message_registry.py
index 29d539faaed6..a3e087296ee9 100644
--- a/mypy/message_registry.py
+++ b/mypy/message_registry.py
@@ -362,3 +362,8 @@ def with_additional_msg(self, info: str) -> ErrorMessage:
 TYPE_ALIAS_WITH_AWAIT_EXPRESSION: Final = ErrorMessage(
     "Await expression cannot be used within a type alias", codes.SYNTAX
 )
+
+# Overloads
+OVERLOADED_FUNCTION_SIGNATURE: Final = ErrorMessage(
+    "Overloaded function signature {} will never be matched", codes.OVERLOAD_CANNOT_MATCH
+)
diff --git a/mypy/messages.py b/mypy/messages.py
index 62846c536f3d..dadce149680e 100644
--- a/mypy/messages.py
+++ b/mypy/messages.py
@@ -1653,6 +1653,7 @@ def overloaded_signature_will_never_match(
                 index1=index1, index2=index2
             ),
             context,
+            code=codes.OVERLOAD_CANNOT_MATCH,
         )
 
     def overloaded_signatures_typevar_specific(self, index: int, context: Context) -> None:
diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test
index c4d72388fba9..08cf01d2189e 100644
--- a/test-data/unit/check-errorcodes.test
+++ b/test-data/unit/check-errorcodes.test
@@ -1196,3 +1196,17 @@ def f(x: str) -> TypeIs[int]:  # E: Narrowed type "int" is not a subtype of inpu
     pass
 
 [builtins fixtures/tuple.pyi]
+
+
+[case testOverloadedFunctionSignature]
+from typing import overload, Union
+
+@overload
+def process(response1: float,response2: float) -> float:
+    ...
+@overload
+def process(response1: int,response2: int) -> int: # E: Overloaded function signature 2 will never be matched: signature 1's parameter type(s) are the same or broader  [overload-cannot-match]
+    ...
+
+def process(response1,response2)-> Union[float,int]:
+   return response1 + response2


Code review comments:
diff_hunk: @@ -1149,6 +1149,32 @@ types you expect.
 
 See :ref:`overloading <function-overloading>` for more explanation.
 
+
+.. _code-overload-cannot-match:
+
+Check error code of overload function signature match
+--------------------------------------------------------------------------
+
+In the case of an overloaded function, if one of the signatures is never accessible, this error may occur.
+An example where this can occur is with the utilization of floats and int types, due to the behavior of integers matching floats in mypy.
path: docs/source/error_code_list.rst
text: @user1:
An example involving float/int isn't great because it relies on another subtle part of the type system. Better to give an example that is more basic, such as having the first overload take `object` and the second `int`.

@author:
Valid point. I made some edits to this- please let me know if that looks ok.

diff_hunk: @@ -362,3 +362,8 @@ def with_additional_msg(self, info: str) -> ErrorMessage:
 TYPE_ALIAS_WITH_AWAIT_EXPRESSION: Final = ErrorMessage(
     "Await expression cannot be used within a type alias", codes.SYNTAX
 )
+
+# Overloads
+OVERLOADED_FUNCTION_SIGNATURE: Final = ErrorMessage(
path: mypy/message_registry.py
text: @user1:
This seems unused.

diff_hunk: @@ -1149,6 +1149,32 @@ types you expect.
 
 See :ref:`overloading <function-overloading>` for more explanation.
 
+
+.. _code-overload-cannot-match:
+
+Check error code of overload function signature match
path: docs/source/error_code_list.rst
text: @user1:
```suggestion
Check for overload signatures that cannot match [overload-cannot-match]
```