From 4ca9619315e7615b101419fbcf72e923f4f9b36d Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Tue, 23 Jun 2026 00:23:39 +0300 Subject: [PATCH] v3: fix post-merge review issues (#27527) --- vlib/v3/gen/c/fn.v | 52 +++--------- vlib/v3/gen/c/stmt.v | 5 +- vlib/v3/gen/c/struct.v | 8 +- vlib/v3/tests/post_merge_review_fixes_test.v | 88 ++++++++++++++++++++ 4 files changed, 111 insertions(+), 42 deletions(-) create mode 100644 vlib/v3/tests/post_merge_review_fixes_test.v diff --git a/vlib/v3/gen/c/fn.v b/vlib/v3/gen/c/fn.v index d741cda89..abb49e4a5 100644 --- a/vlib/v3/gen/c/fn.v +++ b/vlib/v3/gen/c/fn.v @@ -321,33 +321,19 @@ fn (mut g FlatGen) gen_compiler_vexe_env_setup() { g.writeln("\t\tconst char* v3_base = strrchr(v3_arg0, '/');") g.writeln('\t\tv3_base = v3_base == NULL ? v3_arg0 : v3_base + 1;') g.writeln('\t\tif (v3_base[0] == 0) v3_base = "v";') - g.writeln('\t\tchar v3_vexe_target[4096];') - g.writeln('\t\tsnprintf(v3_vexe_target, sizeof(v3_vexe_target), "${root}/%s", v3_base);') + g.writeln('\t\tconst char* v3_checkout_root = "${root}";') + g.writeln('\t\tchar v3_checkout_vexe[4096];') + g.writeln('\t\tsnprintf(v3_checkout_vexe, sizeof(v3_checkout_vexe), "%s/%s", v3_checkout_root, v3_base);') + g.writeln('\t\tif (access(v3_checkout_vexe, F_OK) != 0) snprintf(v3_checkout_vexe, sizeof(v3_checkout_vexe), "%s/v", v3_checkout_root);') g.writeln('\t\tchar v3_src_real[4096];') - g.writeln('\t\tchar v3_dst_real[4096];') g.writeln('\t\tchar* v3_src_real_result = realpath(v3_arg0, v3_src_real);') - g.writeln('\t\tconst char* v3_src = v3_src_real_result != NULL ? v3_src_real : v3_arg0;') - g.writeln('\t\tint v3_same_exe = 0;') - g.writeln('\t\tif (v3_src_real_result != NULL && realpath(v3_vexe_target, v3_dst_real) != NULL && strcmp(v3_src_real, v3_dst_real) == 0) v3_same_exe = 1;') - g.writeln('\t\tif (!v3_same_exe) {') - g.writeln('\t\t\tFILE* v3_in = fopen(v3_src, "rb");') - g.writeln('\t\t\tif (v3_in != NULL) {') - g.writeln('\t\t\t\tFILE* v3_out = fopen(v3_vexe_target, "wb");') - g.writeln('\t\t\t\tif (v3_out != NULL) {') - g.writeln('\t\t\t\t\tchar v3_buf[65536];') - g.writeln('\t\t\t\t\tsize_t v3_nread = 0;') - g.writeln('\t\t\t\t\twhile ((v3_nread = fread(v3_buf, 1, sizeof(v3_buf), v3_in)) > 0) fwrite(v3_buf, 1, v3_nread, v3_out);') - g.writeln('\t\t\t\t\tfclose(v3_out);') - g.writeln('\t\t\t\t\tchmod(v3_vexe_target, 0755);') - g.writeln('\t\t\t\t}') - g.writeln('\t\t\t\tfclose(v3_in);') - g.writeln('\t\t\t}') - g.writeln('\t\t}') - g.writeln('\t\tif (access(v3_vexe_target, F_OK) == 0) {') + g.writeln('\t\tconst char* v3_vexe = v3_src_real_result != NULL ? v3_src_real : v3_arg0;') + g.writeln('\t\tif (access(v3_checkout_vexe, F_OK) == 0) v3_vexe = v3_checkout_vexe;') + g.writeln('\t\tif (v3_vexe[0] != 0) {') g.writeln('#ifdef _WIN32') - g.writeln('\t\t\t_putenv_s("VEXE", v3_vexe_target);') + g.writeln('\t\t\t_putenv_s("VEXE", v3_vexe);') g.writeln('#else') - g.writeln('\t\t\tsetenv("VEXE", v3_vexe_target, 1);') + g.writeln('\t\t\tsetenv("VEXE", v3_vexe, 1);') g.writeln('#endif') g.writeln('\t\t}') g.writeln('\t}') @@ -1121,24 +1107,12 @@ fn (g &FlatGen) enum_receiver_method_name(enum_type types.Enum, method string) ? if direct in g.tc.fn_param_types { return direct } - short_name := name.all_after_last('.') - if short_name != name { - short_method := '${short_name}.${method}' - if short_method in g.tc.fn_param_types { - return short_method - } - for candidate, _ in g.tc.fn_param_types { - if candidate.ends_with('.${short_method}') { - return candidate - } - } + if name.contains('.') { return none } - if !name.contains('.') { - for candidate, _ in g.tc.fn_param_types { - if candidate.ends_with('.${direct}') { - return candidate - } + for candidate, _ in g.tc.fn_param_types { + if candidate.ends_with('.${direct}') { + return candidate } } return none diff --git a/vlib/v3/gen/c/stmt.v b/vlib/v3/gen/c/stmt.v index d413ba642..9311c60d2 100644 --- a/vlib/v3/gen/c/stmt.v +++ b/vlib/v3/gen/c/stmt.v @@ -376,7 +376,10 @@ fn (mut g FlatGen) gen_return_with_defers(node flat.Node) { ret_id := g.a.child(&node, 0) ret_node := g.a.nodes[int(ret_id)] if ret_node.kind == .assoc { - g.gen_return_assoc(ret_node) + tmp := g.tmp_name() + g.gen_assoc_return_tmp(ret_node, tmp) + g.gen_all_defers() + g.writeln('return ${tmp};') return } ct := g.return_c_type() diff --git a/vlib/v3/gen/c/struct.v b/vlib/v3/gen/c/struct.v index eb054c82a..a6fb60b38 100644 --- a/vlib/v3/gen/c/struct.v +++ b/vlib/v3/gen/c/struct.v @@ -688,8 +688,13 @@ fn (g &FlatGen) struct_field_type_at(type_name string, index int) ?types.Type { } fn (mut g FlatGen) gen_return_assoc(node flat.Node) { - ct := g.tc.c_type(g.tc.parse_type(node.value)) tmp := g.tmp_name() + g.gen_assoc_return_tmp(node, tmp) + g.writeln('return ${tmp};') +} + +fn (mut g FlatGen) gen_assoc_return_tmp(node flat.Node, tmp string) { + ct := g.tc.c_type(g.tc.parse_type(node.value)) g.write('${ct} ${tmp} = ') g.gen_expr(g.a.child(&node, 0)) g.writeln(';') @@ -705,7 +710,6 @@ fn (mut g FlatGen) gen_return_assoc(node flat.Node) { g.writeln(';') } } - g.writeln('return ${tmp};') } fn (mut g FlatGen) gen_assoc_expr(node flat.Node) { diff --git a/vlib/v3/tests/post_merge_review_fixes_test.v b/vlib/v3/tests/post_merge_review_fixes_test.v new file mode 100644 index 000000000..ec60bc334 --- /dev/null +++ b/vlib/v3/tests/post_merge_review_fixes_test.v @@ -0,0 +1,88 @@ +import os + +const vexe = @VEXE +const tests_dir = os.dir(@FILE) +const v3_dir = os.dir(tests_dir) +const vlib_dir = os.dir(v3_dir) +const repo_dir = os.dir(vlib_dir) +const v3_src = os.join_path(v3_dir, 'v3.v') +const compiler_src_dir = os.join_path(repo_dir, 'cmd', 'v') + +fn build_v3() string { + v3_bin := os.join_path(os.temp_dir(), 'v3_post_merge_review_fixes_test') + build := + os.execute('${vexe} -gc none -path "${vlib_dir}|@vlib|@vmodules" -o ${v3_bin} ${v3_src}') + assert build.exit_code == 0, build.output + return v3_bin +} + +fn run_good(v3_bin string, name string, src string) string { + good_src := os.join_path(os.temp_dir(), 'v3_${name}.v') + os.write_file(good_src, src) or { panic(err) } + good_bin := os.join_path(os.temp_dir(), 'v3_${name}') + compile := os.execute('${v3_bin} ${good_src} -b c -o ${good_bin}') + assert compile.exit_code == 0, compile.output + assert !compile.output.contains('C compilation failed'), compile.output + run := os.execute(good_bin) + assert run.exit_code == 0, run.output + return run.output.trim_space() +} + +fn write_project_file(root string, rel string, src string) { + path := os.join_path(root, rel) + os.mkdir_all(os.dir(path)) or { panic(err) } + os.write_file(path, src) or { panic(err) } +} + +fn run_good_project(v3_bin string, name string, files map[string]string, input string) string { + root := os.join_path(os.temp_dir(), 'v3_${name}_project') + if os.exists(root) { + os.rmdir_all(root) or { panic(err) } + } + os.mkdir_all(root) or { panic(err) } + for rel, src in files { + write_project_file(root, rel, src) + } + input_path := if input.len == 0 { root } else { os.join_path(root, input) } + good_bin := os.join_path(os.temp_dir(), 'v3_${name}') + compile := os.execute('${v3_bin} ${input_path} -b c -o ${good_bin}') + assert compile.exit_code == 0, compile.output + assert !compile.output.contains('C compilation failed'), compile.output + run := os.execute(good_bin) + assert run.exit_code == 0, run.output + return run.output.trim_space() +} + +fn test_compiler_vexe_env_uses_running_executable() { + v3_bin := build_v3() + c_out := os.join_path(os.temp_dir(), 'v3_review_vexe.c') + os.rm(c_out) or {} + gen := os.execute('${v3_bin} -o ${c_out} ${compiler_src_dir}') + assert gen.exit_code == 0, gen.output + assert os.exists(c_out) + c_source := os.read_file(c_out) or { panic(err) } + assert !c_source.contains('v3_vexe_target') + assert !c_source.contains('fopen(v3_src') + assert c_source.contains('snprintf(v3_checkout_vexe, sizeof(v3_checkout_vexe),') + assert c_source.contains('if (access(v3_checkout_vexe, F_OK) == 0) v3_vexe = v3_checkout_vexe;') + assert c_source.contains('const char* v3_vexe = v3_src_real_result != NULL ? v3_src_real : v3_arg0;') + assert c_source.contains('_putenv_s("VEXE", v3_vexe);') + assert c_source.contains('setenv("VEXE", v3_vexe, 1);') +} + +fn test_assoc_return_runs_defers() { + v3_bin := build_v3() + out := run_good(v3_bin, 'assoc_return_runs_defers', + 'struct Point {\n\tx int\n\ty int\n}\n\n__global hit int\n\nfn make_point() Point {\n\tbase := Point{\n\t\tx: 1\n\t\ty: 2\n\t}\n\tdefer {\n\t\thit = 7\n\t}\n\treturn Point{\n\t\t...base\n\t\tx: 5\n\t}\n}\n\nfn main() {\n\tp := make_point()\n\tprintln(int_str(p.x))\n\tprintln(int_str(hit))\n}\n') + assert out == '5\n7' +} + +fn test_qualified_enum_str_requires_exact_receiver() { + v3_bin := build_v3() + out := run_good_project(v3_bin, 'qualified_enum_str_exact_receiver', { + 'main.v': 'module main\n\nimport moda\nimport modb\n\nfn main() {\n\tprintln(moda.Color.red.str())\n\tprintln(modb.Color.blue.str())\n}\n' + 'moda/moda.v': 'module moda\n\npub enum Color {\n\tred\n}\n' + 'modb/modb.v': "module modb\n\npub enum Color {\n\tblue\n}\n\npub fn (c Color) str() string {\n\treturn 'custom'\n}\n" + }, 'main.v') + assert out == 'red\ncustom' +} -- 2.39.5