v icon indicating copy to clipboard operation
v copied to clipboard

Fixed error handling when appending empty array literal to 2D array

Open TheAhmir opened this issue 8 months ago • 10 comments

Resolves #23854

This PR improves error handling when appending an empty array literal [] to a 2D array such as [][]string.

Currently, doing this results in a cryptic C error because the compiler fails to infer the correct type of the empty literal. The operation is not marked invalid, but compilation fails downstream.

This fix adds a graceful error message during type checking, guiding the user to use an explicitly typed empty array like []string{}.


Example:

Before:

mut rows := [][]string{}
rows << [] // C error

After: error: cannot infer type for empty array literal `[]`. Use `[]string{}` instead.

Test:

  • Added append_empty_array_literal.v to vlib/v/tests/known_errors/testdata/, reproducing the issue and verifying the error message.

TheAhmir avatar Mar 22 '25 05:03 TheAhmir

Connected to Huly®: V_0.6-22395

huly-for-github[bot] avatar Mar 22 '25 05:03 huly-for-github[bot]

I do not get it - why would one want to append an empty array to another array? The result will be either a NOP (the original array stays as it is), or the compiler should warn/error that the operation will have no effect.

spytheman avatar Mar 22 '25 09:03 spytheman

An empty array might be used as a placeholder or for dynamically constructing a 2D array (matrix). Currently, the compiler attempts to infer the type of an empty array when no type is specified and then attempts to append it to the matrix. This does not result in a no-op (NOP) but rather causes a 'C error' if type inference fails.

With this fix, the compiler now errors explicitly due to a typing issue and provides a clear, actionable error message rather than just a C error.

TheAhmir avatar Mar 22 '25 14:03 TheAhmir

Alternatively, why doesn't the compiler infer correctly? When appending [] to an array, the compiler should "know" that it is the same type as the array. Nothing to infer - make it an inherent property... an extra if statement.

JalonSolov avatar Mar 22 '25 14:03 JalonSolov

In the case of a 2D array, a << b, where a is [][]Element could mean that b is either of the same type as a i.e. [][]Element, (adding multiple elements), or b is of type []Element (adding a single element, which for 2D arrays, is a 1D array).

For adding empty [], that distinction is moot though, since in both cases, it should either not cgen error (since adding an empty array should be a NOP), or it should error at the checker stage (which this PR does).

spytheman avatar Mar 22 '25 15:03 spytheman

i.e. I do not question the value of turning the cgen error into a more actionable checker error. I am just not convinced, that the compiler should not just ignore the statement a << [] (which was said to be useful only as a placeholder).

spytheman avatar Mar 22 '25 15:03 spytheman

Placeholder as in adding an empty array to the array of arrays, which can be filled in later.

Using a variation of the original example, doing

mut rows := [][]string{}
println(rows)
rows << []
println(rows)
rows << []
println(rows)
rows[0] << 's'
println(rows)

would be expected to give the same results as

mut rows := [][]string{}
println(rows)
rows << []string{}
println(rows)
rows << []string{}
println(rows)
rows[0] << 's'
println(rows)

which is

[]
[[]]
[[], []]
[['s'], []]

JalonSolov avatar Mar 22 '25 16:03 JalonSolov

I.e. modify cgen to consider a << [], as a new element []Type{}, of the [][]Type 2D array?

That can work too.

spytheman avatar Mar 22 '25 17:03 spytheman

Ok, instead of doing an error message, I've made adjustments to the checker to infer the type of [] to be the same type as the left side's element type.

I've tested it against the original issue and the examples mentioned in this conversation. This approach seems to align better with the expected behavior of the operation.

TheAhmir avatar Apr 29 '25 07:04 TheAhmir

(closing/opening again, to trigger the CI jobs)

spytheman avatar May 22 '25 10:05 spytheman

Another close/open, to check with current CI.

JalonSolov avatar Jun 18 '25 15:06 JalonSolov

The CI failure is due to this (reproduced locally):

#0 12:21:05 ^ fix-empty-array-infix ~/v>v run examples/gg/fire.v
examples/gg/fire.v:63:37: error: expected `[]int`, not `int literal`
   61 |         buf: [][]int{len: height - 1, init: []int{len: width}}
   62 |     }
   63 |     app.buf << []int{len: width, init: 36} // white fire base
      |                                        ~~

spytheman avatar Jul 05 '25 09:07 spytheman

Using this instead: app.buf << [[]int{len: width, init: 36}] works.

spytheman avatar Jul 05 '25 09:07 spytheman

Another open/close, due to check logs disappearing...

JalonSolov avatar Jul 21 '25 13:07 JalonSolov

Since PR #25508 fixes the same bug this PR attempted to fix, I don't think it needs to be open anymore.

@TheAhmir Thanks for this PR 🙇🏻.

StunxFS avatar Oct 22 '25 14:10 StunxFS