@@ -631,7 +631,7 @@ def fix_function_overloads(self, stmts: list[Statement]) -> list[Statement]:
631631 ret : list [Statement ] = []
632632 current_overload : list [OverloadPart ] = []
633633 current_overload_name : str | None = None
634- seen_unconditional_func_def = False
634+ last_unconditional_func_def : str | None = None
635635 last_if_stmt : IfStmt | None = None
636636 last_if_overload : Decorator | FuncDef | OverloadedFuncDef | None = None
637637 last_if_stmt_overload_name : str | None = None
@@ -641,7 +641,7 @@ def fix_function_overloads(self, stmts: list[Statement]) -> list[Statement]:
641641 if_overload_name : str | None = None
642642 if_block_with_overload : Block | None = None
643643 if_unknown_truth_value : IfStmt | None = None
644- if isinstance (stmt , IfStmt ) and seen_unconditional_func_def is False :
644+ if isinstance (stmt , IfStmt ):
645645 # Check IfStmt block to determine if function overloads can be merged
646646 if_overload_name = self ._check_ifstmt_for_overloads (stmt , current_overload_name )
647647 if if_overload_name is not None :
@@ -669,11 +669,18 @@ def fix_function_overloads(self, stmts: list[Statement]) -> list[Statement]:
669669 last_if_unknown_truth_value = None
670670 current_overload .append (stmt )
671671 if isinstance (stmt , FuncDef ):
672- seen_unconditional_func_def = True
672+ # This is, strictly speaking, wrong: there might be a decorated
673+ # implementation. However, it only affects the error message we show:
674+ # ideally it's "already defined", but "implementation must come last"
675+ # is also reasonable.
676+ # TODO: can we get rid of this completely and just always emit
677+ # "implementation must come last" instead?
678+ last_unconditional_func_def = stmt .name
673679 elif (
674680 current_overload_name is not None
675681 and isinstance (stmt , IfStmt )
676682 and if_overload_name == current_overload_name
683+ and last_unconditional_func_def != current_overload_name
677684 ):
678685 # IfStmt only contains stmts relevant to current_overload.
679686 # Check if stmts are reachable and add them to current_overload,
@@ -729,7 +736,7 @@ def fix_function_overloads(self, stmts: list[Statement]) -> list[Statement]:
729736 # most of mypy/mypyc assumes that all the functions in an OverloadedFuncDef are
730737 # related, but multiple underscore functions next to each other aren't necessarily
731738 # related
732- seen_unconditional_func_def = False
739+ last_unconditional_func_def = None
733740 if isinstance (stmt , Decorator ) and not unnamed_function (stmt .name ):
734741 current_overload = [stmt ]
735742 current_overload_name = stmt .name
0 commit comments