Checks a call to an overloaded function.
(
self,
callee: Overloaded,
args: list[Expression],
arg_kinds: list[ArgKind],
arg_names: Sequence[str | None] | None,
callable_name: str | None,
object_type: Type | None,
context: Context,
)
| 2767 | ) |
| 2768 | |
| 2769 | def check_overload_call( |
| 2770 | self, |
| 2771 | callee: Overloaded, |
| 2772 | args: list[Expression], |
| 2773 | arg_kinds: list[ArgKind], |
| 2774 | arg_names: Sequence[str | None] | None, |
| 2775 | callable_name: str | None, |
| 2776 | object_type: Type | None, |
| 2777 | context: Context, |
| 2778 | ) -> tuple[Type, Type]: |
| 2779 | """Checks a call to an overloaded function.""" |
| 2780 | # Normalize unpacked kwargs before checking the call. |
| 2781 | callee = callee.with_unpacked_kwargs() |
| 2782 | arg_types = self.infer_arg_types_in_empty_context(args) |
| 2783 | # Step 1: Filter call targets to remove ones where the argument counts don't match |
| 2784 | plausible_targets = self.plausible_overload_call_targets( |
| 2785 | arg_types, arg_kinds, arg_names, callee |
| 2786 | ) |
| 2787 | |
| 2788 | # Step 2: If the arguments contain a union, we try performing union math first, |
| 2789 | # instead of picking the first matching overload. |
| 2790 | # This is because picking the first overload often ends up being too greedy: |
| 2791 | # for example, when we have a fallback alternative that accepts an unrestricted |
| 2792 | # typevar. See https://github.com/python/mypy/issues/4063 for related discussion. |
| 2793 | erased_targets: list[CallableType] | None = None |
| 2794 | inferred_types: list[Type] | None = None |
| 2795 | unioned_result: tuple[Type, Type] | None = None |
| 2796 | |
| 2797 | # Determine whether we need to encourage union math. This should be generally safe, |
| 2798 | # as union math infers better results in the vast majority of cases, but it is very |
| 2799 | # computationally intensive. |
| 2800 | none_type_var_overlap = self.possible_none_type_var_overlap(arg_types, plausible_targets) |
| 2801 | union_interrupted = False # did we try all union combinations? |
| 2802 | if any(self.real_union(arg) for arg in arg_types): |
| 2803 | try: |
| 2804 | with self.msg.filter_errors(): |
| 2805 | unioned_return = self.union_overload_result( |
| 2806 | plausible_targets, |
| 2807 | args, |
| 2808 | arg_types, |
| 2809 | arg_kinds, |
| 2810 | arg_names, |
| 2811 | callable_name, |
| 2812 | object_type, |
| 2813 | none_type_var_overlap, |
| 2814 | context, |
| 2815 | ) |
| 2816 | except TooManyUnions: |
| 2817 | union_interrupted = True |
| 2818 | else: |
| 2819 | # Record if we succeeded. Next we need to see if maybe normal procedure |
| 2820 | # gives a narrower type. |
| 2821 | if unioned_return: |
| 2822 | returns = [u[0] for u in unioned_return] |
| 2823 | inferred_types = [u[1] for u in unioned_return] |
| 2824 | # Note that we use `combine_function_signatures` instead of just returning |
| 2825 | # a union of inferred callables because for example a call |
| 2826 | # Union[int -> int, str -> str](Union[int, str]) is invalid and |
no test coverage detected