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. > 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. 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`. 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. 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. 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()` 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 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). 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 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. explicitly, so there is no need for an `else{}` branch.
```v nofmt ```v nofmt
@ -4730,12 +4730,12 @@ fn main() {
### Difference Between Channels and Shared Objects ### Difference Between Channels and Shared Objects
**Purpose**: **Purpose**:
- Channels: Used for message passing between threads, ensuring safe communication. - Channels: Used for message passing between threads, ensuring safe communication.
- Shared objects: Used for direct data sharing and modification between threads. - Shared objects: Used for direct data sharing and modification between threads.
**Synchronization**: **Synchronization**:
- Channels: Implicit (via channel operations) - Channels: Implicit (via channel operations)
- Shared objects: Explicit (via `rlock`/`lock` blocks) - Shared objects: Explicit (via `rlock`/`lock` blocks)
## JSON ## JSON
@ -5836,20 +5836,20 @@ pub mut:
Function/method deprecations: Function/method deprecations:
Functions are deprecated before they are finally removed to give users time to migrate their code. 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 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 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. 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 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 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 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 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 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. 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 Depending on the type and impact of the change, you may want to consult with them first, before
deprecating a function. deprecating a function.
@ -7710,7 +7710,7 @@ fn main() {
C.sqlite3_finalize(stmt) C.sqlite3_finalize(stmt)
println('There are ${nr_users} users in the database.') println('There are ${nr_users} users in the database.')
error_msg := &char(0) error_msg := &char(unsafe { nil })
query_all_users := 'select * from users' query_all_users := 'select * from users'
rc := C.sqlite3_exec(db, &char(query_all_users.str), my_callback, voidptr(7), &error_msg) rc := C.sqlite3_exec(db, &char(query_all_users.str), my_callback, voidptr(7), &error_msg)
if rc != C.SQLITE_OK { 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`. 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 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. See https://github.com/vlang/v/blob/master/cmd/tools/vrun for more details.
# Appendices # Appendices

View File

@ -72,7 +72,7 @@ fn main() {
error_code := C.wkhtmltopdf_http_error_code(converter) error_code := C.wkhtmltopdf_http_error_code(converter)
println('wkhtmltopdf_http_error_code: ${error_code}') println('wkhtmltopdf_http_error_code: ${error_code}')
if result { if result {
pdata := &char(0) pdata := &char(unsafe { nil })
ppdata := &pdata ppdata := &pdata
size := C.wkhtmltopdf_get_output(converter, voidptr(ppdata)) size := C.wkhtmltopdf_get_output(converter, voidptr(ppdata))
println('wkhtmltopdf_get_output: ${size} bytes') 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 height: h
num_mipmaps: 0 num_mipmaps: 0
// usage: .dynamic // usage: .dynamic
label: &char(0) label: &char(unsafe { nil })
d3d11_texture: 0 d3d11_texture: 0
} }
// comment, if .dynamic is enabled // 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 height: h
num_mipmaps: 0 num_mipmaps: 0
// usage: .dynamic // usage: .dynamic
label: &char(0) label: &char(unsafe { nil })
d3d11_texture: 0 d3d11_texture: 0
} }
// comment if .dynamic is enabled // 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 // usage: .dynamic
// wrap_u: .clamp_to_edge // wrap_u: .clamp_to_edge
// wrap_v: .clamp_to_edge // wrap_v: .clamp_to_edge
label: &char(0) label: &char(unsafe { nil })
d3d11_texture: 0 d3d11_texture: 0
} }
// comment if .dynamic is enabled // 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 //usage: .dynamic
// wrap_u: .clamp_to_edge // wrap_u: .clamp_to_edge
// wrap_v: .clamp_to_edge // wrap_v: .clamp_to_edge
label: &char(0) label: &char(unsafe { nil })
d3d11_texture: 0 d3d11_texture: 0
} }
// vfmt on // vfmt on

View File

@ -29,7 +29,7 @@ pub fn create_texture(w int, h int, buf &u8) (gfx.Image, gfx.Sampler) {
// usage: .dynamic // usage: .dynamic
// wrap_u: .clamp_to_edge // wrap_u: .clamp_to_edge
// wrap_v: .clamp_to_edge // wrap_v: .clamp_to_edge
label: &char(0) label: &char(unsafe { nil })
d3d11_texture: 0 d3d11_texture: 0
} }
// comment if .dynamic is enabled // 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 height: h
num_mipmaps: 0 num_mipmaps: 0
// usage: .dynamic // usage: .dynamic
label: &u8(0) label: &u8(unsafe { nil })
d3d11_texture: 0 d3d11_texture: 0
} }
// comment if .dynamic is enabled // 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 si.f_max_name_len = sizeof(SymbolInfoContainer) - sizeof(SymbolInfo) - 1
fname := &char(&si.f_name) fname := &char(&si.f_name)
mut sline64 := Line64{ mut sline64 := Line64{
f_file_name: &u8(0) f_file_name: &u8(unsafe { nil })
} }
sline64.f_size_of_struct = sizeof(Line64) sline64.f_size_of_struct = sizeof(Line64)

View File

@ -438,9 +438,9 @@ pub fn malloc(n isize) &u8 {
if n < 0 { if n < 0 {
_memory_panic(@FN, n) _memory_panic(@FN, n)
} else if n == 0 { } else if n == 0 {
return &u8(0) return &u8(unsafe { nil })
} }
mut res := &u8(0) mut res := &u8(unsafe { nil })
$if prealloc { $if prealloc {
return unsafe { prealloc_malloc(n) } return unsafe { prealloc_malloc(n) }
} $else $if gcboehm ? { } $else $if gcboehm ? {
@ -476,7 +476,7 @@ pub fn malloc_noscan(n isize) &u8 {
if n < 0 { if n < 0 {
_memory_panic(@FN, n) _memory_panic(@FN, n)
} }
mut res := &u8(0) mut res := &u8(unsafe { nil })
$if prealloc { $if prealloc {
return unsafe { prealloc_malloc(n) } return unsafe { prealloc_malloc(n) }
} $else $if gcboehm ? { } $else $if gcboehm ? {
@ -529,7 +529,7 @@ pub fn malloc_uncollectable(n isize) &u8 {
_memory_panic(@FN, n) _memory_panic(@FN, n)
} }
mut res := &u8(0) mut res := &u8(unsafe { nil })
$if prealloc { $if prealloc {
return unsafe { prealloc_malloc(n) } return unsafe { prealloc_malloc(n) }
} $else $if gcboehm ? { } $else $if gcboehm ? {
@ -561,7 +561,7 @@ pub fn v_realloc(b &u8, n isize) &u8 {
$if trace_realloc ? { $if trace_realloc ? {
C.fprintf(C.stderr, c'v_realloc %6d\n', n) C.fprintf(C.stderr, c'v_realloc %6d\n', n)
} }
mut new_ptr := &u8(0) mut new_ptr := &u8(unsafe { nil })
$if prealloc { $if prealloc {
unsafe { unsafe {
new_ptr = malloc(n) 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 return new_ptr
} }
} }
mut nptr := &u8(0) mut nptr := &u8(unsafe { nil })
$if gcboehm ? { $if gcboehm ? {
nptr = unsafe { C.GC_REALLOC(old_data, new_size) } nptr = unsafe { C.GC_REALLOC(old_data, new_size) }
} $else { } $else {
@ -636,7 +636,7 @@ pub fn vcalloc(n isize) &u8 {
if n < 0 { if n < 0 {
_memory_panic(@FN, n) _memory_panic(@FN, n)
} else if n == 0 { } else if n == 0 {
return &u8(0) return &u8(unsafe { nil })
} }
$if prealloc { $if prealloc {
return unsafe { prealloc_calloc(n) } return unsafe { prealloc_calloc(n) }
@ -645,7 +645,7 @@ pub fn vcalloc(n isize) &u8 {
} $else { } $else {
return unsafe { C.calloc(1, n) } 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 // special versions of the above that allocate memory which is not scanned
@ -673,7 +673,7 @@ pub fn vcalloc_noscan(n isize) &u8 {
} $else { } $else {
return unsafe { vcalloc(n) } 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`. // 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 // handle this case special since `FormatMessageW()` might not work anymore
return 'insufficient memory' 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, res := C.FormatMessageW(format_message_allocate_buffer | format_message_from_system | format_message_ignore_inserts,
0, err_msg_id, 0, voidptr(&msgbuf), 0, 0) 0, err_msg_id, 0, voidptr(&msgbuf), 0, 0)
err_msg := if res == 0 { err_msg := if res == 0 {

View File

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

View File

@ -200,8 +200,8 @@ fn test_various_map_value() {
m14['test'] = voidptr(0) m14['test'] = voidptr(0)
assert m14['test'] == voidptr(0) assert m14['test'] == voidptr(0)
mut m15 := map[string]&byte{} mut m15 := map[string]&byte{}
m15['test'] = &u8(0) m15['test'] = &u8(unsafe { nil })
assert m15['test'] == &u8(0) assert m15['test'] == &u8(unsafe { nil })
mut m16 := map[string]i64{} mut m16 := map[string]i64{}
m16['test'] = i64(0) m16['test'] = i64(0)
assert 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)) } map_flags := unsafe { MapFlags(int(MapFlags.map_private) | int(MapFlags.map_anonymous)) }
// END CONSTS // 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 { if e == .enoerror {
unsafe { unsafe {
mut ap := &u64(a) mut ap := &u64(a)
@ -19,7 +20,7 @@ fn mm_alloc(size u64) (&u8, Errno) {
return x2, e return x2, e
} }
} }
return &u8(0), e return &u8(unsafe { nil }), e
} }
fn mm_free(addr &u8) Errno { 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)) } map_flags := unsafe { MapFlags(int(MapFlags.map_private) | int(MapFlags.map_anonymous)) }
// END CONSTS // 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 { if e == .enoerror {
return a, size, 0 return a, size, 0

