From 03afa62b2e3093f9e6e367bd5c2c4354bf919ad3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Nathana=C3=ABl=20Soulat?= Date: Wed, 24 Jun 2026 11:32:59 +0200 Subject: [PATCH 1/2] Fix @overload decorator lines classified as Unanalyzed in lineprecision report `@overload` is intentionally absent from the typemap, causing `StatisticsVisitor` to record `TYPE_UNANALYZED` for every decorator line. Route `OVERLOAD_NAMES` through `record_precise_if_checked_scope` and exempt them from its typemap guard. Fixes #21638. --- mypy/stats.py | 13 +++++++++++-- test-data/unit/check-reports.test | 31 +++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/mypy/stats.py b/mypy/stats.py index e3499d2345635..d6c8138b925b6 100644 --- a/mypy/stats.py +++ b/mypy/stats.py @@ -50,6 +50,7 @@ CallableType, FunctionLike, Instance, + OVERLOAD_NAMES, TupleType, Type, TypeOfAny, @@ -239,7 +240,10 @@ def visit_continue_stmt(self, o: ContinueStmt) -> None: self.record_precise_if_checked_scope(o) def visit_name_expr(self, o: NameExpr) -> None: - if o.fullname in ("builtins.None", "builtins.True", "builtins.False", "builtins.Ellipsis"): + if ( + o.fullname in ("builtins.None", "builtins.True", "builtins.False", "builtins.Ellipsis") + or o.fullname in OVERLOAD_NAMES + ): self.record_precise_if_checked_scope(o) else: self.process_node(o) @@ -346,7 +350,12 @@ def process_node(self, node: Expression) -> None: self.type(self.typemap.get(node)) def record_precise_if_checked_scope(self, node: Node) -> None: - if isinstance(node, Expression) and self.typemap and node not in self.typemap: + if ( + isinstance(node, Expression) + and self.typemap + and node not in self.typemap + and not (isinstance(node, NameExpr) and node.fullname in OVERLOAD_NAMES) + ): kind = TYPE_UNANALYZED elif self.is_checked_scope(): kind = TYPE_PRECISE diff --git a/test-data/unit/check-reports.test b/test-data/unit/check-reports.test index 423cbcc49289e..44f6b2023a9bc 100644 --- a/test-data/unit/check-reports.test +++ b/test-data/unit/check-reports.test @@ -343,3 +343,34 @@ Name Lines Precise Imprecise Any Empty Unanalyzed ------------------------------------------------------------- __main__ 5 3 0 1 1 0 m 4 3 0 1 0 0 + +[case testLinePrecisionOverloadDecoratorCheckedScope] +# flags: --lineprecision-report out +from typing import overload + +@overload +def f(x: int) -> int: ... +@overload +def f(x: str) -> str: ... +def f(x): + return x +[outfile out/lineprecision.txt] +Name Lines Precise Imprecise Any Empty Unanalyzed +------------------------------------------------------------- +__main__ 9 5 0 2 2 0 + +[case testLinePrecisionOverloadDecoratorUncheckedScope] +# flags: --lineprecision-report out +from typing import overload + +def outer(): + @overload + def f(x: int) -> int: ... + @overload + def f(x: str) -> str: ... + def f(x): + return x +[outfile out/lineprecision.txt] +Name Lines Precise Imprecise Any Empty Unanalyzed +------------------------------------------------------------- +__main__ 10 1 0 7 2 0 From 8b6df156b4ff7f1b56d3a5162607cdd1ad4e39c6 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 24 Jun 2026 11:08:26 +0000 Subject: [PATCH 2/2] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- mypy/stats.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mypy/stats.py b/mypy/stats.py index d6c8138b925b6..a84099d5ae457 100644 --- a/mypy/stats.py +++ b/mypy/stats.py @@ -46,11 +46,11 @@ from mypy.type_visitor import ANY_STRATEGY, BoolTypeQuery from mypy.typeanal import collect_all_inner_types from mypy.types import ( + OVERLOAD_NAMES, AnyType, CallableType, FunctionLike, Instance, - OVERLOAD_NAMES, TupleType, Type, TypeOfAny,