From 8f425cac4bdd9e6de67ec9f79a9db6ce6338ba55 Mon Sep 17 00:00:00 2001 From: DarathDev Date: Mon, 25 May 2026 22:20:07 -0600 Subject: [PATCH 1/2] fix issue resolving overload with polymorphic arguments when passed a pointer from another function resolves #1495 --- src/server/analysis.odin | 6 ++---- src/server/generics.odin | 14 ++++++++++++++ tests/hover_test.odin | 26 ++++++++++++++++++++++++++ 3 files changed, 42 insertions(+), 4 deletions(-) diff --git a/src/server/analysis.odin b/src/server/analysis.odin index fc2a3d7a..7f0970c9 100644 --- a/src/server/analysis.odin +++ b/src/server/analysis.odin @@ -3759,19 +3759,17 @@ get_package_from_filepath :: proc(file_path: string) -> string { return ret } -wrap_pointer :: proc(expr: ^ast.Expr, times: int) -> ^ast.Expr { - n := 0 +wrap_pointer :: proc(expr: ^ast.Expr, times: int, allocator := context.temp_allocator) -> ^ast.Expr { expr := expr for i in 0 ..< times { - new_pointer := new_type(ast.Pointer_Type, expr.pos, expr.end, context.temp_allocator) + new_pointer := new_type(ast.Pointer_Type, expr.pos, expr.end, allocator) new_pointer.elem = expr expr = new_pointer } - return expr } diff --git a/src/server/generics.odin b/src/server/generics.odin index 4b4fff1a..7f9e4fc8 100644 --- a/src/server/generics.odin +++ b/src/server/generics.odin @@ -53,6 +53,11 @@ resolve_poly :: proc( } else { save_poly_map(ident, symbol_to_expr(call_symbol, call_node.pos.file), poly_map) } + if call_symbol.pointers > 0 { + if expr, expr_ok := get_poly_map(ident, poly_map); expr_ok { + save_poly_map(ident, wrap_pointer(expr, call_symbol.pointers), poly_map) + } + } } } return true @@ -301,6 +306,15 @@ resolve_poly_expression :: proc( } } + call_node := call_node + poly_node := poly_node + + // The expression for the specialization already contains the pointers + // so we don't need to represent it in the next poly + // Note: this function is only ever called by `resolve_poly_specialization` + call_node, _, _ = unwrap_pointer_expr(call_node) + poly_node, _, _ = unwrap_pointer_expr(poly_node) + call_symbol := Symbol{} internal_resolve_type_expression(ast_context, call_node, &call_symbol) return resolve_poly(ast_context, call_node, call_symbol, poly_node, poly_map) diff --git a/tests/hover_test.odin b/tests/hover_test.odin index aa925542..8b6df743 100644 --- a/tests/hover_test.odin +++ b/tests/hover_test.odin @@ -6917,3 +6917,29 @@ ast_hover_overload_resolve_aliased_arguments :: proc(t: ^testing.T) { test.expect_hover(t, &source, "pkg1.Bar :: proc(table: Foo)") } + +@(test) +ast_hover_overload_pointer_arg_from_return :: proc(t: ^testing.T) { + source: = test.Source { + main = `package test + + foo :: proc() -> ^int { + return {} + } + + bar :: proc { + bar_pass, + } + + bar_pass :: proc(value: $T) -> T { + return T{} + } + + main :: proc() { + bar{*}(foo()) + } + ` + } + + test.expect_hover(t, &source, "test.bar :: proc(value: $T) -> T") +} \ No newline at end of file From e2c46ee8287276d8a7036e3f13925189e0ab30b5 Mon Sep 17 00:00:00 2001 From: DarathDev Date: Mon, 25 May 2026 22:21:43 -0600 Subject: [PATCH 2/2] derived_expr should never be used clone_node does currently ensure derived_expr or derived_stmt are kept in sync with derived, so they are not necessarily correct. --- src/odin/printer/visit.odin | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/odin/printer/visit.odin b/src/odin/printer/visit.odin index bed9f4d6..51382393 100644 --- a/src/odin/printer/visit.odin +++ b/src/odin/printer/visit.odin @@ -251,7 +251,7 @@ visit_decl :: proc(p: ^Printer, decl: ^ast.Decl, called_in_stmt := false) -> ^Do } document = cons(document, text("}")) } else if len(v.fullpaths) == 1 { - if _, ok := v.fullpaths[0].derived_expr.(^ast.Basic_Lit); ok { + if _, ok := v.fullpaths[0].derived.(^ast.Basic_Lit); ok { document = cons_with_nopl(document, visit_expr(p, v.fullpaths[0])) } else { document = cons_with_nopl(document, text("{"))