vlang / v

Simple, fast, safe, compiled language for developing maintainable software. Compiles itself in <1s with zero library dependencies. Supports automatic C => V translation. https://vlang.io
MIT License
35.75k stars 2.16k forks source link

Structure field default value crash, on initializer with length 0 #21195

Open amuerta opened 6 months ago

amuerta commented 6 months ago

Describe the bug

Example

Code: https://play.vlang.io/p/f638c371d1

// example bug

// buggy struct 
struct Node {
    next []Node = []Node {len: 0}
}

struct BetterNode {
    next [] BetterNode
}

fn main() {
    // tested with lastest V playground 

    // if we create variable of node
    buggy := Node{} // we get segmentation fault 
    // this will work just fine 
    normal := BetterNode{} 

    bug := []int {len: 0} // works just fine
}

Reproduction Steps

Recently I started working on the first game and it's engine, when doing so I found an edge case that causes program to segfault with no compile time errors.

I won't put original code snippet since it's irrelevant and issue is really easy to reproduce.

When a structure with field that has this self referring structure array with initializer of length 0, structure creation causes crash with no error.

Expected Behavior

I'm aware of that the following code is incorrect (at least in my opinion) which means compiler should throw an error in such a case:

variable []Type = []Type {len: 0}
                          Error.        ^^^^^^
Initializer of length 0 in struct field default value is forbidden

Or compiler has to warn you about such a possible error case scenario

Current Behavior

Output:

code.v:16:1: warning: unused variable: `buggy`
   14 |     
   15 |     // if we create variable of node
   16 |     buggy := Node{} // we get segmentation fault 
      | ~~~~~
   17 |     // this will work just fine 
   18 |     normal := BetterNode{}
code.v:18:1: warning: unused variable: `normal`
   16 |     buggy := Node{} // we get segmentation fault 
   17 |     // this will work just fine 
   18 |     normal := BetterNode{} 
      | ~~~~~~
   19 |     
   20 |
code.v:21:2: warning: unused variable: `bug`
   19 |     
   20 |     
   21 |     bug := []int {len: 0} // works just fine
      |     ~~~
   22 | }
Caught fatal signal 11

Possible Solution

No response

Additional Information/Context

No response

V version

V 0.4.5 31fdf58

Environment details (OS name and version, etc.)

V full version: V 0.4.5 31fdf58
OS: linux, Debian GNU/Linux 11 (bullseye) (VM)
Processor: 1 cpus, 64bit, little endian, Intel(R) Xeon(R) CPU E5-2686 v4 @ 2.30GHz

getwd: /home/admin/playground
vexe: /home/admin/v/v
vexe mtime: 2024-04-06 07:23:24

vroot: OK, value: /home/admin/v
VMODULES: OK, value: .vmodules
VTMP: OK, value: /tmp/v_0

Git version: git version 2.30.2
Git vroot status: Error: fatal: detected dubious ownership in repository at '/home/admin/v'
To add an exception for this directory, call:

    git config --global --add safe.directory /home/admin/v
.git/config present: true

CC version: cc (Debian 10.2.1-6) 10.2.1 20210110
thirdparty/tcc status: Error: fatal: detected dubious ownership in repository at '/home/admin/v/thirdparty/tcc'
To add an exception for this directory, call:

    git config --global --add safe.directory /home/admin/v/thirdparty/tcc
 Error: fatal: detected dubious ownership in repository at '/home/admin/v/thirdparty/tcc'
To add an exception for this directory, call:

    git config --global --add safe.directory /home/admin/v/thirdparty/tcc

[!NOTE] You can use the πŸ‘ reaction to increase the issue's priority for developers.

Please note that only the πŸ‘ reaction to the issue itself counts as a vote. Other reactions and those to comments will not be taken into account.

felipensp commented 6 months ago

The problem is not the len:0 but the recursive type declaration.

felipensp commented 6 months ago

To use the type recursively you must to use it as pointer type.

struct Node {
    next []&Node = []&Node {len: 0}
}
amuerta commented 6 months ago

I understand why this is the case, but if I don't initialize the variable and then append to the array, everything works as intended

Example: https://play.vlang.io/p/da5120390c

Does V handle the pointers for me under the hood, or there's something other that I miss on?

[Edit] ignore comments in code example, I haven't changed them since the issue was sent

felipensp commented 6 months ago

Yes, the problem is the code generator going into infinte recursive call because the initialization part.

amuerta commented 6 months ago

I think it would be enough to add a warning if compiler detects non pointer struct type array in the same struct and error out if user tires to initialize variable directly

This way it's more clear what's going on