From 9828cd834a85b84fba616388eb31125a9b2044b7 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Mon, 9 Feb 2026 16:00:33 +0300 Subject: [PATCH] parser: show where another declaration is located (fixes #26483) --- vlib/v/parser/struct.v | 32 +++++++++++++++++-- vlib/v/parser/tests/duplicate_type_b.out | 5 +++ ...rohibit_redeclaration_of_builtin_types.out | 7 ++++ 3 files changed, 42 insertions(+), 2 deletions(-) diff --git a/vlib/v/parser/struct.v b/vlib/v/parser/struct.v index 935ee1d2d..f98dea8a4 100644 --- a/vlib/v/parser/struct.v +++ b/vlib/v/parser/struct.v @@ -4,6 +4,7 @@ module parser import v.ast +import v.errors import v.token import v.util @@ -479,8 +480,35 @@ fn (mut p Parser) struct_decl(is_anon bool) ast.StructDecl { } // allow duplicate c struct declarations if ret == -1 && language != .c && !p.pref.is_fmt { - p.error_with_pos('cannot register struct `${name}`, another type with this name exists', - name_pos) + msg := 'cannot register struct `${name}`, another type with this name exists' + mut existing_sym, mut existing_idx := p.table.find_sym_and_type_idx(name) + if existing_idx <= 0 && name.starts_with('main.') { + existing_sym, existing_idx = p.table.find_sym_and_type_idx(name.trim_string_left('main.')) + } + if existing_idx > 0 { + if existing_name_pos := existing_sym.info.get_name_pos() { + existing_file_path := if existing_name_pos.file_idx < 0 { + p.file_path + } else { + p.table.filelist[existing_name_pos.file_idx] + } + error_file_path := if name_pos.file_idx < 0 { + p.file_path + } else { + p.table.filelist[name_pos.file_idx] + } + p.error_with_error(errors.Error{ + file_path: error_file_path + pos: name_pos + reporter: .parser + message: msg + details: util.formatted_error('details:', 'another declaration was found here', + existing_file_path, existing_name_pos) + }) + return ast.StructDecl{} + } + } + p.error_with_pos(msg, name_pos) return ast.StructDecl{} } p.expr_mod = '' diff --git a/vlib/v/parser/tests/duplicate_type_b.out b/vlib/v/parser/tests/duplicate_type_b.out index 6831fdacb..fc1c69632 100644 --- a/vlib/v/parser/tests/duplicate_type_b.out +++ b/vlib/v/parser/tests/duplicate_type_b.out @@ -3,3 +3,8 @@ vlib/v/parser/tests/duplicate_type_b.vv:3:8: error: cannot register struct `Foo` 2 | 3 | struct Foo {} | ~~~ +Details: vlib/v/parser/tests/duplicate_type_b.vv:1:1: details: another declaration was found here + 1 | interface Foo {} + | ^ + 2 | + 3 | struct Foo {} diff --git a/vlib/v/parser/tests/prohibit_redeclaration_of_builtin_types.out b/vlib/v/parser/tests/prohibit_redeclaration_of_builtin_types.out index e292e0a01..28b86f44a 100644 --- a/vlib/v/parser/tests/prohibit_redeclaration_of_builtin_types.out +++ b/vlib/v/parser/tests/prohibit_redeclaration_of_builtin_types.out @@ -1,3 +1,10 @@ vlib/v/parser/tests/prohibit_redeclaration_of_builtin_types.vv:1:8: error: cannot register struct `Option`, another type with this name exists 1 | struct Option {} | ~~~~~~ +Details: vlib/builtin/chan_option_result.v:142:8: details: another declaration was found here + 140 | + 141 | // Option is the base of V's internal option return system. + 142 | struct Option { + | ~~~~~~ + 143 | state u8 // 0 - ok; 2 - none; 1 - ? + 144 | err IError = none__ -- 2.39.5