|
122 | 122 | from mypy.semanal_enum import ENUM_BASES |
123 | 123 | from mypy.state import state |
124 | 124 | from mypy.subtypes import ( |
| 125 | + common_type, |
125 | 126 | covers_at_runtime, |
126 | 127 | find_member, |
| 128 | + has_any_type, |
127 | 129 | is_same_type, |
128 | 130 | is_subtype, |
129 | 131 | merge_typevars_in_callables_by_name, |
|
204 | 206 | has_recursive_types, |
205 | 207 | has_type_vars, |
206 | 208 | is_named_instance, |
| 209 | + remove_dups, |
207 | 210 | split_with_prefix_and_suffix, |
208 | 211 | ) |
209 | 212 | from mypy.types_utils import ( |
|
228 | 231 | # see https://github.com/python/mypy/pull/5255#discussion_r196896335 for discussion. |
229 | 232 | MAX_UNIONS: Final = 5 |
230 | 233 |
|
| 234 | +# Maximum number or unique matched overload return types caused by Any |
| 235 | +# ambiguity where we try to find a precise fallback. |
| 236 | +MAX_PRECISE_OVERLOAD_FALLBACK: Final = 8 |
231 | 237 |
|
232 | 238 | # Types considered safe for comparisons with --strict-equality due to known behaviour of __eq__. |
233 | 239 | # NOTE: All these types are subtypes of AbstractSet. |
@@ -3097,11 +3103,17 @@ def infer_overload_return_type( |
3097 | 3103 | if not matches: |
3098 | 3104 | return None |
3099 | 3105 | elif any_causes_overload_ambiguity(matches, return_types, arg_types, arg_kinds, arg_names): |
| 3106 | + return_types = remove_dups(return_types) |
3100 | 3107 | # An argument of type or containing the type 'Any' caused ambiguity. |
3101 | 3108 | # We try returning a precise type if we can. If not, we give up and just return 'Any'. |
3102 | 3109 | if all_same_types(return_types): |
3103 | 3110 | self.chk.store_types(type_maps[0]) |
3104 | 3111 | return return_types[0], inferred_types[0] |
| 3112 | + elif len(return_types) < MAX_PRECISE_OVERLOAD_FALLBACK and ( |
| 3113 | + common := common_type(return_types) |
| 3114 | + ): |
| 3115 | + self.chk.store_types(type_maps[0]) |
| 3116 | + return common, erase_type(inferred_types[0]) |
3105 | 3117 | elif all_same_types([erase_type(typ) for typ in return_types]): |
3106 | 3118 | self.chk.store_types(type_maps[0]) |
3107 | 3119 | return erase_type(return_types[0]), erase_type(inferred_types[0]) |
@@ -6660,37 +6672,6 @@ def try_parse_as_type_expression(self, maybe_type_expr: Expression) -> Type | No |
6660 | 6672 | return None |
6661 | 6673 |
|
6662 | 6674 |
|
6663 | | -def has_any_type(t: Type, ignore_in_type_obj: bool = False) -> bool: |
6664 | | - """Whether t contains an Any type""" |
6665 | | - return t.accept(HasAnyType(ignore_in_type_obj)) |
6666 | | - |
6667 | | - |
6668 | | -class HasAnyType(types.BoolTypeQuery): |
6669 | | - def __init__(self, ignore_in_type_obj: bool) -> None: |
6670 | | - super().__init__(types.ANY_STRATEGY) |
6671 | | - self.ignore_in_type_obj = ignore_in_type_obj |
6672 | | - |
6673 | | - def visit_any(self, t: AnyType) -> bool: |
6674 | | - return t.type_of_any != TypeOfAny.special_form # special forms are not real Any types |
6675 | | - |
6676 | | - def visit_callable_type(self, t: CallableType) -> bool: |
6677 | | - if self.ignore_in_type_obj and t.is_type_obj(): |
6678 | | - return False |
6679 | | - return super().visit_callable_type(t) |
6680 | | - |
6681 | | - def visit_type_var(self, t: TypeVarType) -> bool: |
6682 | | - default = [t.default] if t.has_default() else [] |
6683 | | - return self.query_types([t.upper_bound, *default] + t.values) |
6684 | | - |
6685 | | - def visit_param_spec(self, t: ParamSpecType) -> bool: |
6686 | | - default = [t.default] if t.has_default() else [] |
6687 | | - return self.query_types([t.upper_bound, *default, t.prefix]) |
6688 | | - |
6689 | | - def visit_type_var_tuple(self, t: TypeVarTupleType) -> bool: |
6690 | | - default = [t.default] if t.has_default() else [] |
6691 | | - return self.query_types([t.upper_bound, *default]) |
6692 | | - |
6693 | | - |
6694 | 6675 | def has_coroutine_decorator(t: Type) -> bool: |
6695 | 6676 | """Whether t came from a function decorated with `@coroutine`.""" |
6696 | 6677 | t = get_proper_type(t) |
|
0 commit comments