Repository: python/mypy

Issue:
Mypy reports error for different argument, than the one which is actually wrong
<!--
If you're not sure whether what you're experiencing is a mypy bug, please see the "Question and Help" form instead.
Please consider:

- checking our common issues page: https://mypy.readthedocs.io/en/stable/common_issues.html
- searching our issue tracker: https://github.com/python/mypy/issues to see if it's already been reported
- asking on gitter chat: https://gitter.im/python/typing
-->

**Bug Report**

<!--
If you're reporting a problem with a specific library function, the typeshed tracker is better suited for this report: https://github.com/python/typeshed/issues

If the project you encountered the issue in is open source, please provide a link to the project.
-->

When using generic Callables as parameters, the error is correctly reported, but it's reported for different argument than the one which is in fact wrong.

**To Reproduce**

```python
from typing import Callable, TypeVar, List

T1 = TypeVar('T1')
T2 = TypeVar('T2')

def bigfunc(
    a: int,
    b: T1,
    c: Callable[[T1], T2],
    d: Callable[[T2], str],
) -> None:
    res = d(c(b))
    print(f'{a=}, {b=}, {res=}')


# should be:
#   c_func(x: float) -> List[float]:
def c_func(x: float) -> None:
    pass

def d_func(y: List[float]) -> str:
    return str(y)

bigfunc(1, 0.1, c_func, d_func)
```

**Expected Behavior**

<!--
How did you expect mypy to behave? It’s fine if you’re not sure your understanding is correct.
Write down what you thought would happen. If you expected no errors, delete this section.
-->
I would expect mypy to complain about 3rd argument (`c - c_func`).

**Actual Behavior**

<!-- What went wrong? Paste mypy's output. -->

Mypy complains about 1st argument, which is 100% correct (`a: int`)
```
a.py:24: error: Cannot infer type argument 1 of "bigfunc"  [misc]
Found 1 error in 1 file (checked 1 source file)
```

**Your Environment**

<!-- Include as many relevant details about the environment you experienced the bug in -->

- Mypy version used: 1.16.0
- Mypy command-line flags: None
- Mypy configuration options from `mypy.ini` (and other config files): None
- Python version used: 3.11.2

<!-- You can freely edit this text, please remove all the lines you believe are unnecessary. -->



Discussion:
To clarify, it's complaining about the first type argument, not the type of the first argument. `bigfunc` takes two type arguments, one for each of `T1` and `T2`. The error is stating that it failed to infer a value for the first one, `T1`.

_However_, that's still wrong. It actually infers `T1` fine and wittles the signature of `bigfunc` down to
```
def [T2] (a: builtins.int, b: builtins.float, c: def (builtins.float) -> T2, d: def (T2) -> builtins.str)
```
mypy then fails to infer a value for `T2`, which it sees as being the first type parameter of the refined signature.
Can we just use tvar name instead of index? Names don't change when some generics are substituted, and are no less helpful for identification.
@sterliakov that would be great!



