diff --git a/mypy/checkexpr.py b/mypy/checkexpr.py index 2e93a598fb7e..5c6db86964ac 100644 --- a/mypy/checkexpr.py +++ b/mypy/checkexpr.py @@ -2213,7 +2213,7 @@ def check_overload_call( # we don't want to introduce internal inconsistencies. unioned_result = ( make_simplified_union(list(returns), context.line, context.column), - self.combine_function_signatures(inferred_types), + self.combine_function_signatures(get_proper_types(inferred_types)), ) # Step 3: We try checking each branch one-by-one. @@ -2554,7 +2554,7 @@ def type_overrides_set( for expr in exprs: del self.type_overrides[expr] - def combine_function_signatures(self, types: Sequence[Type]) -> AnyType | CallableType: + def combine_function_signatures(self, types: list[ProperType]) -> AnyType | CallableType: """Accepts a list of function signatures and attempts to combine them together into a new CallableType consisting of the union of all of the given arguments and return types. @@ -2562,10 +2562,9 @@ def combine_function_signatures(self, types: Sequence[Type]) -> AnyType | Callab an ambiguity because of Any in arguments). """ assert types, "Trying to merge no callables" - types = get_proper_types(types) if not all(isinstance(c, CallableType) for c in types): return AnyType(TypeOfAny.special_form) - callables = cast(Sequence[CallableType], types) + callables = cast("list[CallableType]", types) if len(callables) == 1: return callables[0] @@ -3463,7 +3462,7 @@ def check_op( # we call 'combine_function_signature' instead of just unioning the inferred # callable types. results_final = make_simplified_union(all_results) - inferred_final = self.combine_function_signatures(all_inferred) + inferred_final = self.combine_function_signatures(get_proper_types(all_inferred)) return results_final, inferred_final else: return self.check_method_call_by_name( diff --git a/mypy/types.py b/mypy/types.py index fa1502f48fa4..354a740567dc 100644 --- a/mypy/types.py +++ b/mypy/types.py @@ -2888,23 +2888,35 @@ def get_proper_type(typ: Type | None) -> ProperType | None: typ = typ.type_guard while isinstance(typ, TypeAliasType): typ = typ._expand_once() - assert isinstance(typ, ProperType), typ # TODO: store the name of original type alias on this type, so we can show it in errors. - return typ + return cast(ProperType, typ) @overload -def get_proper_types(it: Iterable[Type]) -> list[ProperType]: # type: ignore[misc] +def get_proper_types(types: list[Type] | tuple[Type, ...]) -> list[ProperType]: # type: ignore[misc] ... @overload -def get_proper_types(it: Iterable[Type | None]) -> list[ProperType | None]: +def get_proper_types( + types: list[Type | None] | tuple[Type | None, ...] +) -> list[ProperType | None]: ... -def get_proper_types(it: Iterable[Type | None]) -> list[ProperType] | list[ProperType | None]: - return [get_proper_type(t) for t in it] +def get_proper_types( + types: list[Type] | list[Type | None] | tuple[Type | None, ...] +) -> list[ProperType] | list[ProperType | None]: + if isinstance(types, list): + typelist = types + # Optimize for the common case so that we don't need to allocate anything + if not any( + isinstance(t, (TypeAliasType, TypeGuardedType)) for t in typelist # type: ignore[misc] + ): + return cast("list[ProperType]", typelist) + return [get_proper_type(t) for t in typelist] + else: + return [get_proper_type(t) for t in types] # We split off the type visitor base classes to another module