Skip to content

Commit 324edc6

Browse files
authored
checker: fix stack var outside usage when var is a mutable param (#24249)
1 parent 2edfb58 commit 324edc6

4 files changed

Lines changed: 47 additions & 7 deletions

File tree

‎vlib/v/checker/checker.v‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5594,6 +5594,11 @@ fn (mut c Checker) fail_if_stack_struct_action_outside_unsafe(mut ident ast.Iden
55945594
sym := c.table.sym(obj.typ.set_nr_muls(0))
55955595
is_heap := sym.is_heap()
55965596
if (!is_heap || !obj.typ.is_ptr()) && !c.pref.translated && !c.file.is_translated {
5597+
is_mut_param := c.table.cur_fn != unsafe { nil }
5598+
&& c.table.cur_fn.params.filter(it.name == ident.name && it.is_mut).len > 0
5599+
if is_mut_param {
5600+
return
5601+
}
55975602
suggestion := if !is_heap && sym.kind == .struct {
55985603
'declaring `${sym.name}` as `@[heap]`'
55995604
} else if !is_heap {

‎vlib/v/checker/tests/no_heap_struct.out‎

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,6 @@ vlib/v/checker/tests/no_heap_struct.vv:13:6: error: `x` cannot be assigned outsi
55
| ^
66
14 | }
77
15 | return s
8-
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]`.
9-
17 |
10-
18 | fn g(mut x Abc) &Abc {
11-
19 | return x
12-
| ^
13-
20 | }
14-
21 |
158
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]`.
169
21 |
1710
22 | fn h(x &Abc) &Abc {

‎vlib/v/checker/tests/stack_var_check_err.out‎

Whitespace-only changes.
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
module main
2+
3+
@[heap]
4+
interface IGameObject {
5+
mut:
6+
name string
7+
parent ?&IGameObject
8+
next ?&IGameObject
9+
child ?&IGameObject
10+
last_child ?&IGameObject
11+
add_child(mut o IGameObject)
12+
}
13+
14+
@[heap]
15+
struct GameObject implements IGameObject {
16+
mut:
17+
name string
18+
parent ?&IGameObject
19+
next ?&IGameObject
20+
child ?&IGameObject
21+
last_child ?&IGameObject
22+
}
23+
24+
fn (mut gameobject GameObject) add_child(mut o IGameObject) {
25+
o.parent = gameobject
26+
if mut last_child := gameobject.last_child {
27+
last_child.next = o
28+
} else {
29+
gameobject.child = o
30+
}
31+
gameobject.last_child = o
32+
}
33+
34+
fn main() {
35+
mut v1 := &GameObject{
36+
name: 'v1'
37+
}
38+
mut v2 := &GameObject{
39+
name: 'v2'
40+
}
41+
v1.add_child(mut v2)
42+
}

0 commit comments

Comments
 (0)