Patch:
diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py
index 4ca55e1679e4..26cb2a35794b 100644
--- a/mypy/checkexpr.py
+++ b/mypy/checkexpr.py
@@ -2338,10 +2338,10 @@ def apply_inferred_arguments(
         # Report error if some of the variables could not be solved. In that
         # case assume that all variables have type Any to avoid extra
         # bogus error messages.
-        for i, inferred_type in enumerate(inferred_args):
+        for inferred_type, tv in zip(inferred_args, callee_type.variables):
             if not inferred_type or has_erased_component(inferred_type):
                 # Could not infer a non-trivial type for a type variable.
-                self.msg.could_not_infer_type_arguments(callee_type, i + 1, context)
+                self.msg.could_not_infer_type_arguments(callee_type, tv, context)
                 inferred_args = [AnyType(TypeOfAny.from_error)] * len(inferred_args)
         # Apply the inferred types to the function type. In this case the
         # return type must be CallableType, since we give the right number of type
diff --git a/mypy/messages.py b/mypy/messages.py
index 01414f1c7f2b..13a4facc82b0 100644
--- a/mypy/messages.py
+++ b/mypy/messages.py
@@ -1370,11 +1370,14 @@ def incompatible_type_application(
             self.fail(f"Type application has too few types ({s})", context)
 
     def could_not_infer_type_arguments(
-        self, callee_type: CallableType, n: int, context: Context
+        self, callee_type: CallableType, tv: TypeVarLikeType, context: Context
     ) -> None:
         callee_name = callable_name(callee_type)
-        if callee_name is not None and n > 0:
-            self.fail(f"Cannot infer type argument {n} of {callee_name}", context)
+        if callee_name is not None:
+            self.fail(
+                f"Cannot infer value of type parameter {format_type(tv, self.options)} of {callee_name}",
+                context,
+            )
             if callee_name == "<dict>":
                 # Invariance in key type causes more of these errors than we would want.
                 self.note(


Test patch:
diff --git a/test-data/unit/check-dataclasses.test b/test-data/unit/check-dataclasses.test
index 30d8497c9cd2..2ead202bd6af 100644
--- a/test-data/unit/check-dataclasses.test
+++ b/test-data/unit/check-dataclasses.test
@@ -705,7 +705,7 @@ class A(Generic[T]):
     return self.z  # E: Incompatible return value type (got "list[T]", expected "T")
 
 reveal_type(A)  # N: Revealed type is "def [T] (x: T`1, y: T`1, z: builtins.list[T`1]) -> __main__.A[T`1]"
-A(1, 2, ["a", "b"])  # E: Cannot infer type argument 1 of "A"
+A(1, 2, ["a", "b"])  # E: Cannot infer value of type parameter "T" of "A"
 a = A(1, 2, [1, 2])
 reveal_type(a)  # N: Revealed type is "__main__.A[builtins.int]"
 reveal_type(a.x)  # N: Revealed type is "builtins.int"
diff --git a/test-data/unit/check-expressions.test b/test-data/unit/check-expressions.test
index f3c00627892e..33271a3cc04c 100644
--- a/test-data/unit/check-expressions.test
+++ b/test-data/unit/check-expressions.test
@@ -1878,7 +1878,7 @@ a = {'a': 1}
 b = {'z': 26, **a}
 c = {**b}
 d = {**a, **b, 'c': 3}
-e = {1: 'a', **a}  # E: Cannot infer type argument 1 of <dict> \
+e = {1: 'a', **a}  # E: Cannot infer value of type parameter "KT" of <dict> \
                    # N: Try assigning the literal to a variable annotated as dict[<key>, <val>]
 f = {**b}  # type: Dict[int, int]  # E: Unpacked dict entry 0 has incompatible type "dict[str, int]"; expected "SupportsKeysAndGetItem[int, int]"
 g = {**Thing()}
@@ -1893,7 +1893,7 @@ i = {**Thing()}  # type: Dict[int, int]  # E: Unpacked dict entry 0 has incompat
                  # N:         def keys(self) -> Iterable[int] \
                  # N:     Got: \
                  # N:         def keys(self) -> Iterable[str]
-j = {1: 'a', **Thing()}  # E: Cannot infer type argument 1 of <dict> \
+j = {1: 'a', **Thing()}  # E: Cannot infer value of type parameter "KT" of <dict> \
                          # N: Try assigning the literal to a variable annotated as dict[<key>, <val>]
 [builtins fixtures/dict.pyi]
 [typing fixtures/typing-medium.pyi]
diff --git a/test-data/unit/check-generics.test b/test-data/unit/check-generics.test
index 8839dfb954f4..0be9d918c69f 100644
--- a/test-data/unit/check-generics.test
+++ b/test-data/unit/check-generics.test
@@ -584,7 +584,7 @@ def func2(x: SameNode[T]) -> SameNode[T]:
     return x
 reveal_type(func2) # N: Revealed type is "def [T] (x: __main__.Node[T`-1, T`-1]) -> __main__.Node[T`-1, T`-1]"
 
-func2(Node(1, 'x')) # E: Cannot infer type argument 1 of "func2"
+func2(Node(1, 'x')) # E: Cannot infer value of type parameter "T" of "func2"
 y = func2(Node('x', 'x'))
 reveal_type(y) # N: Revealed type is "__main__.Node[builtins.str, builtins.str]"
 
@@ -888,7 +888,7 @@ def fun2(v: Vec[T], scale: T) -> Vec[T]:
 
 reveal_type(fun1([(1, 1)])) # N: Revealed type is "builtins.int"
 fun1(1) # E: Argument 1 to "fun1" has incompatible type "int"; expected "list[tuple[bool, bool]]"
-fun1([(1, 'x')]) # E: Cannot infer type argument 1 of "fun1"
+fun1([(1, 'x')]) # E: Cannot infer value of type parameter "T" of "fun1"
 
 reveal_type(fun2([(1, 1)], 1)) # N: Revealed type is "builtins.list[tuple[builtins.int, builtins.int]]"
 fun2([('x', 'x')], 'x') # E: Value of type variable "T" of "fun2" cannot be "str"
@@ -909,7 +909,7 @@ def f(x: Node[T, T]) -> TupledNode[T]:
     return Node(x.x, (x.x, x.x))
 
 f(1) # E: Argument 1 to "f" has incompatible type "int"; expected "Node[Never, Never]"
-f(Node(1, 'x')) # E: Cannot infer type argument 1 of "f"
+f(Node(1, 'x')) # E: Cannot infer value of type parameter "T" of "f"
 reveal_type(Node('x', 'x')) # N: Revealed type is "a.Node[builtins.str, builtins.str]"
 
 [file a.py]
diff --git a/test-data/unit/check-inference-context.test b/test-data/unit/check-inference-context.test
index 67ae22a369b1..ff726530cf9f 100644
--- a/test-data/unit/check-inference-context.test
+++ b/test-data/unit/check-inference-context.test
@@ -1009,7 +1009,7 @@ class D(C): ...
 
 def f(x: List[T], y: List[T]) -> List[T]: ...
 
-f([C()], [D()]) # E: Cannot infer type argument 1 of "f"
+f([C()], [D()]) # E: Cannot infer value of type parameter "T" of "f"
 [builtins fixtures/list.pyi]
 
 [case testInferTypeVariableFromTwoGenericTypes3]
diff --git a/test-data/unit/check-inference.test b/test-data/unit/check-inference.test
index 856d430a544c..90cb7d3799cf 100644
--- a/test-data/unit/check-inference.test
+++ b/test-data/unit/check-inference.test
@@ -693,8 +693,8 @@ class A(Generic[T]): pass
 class B: pass
 
 
-f(ao, ab) # E: Cannot infer type argument 1 of "f"
-f(ab, ao) # E: Cannot infer type argument 1 of "f"
+f(ao, ab) # E: Cannot infer value of type parameter "T" of "f"
+f(ab, ao) # E: Cannot infer value of type parameter "T" of "f"
 f(ao, ao)
 f(ab, ab)
 
@@ -3774,8 +3774,8 @@ reveal_type(f(x, []))  # N: Revealed type is "builtins.str"
 reveal_type(f(["yes"], []))  # N: Revealed type is "builtins.str"
 
 empty: List[NoReturn]
-f(x, empty)  # E: Cannot infer type argument 1 of "f"
-f(["no"], empty)  # E: Cannot infer type argument 1 of "f"
+f(x, empty)  # E: Cannot infer value of type parameter "T" of "f"
+f(["no"], empty)  # E: Cannot infer value of type parameter "T" of "f"
 [builtins fixtures/list.pyi]
 
 [case testInferenceWorksWithEmptyCollectionsUnion]
@@ -4149,3 +4149,19 @@ class Foo:
         else:
             self.qux = {}  # E: Need type annotation for "qux" (hint: "qux: dict[<type>, <type>] = ...")
 [builtins fixtures/dict.pyi]
+
+[case testConstraintSolvingFailureShowsCorrectArgument]
+from typing import Callable, TypeVar
+
+T1 = TypeVar('T1')
+T2 = TypeVar('T2')
+def foo(
+    a: T1,
+    b: T2,
+    c: Callable[[T2], T2],
+) -> tuple[T1, T2]: ...
+
+def bar(y: float) -> float: ...
+
+foo(1, None, bar)  # E: Cannot infer value of type parameter "T2" of "foo"
+[builtins fixtures/tuple.pyi]
diff --git a/test-data/unit/check-literal.test b/test-data/unit/check-literal.test
index f995332643af..3c9290b8dbbb 100644
--- a/test-data/unit/check-literal.test
+++ b/test-data/unit/check-literal.test
@@ -2989,9 +2989,9 @@ def g(a: T, t: A[T]) -> T: ...
 
 def check(obj: A[Literal[1]]) -> None:
     reveal_type(f(obj, 1))  # N: Revealed type is "Literal[1]"
-    reveal_type(f(obj, ''))  # E: Cannot infer type argument 1 of "f" \
+    reveal_type(f(obj, ''))  # E: Cannot infer value of type parameter "T" of "f" \
                              # N: Revealed type is "Any"
     reveal_type(g(1, obj))  # N: Revealed type is "Literal[1]"
-    reveal_type(g('', obj))  # E: Cannot infer type argument 1 of "g" \
+    reveal_type(g('', obj))  # E: Cannot infer value of type parameter "T" of "g" \
                              # N: Revealed type is "Any"
 [builtins fixtures/tuple.pyi]
diff --git a/test-data/unit/check-overloading.test b/test-data/unit/check-overloading.test
index 0ccc8a2a353c..e427d5b21d40 100644
--- a/test-data/unit/check-overloading.test
+++ b/test-data/unit/check-overloading.test
@@ -3370,10 +3370,10 @@ def wrapper() -> None:
     obj2: Union[W1[A], W2[B]]
 
     reveal_type(foo(obj2))  # N: Revealed type is "Union[__main__.A, __main__.B]"
-    bar(obj2)  # E: Cannot infer type argument 1 of "bar"
+    bar(obj2)  # E: Cannot infer value of type parameter "T" of "bar"
 
     b1_overload: A = foo(obj2)  # E: Incompatible types in assignment (expression has type "Union[A, B]", variable has type "A")
-    b1_union: A    = bar(obj2)  # E: Cannot infer type argument 1 of "bar"
+    b1_union: A    = bar(obj2)  # E: Cannot infer value of type parameter "T" of "bar"
 
 [case testOverloadingInferUnionReturnWithObjectTypevarReturn]
 from typing import overload, Union, TypeVar, Generic
@@ -3496,7 +3496,7 @@ def t_is_same_bound(arg1: T1, arg2: S) -> Tuple[T1, S]:
     # The arguments in the tuple are swapped
     x3: Union[List[S], List[Tuple[S, T1]]]
     y3: S
-    Dummy[T1]().foo(x3, y3)  # E: Cannot infer type argument 1 of "foo" of "Dummy" \
+    Dummy[T1]().foo(x3, y3)  # E: Cannot infer value of type parameter "S" of "foo" of "Dummy" \
                              # E: Argument 1 to "foo" of "Dummy" has incompatible type "Union[list[S], list[tuple[S, T1]]]"; expected "list[tuple[T1, Any]]"
 
     x4: Union[List[int], List[Tuple[C, int]]]
diff --git a/test-data/unit/check-parameter-specification.test b/test-data/unit/check-parameter-specification.test
index 085f6fe59809..e53c45b5b512 100644
--- a/test-data/unit/check-parameter-specification.test
+++ b/test-data/unit/check-parameter-specification.test
@@ -2135,7 +2135,7 @@ def d(f: Callable[P, None], fn: Callable[Concatenate[Callable[P, None], P], None
 
 reveal_type(d(a, f1))  # N: Revealed type is "def (i: builtins.int)"
 reveal_type(d(a, f2))  # N: Revealed type is "def (i: builtins.int)"
-reveal_type(d(b, f1))  # E: Cannot infer type argument 1 of "d" \
+reveal_type(d(b, f1))  # E: Cannot infer value of type parameter "P" of "d" \
                        # N: Revealed type is "def (*Any, **Any)"
 reveal_type(d(b, f2))  # N: Revealed type is "def (builtins.int)"
 [builtins fixtures/paramspec.pyi]
diff --git a/test-data/unit/check-plugin-attrs.test b/test-data/unit/check-plugin-attrs.test
index 6415b5104296..00bec13ab16d 100644
--- a/test-data/unit/check-plugin-attrs.test
+++ b/test-data/unit/check-plugin-attrs.test
@@ -470,8 +470,8 @@ reveal_type(a)  # N: Revealed type is "__main__.A[builtins.int]"
 reveal_type(a.x)  # N: Revealed type is "builtins.list[builtins.int]"
 reveal_type(a.y)  # N: Revealed type is "builtins.int"
 
-A(['str'], 7)  # E: Cannot infer type argument 1 of "A"
-A([1], '2')  # E: Cannot infer type argument 1 of "A"
+A(['str'], 7)  # E: Cannot infer value of type parameter "T" of "A"
+A([1], '2')  # E: Cannot infer value of type parameter "T" of "A"
 
 [builtins fixtures/list.pyi]
 
diff --git a/test-data/unit/check-protocols.test b/test-data/unit/check-protocols.test
index c6c2c5f8da98..79207c9aad56 100644
--- a/test-data/unit/check-protocols.test
+++ b/test-data/unit/check-protocols.test
@@ -4217,10 +4217,10 @@ def g2(a: Input[bytes], b: Output[bytes]) -> None:
     f(a, b)
 
 def g3(a: Input[str], b: Output[bytes]) -> None:
-    f(a, b)  # E: Cannot infer type argument 1 of "f"
+    f(a, b)  # E: Cannot infer value of type parameter "AnyStr" of "f"
 
 def g4(a: Input[bytes], b: Output[str]) -> None:
-    f(a, b)  # E: Cannot infer type argument 1 of "f"
+    f(a, b)  # E: Cannot infer value of type parameter "AnyStr" of "f"
 
 [builtins fixtures/tuple.pyi]
 
diff --git a/test-data/unit/check-typevar-tuple.test b/test-data/unit/check-typevar-tuple.test
index 0f69d0a56f47..9792df056a87 100644
--- a/test-data/unit/check-typevar-tuple.test
+++ b/test-data/unit/check-typevar-tuple.test
@@ -2372,9 +2372,9 @@ def pointwise_multiply(x: Array[Unpack[Ts]], y: Array[Unpack[Ts]]) -> Array[Unpa
 
 def a1(x: Array[int], y: Array[str], z: Array[int, str]) -> None:
     reveal_type(pointwise_multiply(x, x))  # N: Revealed type is "__main__.Array[builtins.int]"
-    reveal_type(pointwise_multiply(x, y))  # E: Cannot infer type argument 1 of "pointwise_multiply" \
+    reveal_type(pointwise_multiply(x, y))  # E: Cannot infer value of type parameter "Ts" of "pointwise_multiply" \
                                            # N: Revealed type is "__main__.Array[Unpack[builtins.tuple[Any, ...]]]"
-    reveal_type(pointwise_multiply(x, z))  # E: Cannot infer type argument 1 of "pointwise_multiply" \
+    reveal_type(pointwise_multiply(x, z))  # E: Cannot infer value of type parameter "Ts" of "pointwise_multiply" \
                                            # N: Revealed type is "__main__.Array[Unpack[builtins.tuple[Any, ...]]]"
 
 def func(x: Array[Unpack[Ts]], *args: Unpack[Ts]) -> Tuple[Unpack[Ts]]:
@@ -2382,9 +2382,9 @@ def func(x: Array[Unpack[Ts]], *args: Unpack[Ts]) -> Tuple[Unpack[Ts]]:
 
 def a2(x: Array[int, str]) -> None:
     reveal_type(func(x, 2, "Hello"))  # N: Revealed type is "tuple[builtins.int, builtins.str]"
-    reveal_type(func(x, 2))           # E: Cannot infer type argument 1 of "func" \
+    reveal_type(func(x, 2))           # E: Cannot infer value of type parameter "Ts" of "func" \
                                       # N: Revealed type is "builtins.tuple[Any, ...]"
-    reveal_type(func(x, 2, "Hello", True))   # E: Cannot infer type argument 1 of "func" \
+    reveal_type(func(x, 2, "Hello", True))   # E: Cannot infer value of type parameter "Ts" of "func" \
                                              # N: Revealed type is "builtins.tuple[Any, ...]"
 [builtins fixtures/tuple.pyi]