From f7d047cd6dc008ab767510211d5c466d1c5e9215 Mon Sep 17 00:00:00 2001 From: Jukka Lehtosalo Date: Fri, 27 Oct 2023 13:45:51 +0100 Subject: [PATCH] [mypyc] Generate error on duplicate function definitions (#16309) Previously we produced duplicate functions in C, which caused C compiler errors. --- mypyc/irbuild/builder.py | 9 +++++++++ mypyc/irbuild/function.py | 2 +- mypyc/test-data/irbuild-statements.test | 24 ++++++++++++++++++++++++ mypyc/test-data/run-misc.test | 4 ---- 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/mypyc/irbuild/builder.py b/mypyc/irbuild/builder.py index 573ca334a5d1..5ed617aa925f 100644 --- a/mypyc/irbuild/builder.py +++ b/mypyc/irbuild/builder.py @@ -175,6 +175,7 @@ def __init__( self.graph = graph self.ret_types: list[RType] = [] self.functions: list[FuncIR] = [] + self.function_names: set[tuple[str | None, str]] = set() self.classes: list[ClassIR] = [] self.final_names: list[tuple[str, RType]] = [] self.callable_class_names: set[str] = set() @@ -1326,6 +1327,14 @@ def error(self, msg: str, line: int) -> None: def note(self, msg: str, line: int) -> None: self.errors.note(msg, self.module_path, line) + def add_function(self, func_ir: FuncIR, line: int) -> None: + name = (func_ir.class_name, func_ir.name) + if name in self.function_names: + self.error(f'Duplicate definition of "{name[1]}" not supported by mypyc', line) + return + self.function_names.add(name) + self.functions.append(func_ir) + def gen_arg_defaults(builder: IRBuilder) -> None: """Generate blocks for arguments that have default values. diff --git a/mypyc/irbuild/function.py b/mypyc/irbuild/function.py index ebf7fa9a54de..b1785f40550e 100644 --- a/mypyc/irbuild/function.py +++ b/mypyc/irbuild/function.py @@ -103,7 +103,7 @@ def transform_func_def(builder: IRBuilder, fdef: FuncDef) -> None: if func_reg: builder.assign(get_func_target(builder, fdef), func_reg, fdef.line) maybe_insert_into_registry_dict(builder, fdef) - builder.functions.append(func_ir) + builder.add_function(func_ir, fdef.line) def transform_overloaded_func_def(builder: IRBuilder, o: OverloadedFuncDef) -> None: diff --git a/mypyc/test-data/irbuild-statements.test b/mypyc/test-data/irbuild-statements.test index 490b41336e88..b7c67730a05f 100644 --- a/mypyc/test-data/irbuild-statements.test +++ b/mypyc/test-data/irbuild-statements.test @@ -1123,3 +1123,27 @@ L6: r14 = CPy_NoErrOccured() L7: return 1 + +[case testConditionalFunctionDefinition] +if int(): + def foo() -> int: + return 0 +else: + def foo() -> int: # E + return 1 + +def bar() -> int: + return 0 + +if int(): + def bar() -> int: # E + return 1 +[out] +main:5: error: Duplicate definition of "foo" not supported by mypyc +main:12: error: Duplicate definition of "bar" not supported by mypyc + +[case testRepeatedUnderscoreFunctions] +def _(arg): pass +def _(arg): pass +[out] +main:2: error: Duplicate definition of "_" not supported by mypyc diff --git a/mypyc/test-data/run-misc.test b/mypyc/test-data/run-misc.test index c40e0fc55f0e..f77ba3a1302b 100644 --- a/mypyc/test-data/run-misc.test +++ b/mypyc/test-data/run-misc.test @@ -1117,10 +1117,6 @@ for _ in range(2): except AssertionError: pass -[case testRepeatedUnderscoreFunctions] -def _(arg): pass -def _(arg): pass - [case testUnderscoreFunctionsInMethods] class A: