Skip to content

Commit 2561998

Browse files
Kunal SaliKunal Sali
authored andcommitted
fix-callable-any-narrowing
1 parent 9e0fb86 commit 2561998

1 file changed

Lines changed: 13 additions & 11 deletions

File tree

mypy/checker.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6252,17 +6252,19 @@ def conditional_callable_type_map(
62526252
proper_type = get_proper_type(current_type)
62536253
if isinstance(proper_type, AnyType):
62546254
# Narrow Any to a generic callable type to satisfy no-any-return in strict mode.
6255-
return {
6256-
expr: CallableType(
6257-
[AnyType(TypeOfAny.from_another_any, source_any=proper_type),
6258-
AnyType(TypeOfAny.from_another_any, source_any=proper_type)],
6259-
[nodes.ARG_STAR, nodes.ARG_STAR2],
6260-
[None, None],
6261-
ret_type=AnyType(TypeOfAny.from_another_any, source_any=proper_type),
6262-
fallback=self.named_type("builtins.function"),
6263-
is_ellipsis_args=True,
6264-
)
6265-
}, {}
6255+
# We use a synthesized fallback with fallback_to_any=True to preserve attribute access
6256+
# (fixing regressions in sympy, pandas, etc. where Any behavior was expected).
6257+
fallback = self.named_type("builtins.object")
6258+
if fallback.type.fullname == "builtins.object":
6259+
# Create a synthesized type that behaves like 'Any' but is an 'Instance'
6260+
# This satisfies callability checkpoints while preserving dynamic attribute access.
6261+
cdef = nodes.ClassDef("<any callable>", nodes.Block([]))
6262+
cdef._fullname = "<any callable>"
6263+
info = TypeInfo(nodes.SymbolTable(), cdef, "")
6264+
info.mro = fallback.type.mro
6265+
info.bases = fallback.type.bases
6266+
info.fallback_to_any = True
6267+
return {expr: Instance(info, [])}, {}
62666268

62676269
callables, uncallables = self.partition_by_callable(current_type, unsound_partition=False)
62686270

0 commit comments

Comments
 (0)