checker: add check for recursive array init on struct (fix #21195) (#24278)

This commit is contained in:
Felipe Pena 2025-04-21 13:02:28 -03:00 committed by GitHub
parent 157d8e84e5
commit 38ff647250
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 42 additions and 3 deletions

View File

@ -96,7 +96,7 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
symfield.is_recursive = true
} else {
c.error('recursive struct is only possible with optional pointer (e.g. ?&${c.table.type_to_str(field.typ.clear_flag(.option))})',
node.pos)
field.pos)
}
}
}
@ -249,6 +249,13 @@ fn (mut c Checker) struct_decl(mut node ast.StructDecl) {
}
}
}
if field.default_expr is ast.ArrayInit {
if c.table.final_sym(field.default_expr_typ).kind in [.array, .array_fixed]
&& c.table.value_type(field.default_expr_typ) == struct_typ_idx {
c.error('cannot initialize array of same struct type that is being defined (recursion detected)',
field.pos)
}
}
interface_implemented := sym.kind == .interface
&& c.type_implements(field.default_expr_typ, field.typ, field.pos)
c.check_expected(field.default_expr_typ, field.typ) or {

View File

@ -1,5 +1,6 @@
vlib/v/checker/tests/invalid_recursive_struct_err.vv:1:1: error: recursive struct is only possible with optional pointer (e.g. ?&Node)
vlib/v/checker/tests/invalid_recursive_struct_err.vv:3:2: error: recursive struct is only possible with optional pointer (e.g. ?&Node)
1 | struct Node {
| ~~~~~~~~~~~
2 | mut:
3 | next ?Node
| ~~~~~~~~~~
4 | }

View File

@ -0,0 +1,19 @@
vlib/v/checker/tests/recursive_struct_inited_array_err.vv:10:2: warning: unused variable: `buggy`
8 |
9 | fn main() {
10 | buggy := Node{}
| ~~~~~
11 | normal := BetterNode{}
12 | }
vlib/v/checker/tests/recursive_struct_inited_array_err.vv:11:2: warning: unused variable: `normal`
9 | fn main() {
10 | buggy := Node{}
11 | normal := BetterNode{}
| ~~~~~~
12 | }
vlib/v/checker/tests/recursive_struct_inited_array_err.vv:2:2: error: cannot initialize array of same struct type that is being defined (recursion detected)
1 | struct Node {
2 | next []Node = []Node{len: 1}
| ~~~~~~~~~~~
3 | }
4 |

View File

@ -0,0 +1,12 @@
struct Node {
next []Node = []Node{len: 1}
}
struct BetterNode {
next []BetterNode
}
fn main() {
buggy := Node{}
normal := BetterNode{}
}