From c7f95a48a2d08054ac72cd618206273c8cdbdad7 Mon Sep 17 00:00:00 2001 From: Karel Kenens Date: Mon, 20 Oct 2025 21:28:54 +0200 Subject: [PATCH 1/5] fix: add lookup_qualified --- mypy/exprtotype.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/mypy/exprtotype.py b/mypy/exprtotype.py index 506194a4b285..03e700d76f83 100644 --- a/mypy/exprtotype.py +++ b/mypy/exprtotype.py @@ -126,7 +126,14 @@ def expr_to_unanalyzed_type( # losing all the annotations. return expr_to_unanalyzed_type(args[0], options, allow_new_syntax, expr) base.args = tuple( - expr_to_unanalyzed_type(arg, options, allow_new_syntax, expr, allow_unpack=True) + expr_to_unanalyzed_type( + arg, + options, + allow_new_syntax, + expr, + allow_unpack=True, + lookup_qualified=lookup_qualified, + ) for arg in args ) if not base.args: From b47d21e93c38d421cb617dd85337375fdf00d9b4 Mon Sep 17 00:00:00 2001 From: Karel Kenens Date: Mon, 20 Oct 2025 21:29:44 +0200 Subject: [PATCH 2/5] test: type keyword would fail before fix --- test-data/unit/check-type-aliases.test | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/test-data/unit/check-type-aliases.test b/test-data/unit/check-type-aliases.test index 5bbb503a578a..277c3e5b6a55 100644 --- a/test-data/unit/check-type-aliases.test +++ b/test-data/unit/check-type-aliases.test @@ -1318,3 +1318,25 @@ from typing_extensions import TypeAlias Foo: TypeAlias = ClassVar[int] # E: ClassVar[...] can't be used inside a type alias [builtins fixtures/tuple.pyi] + +[case testAnnotatedWithCallableAsParameterTypeKeyword] +# flags: --python-version 3.12 +from typing_extensions import Annotated + +def something() -> None: ... + +type A = list[Annotated[str, something()]] +a: A +reveal_type(a) # N: Revealed type is "builtins.list[builtins.str]" +[builtins fixtures/tuple.pyi] + +[case testAnnotatedWithCallableAsParameterTypeAlias] +# flags: --python-version 3.12 +from typing_extensions import Annotated, TypeAlias + +def something() -> None: ... + +B: TypeAlias = list[Annotated[str, something()]] +b: B +reveal_type(b) # N: Revealed type is "builtins.list[builtins.str]" +[builtins fixtures/tuple.pyi] From 777e4c35cef44b4b15e7659ba70db860bd07264f Mon Sep 17 00:00:00 2001 From: Karel Kenens Date: Mon, 20 Oct 2025 23:46:23 +0200 Subject: [PATCH 3/5] test: restructure to run with correct python version --- test-data/unit/check-python312.test | 10 ++++++++++ test-data/unit/check-type-aliases.test | 18 +++--------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/test-data/unit/check-python312.test b/test-data/unit/check-python312.test index be46ff6ee5c0..25d19be95d52 100644 --- a/test-data/unit/check-python312.test +++ b/test-data/unit/check-python312.test @@ -2168,3 +2168,13 @@ x: MyTuple[int, str] reveal_type(x[0]) # N: Revealed type is "Any" [builtins fixtures/tuple.pyi] [typing fixtures/typing-full.pyi] + +[case testAnnotatedWithCallableAsParameterTypeKeyword] +from typing_extensions import Annotated + +def something() -> None: ... + +type A = list[Annotated[str, something()]] +a: A +reveal_type(a) # N: Revealed type is "builtins.list[builtins.str]" +[builtins fixtures/tuple.pyi] diff --git a/test-data/unit/check-type-aliases.test b/test-data/unit/check-type-aliases.test index 277c3e5b6a55..6f3bb5d497f4 100644 --- a/test-data/unit/check-type-aliases.test +++ b/test-data/unit/check-type-aliases.test @@ -1319,24 +1319,12 @@ from typing_extensions import TypeAlias Foo: TypeAlias = ClassVar[int] # E: ClassVar[...] can't be used inside a type alias [builtins fixtures/tuple.pyi] -[case testAnnotatedWithCallableAsParameterTypeKeyword] -# flags: --python-version 3.12 -from typing_extensions import Annotated - -def something() -> None: ... - -type A = list[Annotated[str, something()]] -a: A -reveal_type(a) # N: Revealed type is "builtins.list[builtins.str]" -[builtins fixtures/tuple.pyi] - [case testAnnotatedWithCallableAsParameterTypeAlias] -# flags: --python-version 3.12 from typing_extensions import Annotated, TypeAlias def something() -> None: ... -B: TypeAlias = list[Annotated[str, something()]] -b: B -reveal_type(b) # N: Revealed type is "builtins.list[builtins.str]" +A: TypeAlias = list[Annotated[str, something()]] +a: A +reveal_type(a) # N: Revealed type is "builtins.list[builtins.str]" [builtins fixtures/tuple.pyi] From 0bd6bb5cc6bd2c75b0741a2b5bb99c020823f837 Mon Sep 17 00:00:00 2001 From: Karel Kenens Date: Wed, 22 Oct 2025 21:27:32 +0200 Subject: [PATCH 4/5] fix: pass through argument to all recursive calls --- mypy/exprtotype.py | 52 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 11 deletions(-) diff --git a/mypy/exprtotype.py b/mypy/exprtotype.py index 03e700d76f83..6fd43c08dbac 100644 --- a/mypy/exprtotype.py +++ b/mypy/exprtotype.py @@ -100,7 +100,9 @@ def expr_to_unanalyzed_type( else: raise TypeTranslationError() elif isinstance(expr, IndexExpr): - base = expr_to_unanalyzed_type(expr.base, options, allow_new_syntax, expr) + base = expr_to_unanalyzed_type( + expr.base, options, allow_new_syntax, expr, lookup_qualified=lookup_qualified + ) if isinstance(base, UnboundType): if base.args: raise TypeTranslationError() @@ -124,7 +126,9 @@ def expr_to_unanalyzed_type( # TODO: this is not the optimal solution as we are basically getting rid # of the Annotation definition and only returning the type information, # losing all the annotations. - return expr_to_unanalyzed_type(args[0], options, allow_new_syntax, expr) + return expr_to_unanalyzed_type( + args[0], options, allow_new_syntax, expr, lookup_qualified=lookup_qualified + ) base.args = tuple( expr_to_unanalyzed_type( arg, @@ -148,8 +152,12 @@ def expr_to_unanalyzed_type( ): return UnionType( [ - expr_to_unanalyzed_type(expr.left, options, allow_new_syntax), - expr_to_unanalyzed_type(expr.right, options, allow_new_syntax), + expr_to_unanalyzed_type( + expr.left, options, allow_new_syntax, lookup_qualified=lookup_qualified + ), + expr_to_unanalyzed_type( + expr.right, options, allow_new_syntax, lookup_qualified=lookup_qualified + ), ], uses_pep604_syntax=True, ) @@ -185,12 +193,16 @@ def expr_to_unanalyzed_type( if typ is not default_type: # Two types raise TypeTranslationError() - typ = expr_to_unanalyzed_type(arg, options, allow_new_syntax, expr) + typ = expr_to_unanalyzed_type( + arg, options, allow_new_syntax, expr, lookup_qualified=lookup_qualified + ) continue else: raise TypeTranslationError() elif i == 0: - typ = expr_to_unanalyzed_type(arg, options, allow_new_syntax, expr) + typ = expr_to_unanalyzed_type( + arg, options, allow_new_syntax, expr, lookup_qualified=lookup_qualified + ) elif i == 1: name = _extract_argument_name(arg) else: @@ -199,7 +211,14 @@ def expr_to_unanalyzed_type( elif isinstance(expr, ListExpr): return TypeList( [ - expr_to_unanalyzed_type(t, options, allow_new_syntax, expr, allow_unpack=True) + expr_to_unanalyzed_type( + t, + options, + allow_new_syntax, + expr, + allow_unpack=True, + lookup_qualified=lookup_qualified, + ) for t in expr.items ], line=expr.line, @@ -210,7 +229,9 @@ def expr_to_unanalyzed_type( elif isinstance(expr, BytesExpr): return parse_type_string(expr.value, "builtins.bytes", expr.line, expr.column) elif isinstance(expr, UnaryExpr): - typ = expr_to_unanalyzed_type(expr.expr, options, allow_new_syntax) + typ = expr_to_unanalyzed_type( + expr.expr, options, allow_new_syntax, lookup_qualified=lookup_qualified + ) if isinstance(typ, RawExpressionType): if isinstance(typ.literal_value, int): if expr.op == "-": @@ -232,7 +253,10 @@ def expr_to_unanalyzed_type( return EllipsisType(expr.line) elif allow_unpack and isinstance(expr, StarExpr): return UnpackType( - expr_to_unanalyzed_type(expr.expr, options, allow_new_syntax), from_star_syntax=True + expr_to_unanalyzed_type( + expr.expr, options, allow_new_syntax, lookup_qualified=lookup_qualified + ), + from_star_syntax=True, ) elif isinstance(expr, DictExpr): if not expr.items: @@ -243,12 +267,18 @@ def expr_to_unanalyzed_type( if not isinstance(item_name, StrExpr): if item_name is None: extra_items_from.append( - expr_to_unanalyzed_type(value, options, allow_new_syntax, expr) + expr_to_unanalyzed_type( + value, + options, + allow_new_syntax, + expr, + lookup_qualified=lookup_qualified, + ) ) continue raise TypeTranslationError() items[item_name.value] = expr_to_unanalyzed_type( - value, options, allow_new_syntax, expr + value, options, allow_new_syntax, expr, lookup_qualified=lookup_qualified ) result = TypedDictType( items, set(), set(), Instance(MISSING_FALLBACK, ()), expr.line, expr.column From 9ad2101caac146b32dda97f2ffab413727d3761c Mon Sep 17 00:00:00 2001 From: Karel Kenens Date: Wed, 22 Oct 2025 21:27:47 +0200 Subject: [PATCH 5/5] test: deeper nested annotated --- test-data/unit/check-python312.test | 10 ++++++++++ test-data/unit/check-type-aliases.test | 10 ++++++++++ 2 files changed, 20 insertions(+) diff --git a/test-data/unit/check-python312.test b/test-data/unit/check-python312.test index 25d19be95d52..8ca68c5dab9c 100644 --- a/test-data/unit/check-python312.test +++ b/test-data/unit/check-python312.test @@ -2178,3 +2178,13 @@ type A = list[Annotated[str, something()]] a: A reveal_type(a) # N: Revealed type is "builtins.list[builtins.str]" [builtins fixtures/tuple.pyi] + +[case testAnnotatedWithCallableAsParameterTypeKeywordDeeper] +from typing_extensions import Annotated + +def something() -> None: ... + +type A = list[Annotated[Annotated[str, something()], something()]] +a: A +reveal_type(a) # N: Revealed type is "builtins.list[builtins.str]" +[builtins fixtures/tuple.pyi] diff --git a/test-data/unit/check-type-aliases.test b/test-data/unit/check-type-aliases.test index 6f3bb5d497f4..da92e8554113 100644 --- a/test-data/unit/check-type-aliases.test +++ b/test-data/unit/check-type-aliases.test @@ -1328,3 +1328,13 @@ A: TypeAlias = list[Annotated[str, something()]] a: A reveal_type(a) # N: Revealed type is "builtins.list[builtins.str]" [builtins fixtures/tuple.pyi] + +[case testAnnotatedWithCallableAsParameterTypeAliasDeeper] +from typing_extensions import Annotated, TypeAlias + +def something() -> None: ... + +A: TypeAlias = list[Annotated[Annotated[str, something()], something()]] +a: A +reveal_type(a) # N: Revealed type is "builtins.list[builtins.str]" +[builtins fixtures/tuple.pyi]