Skip to content

Commit e6752b3

Browse files
committed
Use meet/join for non-trivial fallback
1 parent d64cd95 commit e6752b3

File tree

2 files changed

+19
-7
lines changed

2 files changed

+19
-7
lines changed

mypy/join.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -733,10 +733,10 @@ def combine_parameters_with(
733733
if s_kind.is_star():
734734
continue
735735

736-
candidates = [t.argument_by_position(s_a.pos)]
736+
raw_candidates = [t.argument_by_position(s_a.pos)]
737737
if s_a.name is not None and s_a.name not in spent_names:
738-
candidates.append(t.argument_by_name(s_a.name))
739-
candidates = [c for c in candidates if c is not None]
738+
raw_candidates.append(t.argument_by_name(s_a.name))
739+
candidates = [c for c in raw_candidates if c is not None]
740740
if not candidates:
741741
if s_a.required:
742742
return None
@@ -782,10 +782,14 @@ def join_similar_callables(t: CallableType, s: CallableType) -> CallableType | N
782782
# TODO in combine_similar_callables also applies here (names and kinds; user metaclasses)
783783
# The fallback type can be either 'function', 'type', or some user-provided metaclass.
784784
# The result should always use 'function' as a fallback if either operands are using it.
785+
fallback: ProperType
785786
if t.fallback.type.fullname == "builtins.function":
786787
fallback = t.fallback
787-
else:
788+
elif s.fallback.type.fullname == "builtins.function":
788789
fallback = s.fallback
790+
else:
791+
fallback = join_types(s.fallback, t.fallback)
792+
assert isinstance(fallback, Instance)
789793
return t.copy_modified(
790794
arg_types=joined_params.arg_types,
791795
arg_names=joined_params.arg_names,
@@ -842,10 +846,14 @@ def combine_similar_callables(t: CallableType, s: CallableType) -> CallableType:
842846
# TODO what should happen if one fallback is 'type' and the other is a user-provided metaclass?
843847
# The fallback type can be either 'function', 'type', or some user-provided metaclass.
844848
# The result should always use 'function' as a fallback if either operands are using it.
849+
fallback: ProperType
845850
if t.fallback.type.fullname == "builtins.function":
846851
fallback = t.fallback
847-
else:
852+
elif s.fallback.type.fullname == "builtins.function":
848853
fallback = s.fallback
854+
else:
855+
fallback = join_types(s.fallback, t.fallback)
856+
assert isinstance(fallback, Instance)
849857
return t.copy_modified(
850858
arg_types=joined_params.arg_types,
851859
arg_names=joined_params.arg_names,

mypy/meet.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1126,10 +1126,14 @@ def meet_similar_callables(t: CallableType, s: CallableType) -> CallableType | N
11261126
# TODO in combine_similar_callables also applies here (names and kinds)
11271127
# The fallback type can be either 'function' or 'type'. The result should have 'function' as
11281128
# fallback only if both operands have it as 'function'.
1129-
if t.fallback.type.fullname != "builtins.function":
1129+
fallback: ProperType
1130+
if t.fallback.type.fullname == "builtins.function":
1131+
fallback = s.fallback
1132+
elif s.fallback.type.fullname == "builtins.function":
11301133
fallback = t.fallback
11311134
else:
1132-
fallback = s.fallback
1135+
fallback = meet_types(s.fallback, t.fallback)
1136+
assert isinstance(fallback, Instance)
11331137
return t.copy_modified(
11341138
arg_types=joined_params.arg_types,
11351139
arg_names=joined_params.arg_names,

0 commit comments

Comments
 (0)