From 2a644b448fa743cd608c287da3fc17d54cad45ee Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 18 Oct 2024 10:56:34 +0100 Subject: [PATCH] Fix type object with type var default in union context Union type context wasn's handled previously, and it triggered false positives, but apparently only if a type object had type var defaults. Fixes #17942. --- mypy/checkexpr.py | 13 +++++++++++-- test-data/unit/check-typevar-defaults.test | 12 ++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index b06aaa8f89f5..08d7345452fb 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -399,8 +399,8 @@ def analyze_ref_expr(self, e: RefExpr, lvalue: bool = False) -> Type: # TODO: always do this in type_object_type by passing the original context result.ret_type.line = e.line result.ret_type.column = e.column - if isinstance(get_proper_type(self.type_context[-1]), TypeType): - # This is the type in a Type[] expression, so substitute type + if is_type_type_context(self.type_context[-1]): + # This is the type in a type[] expression, so substitute type # variables with Any. result = erasetype.erase_typevars(result) elif isinstance(node, MypyFile): @@ -6617,3 +6617,12 @@ def get_partial_instance_type(t: Type | None) -> PartialType | None: if t is None or not isinstance(t, PartialType) or t.type is None: return None return t + + +def is_type_type_context(context: Type | None) -> bool: + context = get_proper_type(context) + if isinstance(context, TypeType): + return True + if isinstance(context, UnionType): + return any(is_type_type_context(item) for item in context.items) + return False diff --git a/test-data/unit/check-typevar-defaults.test b/test-data/unit/check-typevar-defaults.test index 9ca67376da26..22e2594eb38b 100644 --- a/test-data/unit/check-typevar-defaults.test +++ b/test-data/unit/check-typevar-defaults.test @@ -717,3 +717,15 @@ def func_d3( reveal_type(c) # N: Revealed type is "__main__.B[__main__.A[builtins.dict[builtins.int, builtins.float]]]" reveal_type(d) # N: Revealed type is "__main__.B[builtins.int]" [builtins fixtures/dict.pyi] + +[case testTypeVarDefaultsAndTypeObjectTypeInUnion] +from __future__ import annotations +from typing import Generic +from typing_extensions import TypeVar + +_I = TypeVar("_I", default=int) + +class C(Generic[_I]): pass + +t: type[C] | int = C +[builtins fixtures/tuple.pyi]