From 324edc6eabde255ab9bdc620a241c728618882e3 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Sat, 19 Apr 2025 21:03:20 -0300 Subject: [PATCH] checker: fix stack var outside usage when var is a mutable param (#24249) --- vlib/v/checker/checker.v | 5 +++ vlib/v/checker/tests/no_heap_struct.out | 7 ---- vlib/v/checker/tests/stack_var_check_err.out | 0 vlib/v/checker/tests/stack_var_check_err.vv | 42 ++++++++++++++++++++ 4 files changed, 47 insertions(+), 7 deletions(-) create mode 100644 vlib/v/checker/tests/stack_var_check_err.out create mode 100644 vlib/v/checker/tests/stack_var_check_err.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index e197d1785..b943e1a1b 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -5594,6 +5594,11 @@ fn (mut c Checker) fail_if_stack_struct_action_outside_unsafe(mut ident ast.Iden sym := c.table.sym(obj.typ.set_nr_muls(0)) is_heap := sym.is_heap() if (!is_heap || !obj.typ.is_ptr()) && !c.pref.translated && !c.file.is_translated { + is_mut_param := c.table.cur_fn != unsafe { nil } + && c.table.cur_fn.params.filter(it.name == ident.name && it.is_mut).len > 0 + if is_mut_param { + return + } suggestion := if !is_heap && sym.kind == .struct { 'declaring `${sym.name}` as `@[heap]`' } else if !is_heap { diff --git a/vlib/v/checker/tests/no_heap_struct.out b/vlib/v/checker/tests/no_heap_struct.out index 7b3bbb3e6..b56943d2d 100644 --- a/vlib/v/checker/tests/no_heap_struct.out +++ b/vlib/v/checker/tests/no_heap_struct.out @@ -5,13 +5,6 @@ vlib/v/checker/tests/no_heap_struct.vv:13:6: error: `x` cannot be assigned outsi | ^ 14 | } 15 | return s -vlib/v/checker/tests/no_heap_struct.vv:19:9: error: `x` cannot be returned outside `unsafe` blocks as it might refer to an object stored on stack. Consider declaring `Abc` as `@[heap]`. - 17 | - 18 | fn g(mut x Abc) &Abc { - 19 | return x - | ^ - 20 | } - 21 | vlib/v/checker/tests/no_heap_struct.vv:23:7: error: `x` cannot be assigned outside `unsafe` blocks as it might refer to an object stored on stack. Consider declaring `Abc` as `@[heap]`. 21 | 22 | fn h(x &Abc) &Abc { diff --git a/vlib/v/checker/tests/stack_var_check_err.out b/vlib/v/checker/tests/stack_var_check_err.out new file mode 100644 index 000000000..e69de29bb diff --git a/vlib/v/checker/tests/stack_var_check_err.vv b/vlib/v/checker/tests/stack_var_check_err.vv new file mode 100644 index 000000000..14c02afb7 --- /dev/null +++ b/vlib/v/checker/tests/stack_var_check_err.vv @@ -0,0 +1,42 @@ +module main + +@[heap] +interface IGameObject { +mut: + name string + parent ?&IGameObject + next ?&IGameObject + child ?&IGameObject + last_child ?&IGameObject + add_child(mut o IGameObject) +} + +@[heap] +struct GameObject implements IGameObject { +mut: + name string + parent ?&IGameObject + next ?&IGameObject + child ?&IGameObject + last_child ?&IGameObject +} + +fn (mut gameobject GameObject) add_child(mut o IGameObject) { + o.parent = gameobject + if mut last_child := gameobject.last_child { + last_child.next = o + } else { + gameobject.child = o + } + gameobject.last_child = o +} + +fn main() { + mut v1 := &GameObject{ + name: 'v1' + } + mut v2 := &GameObject{ + name: 'v2' + } + v1.add_child(mut v2) +} -- 2.39.5