View File

@ -19,7 +19,7 @@ pub fn mm_alloc(size u64) (&u8, Errno) {
*ap = pages *ap = pages
return &u8(a + 4), e return &u8(a + 4), e
} }
return &u8(0), e return &u8(unsafe { nil }), e
} }
pub fn mm_free(addr &u8) Errno { 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 { fn map_hash_string(pkey voidptr) u64 {
key := *unsafe { &string(pkey) } 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 { fn map_hash_int_1(pkey voidptr) u64 {

View File

@ -213,8 +213,8 @@ fn test_various_map_value() {
m14['test'] = unsafe { nil } m14['test'] = unsafe { nil }
assert unsafe { m14['test'] } == unsafe { nil } assert unsafe { m14['test'] } == unsafe { nil }
mut m15 := map[string]&u8{} mut m15 := map[string]&u8{}
m15['test'] = &u8(0) m15['test'] = &u8(unsafe { nil })
assert unsafe { m15['test'] } == &u8(0) assert unsafe { m15['test'] } == &u8(unsafe { nil })
mut m16 := map[string]i64{} mut m16 := map[string]i64{}
m16['test'] = i64(0) m16['test'] = i64(0)
assert 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 actual_format := 0
nitems := u64(0) nitems := u64(0)
bytes_after := u64(0) bytes_after := u64(0)
ret := &u8(0) ret := &u8(unsafe { nil })
mut read_bytes := 1024 mut read_bytes := 1024
for { for {
if ret != 0 { 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. // NOTE: remember to release the memory allocated for an output buffer.
// for large entries, please take a look at zip_entry_extract function. // for large entries, please take a look at zip_entry_extract function.
pub fn (mut zentry Zip) read_entry() !voidptr { pub fn (mut zentry Zip) read_entry() !voidptr {
mut buf := &u8(0) mut buf := &u8(unsafe { nil })
mut bsize := usize(0) mut bsize := usize(0)
res := C.zip_entry_read(zentry, unsafe { &voidptr(&buf) }, &bsize) res := C.zip_entry_read(zentry, unsafe { &voidptr(&buf) }, &bsize)
if res == -1 { 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_string, .type_var_string, .type_blob, .type_tiny_blob, .type_medium_blob,
.type_long_blob { .type_long_blob {
// Memory will be allocated later dynamically depending on the length of the value. // Memory will be allocated later dynamically depending on the length of the value.
data_pointers << &u8(0) data_pointers << &u8(unsafe { nil })
} }
else { else {
return error('\'${unsafe { FieldType(field.type) }}\' is not yet implemented. Please create a new issue at https://github.com/vlang/v/issues/new') 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 { orm.Null {
types << u32(0) // we do not know col type, let server infer 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 lens << int(0) // ignored
formats << 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 { if code != 1 {
return error('pg copy error: Failed to finish copy command, code: ${code}') return error('pg copy error: Failed to finish copy command, code: ${code}')
} }
} else if status == .copy_out { } else if status == .copy_out {
for { for {
address := &char(0) address := &char(unsafe { nil })
n_bytes := C.PQgetCopyData(db.conn, &address, 0) n_bytes := C.PQgetCopyData(db.conn, &address, 0)
if n_bytes > 0 { if n_bytes > 0 {
mut local_buf := []u8{len: n_bytes} 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) return db.error_message(code, query)
} }
val := unsafe { &u8(C.sqlite3_column_text(stmt, 0)) } 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 // 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)) } val := unsafe { &u8(C.sqlite3_column_text(stmt, i)) }
col_char := unsafe { &u8(C.sqlite3_column_name(stmt, i)) } col_char := unsafe { &u8(C.sqlite3_column_name(stmt, i)) }
col := unsafe { col_char.vstring() } col := unsafe { col_char.vstring() }
if val == &u8(0) { if val == &u8(unsafe { nil }) {
row[col] = '' row[col] = ''
} else { } else {
row[col] = unsafe { tos_clone(val) } row[col] = unsafe { tos_clone(val) }
@ -294,7 +294,7 @@ pub fn (db &DB) exec(query string) ![]Row {
mut row := Row{} mut row := Row{}
for i in 0 .. nr_cols { for i in 0 .. nr_cols {
val := unsafe { &u8(C.sqlite3_column_text(stmt, i)) } val := unsafe { &u8(C.sqlite3_column_text(stmt, i)) }
if val == &u8(0) { if val == &u8(unsafe { nil }) {
row.vals << '' row.vals << ''
} else { } else {
row.vals << unsafe { val.vstring() } row.vals << unsafe { val.vstring() }
@ -388,7 +388,7 @@ pub fn (db &DB) exec_param_many(query string, params []string) ![]Row {
mut row := Row{} mut row := Row{}
for i in 0 .. nr_cols { for i in 0 .. nr_cols {
val := unsafe { &u8(C.sqlite3_column_text(stmt, i)) } val := unsafe { &u8(C.sqlite3_column_text(stmt, i)) }
if val == &u8(0) { if val == &u8(unsafe { nil }) {
row.vals << '' row.vals << ''
} else { } else {
row.vals << unsafe { val.vstring() } row.vals << unsafe { val.vstring() }

View File

@ -71,7 +71,7 @@ fn (stmt &Stmt) get_text(idx int) ?string {
return none return none
} else { } else {
b := &char(C.sqlite3_column_text(stmt.stmt, idx)) b := &char(C.sqlite3_column_text(stmt.stmt, idx))
if b == &char(0) { if b == &char(unsafe { nil }) {
return '' return ''
} }
return unsafe { b.vstring() } 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. // The function returns the `x` coordinate of the resulting render.
@[inline] @[inline]
pub fn (s &Context) draw_text(x f32, y f32, text string) f32 { 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 // 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. // `bounds[3]` is the `y` coordinate of the bottom-right point.
@[inline] @[inline]
pub fn (s &Context) text_bounds(x f32, y f32, text string, bounds &f32) f32 { 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` // 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 return
} }
if img.width == 0 { if img.width == 0 {
println('w=0') println('gg: draw_image() width=0')
return return
} }
if !os.exists(img.path) { 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`. // wyhash_c returns a hash given a byte string `key`, its `len`, and a `seed`.
@[inline] @[inline]
pub fn wyhash_c(key &u8, len u64, seed u64) u64 { 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`. // 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 // 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 // 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 { pub fn environ() map[string]string {
mut res := map[string]string{} mut res := map[string]string{}
$if windows { $if windows {
@ -102,7 +105,7 @@ pub fn environ() map[string]string {
} }
C.FreeEnvironmentStringsW(estrings) C.FreeEnvironmentStringsW(estrings)
} $else { } $else {
start := &&char(C.environ) start := &&char(voidptr(C.environ))
mut i := 0 mut i := 0
for { for {
x := unsafe { start[i] } x := unsafe { start[i] }

View File

@ -579,7 +579,7 @@ pub fn get_raw_line() string {
} }
} $else { } $else {
max := usize(0) max := usize(0)
buf := unsafe { &u8(0) } buf := &u8(unsafe { nil })
nr_chars := unsafe { C.getline(voidptr(&buf), &max, C.stdin) } nr_chars := unsafe { C.getline(voidptr(&buf), &max, C.stdin) }
str := unsafe { tos(buf, if nr_chars < 0 { 0 } else { nr_chars }) } str := unsafe { tos(buf, if nr_chars < 0 { 0 } else { nr_chars }) }
ret := str.clone() ret := str.clone()
@ -624,7 +624,7 @@ pub fn get_raw_stdin() []u8 {
} }
} $else { } $else {
max := usize(0) max := usize(0)
buf := unsafe { &u8(0) } buf := &u8(unsafe { nil })
nr_chars := unsafe { C.getline(voidptr(&buf), &max, C.stdin) } nr_chars := unsafe { C.getline(voidptr(&buf), &max, C.stdin) }
return array{ return array{
element_size: 1 element_size: 1
@ -995,7 +995,7 @@ pub fn execvp(cmdpath string, cmdargs []string) ! {
for i in 0 .. cmdargs.len { for i in 0 .. cmdargs.len {
cargs << &char(cmdargs[i].str) cargs << &char(cmdargs[i].str)
} }
cargs << &char(0) cargs << &char(unsafe { nil })
mut res := int(0) mut res := int(0)
$if windows { $if windows {
res = C._execvp(&char(cmdpath.str), cargs.data) 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 { for i in 0 .. envs.len {
cenvs << &char(envs[i].str) cenvs << &char(envs[i].str)
} }
cargv << &char(0) cargv << &char(unsafe { nil })
cenvs << &char(0) cenvs << &char(unsafe { nil })
mut res := int(0) mut res := int(0)
$if windows { $if windows {
res = C._execve(&char(cmdpath.str), cargv.data, cenvs.data) 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. // user provided escape sequences.
@[unsafe] @[unsafe]
pub fn raw_execute(cmd string) Result { pub fn raw_execute(cmd string) Result {
mut child_stdin := &u32(0) mut child_stdin := &u32(unsafe { nil })
mut child_stdout_read := &u32(0) mut child_stdout_read := &u32(unsafe { nil })
mut child_stdout_write := &u32(0) mut child_stdout_write := &u32(unsafe { nil })
mut sa := SecurityAttributes{} mut sa := SecurityAttributes{}
sa.n_length = sizeof(C.SECURITY_ATTRIBUTES) sa.n_length = sizeof(C.SECURITY_ATTRIBUTES)
sa.b_inherit_handle = true sa.b_inherit_handle = true
@ -609,8 +609,8 @@ pub fn disk_usage(path string) !DiskUsage {
mut available := u64(0) mut available := u64(0)
mut ret := false mut ret := false
if path == '.' || path == '' { if path == '.' || path == '' {
ret = C.GetDiskFreeSpaceExA(&char(0), &free_bytes_available_to_caller, &total, ret = C.GetDiskFreeSpaceExA(&char(unsafe { nil }), &free_bytes_available_to_caller,
&available) &total, &available)
} else { } else {
ret = C.GetDiskFreeSpaceExA(&char(path.str), &free_bytes_available_to_caller, ret = C.GetDiskFreeSpaceExA(&char(path.str), &free_bytes_available_to_caller,
&total, &available) &total, &available)

View File

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

View File

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

View File

@ -29,7 +29,7 @@ pub fn screenshot_window() &Screenshot {
pub fn (mut ss Screenshot) free() { pub fn (mut ss Screenshot) free() {
unsafe { unsafe {
free(ss.pixels) 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 { fn new_channel_st(n u32, st u32) &Channel {
wsem := if n > 0 { n } else { 1 } wsem := if n > 0 { n } else { 1 }
rsem := if n > 0 { u32(0) } else { 1 } rsem := if n > 0 { u32(0) } else { 1 }
rbuf := if n > 0 { unsafe { malloc(int(n * st)) } } 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(0) } sbuf := if n > 0 { vcalloc_noscan(int(n * 2)) } else { &u8(unsafe { nil }) }
mut ch := Channel{ mut ch := Channel{
objsize: st objsize: st
cap: n cap: n
@ -92,8 +92,8 @@ fn new_channel_st_noscan(n u32, st u32) &Channel {
$if gcboehm_opt ? { $if gcboehm_opt ? {
wsem := if n > 0 { n } else { 1 } wsem := if n > 0 { n } else { 1 }
rsem := if n > 0 { u32(0) } else { 1 } rsem := if n > 0 { u32(0) } else { 1 }
rbuf := if n > 0 { unsafe { malloc_noscan(int(n * st)) } } 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(0) } sbuf := if n > 0 { vcalloc_noscan(int(n * 2)) } else { &u8(unsafe { nil }) }
mut ch := Channel{ mut ch := Channel{
objsize: st objsize: st
cap: n 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 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 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{}) mut t_map := ast.Value(ast.Null{})
unsafe { 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) 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 // T(0) where T is array or map
if node.typ.has_flag(.generic) && to_sym.kind in [.array, .map, .array_fixed] if node.typ.has_flag(.generic) && to_sym.kind in [.array, .map, .array_fixed]
&& node.expr.is_literal() { && 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` vlib/v/checker/tests/cast_expr_T_type_err.vv:4:6: error: unknown type `A`
2 | 2 |
3 | fn main() { 3 | fn main() {
4 | _ = A(0) 4 | _ = A(0)
| ~~~~ | ~~~~
5 | _ = &A(0) 5 | _ = &A(unsafe { nil })
6 | } 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() { 3 | fn main() {
4 | _ = A(0) 4 | _ = A(0)
5 | _ = &A(0) 5 | _ = &A(unsafe { nil })
| ~~~~~ | ~~~~~~~~~~~~~~~~~~
6 | } 6 | }

View File

@ -1,6 +1,6 @@
module main module main
fn 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 } 2 | mut p := unsafe { nil }
3 | p = arr 3 | p = arr
| ~~~ | ~~~
4 | mut ip := &int(0) 4 | mut ip := &int(unsafe { nil })
5 | ip = arr 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 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 3 | p = arr
4 | mut ip := &int(0) 4 | mut ip := &int(unsafe { nil })
5 | ip = arr 5 | ip = arr
| ~~~ | ~~~
6 | _ = &int(arr) 6 | _ = &int(arr)
7 | _ = p 7 | _ = p
vlib/v/checker/tests/fixed_array_conv.vv:6:5: warning: cannot cast a fixed array (use e.g. `&arr[0]` instead) 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 5 | ip = arr
6 | _ = &int(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 } 2 | mut p := unsafe { nil }
3 | p = arr 3 | p = arr
| ^ | ^
4 | mut ip := &int(0) 4 | mut ip := &int(unsafe { nil })
5 | ip = arr 5 | ip = arr
vlib/v/checker/tests/fixed_array_conv.vv:3:5: error: cannot assign to `p`: expected `voidptr`, not `[2]int` vlib/v/checker/tests/fixed_array_conv.vv:3:5: error: cannot assign to `p`: expected `voidptr`, not `[2]int`
1 | arr := [2, 3]! 1 | arr := [2, 3]!
2 | mut p := unsafe { nil } 2 | mut p := unsafe { nil }
3 | p = arr 3 | p = arr
| ~~~ | ~~~
4 | mut ip := &int(0) 4 | mut ip := &int(unsafe { nil })
5 | ip = arr 5 | ip = arr
vlib/v/checker/tests/fixed_array_conv.vv:5:4: error: mismatched types `&int` and `[2]int` vlib/v/checker/tests/fixed_array_conv.vv:5:4: error: mismatched types `&int` and `[2]int`
3 | p = arr 3 | p = arr
4 | mut ip := &int(0) 4 | mut ip := &int(unsafe { nil })
5 | ip = arr 5 | ip = arr
| ^ | ^
6 | _ = &int(arr) 6 | _ = &int(arr)
7 | _ = p 7 | _ = p
vlib/v/checker/tests/fixed_array_conv.vv:5:6: error: cannot assign to `ip`: expected `&int`, not `[2]int` vlib/v/checker/tests/fixed_array_conv.vv:5:6: error: cannot assign to `ip`: expected `&int`, not `[2]int`
3 | p = arr 3 | p = arr
4 | mut ip := &int(0) 4 | mut ip := &int(unsafe { nil })
5 | ip = arr 5 | ip = arr
| ~~~ | ~~~
6 | _ = &int(arr) 6 | _ = &int(arr)

View File

@ -1,7 +1,7 @@
arr := [2, 3]! arr := [2, 3]!
mut p := unsafe { nil } mut p := unsafe { nil }
p = arr p = arr
mut ip := &int(0) mut ip := &int(unsafe { nil })
ip = arr ip = arr
_ = &int(arr) _ = &int(arr)
_ = p _ = 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` vlib/v/checker/tests/globals/cast_expr_T_type_err.vv:4:7: error: unknown type `A`
2 | 2 |
3 | __global ( 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` 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 5 | a := 1
6 | 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 }) 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 5 | b := 0
6 | 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{}] [&Blah{}]

View File

@ -26,11 +26,11 @@ pub fn (mut ed EmbedFileData) free() {
ed.compression_type.free() ed.compression_type.free()
if ed.free_compressed { if ed.free_compressed {
free(ed.compressed) free(ed.compressed)
ed.compressed = &u8(0) ed.compressed = &u8(nil)
} }
if ed.free_uncompressed { if ed.free_uncompressed {
free(ed.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(ppb))
dump(voidptr(pppb)) dump(voidptr(pppb))
dump(voidptr(ppppb)) dump(voidptr(ppppb))
pc := &char(0) pc := &char(nil)
ppc := &&char(0) ppc := &&char(nil)
pppc := &&&char(0) pppc := &&&char(nil)
ppppc := &&&&char(0) ppppc := &&&&char(nil)
dump(voidptr(pc)) dump(voidptr(pc))
dump(voidptr(ppc)) dump(voidptr(ppc))
dump(voidptr(pppc)) 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_assign_lhs bool // inside left part of assign expr (for array_set(), etc)
is_void_expr_stmt bool // ExprStmt whose result is discarded is_void_expr_stmt bool // ExprStmt whose result is discarded
is_arraymap_set bool // map or array set value state 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_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_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 is_vlines_enabled bool // is it safe to generate #line directives when -g is passed

View File

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

View File

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

View File

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

View File

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

View File

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