diff --git a/src/analyze.cpp b/src/analyze.cpp index 1010ff70d7..480f0c7b3a 100644 --- a/src/analyze.cpp +++ b/src/analyze.cpp @@ -5062,12 +5062,20 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast case NodeTypeFnProto: { // if the name is missing, we immediately announce an error - Buf *name = &node->data.fn_proto.name; - if (buf_len(name) == 0) { + Buf *fn_name = &node->data.fn_proto.name; + if (buf_len(fn_name) == 0) { node->data.fn_proto.skip = true; add_node_error(g, node, buf_sprintf("missing function name")); break; } + Buf *qualified_name; + AstNode *struct_node = node->data.fn_proto.struct_node; + if (struct_node) { + Buf *struct_name = &struct_node->data.struct_decl.name; + qualified_name = buf_sprintf("%s.%s", buf_ptr(struct_name), buf_ptr(fn_name)); + } else { + qualified_name = fn_name; + } // determine which other top level declarations this function prototype depends on. @@ -5076,14 +5084,14 @@ static void detect_top_level_decl_deps(CodeGen *g, ImportTableEntry *import, Ast collect_expr_decl_deps(g, import, node, decl_node); - decl_node->name = name; + decl_node->name = qualified_name; decl_node->import = import; if (decl_node->deps.size() > 0) { - if (g->unresolved_top_level_decls.maybe_get(name)) { + if (g->unresolved_top_level_decls.maybe_get(qualified_name)) { node->data.fn_proto.skip = true; - add_node_error(g, node, buf_sprintf("redefinition of '%s'", buf_ptr(name))); + add_node_error(g, node, buf_sprintf("redefinition of '%s'", buf_ptr(fn_name))); } else { - g->unresolved_top_level_decls.put(name, node); + g->unresolved_top_level_decls.put(qualified_name, node); } } else { resolve_top_level_decl(g, import, node); diff --git a/test/run_tests.cpp b/test/run_tests.cpp index b8cc6fc210..dd5f085276 100644 --- a/test/run_tests.cpp +++ b/test/run_tests.cpp @@ -1549,6 +1549,35 @@ pub fn main(args: [][]u8) -> %void { } )SOURCE", "OK\n"); + + + add_simple_case("same named methods in incomplete struct", R"SOURCE( +import "std.zig"; + +struct Foo { + field1: Bar, + + fn method(a: &Foo) -> bool { true } +} + +struct Bar { + field2: i32, + + fn method(b: &Bar) -> bool { true } +} + +pub fn main(args: [][]u8) -> %void { + const bar = Bar {.field2 = 13,}; + const foo = Foo {.field1 = bar,}; + if (!foo.method()) { + %%stdout.printf("BAD\n"); + } + if (!bar.method()) { + %%stdout.printf("BAD\n"); + } + %%stdout.printf("OK\n"); +} + )SOURCE", "OK\n"); }