checker: do not allow &u8(0), force nil like we do with &Type(0)

This commit is contained in:
Alexander Medvednikov 2025-05-03 22:37:51 +03:00
parent 3ab660b4c6
commit 7d57a19d7e
52 changed files with 184 additions and 118 deletions

View File

@ -1599,11 +1599,11 @@ println('Your OS is ${current_os}.')
> This section is valid when .v files are not in the project's root directory.
Modules names in .v files, must match the name of their directory.
A .v file `./abc/source.v` must start with `module abc`. All .v files in this directory
A .v file `./abc/source.v` must start with `module abc`. All .v files in this directory
belong to the same module `abc`. They should also start with `module abc`.
If you have `abc/def/`, and .v files in both folders, you can `import abc`, but you will have
If you have `abc/def/`, and .v files in both folders, you can `import abc`, but you will have
to `import abc.def` too, to get to the symbols in the subfolder. It is independent.
In `module name` statement, name never repeats directory's hierarchy, but only its directory.
@ -1637,7 +1637,7 @@ fn main() {
A function, located in `abc/def/source.v`, is called with `def.func()`, not `abc.def.func()`
This always implies a *single prefix*, whatever sub-module depth. This behavior flattens
This always implies a *single prefix*, whatever sub-module depth. This behavior flattens
modules/sub-modules hierarchy. Should you have two modules with the same name in different
directories, then you should use Module import aliasing (see below).
@ -1963,7 +1963,7 @@ println(typ)
```
A match statement also can match the variant types of a `sumtype`. Note that
in that case, the match is exhaustive, since all variant types are mentioned
in that case, the match is exhaustive, since all variant types are mentioned
explicitly, so there is no need for an `else{}` branch.
```v nofmt
@ -4730,12 +4730,12 @@ fn main() {
### Difference Between Channels and Shared Objects
**Purpose**:
**Purpose**:
- Channels: Used for message passing between threads, ensuring safe communication.
- Shared objects: Used for direct data sharing and modification between threads.
**Synchronization**:
- Channels: Implicit (via channel operations)
**Synchronization**:
- Channels: Implicit (via channel operations)
- Shared objects: Explicit (via `rlock`/`lock` blocks)
## JSON
@ -5836,20 +5836,20 @@ pub mut:
Function/method deprecations:
Functions are deprecated before they are finally removed to give users time to migrate their code.
Adding a date is preferable in most cases. An immediate change, without a deprecation date, may be
used for functions that are found to be conceptually broken and obsoleted by much better
functionality. Other than that setting a date is advisable to grant users a grace period.
Functions are deprecated before they are finally removed to give users time to migrate their code.
Adding a date is preferable in most cases. An immediate change, without a deprecation date, may be
used for functions that are found to be conceptually broken and obsoleted by much better
functionality. Other than that setting a date is advisable to grant users a grace period.
Deprecated functions cause warnings, which cause errors if built with `-prod`. To avoid immediate
CI breakage, it is advisable to set a future date, ahead of the date when the code is merged. This
gives people who actively developed V projects, the chance to see the deprecation notice at least
once and fix the uses. Setting a date in the next 30 days, assumes they would have compiled their
Deprecated functions cause warnings, which cause errors if built with `-prod`. To avoid immediate
CI breakage, it is advisable to set a future date, ahead of the date when the code is merged. This
gives people who actively developed V projects, the chance to see the deprecation notice at least
once and fix the uses. Setting a date in the next 30 days, assumes they would have compiled their
projects manually at least once, within that time. For small changes, this should be plenty
of time. For complex changes, this time may need to be longer.
of time. For complex changes, this time may need to be longer.
Different V projects and maintainers may reasonably choose different deprecation policies.
Depending on the type and impact of the change, you may want to consult with them first, before
Different V projects and maintainers may reasonably choose different deprecation policies.
Depending on the type and impact of the change, you may want to consult with them first, before
deprecating a function.
@ -7710,7 +7710,7 @@ fn main() {
C.sqlite3_finalize(stmt)
println('There are ${nr_users} users in the database.')
error_msg := &char(0)
error_msg := &char(unsafe { nil })
query_all_users := 'select * from users'
rc := C.sqlite3_exec(db, &char(query_all_users.str), my_callback, voidptr(7), &error_msg)
if rc != C.SQLITE_OK {
@ -8193,7 +8193,7 @@ exists the file will be overridden. If you want to rebuild each time and not kee
instead use `#!/usr/bin/env -S v -raw-vsh-tmp-prefix tmp run`.
Note: there is a small shell script `cmd/tools/vrun`, that can be useful for systems, that have an
env program (`/usr/bin/env`), that still does not support an `-S` option (like BusyBox).
env program (`/usr/bin/env`), that still does not support an `-S` option (like BusyBox).
See https://github.com/vlang/v/blob/master/cmd/tools/vrun for more details.
# Appendices

View File

@ -72,7 +72,7 @@ fn main() {
error_code := C.wkhtmltopdf_http_error_code(converter)
println('wkhtmltopdf_http_error_code: ${error_code}')
if result {
pdata := &char(0)
pdata := &char(unsafe { nil })
ppdata := &pdata
size := C.wkhtmltopdf_get_output(converter, voidptr(ppdata))
println('wkhtmltopdf_get_output: ${size} bytes')

View File

@ -37,7 +37,7 @@ fn create_texture(w int, h int, buf &u8) (gfx.Image, gfx.Sampler) {
height: h
num_mipmaps: 0
// usage: .dynamic
label: &char(0)
label: &char(unsafe { nil })
d3d11_texture: 0
}
// comment, if .dynamic is enabled

View File

@ -61,7 +61,7 @@ fn create_texture(w int, h int, buf &u8) (gfx.Image, gfx.Sampler) {
height: h
num_mipmaps: 0
// usage: .dynamic
label: &char(0)
label: &char(unsafe { nil })
d3d11_texture: 0
}
// comment if .dynamic is enabled

View File

@ -64,7 +64,7 @@ fn create_texture(w int, h int, buf &u8) (gfx.Image, gfx.Sampler) {
// usage: .dynamic
// wrap_u: .clamp_to_edge
// wrap_v: .clamp_to_edge
label: &char(0)
label: &char(unsafe { nil })
d3d11_texture: 0
}
// comment if .dynamic is enabled

View File

@ -75,7 +75,7 @@ fn create_texture(w int, h int, buf byteptr) (gfx.Image, gfx.Sampler) {
//usage: .dynamic
// wrap_u: .clamp_to_edge
// wrap_v: .clamp_to_edge
label: &char(0)
label: &char(unsafe { nil })
d3d11_texture: 0
}
// vfmt on

View File

@ -29,7 +29,7 @@ pub fn create_texture(w int, h int, buf &u8) (gfx.Image, gfx.Sampler) {
// usage: .dynamic
// wrap_u: .clamp_to_edge
// wrap_v: .clamp_to_edge
label: &char(0)
label: &char(unsafe { nil })
d3d11_texture: 0
}
// comment if .dynamic is enabled

View File

@ -119,7 +119,7 @@ fn create_texture(w int, h int, buf &u8) (gfx.Image, gfx.Sampler) {
height: h
num_mipmaps: 0
// usage: .dynamic
label: &u8(0)
label: &u8(unsafe { nil })
d3d11_texture: 0
}
// comment if .dynamic is enabled

View File

@ -87,7 +87,7 @@ fn print_backtrace_skipping_top_frames_msvc(skipframes int) bool {
si.f_max_name_len = sizeof(SymbolInfoContainer) - sizeof(SymbolInfo) - 1
fname := &char(&si.f_name)
mut sline64 := Line64{
f_file_name: &u8(0)
f_file_name: &u8(unsafe { nil })
}
sline64.f_size_of_struct = sizeof(Line64)

View File

@ -438,9 +438,9 @@ pub fn malloc(n isize) &u8 {
if n < 0 {
_memory_panic(@FN, n)
} else if n == 0 {
return &u8(0)
return &u8(unsafe { nil })
}
mut res := &u8(0)
mut res := &u8(unsafe { nil })
$if prealloc {
return unsafe { prealloc_malloc(n) }
} $else $if gcboehm ? {
@ -476,7 +476,7 @@ pub fn malloc_noscan(n isize) &u8 {
if n < 0 {
_memory_panic(@FN, n)
}
mut res := &u8(0)
mut res := &u8(unsafe { nil })
$if prealloc {
return unsafe { prealloc_malloc(n) }
} $else $if gcboehm ? {
@ -529,7 +529,7 @@ pub fn malloc_uncollectable(n isize) &u8 {
_memory_panic(@FN, n)
}
mut res := &u8(0)
mut res := &u8(unsafe { nil })
$if prealloc {
return unsafe { prealloc_malloc(n) }
} $else $if gcboehm ? {
@ -561,7 +561,7 @@ pub fn v_realloc(b &u8, n isize) &u8 {
$if trace_realloc ? {
C.fprintf(C.stderr, c'v_realloc %6d\n', n)
}
mut new_ptr := &u8(0)
mut new_ptr := &u8(unsafe { nil })
$if prealloc {
unsafe {
new_ptr = malloc(n)
@ -613,7 +613,7 @@ pub fn realloc_data(old_data &u8, old_size int, new_size int) &u8 {
return new_ptr
}
}
mut nptr := &u8(0)
mut nptr := &u8(unsafe { nil })
$if gcboehm ? {
nptr = unsafe { C.GC_REALLOC(old_data, new_size) }
} $else {
@ -636,7 +636,7 @@ pub fn vcalloc(n isize) &u8 {
if n < 0 {
_memory_panic(@FN, n)
} else if n == 0 {
return &u8(0)
return &u8(unsafe { nil })
}
$if prealloc {
return unsafe { prealloc_calloc(n) }
@ -645,7 +645,7 @@ pub fn vcalloc(n isize) &u8 {
} $else {
return unsafe { C.calloc(1, n) }
}
return &u8(0) // not reached, TODO: remove when V's checker is improved
return &u8(unsafe { nil }) // not reached, TODO: remove when V's checker is improved
}
// special versions of the above that allocate memory which is not scanned
@ -673,7 +673,7 @@ pub fn vcalloc_noscan(n isize) &u8 {
} $else {
return unsafe { vcalloc(n) }
}
return &u8(0) // not reached, TODO: remove when V's checker is improved
return &u8(unsafe { nil }) // not reached, TODO: remove when V's checker is improved
}
// free allows for manually freeing memory allocated at the address `ptr`.

View File

@ -172,7 +172,7 @@ pub fn winapi_lasterr_str() string {
// handle this case special since `FormatMessageW()` might not work anymore
return 'insufficient memory'
}
mut msgbuf := &u16(0)
mut msgbuf := &u16(unsafe { nil })
res := C.FormatMessageW(format_message_allocate_buffer | format_message_from_system | format_message_ignore_inserts,
0, err_msg_id, 0, voidptr(&msgbuf), 0, 0)
err_msg := if res == 0 {

View File

@ -1,5 +1,5 @@
fn test_isnil_byteptr() {
pb := &u8(0)
pb := &u8(unsafe { nil })
assert isnil(pb)
}
@ -9,7 +9,7 @@ fn test_isnil_voidptr() {
}
fn test_isnil_charptr() {
pc := &char(0)
pc := &char(unsafe { nil })
assert isnil(pc)
}

View File

@ -200,8 +200,8 @@ fn test_various_map_value() {
m14['test'] = voidptr(0)
assert m14['test'] == voidptr(0)
mut m15 := map[string]&byte{}
m15['test'] = &u8(0)
assert m15['test'] == &u8(0)
m15['test'] = &u8(unsafe { nil })
assert m15['test'] == &u8(unsafe { nil })
mut m16 := map[string]i64{}
m16['test'] = i64(0)
assert m16['test'] == i64(0)

View File

@ -10,7 +10,8 @@ fn mm_alloc(size u64) (&u8, Errno) {
map_flags := unsafe { MapFlags(int(MapFlags.map_private) | int(MapFlags.map_anonymous)) }
// END CONSTS
a, e := sys_mmap(&u8(0), size + sizeof(u64), mem_prot, map_flags, -1, 0)
a, e := sys_mmap(&u8(unsafe { nil }), size + sizeof(u64), mem_prot, map_flags, -1,
0)
if e == .enoerror {
unsafe {
mut ap := &u64(a)
@ -19,7 +20,7 @@ fn mm_alloc(size u64) (&u8, Errno) {
return x2, e
}
}
return &u8(0), e
return &u8(unsafe { nil }), e
}
fn mm_free(addr &u8) Errno {
@ -38,7 +39,7 @@ fn system_alloc(_ voidptr, size usize) (voidptr, usize, u32) {
map_flags := unsafe { MapFlags(int(MapFlags.map_private) | int(MapFlags.map_anonymous)) }
// END CONSTS
a, e := sys_mmap(&u8(0), u64(size), mem_prot, map_flags, -1, 0)
a, e := sys_mmap(&u8(unsafe { nil }), u64(size), mem_prot, map_flags, -1, 0)
if e == .enoerror {
return a, size, 0

View File

@ -19,7 +19,7 @@ pub fn mm_alloc(size u64) (&u8, Errno) {
*ap = pages
return &u8(a + 4), e
}
return &u8(0), e
return &u8(unsafe { nil }), e
}
pub fn mm_free(addr &u8) Errno {

View File

@ -19,7 +19,8 @@ fn fast_string_eq(a string, b string) bool {
fn map_hash_string(pkey voidptr) u64 {
key := *unsafe { &string(pkey) }
return C.wyhash(key.str, u64(key.len), 0, &u64(C._wyp))
// XTODO remove voidptr cast once virtual C.consts can be declared
return C.wyhash(key.str, u64(key.len), 0, &u64(voidptr(C._wyp)))
}
fn map_hash_int_1(pkey voidptr) u64 {

View File

@ -213,8 +213,8 @@ fn test_various_map_value() {
m14['test'] = unsafe { nil }
assert unsafe { m14['test'] } == unsafe { nil }
mut m15 := map[string]&u8{}
m15['test'] = &u8(0)
assert unsafe { m15['test'] } == &u8(0)
m15['test'] = &u8(unsafe { nil })
assert unsafe { m15['test'] } == &u8(unsafe { nil })
mut m16 := map[string]i64{}
m16['test'] = i64(0)
assert m16['test'] == i64(0)

View File

@ -409,7 +409,7 @@ fn read_property(d &C.Display, w Window, p Atom) Property {
actual_format := 0
nitems := u64(0)
bytes_after := u64(0)
ret := &u8(0)
ret := &u8(unsafe { nil })
mut read_bytes := 1024
for {
if ret != 0 {

View File

@ -205,7 +205,7 @@ pub fn (mut zentry Zip) create_entry(name string) ! {
// NOTE: remember to release the memory allocated for an output buffer.
// for large entries, please take a look at zip_entry_extract function.
pub fn (mut zentry Zip) read_entry() !voidptr {
mut buf := &u8(0)
mut buf := &u8(unsafe { nil })
mut bsize := usize(0)
res := C.zip_entry_read(zentry, unsafe { &voidptr(&buf) }, &bsize)
if res == -1 {

View File

@ -45,7 +45,7 @@ pub fn (db DB) select(config orm.SelectConfig, data orm.QueryData, where orm.Que
.type_string, .type_var_string, .type_blob, .type_tiny_blob, .type_medium_blob,
.type_long_blob {
// Memory will be allocated later dynamically depending on the length of the value.
data_pointers << &u8(0)
data_pointers << &u8(unsafe { nil })
}
else {
return error('\'${unsafe { FieldType(field.type) }}\' is not yet implemented. Please create a new issue at https://github.com/vlang/v/issues/new')

View File

@ -176,7 +176,7 @@ fn pg_stmt_match(mut types []u32, mut vals []&char, mut lens []int, mut formats
}
orm.Null {
types << u32(0) // we do not know col type, let server infer
vals << &char(0) // NULL pointer indicates NULL
vals << &char(unsafe { nil }) // NULL pointer indicates NULL
lens << int(0) // ignored
formats << 0 // ignored
}

View File

@ -392,14 +392,14 @@ pub fn (db DB) copy_expert(query string, mut file io.ReaderWriter) !int {
}
}
code := C.PQputCopyEnd(db.conn, &char(0))
code := C.PQputCopyEnd(db.conn, &char(unsafe { nil }))
if code != 1 {
return error('pg copy error: Failed to finish copy command, code: ${code}')
}
} else if status == .copy_out {
for {
address := &char(0)
address := &char(unsafe { nil })
n_bytes := C.PQgetCopyData(db.conn, &address, 0)
if n_bytes > 0 {
mut local_buf := []u8{len: n_bytes}

View File

@ -224,7 +224,7 @@ pub fn (db &DB) q_string(query string) !string {
return db.error_message(code, query)
}
val := unsafe { &u8(C.sqlite3_column_text(stmt, 0)) }
return if val != &u8(0) { unsafe { tos_clone(val) } } else { '' }
return if val != &u8(unsafe { nil }) { unsafe { tos_clone(val) } } else { '' }
}
// exec_map executes the query on the given `db`, and returns an array of maps of strings, or an error on failure
@ -254,7 +254,7 @@ pub fn (db &DB) exec_map(query string) ![]map[string]string {
val := unsafe { &u8(C.sqlite3_column_text(stmt, i)) }
col_char := unsafe { &u8(C.sqlite3_column_name(stmt, i)) }
col := unsafe { col_char.vstring() }
if val == &u8(0) {
if val == &u8(unsafe { nil }) {
row[col] = ''
} else {
row[col] = unsafe { tos_clone(val) }
@ -294,7 +294,7 @@ pub fn (db &DB) exec(query string) ![]Row {
mut row := Row{}
for i in 0 .. nr_cols {
val := unsafe { &u8(C.sqlite3_column_text(stmt, i)) }
if val == &u8(0) {
if val == &u8(unsafe { nil }) {
row.vals << ''
} else {
row.vals << unsafe { val.vstring() }
@ -388,7 +388,7 @@ pub fn (db &DB) exec_param_many(query string, params []string) ![]Row {
mut row := Row{}
for i in 0 .. nr_cols {
val := unsafe { &u8(C.sqlite3_column_text(stmt, i)) }
if val == &u8(0) {
if val == &u8(unsafe { nil }) {
row.vals << ''
} else {
row.vals << unsafe { val.vstring() }

View File

@ -71,7 +71,7 @@ fn (stmt &Stmt) get_text(idx int) ?string {
return none
} else {
b := &char(C.sqlite3_column_text(stmt.stmt, idx))
if b == &char(0) {
if b == &char(unsafe { nil }) {
return ''
}
return unsafe { b.vstring() }

View File

@ -204,7 +204,7 @@ pub fn (s &Context) set_font(font_id int) {
// The function returns the `x` coordinate of the resulting render.
@[inline]
pub fn (s &Context) draw_text(x f32, y f32, text string) f32 {
return C.fonsDrawText(s, x, y, &char(text.str), &char(0))
return C.fonsDrawText(s, x, y, &char(text.str), &char(unsafe { nil }))
}
// text_bounds fills the `bounds` argument with the pixel dimensions
@ -218,7 +218,7 @@ pub fn (s &Context) draw_text(x f32, y f32, text string) f32 {
// `bounds[3]` is the `y` coordinate of the bottom-right point.
@[inline]
pub fn (s &Context) text_bounds(x f32, y f32, text string, bounds &f32) f32 {
return C.fonsTextBounds(s, x, y, &char(text.str), &char(0), bounds)
return C.fonsTextBounds(s, x, y, &char(text.str), &char(unsafe { nil }), bounds)
}
// line_bounds fills `miny` and `maxy` with the values of the `minimum`

View File

@ -307,7 +307,7 @@ pub fn (ctx &Context) draw_image_with_config(config DrawImageConfig) {
return
}
if img.width == 0 {
println('w=0')
println('gg: draw_image() width=0')
return
}
if !os.exists(img.path) {

View File

@ -9,7 +9,7 @@ fn C.wyhash64(u64, u64) u64
// wyhash_c returns a hash given a byte string `key`, its `len`, and a `seed`.
@[inline]
pub fn wyhash_c(key &u8, len u64, seed u64) u64 {
return C.wyhash(key, len, seed, &u64(C._wyp))
return C.wyhash(key, len, seed, &u64(voidptr(C._wyp)))
}
// wyhash64_c returns a hash given two u64 values `a` and `b`.

View File

@ -85,6 +85,9 @@ pub fn unsetenv(name string) int {
// See: https://docs.microsoft.com/bg-bg/windows/win32/api/processenv/nf-processenv-getenvironmentstrings
// os.environ returns a map of all the current environment variables
// TODO how to declare Virtual C globals?
// const C.environ &&char
pub fn environ() map[string]string {
mut res := map[string]string{}
$if windows {
@ -102,7 +105,7 @@ pub fn environ() map[string]string {
}
C.FreeEnvironmentStringsW(estrings)
} $else {
start := &&char(C.environ)
start := &&char(voidptr(C.environ))
mut i := 0
for {
x := unsafe { start[i] }

View File

@ -579,7 +579,7 @@ pub fn get_raw_line() string {
}
} $else {
max := usize(0)
buf := unsafe { &u8(0) }
buf := &u8(unsafe { nil })
nr_chars := unsafe { C.getline(voidptr(&buf), &max, C.stdin) }
str := unsafe { tos(buf, if nr_chars < 0 { 0 } else { nr_chars }) }
ret := str.clone()
@ -624,7 +624,7 @@ pub fn get_raw_stdin() []u8 {
}
} $else {
max := usize(0)
buf := unsafe { &u8(0) }
buf := &u8(unsafe { nil })
nr_chars := unsafe { C.getline(voidptr(&buf), &max, C.stdin) }
return array{
element_size: 1
@ -995,7 +995,7 @@ pub fn execvp(cmdpath string, cmdargs []string) ! {
for i in 0 .. cmdargs.len {
cargs << &char(cmdargs[i].str)
}
cargs << &char(0)
cargs << &char(unsafe { nil })
mut res := int(0)
$if windows {
res = C._execvp(&char(cmdpath.str), cargs.data)
@ -1026,8 +1026,8 @@ pub fn execve(cmdpath string, cmdargs []string, envs []string) ! {
for i in 0 .. envs.len {
cenvs << &char(envs[i].str)
}
cargv << &char(0)
cenvs << &char(0)
cargv << &char(unsafe { nil })
cenvs << &char(unsafe { nil })
mut res := int(0)
$if windows {
res = C._execve(&char(cmdpath.str), cargv.data, cenvs.data)

View File

@ -293,9 +293,9 @@ pub fn execute(cmd string) Result {
// user provided escape sequences.
@[unsafe]
pub fn raw_execute(cmd string) Result {
mut child_stdin := &u32(0)
mut child_stdout_read := &u32(0)
mut child_stdout_write := &u32(0)
mut child_stdin := &u32(unsafe { nil })
mut child_stdout_read := &u32(unsafe { nil })
mut child_stdout_write := &u32(unsafe { nil })
mut sa := SecurityAttributes{}
sa.n_length = sizeof(C.SECURITY_ATTRIBUTES)
sa.b_inherit_handle = true
@ -609,8 +609,8 @@ pub fn disk_usage(path string) !DiskUsage {
mut available := u64(0)
mut ret := false
if path == '.' || path == '' {
ret = C.GetDiskFreeSpaceExA(&char(0), &free_bytes_available_to_caller, &total,
&available)
ret = C.GetDiskFreeSpaceExA(&char(unsafe { nil }), &free_bytes_available_to_caller,
&total, &available)
} else {
ret = C.GetDiskFreeSpaceExA(&char(path.str), &free_bytes_available_to_caller,
&total, &available)

View File

@ -32,10 +32,10 @@ fn failed_cfn_report_error(ok bool, label string) {
fn close_valid_handle(p voidptr) {
h := &&u32(p)
if *h != &u32(0) {
if *h != &u32(unsafe { nil }) {
C.CloseHandle(*h)
unsafe {
*h = &u32(0)
*h = &u32(nil)
}
}
}
@ -231,7 +231,7 @@ fn (mut p Process) win_read_string(idx int, _maxbytes int) (string, int) {
if unsafe { wdata == 0 } {
return '', 0
}
mut rhandle := &u32(0)
mut rhandle := &u32(unsafe { nil })
if idx == 1 {
rhandle = wdata.child_stdout_read
}
@ -263,7 +263,7 @@ fn (mut p Process) win_is_pending(idx int) bool {
if unsafe { wdata == 0 } {
return false
}
mut rhandle := &u32(0)
mut rhandle := &u32(unsafe { nil })
if idx == 1 {
rhandle = wdata.child_stdout_read
}
@ -285,7 +285,7 @@ fn (mut p Process) win_slurp(idx int) string {
if unsafe { wdata == 0 } {
return ''
}
mut rhandle := &u32(0)
mut rhandle := &u32(unsafe { nil })
if idx == 1 {
rhandle = wdata.child_stdout_read
}

View File

@ -49,7 +49,7 @@ pub mut:
sample_count int
blend_color Color
alpha_to_coverage_enabled bool
label &char = &char(0)
label &char = &char(unsafe { nil })
}
pub type PipelineDesc = C.sg_pipeline_desc

View File

@ -29,7 +29,7 @@ pub fn screenshot_window() &Screenshot {
pub fn (mut ss Screenshot) free() {
unsafe {
free(ss.pixels)
ss.pixels = &u8(0)
ss.pixels = &u8(nil)
}
}

View File

@ -69,8 +69,8 @@ pub fn new_channel[T](n u32) &Channel {
fn new_channel_st(n u32, st u32) &Channel {
wsem := if n > 0 { n } else { 1 }
rsem := if n > 0 { u32(0) } else { 1 }
rbuf := if n > 0 { unsafe { malloc(int(n * st)) } } else { &u8(0) }
sbuf := if n > 0 { vcalloc_noscan(int(n * 2)) } else { &u8(0) }
rbuf := if n > 0 { unsafe { malloc(int(n * st)) } } else { &u8(unsafe { nil }) }
sbuf := if n > 0 { vcalloc_noscan(int(n * 2)) } else { &u8(unsafe { nil }) }
mut ch := Channel{
objsize: st
cap: n
@ -92,8 +92,8 @@ fn new_channel_st_noscan(n u32, st u32) &Channel {
$if gcboehm_opt ? {
wsem := if n > 0 { n } else { 1 }
rsem := if n > 0 { u32(0) } else { 1 }
rbuf := if n > 0 { unsafe { malloc_noscan(int(n * st)) } } else { &u8(0) }
sbuf := if n > 0 { vcalloc_noscan(int(n * 2)) } else { &u8(0) }
rbuf := if n > 0 { unsafe { malloc_noscan(int(n * st)) } } else { &u8(unsafe { nil }) }
sbuf := if n > 0 { vcalloc_noscan(int(n * 2)) } else { &u8(unsafe { nil }) }
mut ch := Channel{
objsize: st
cap: n

View File

@ -914,7 +914,7 @@ pub fn (mut p Parser) double_array_of_tables(mut table map[string]ast.Value) ! {
first := DottedKey([dotted_key[0]]) // The array that holds the entries
last := DottedKey([dotted_key[1]]) // The key the parsed array data should be added to
mut t_arr := &[]ast.Value(0)
mut t_arr := &[]ast.Value(unsafe { nil })
mut t_map := ast.Value(ast.Null{})
unsafe {

View File

@ -3594,6 +3594,17 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
c.error('cannot cast type `${ft}` to `${tt}`', node.pos)
}
// if from_type == ast.voidptr_type_idx && !c.inside_unsafe && !c.pref.translated
// Do not allow `&u8(unsafe { nil })` etc, force nil or voidptr cast
if from_type.is_number() && to_type.is_ptr() && !c.inside_unsafe && !c.pref.translated
&& !c.file.is_translated {
if from_sym.language != .c {
// TODO make an error
c.warn('cannot cast a number to a type reference, use `nil` or a voidptr cast first: `&Type(voidptr(123))`',
node.pos)
}
}
// T(0) where T is array or map
if node.typ.has_flag(.generic) && to_sym.kind in [.array, .map, .array_fixed]
&& node.expr.is_literal() {

View File

@ -1,13 +1,13 @@
vlib/v/checker/tests/cast_expr_T_type_err.vv:4:9: error: unknown type `A`
2 |
vlib/v/checker/tests/cast_expr_T_type_err.vv:4:6: error: unknown type `A`
2 |
3 | fn main() {
4 | _ = A(0)
| ~~~~
5 | _ = &A(0)
5 | _ = &A(unsafe { nil })
6 | }
vlib/v/checker/tests/cast_expr_T_type_err.vv:5:9: error: unknown type `A`
vlib/v/checker/tests/cast_expr_T_type_err.vv:5:6: error: unknown type `A`
3 | fn main() {
4 | _ = A(0)
5 | _ = &A(0)
| ~~~~~
5 | _ = &A(unsafe { nil })
| ~~~~~~~~~~~~~~~~~~
6 | }

View File

@ -1,6 +1,6 @@
module main
fn main() {
_ = A(0)
_ = &A(0)
_ = A(0)
_ = &A(unsafe { nil })
}

View File

@ -3,17 +3,17 @@ vlib/v/checker/tests/fixed_array_conv.vv:3:5: notice: left-side of assignment ex
2 | mut p := unsafe { nil }
3 | p = arr
| ~~~
4 | mut ip := &int(0)
4 | mut ip := &int(unsafe { nil })
5 | ip = arr
vlib/v/checker/tests/fixed_array_conv.vv:5:6: notice: left-side of assignment expects a mutable reference, but variable `arr` is immutable, declare it with `mut` to make it mutable or clone it
3 | p = arr
4 | mut ip := &int(0)
4 | mut ip := &int(unsafe { nil })
5 | ip = arr
| ~~~
6 | _ = &int(arr)
7 | _ = p
vlib/v/checker/tests/fixed_array_conv.vv:6:5: warning: cannot cast a fixed array (use e.g. `&arr[0]` instead)
4 | mut ip := &int(0)
4 | mut ip := &int(unsafe { nil })
5 | ip = arr
6 | _ = &int(arr)
| ~~~~~~~~~
@ -24,25 +24,25 @@ vlib/v/checker/tests/fixed_array_conv.vv:3:3: error: mismatched types `voidptr`
2 | mut p := unsafe { nil }
3 | p = arr
| ^
4 | mut ip := &int(0)
4 | mut ip := &int(unsafe { nil })
5 | ip = arr
vlib/v/checker/tests/fixed_array_conv.vv:3:5: error: cannot assign to `p`: expected `voidptr`, not `[2]int`
1 | arr := [2, 3]!
2 | mut p := unsafe { nil }
3 | p = arr
| ~~~
4 | mut ip := &int(0)
4 | mut ip := &int(unsafe { nil })
5 | ip = arr
vlib/v/checker/tests/fixed_array_conv.vv:5:4: error: mismatched types `&int` and `[2]int`
3 | p = arr
4 | mut ip := &int(0)
4 | mut ip := &int(unsafe { nil })
5 | ip = arr
| ^
6 | _ = &int(arr)
7 | _ = p
vlib/v/checker/tests/fixed_array_conv.vv:5:6: error: cannot assign to `ip`: expected `&int`, not `[2]int`
3 | p = arr
4 | mut ip := &int(0)
4 | mut ip := &int(unsafe { nil })
5 | ip = arr
| ~~~
6 | _ = &int(arr)

View File

@ -1,7 +1,7 @@
arr := [2, 3]!
mut p := unsafe { nil }
p = arr
mut ip := &int(0)
mut ip := &int(unsafe { nil })
ip = arr
_ = &int(arr)
_ = p

View File

@ -1,3 +1,10 @@
vlib/v/checker/tests/globals/cast_expr_T_type_err.vv:5:8: warning: cannot cast a number to a type reference, use `nil` or a voidptr cast first: `&Type(voidptr(123))`
3 | __global (
4 | fo = A(0)
5 | fo1 = &A(0)
| ~~~~~
6 | )
7 |
vlib/v/checker/tests/globals/cast_expr_T_type_err.vv:4:7: error: unknown type `A`
2 |
3 | __global (

View File

@ -1,3 +1,21 @@
vlib/v/checker/tests/struct_ptr_cast_int_outside_unsafe_err.vv:7:5: warning: cannot cast a number to a type reference, use `nil` or a voidptr cast first: `&Type(voidptr(123))`
5 | a := 1
6 |
7 | _ = &Context(a)
| ~~~~~~~~~~~
8 | _ = &Context(b)
9 | _ = &Context(1)
vlib/v/checker/tests/struct_ptr_cast_int_outside_unsafe_err.vv:8:5: warning: cannot cast a number to a type reference, use `nil` or a voidptr cast first: `&Type(voidptr(123))`
6 |
7 | _ = &Context(a)
8 | _ = &Context(b)
| ~~~~~~~~~~~
9 | _ = &Context(1)
vlib/v/checker/tests/struct_ptr_cast_int_outside_unsafe_err.vv:9:5: warning: cannot cast a number to a type reference, use `nil` or a voidptr cast first: `&Type(voidptr(123))`
7 | _ = &Context(a)
8 | _ = &Context(b)
9 | _ = &Context(1)
| ~~~~~~~~~~~
vlib/v/checker/tests/struct_ptr_cast_int_outside_unsafe_err.vv:7:5: error: cannot cast int to a struct pointer outside `unsafe`
5 | a := 1
6 |

View File

@ -1,3 +1,21 @@
vlib/v/checker/tests/struct_ptr_cast_zero_err.vv:7:5: warning: cannot cast a number to a type reference, use `nil` or a voidptr cast first: `&Type(voidptr(123))`
5 | b := 0
6 |
7 | _ = &Context(0)
| ~~~~~~~~~~~
8 | _ = &Context(a)
9 | _ = &Context(b)
vlib/v/checker/tests/struct_ptr_cast_zero_err.vv:8:5: warning: cannot cast a number to a type reference, use `nil` or a voidptr cast first: `&Type(voidptr(123))`
6 |
7 | _ = &Context(0)
8 | _ = &Context(a)
| ~~~~~~~~~~~
9 | _ = &Context(b)
vlib/v/checker/tests/struct_ptr_cast_zero_err.vv:9:5: warning: cannot cast a number to a type reference, use `nil` or a voidptr cast first: `&Type(voidptr(123))`
7 | _ = &Context(0)
8 | _ = &Context(a)
9 | _ = &Context(b)
| ~~~~~~~~~~~
vlib/v/checker/tests/struct_ptr_cast_zero_err.vv:7:5: error: cannot null cast a struct pointer, use &Context(unsafe { nil })
5 | b := 0
6 |

View File

@ -1 +1,8 @@
vlib/v/checker/tests/unsafe_generic_call_test.vv:8:15: warning: cannot cast a number to a type reference, use `nil` or a voidptr cast first: `&Type(voidptr(123))`
6 |
7 | fn test_main() {
8 | pointers := [&int(1234)]
| ~~~~~~~~~~
9 | length := 1
10 | array := unsafe { arrays.carray_to_varray[&Blah](pointers, length) }
[&Blah{}]

View File

@ -26,11 +26,11 @@ pub fn (mut ed EmbedFileData) free() {
ed.compression_type.free()
if ed.free_compressed {
free(ed.compressed)
ed.compressed = &u8(0)
ed.compressed = &u8(nil)
}
if ed.free_uncompressed {
free(ed.uncompressed)
ed.uncompressed = &u8(0)
ed.uncompressed = &u8(nil)
}
}
}

View File

@ -13,10 +13,10 @@ fn main() {
dump(voidptr(ppb))
dump(voidptr(pppb))
dump(voidptr(ppppb))
pc := &char(0)
ppc := &&char(0)
pppc := &&&char(0)
ppppc := &&&&char(0)
pc := &char(nil)
ppc := &&char(nil)
pppc := &&&char(nil)
ppppc := &&&&char(nil)
dump(voidptr(pc))
dump(voidptr(ppc))
dump(voidptr(pppc))

View File

@ -96,7 +96,7 @@ mut:
is_assign_lhs bool // inside left part of assign expr (for array_set(), etc)
is_void_expr_stmt bool // ExprStmt whose result is discarded
is_arraymap_set bool // map or array set value state
is_amp bool // for `&Foo{}` to merge PrefixExpr `&` and StructInit `Foo{}`; also for `&u8(0)` etc
is_amp bool // for `&Foo{}` to merge PrefixExpr `&` and StructInit `Foo{}`; also for `&u8(unsafe { nil })` etc
is_sql bool // Inside `sql db{}` statement, generating sql instead of C (e.g. `and` instead of `&&` etc)
is_shared bool // for initialization of hidden mutex in `[rw]shared` literals
is_vlines_enabled bool // is it safe to generate #line directives when -g is passed

View File

@ -1,8 +1,8 @@
type ALchar = char
fn test_alias_char_type_reference() {
c1 := &char(0)
c2 := &ALchar(0)
c1 := &char(unsafe { nil })
c2 := &ALchar(unsafe { nil })
println('${typeof(c1).name} ${c1}')
assert '${c1}' == '0'
println('${typeof(c2).name} ${c2}')

View File

@ -96,7 +96,7 @@ fn test_inttypes_string_interpolation() {
i := -1622999040 // -0x60BD 0000
ui := u32(3421958087) // 0xCBF6 EFC7
vp := voidptr(ui)
mut bp := &u8(0)
mut bp := &u8(unsafe { nil })
$if x64 {
bp = &u8(15541149836) // 0x3 9E53 208C
} $else {

View File

@ -3,7 +3,7 @@ fn multi_voidptr_ret() (voidptr, bool) {
}
fn multi_byteptr_ret() (&u8, bool) {
return &u8(0), true
return &u8(unsafe { nil }), true
}
fn test_multi_ptrtype_ret() {

View File

@ -2,12 +2,12 @@
module trace_calls
@[markused]
__global g_stack_base = &u8(0)
__global g_stack_base = &u8(unsafe { nil })
__global g_start_time = u64(0)
@[markused]
pub fn on_call(fname string) {
mut volatile pfbase := unsafe { &u8(0) }
mut volatile pfbase := &u8(unsafe { nil })
volatile fbase := u8(0)
ns := current_time() - g_start_time
mut ssize := u64(0)

View File

@ -131,7 +131,7 @@ pub fn (mut tf_skl TTF_render_Sokol) create_texture() {
height: h
num_mipmaps: 0
// usage: .dynamic
label: &char(0)
label: &char(unsafe { nil })
d3d11_texture: 0
}
// comment for dynamic