From 947434b81683667818cb12e9ba570b401bcc0912 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Wed, 15 Apr 2026 04:58:20 +0300 Subject: [PATCH] comptime: fix $compile_error to locate the actual error position (fixes #24575) --- vlib/v/checker/comptime.v | 16 ++++++---------- .../tests/compile_error_call_position.out | 9 +-------- .../tests/compile_error_explicit_type.out | 15 +++++++-------- ...ching_working_with_a_custom_compile_error.out | 9 +-------- .../comptime_else_compile_error_no_return.out | 9 +-------- .../checker/tests/sync_stdatomic_compile_err.out | 9 +-------- 6 files changed, 17 insertions(+), 50 deletions(-) diff --git a/vlib/v/checker/comptime.v b/vlib/v/checker/comptime.v index 5bfb79b62..778fc0302 100644 --- a/vlib/v/checker/comptime.v +++ b/vlib/v/checker/comptime.v @@ -40,20 +40,16 @@ fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type { node.left_type = c.expr(mut node.left) } if node.kind == .compile_error { - // Add call stack information for `$compile_error()` - mut call_stack := []errors.CallStackItem{} - // Only add call stack if we're inside a function (not at module level) + mut err_pos := node.pos + // During generic rechecks, report the instantiation site instead of the + // `$compile_error()` directive inside the generic body. if c.fn_level > 0 && c.table.cur_fn != unsafe { nil } { call_key := c.build_generic_call_key(c.table.cur_fn.fkey(), c.table.cur_concrete_types) - pos := c.generic_call_positions[call_key] or { c.table.cur_fn.name_pos } - // Use the file path from the position, not the current file - file_path := if pos.file_idx >= 0 { c.table.filelist[pos.file_idx] } else { c.file.path } - call_stack << errors.CallStackItem{ - file_path: file_path - pos: pos + if pos := c.generic_call_positions[call_key] { + err_pos = pos } } - c.error(c.comptime_call_msg(node), node.pos, call_stack: call_stack) + c.error(c.comptime_call_msg(node), err_pos) return ast.void_type } else if node.kind == .compile_warn { c.warn(c.comptime_call_msg(node), node.pos) diff --git a/vlib/v/checker/tests/compile_error_call_position.out b/vlib/v/checker/tests/compile_error_call_position.out index 5d021a950..087255685 100644 --- a/vlib/v/checker/tests/compile_error_call_position.out +++ b/vlib/v/checker/tests/compile_error_call_position.out @@ -5,14 +5,7 @@ vlib/v/checker/tests/compile_error_call_position.vv:3:11: notice: unused paramet | ~~~ 4 | $if T !is int { 5 | $compile_error('son only taken int as input') -vlib/v/checker/tests/compile_error_call_position.vv:5:3: error: son only taken int as input - 3 | fn son[T](val T) { - 4 | $if T !is int { - 5 | $compile_error('son only taken int as input') - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 6 | } - 7 | } -called from vlib/v/checker/tests/compile_error_call_position.vv:10:2 +vlib/v/checker/tests/compile_error_call_position.vv:10:2: error: son only taken int as input 8 | 9 | fn main() { 10 | son(false) diff --git a/vlib/v/checker/tests/compile_error_explicit_type.out b/vlib/v/checker/tests/compile_error_explicit_type.out index a178f3a25..145b7ec97 100644 --- a/vlib/v/checker/tests/compile_error_explicit_type.out +++ b/vlib/v/checker/tests/compile_error_explicit_type.out @@ -5,17 +5,16 @@ vlib/v/checker/tests/compile_error_explicit_type.vv:3:11: notice: unused paramet | ~~~ 4 | $if T !is int { 5 | $compile_error('son only take `int` as input') -vlib/v/checker/tests/compile_error_explicit_type.vv:5:3: error: son only take `int` as input - 3 | fn son[T](val T) { - 4 | $if T !is int { - 5 | $compile_error('son only take `int` as input') - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 6 | } - 7 | } -called from vlib/v/checker/tests/compile_error_explicit_type.vv:11:2 +vlib/v/checker/tests/compile_error_explicit_type.vv:11:2: error: son only take `int` as input 9 | fn main() { 10 | son[int](123) 11 | son[bool](false) | ~~~~~~~~~~~~~~~~ 12 | son[int](456) 13 | son[string]('hello') +vlib/v/checker/tests/compile_error_explicit_type.vv:13:2: error: son only take `int` as input + 11 | son[bool](false) + 12 | son[int](456) + 13 | son[string]('hello') + | ~~~~~~~~~~~~~~~~~~~~ + 14 | } diff --git a/vlib/v/checker/tests/comptime_branching_working_with_a_custom_compile_error.out b/vlib/v/checker/tests/comptime_branching_working_with_a_custom_compile_error.out index 523bfd3de..251e036ba 100644 --- a/vlib/v/checker/tests/comptime_branching_working_with_a_custom_compile_error.out +++ b/vlib/v/checker/tests/comptime_branching_working_with_a_custom_compile_error.out @@ -1,11 +1,4 @@ -vlib/v/checker/tests/comptime_branching_working_with_a_custom_compile_error.vv:8:3: error: 11 - 6 | return Value(val) - 7 | } $else { - 8 | $compile_error('11') - | ~~~~~~~~~~~~~~~~~~~~ - 9 | println('not bool ${val}') - 10 | } -called from vlib/v/checker/tests/comptime_branching_working_with_a_custom_compile_error.vv:15:10 +vlib/v/checker/tests/comptime_branching_working_with_a_custom_compile_error.vv:15:10: error: 11 13 | 14 | fn main() { 15 | println(create(123)) diff --git a/vlib/v/checker/tests/comptime_else_compile_error_no_return.out b/vlib/v/checker/tests/comptime_else_compile_error_no_return.out index 659fcfef4..5d6e9daac 100644 --- a/vlib/v/checker/tests/comptime_else_compile_error_no_return.out +++ b/vlib/v/checker/tests/comptime_else_compile_error_no_return.out @@ -1,11 +1,4 @@ -vlib/v/checker/tests/comptime_else_compile_error_no_return.vv:5:3: error: not an int - 3 | return val - 4 | } $else { - 5 | $compile_error('not an int') - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 6 | } - 7 | } -called from vlib/v/checker/tests/comptime_else_compile_error_no_return.vv:11:2 +vlib/v/checker/tests/comptime_else_compile_error_no_return.vv:11:2: error: not an int 9 | fn main() { 10 | onlyint(7) 11 | onlyint([]int{}) diff --git a/vlib/v/checker/tests/sync_stdatomic_compile_err.out b/vlib/v/checker/tests/sync_stdatomic_compile_err.out index 2389b03fd..fd126baa0 100644 --- a/vlib/v/checker/tests/sync_stdatomic_compile_err.out +++ b/vlib/v/checker/tests/sync_stdatomic_compile_err.out @@ -1,11 +1,4 @@ -vlib/sync/stdatomic/atomic.c.v:85:3: error: atomic: only support number, bool, and voidptr types - 83 | } - 84 | } $else { - 85 | $compile_error('atomic: only support number, bool, and voidptr types') - | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - 86 | } - 87 | return unsafe { nil } -called from vlib/v/checker/tests/sync_stdatomic_compile_err.vv:3:6 +vlib/v/checker/tests/sync_stdatomic_compile_err.vv:3:6: error: atomic: only support number, bool, and voidptr types 1 | import sync.stdatomic {new_atomic} 2 | 3 | _ := new_atomic(`1`) -- 2.39.5