From 87f15888a9d6634ed6dec98c46b83871a84c7a07 Mon Sep 17 00:00:00 2001 From: Taksh Date: Mon, 6 Apr 2026 14:18:56 +0530 Subject: [PATCH] Suppress misleading Foo[...] suggestion when annotation has keyword args When a call expression with keyword arguments is used in a type annotation (e.g., `Foo(arg=val)`), mypy previously suggested using `Foo[...]` instead. However, `Foo[arg=val]` is a SyntaxError in Python, making the suggestion misleading. This change suppresses the bracket syntax suggestion when the call contains keyword arguments. Fixes #16506 Co-Authored-By: Claude Opus 4.6 (1M context) --- mypy/fastparse.py | 4 +++- test-data/unit/check-errorcodes.test | 5 +++++ test-data/unit/check-fastparse.test | 12 ++++++++++++ 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/mypy/fastparse.py b/mypy/fastparse.py index e85b8fffaf9e9..1d8e5811827b5 100644 --- a/mypy/fastparse.py +++ b/mypy/fastparse.py @@ -1957,7 +1957,9 @@ def visit_Call(self, e: Call) -> Type: if not isinstance(self.parent(), ast3.List): note = None - if constructor: + if constructor and not e.keywords: + # Only suggest Foo[...] when there are no keyword arguments, + # since Foo[arg=val] is a SyntaxError (see #16506). note = "Suggestion: use {0}[...] instead of {0}(...)".format(constructor) return self.invalid_type(e, note=note) if not constructor: diff --git a/test-data/unit/check-errorcodes.test b/test-data/unit/check-errorcodes.test index 85a2264c2088b..80ad703bfe324 100644 --- a/test-data/unit/check-errorcodes.test +++ b/test-data/unit/check-errorcodes.test @@ -122,6 +122,11 @@ for v in x: # type: int, int # E: Syntax error in type annotation [syntax] \ # N: Suggestion: Use Tuple[T1, ..., Tn] instead of (T1, ..., Tn) pass +[case testErrorCodeSyntaxError4_no_native_parse] +# Keyword arguments in type annotation should not suggest Foo[...] (see #16506) +def f(a: Foo(arg=int)) -> int: # E: Invalid type comment or annotation [valid-type] + pass + [case testErrorCodeSyntaxErrorIgnoreNote] # This is a bit inconsistent -- syntax error would be more logical? x: 'a b' # type: ignore[valid-type] diff --git a/test-data/unit/check-fastparse.test b/test-data/unit/check-fastparse.test index 7ee5a9c432169..6596dd36adef8 100644 --- a/test-data/unit/check-fastparse.test +++ b/test-data/unit/check-fastparse.test @@ -207,6 +207,18 @@ def f(a: Foo(int)) -> int: main:7: error: Invalid type comment or annotation main:7: note: Suggestion: use Foo[...] instead of Foo(...) +[case testFasterParseTypeErrorCustomWithKeyword_no_native_parse] + +from typing import TypeVar, Generic +T = TypeVar('T') +class Foo(Generic[T]): + pass + +def f(a: Foo(arg=int)) -> int: + pass +[out] +main:7: error: Invalid type comment or annotation + [case testFastParseMatMul] from typing import Any