1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: require unsafe for Struct(voidptr) casts

This commit is contained in:
Alexander Medvednikov 2023-01-06 09:28:01 +03:00
parent 0146509516
commit 868908b80d
25 changed files with 64 additions and 83 deletions

View File

@ -376,7 +376,7 @@ pub fn (mut ts TestSession) test() {
}
fn worker_trunner(mut p pool.PoolProcessor, idx int, thread_id int) voidptr {
mut ts := &TestSession(p.get_shared_context())
mut ts := unsafe { &TestSession(p.get_shared_context()) }
if ts.fail_fast {
if ts.failed_cmds.len > 0 {
return pool.no_result
@ -384,7 +384,7 @@ fn worker_trunner(mut p pool.PoolProcessor, idx int, thread_id int) voidptr {
}
tmpd := ts.vtmp_dir
// tls_bench is used to format the step messages/timings
mut tls_bench := &benchmark.Benchmark(p.get_thread_context(idx))
mut tls_bench := unsafe { &benchmark.Benchmark(p.get_thread_context(idx)) }
if isnil(tls_bench) {
tls_bench = benchmark.new_benchmark_pointer()
tls_bench.set_total_expected_steps(ts.benchmark.nexpected_steps)

View File

@ -35,9 +35,8 @@ fn init(user_data voidptr) {
sgl.setup(&sgl_desc)
}
fn frame(user_data voidptr) {
fn frame(state &AppState) {
// println('frame')
state := &AppState(user_data)
draw()
gfx.begin_default_pass(&state.pass_action, sapp.width(), sapp.height())
sgl.draw()

View File

@ -55,8 +55,7 @@ fn init(mut state AppState) {
}
}
fn frame(user_data voidptr) {
mut state := &AppState(user_data)
fn frame(mut state AppState) {
state.render_font()
gfx.begin_default_pass(&state.pass_action, sapp.width(), sapp.height())
sgl.draw()

View File

@ -91,8 +91,7 @@ fn main() {
sapp.run(&desc)
}
fn init(user_data voidptr) {
mut state := &AppState(user_data)
fn init(mut state AppState) {
desc := sapp.create_desc()
gfx.setup(&desc)
s := &sgl.Desc{}
@ -107,8 +106,7 @@ fn init(user_data voidptr) {
}
}
fn frame(user_data voidptr) {
mut state := &AppState(user_data)
fn frame(mut state AppState) {
state.render_font()
gfx.begin_default_pass(&state.pass_action, sapp.width(), sapp.height())
sgl.draw()

View File

@ -73,8 +73,7 @@ fn (a App) draw() {
a.ps.draw()
}
fn init(user_data voidptr) {
mut app := &App(user_data)
fn init(mut app App) {
desc := sapp.create_desc()
gfx.setup(&desc)
sgl_desc := sgl.Desc{
@ -96,14 +95,12 @@ fn init(user_data voidptr) {
app.alpha_pip = sgl.make_pipeline(&pipdesc)
}
fn cleanup(user_data voidptr) {
mut app := &App(user_data)
fn cleanup(mut app App) {
app.cleanup()
gfx.shutdown()
}
fn frame(user_data voidptr) {
mut app := &App(user_data)
fn frame(mut app App) {
app.width = sapp.width()
app.height = sapp.height()
t := time.ticks()

View File

@ -25,9 +25,7 @@ mut:
cut_rate f64 = 5
}
fn frame(x voidptr) {
mut app := &App(x)
fn frame(mut app App) {
app.tui.clear()
if app.points.len > 0 {
@ -55,9 +53,7 @@ fn frame(x voidptr) {
app.tui.flush()
}
fn event(e &tui.Event, x voidptr) {
mut app := &App(x)
fn event(e &tui.Event, mut app App) {
match e.typ {
.key_down {
match e.code {

View File

@ -5,8 +5,7 @@ mut:
tui &tui.Context = unsafe { nil }
}
fn event(e &tui.Event, x voidptr) {
mut app := &App(x)
fn event(e &tui.Event, mut app App) {
app.tui.clear()
app.tui.set_cursor_position(0, 0)
app.tui.write('V term.input event viewer (press `esc` to exit)\n\n')

View File

@ -458,18 +458,15 @@ fn (mut g Game) free() {
}
// TODO Remove these wrapper functions when we can assign methods as callbacks
fn init(x voidptr) {
mut app := &App(x)
fn init(mut app App) {
app.init()
}
fn frame(x voidptr) {
mut app := &App(x)
fn frame(mut app App) {
app.frame()
}
fn cleanup(x voidptr) {
mut app := &App(x)
fn cleanup(mut app App) {
unsafe {
app.free()
}
@ -479,8 +476,7 @@ fn fail(error string) {
eprintln(error)
}
fn event(e &ui.Event, x voidptr) {
mut app := &App(x)
fn event(e &ui.Event, mut app App) {
app.event(e)
}

View File

@ -27,8 +27,7 @@ fn random_color() tui.Color {
}
}
fn event(e &tui.Event, x voidptr) {
mut app := &App(x)
fn event(e &tui.Event, mut app App) {
match e.typ {
.mouse_down {
app.is_drag = true
@ -60,8 +59,7 @@ fn event(e &tui.Event, x voidptr) {
app.redraw = true
}
fn frame(x voidptr) {
mut app := &App(x)
fn frame(mut app App) {
if !app.redraw {
return
}

View File

@ -128,8 +128,7 @@ fn main() {
app.ui.run()?
}
fn frame(x voidptr) {
mut app := &App(x)
fn frame(mut app App) {
mut redraw := app.should_redraw
if app.msg != '' && app.ui.frame_count >= app.msg_hide_tick {
app.msg = ''
@ -141,8 +140,7 @@ fn frame(x voidptr) {
}
}
fn event(event &ui.Event, x voidptr) {
mut app := &App(x)
fn event(event &ui.Event, mut app App) {
match event.typ {
.mouse_down {
app.is_dragging = true

View File

@ -473,9 +473,8 @@ fn (c Cursor) xy() (int, int) {
}
// App callbacks
fn init(x voidptr) {
mut a := &App(x)
a.init_file()
fn init(mut app App) {
app.init_file()
}
fn (mut a App) init_file() {
@ -523,8 +522,7 @@ fn (mut a App) magnet_cursor_x() {
}
}
fn frame(x voidptr) {
mut a := &App(x)
fn frame(mut a App) {
mut ed := a.ed
a.tui.clear()
scroll_limit := a.view_height()
@ -551,8 +549,7 @@ fn frame(x voidptr) {
a.tui.flush()
}
fn event(e &tui.Event, x voidptr) {
mut a := &App(x)
fn event(e &tui.Event, mut a App) {
mut buffer := a.ed
if e.typ == .key_down {
match e.code {

View File

@ -286,8 +286,7 @@ fn (mut a App) new_game() {
}
// initialize the app and record the width and height of the window
fn init(x voidptr) {
mut app := &App(x)
fn init(mut app App) {
w, h := app.termui.window_width, app.termui.window_height
app.width = w
app.height = h
@ -295,8 +294,7 @@ fn init(x voidptr) {
}
// event handles different events for the app as they occur
fn event(e &termui.Event, x voidptr) {
mut app := &App(x)
fn event(e &termui.Event, mut app App) {
match e.typ {
.mouse_down {}
.mouse_drag {}
@ -324,8 +322,7 @@ fn event(e &termui.Event, x voidptr) {
}
// frame perform actions on every tick
fn frame(x voidptr) {
mut app := &App(x)
fn frame(mut app App) {
app.update()
app.draw()
}

View File

@ -656,9 +656,8 @@ pub:
// interpolation function
[direct_array_access; manualfree]
pub fn str_intp(data_len int, in_data voidptr) string {
pub fn str_intp(data_len int, input_base &StrIntpData) string {
mut res := strings.new_builder(256)
input_base := &StrIntpData(in_data)
for i := 0; i < data_len; i++ {
data := unsafe { &input_base[i] }
// avoid empty strings

View File

@ -285,7 +285,6 @@ pub fn (ctx &Context) draw_image_with_config(config DrawImageConfig) {
y := config.img_rect.y
C.darwin_draw_image(x, ctx.height - (y + config.img_rect.height), config.img_rect.width,
config.img_rect.height, img)
println('ok')
return
}
}

View File

@ -86,7 +86,7 @@ pub fn (stmt Stmt) prepare() ! {
}
pub fn (stmt Stmt) bind_params() ! {
res := C.mysql_stmt_bind_param(stmt.stmt, &C.MYSQL_BIND(stmt.binds.data))
res := C.mysql_stmt_bind_param(stmt.stmt, unsafe { &C.MYSQL_BIND(stmt.binds.data) })
if res && stmt.get_error_msg() != '' {
return stmt.error(1)
}
@ -223,7 +223,7 @@ pub fn (mut stmt Stmt) bind_res(fields &C.MYSQL_FIELD, dataptr []&u8, lens []u32
}
pub fn (mut stmt Stmt) bind_result_buffer() ! {
res := C.mysql_stmt_bind_result(stmt.stmt, &C.MYSQL_BIND(stmt.res.data))
res := C.mysql_stmt_bind_result(stmt.stmt, unsafe { &C.MYSQL_BIND(stmt.res.data) })
if res && stmt.get_error_msg() != '' {
return stmt.error(1)
}

View File

@ -117,7 +117,7 @@ fn (mut p Process) win_stop_process() {
if voidptr(the_fn) == 0 {
return
}
wdata := &WProcess(p.wdata)
wdata := unsafe { &WProcess(p.wdata) }
the_fn(wdata.proc_info.h_process)
}
@ -126,17 +126,17 @@ fn (mut p Process) win_resume_process() {
if voidptr(the_fn) == 0 {
return
}
wdata := &WProcess(p.wdata)
wdata := unsafe { &WProcess(p.wdata) }
the_fn(wdata.proc_info.h_process)
}
fn (mut p Process) win_kill_process() {
wdata := &WProcess(p.wdata)
wdata := unsafe { &WProcess(p.wdata) }
C.TerminateProcess(wdata.proc_info.h_process, 3)
}
fn (mut p Process) win_kill_pgroup() {
wdata := &WProcess(p.wdata)
wdata := unsafe { &WProcess(p.wdata) }
C.GenerateConsoleCtrlEvent(C.CTRL_BREAK_EVENT, wdata.proc_info.dw_process_id)
C.Sleep(20)
C.TerminateProcess(wdata.proc_info.h_process, 3)
@ -144,7 +144,7 @@ fn (mut p Process) win_kill_pgroup() {
fn (mut p Process) win_wait() {
exit_code := u32(1)
mut wdata := &WProcess(p.wdata)
mut wdata := unsafe { &WProcess(p.wdata) }
if p.wdata != 0 {
C.WaitForSingleObject(wdata.proc_info.h_process, C.INFINITE)
C.GetExitCodeProcess(wdata.proc_info.h_process, voidptr(&exit_code))
@ -160,7 +160,7 @@ fn (mut p Process) win_wait() {
fn (mut p Process) win_is_alive() bool {
exit_code := u32(0)
wdata := &WProcess(p.wdata)
wdata := unsafe { &WProcess(p.wdata) }
C.GetExitCodeProcess(wdata.proc_info.h_process, voidptr(&exit_code))
if exit_code == C.STILL_ACTIVE {
return true
@ -175,7 +175,7 @@ fn (mut p Process) win_write_string(idx int, s string) {
}
fn (mut p Process) win_read_string(idx int, maxbytes int) (string, int) {
mut wdata := &WProcess(p.wdata)
mut wdata := unsafe { &WProcess(p.wdata) }
if unsafe { wdata == 0 } {
return '', 0
}
@ -207,7 +207,7 @@ fn (mut p Process) win_read_string(idx int, maxbytes int) (string, int) {
}
fn (mut p Process) win_slurp(idx int) string {
mut wdata := &WProcess(p.wdata)
mut wdata := unsafe { &WProcess(p.wdata) }
if unsafe { wdata == 0 } {
return ''
}

View File

@ -118,13 +118,13 @@ fn process_in_thread(mut pool PoolProcessor, task_id int) {
// get_item - called by the worker callback.
// Retrieves a type safe instance of the currently processed item
pub fn (pool &PoolProcessor) get_item[T](idx int) T {
return *(&T(pool.items[idx]))
return unsafe { *(&T(pool.items[idx])) }
}
// get_result - called by the main thread to get a specific result.
// Retrieves a type safe instance of the produced result.
pub fn (pool &PoolProcessor) get_result[T](idx int) T {
return *(&T(pool.results[idx]))
return unsafe { *(&T(pool.results[idx])) }
}
// get_results - get a list of type safe results in the main thread.
@ -140,7 +140,7 @@ pub fn (pool &PoolProcessor) get_results[T]() []T {
pub fn (pool &PoolProcessor) get_results_ref[T]() []&T {
mut res := []&T{cap: pool.results.len}
for i in 0 .. pool.results.len {
res << &T(pool.results[i])
res << unsafe { &T(pool.results[i]) }
}
return res
}

View File

@ -116,7 +116,7 @@ pub mut:
receiver_type Type // != 0, when .is_method == true
name string
params []Param
source_fn voidptr // set in the checker, while processing fn declarations
source_fn voidptr // set in the checker, while processing fn declarations // TODO get rid of voidptr
usages int
generic_names []string
dep_names []string // globals or consts dependent names

View File

@ -2695,6 +2695,10 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type {
if from_sym.kind == .alias {
from_type = (from_sym.info as ast.Alias).parent_type.derive_add_muls(from_type)
}
if from_type == ast.voidptr_type_idx && !c.inside_unsafe {
// TODO make this an error
c.warn('cannot cast voidptr to a struct outside `unsafe`', node.pos)
}
if !from_type.is_int() && final_from_sym.kind != .enum_ && !from_type.is_pointer()
&& !from_type.is_ptr() {
ft := c.table.type_to_str(from_type)

View File

@ -421,7 +421,7 @@ fn (mut c Checker) verify_all_vweb_routes() {
if m.return_type == typ_vweb_result {
is_ok, nroute_attributes, nargs := c.verify_vweb_params_for_method(m)
if !is_ok {
f := &ast.FnDecl(m.source_fn)
f := unsafe { &ast.FnDecl(m.source_fn) }
if f == unsafe { nil } {
continue
}

View File

@ -180,7 +180,8 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
root_ident := node.cond.root_ident() or { node.cond.expr as ast.Ident }
if root_ident.kind != .unresolved {
if !(root_ident.obj as ast.Var).is_mut {
c.error('field `${node.cond.field_name}` is immutable, it cannot be changed',
sym2 := c.table.sym(root_ident.obj.typ)
c.error('field `${sym2.name}.${node.cond.field_name}` is immutable, it cannot be changed',
node.cond.pos)
}
}

View File

@ -40,7 +40,7 @@ vlib/v/checker/tests/for_in_mut_val_type.vv:20:18: error: map literal is immutab
| ~~~~~~~~~~~~~~~~~~
21 | j *= 2
22 | }
vlib/v/checker/tests/for_in_mut_val_type.vv:30:17: error: field `a` is immutable, it cannot be changed
vlib/v/checker/tests/for_in_mut_val_type.vv:30:17: error: field `Test.a` is immutable, it cannot be changed
28 |
29 | fn foo(t Test) {
30 | for mut e in t.a {

View File

@ -104,14 +104,14 @@ pub struct EmbedFileIndexEntry {
// find_index_entry_by_path is used internally by the V compiler:
pub fn find_index_entry_by_path(start voidptr, path string, algo string) &EmbedFileIndexEntry {
mut x := &EmbedFileIndexEntry(start)
for x.id >= 0 && x.data != 0 && (x.algo != algo || x.path != path) {
unsafe {
unsafe {
mut x := &EmbedFileIndexEntry(start)
for x.id >= 0 && x.data != 0 && (x.algo != algo || x.path != path) {
x++
}
$if trace_embed_file ? {
eprintln('>> v.embed_file find_index_entry_by_path ${ptr_str(start)}, id: ${x.id}, path: "${path}", algo: "${algo}" => ${ptr_str(x)}')
}
return x
}
$if trace_embed_file ? {
eprintln('>> v.embed_file find_index_entry_by_path ${ptr_str(start)}, id: ${x.id}, path: "${path}", algo: "${algo}" => ${ptr_str(x)}')
}
return x
}

View File

@ -613,7 +613,7 @@ pub fn gen(files []&ast.File, table &ast.Table, pref &pref.Preferences) (string,
fn cgen_process_one_file_cb(mut p pool.PoolProcessor, idx int, wid int) &Gen {
file := p.get_item[&ast.File](idx)
mut global_g := &Gen(p.get_shared_context())
mut global_g := unsafe { &Gen(p.get_shared_context()) }
mut g := &Gen{
file: file
out: strings.new_builder(512000)

View File

@ -152,7 +152,9 @@ pub fn (mut w Walker) stmt(node_ ast.Stmt) {
// the .next() method of the struct will be used for iteration:
cond_type_sym := w.table.sym(node.cond_type)
if next_fn := cond_type_sym.find_method('next') {
w.fn_decl(mut &ast.FnDecl(next_fn.source_fn))
unsafe {
w.fn_decl(mut &ast.FnDecl(next_fn.source_fn))
}
}
}
}
@ -303,7 +305,9 @@ fn (mut w Walker) expr(node_ ast.Expr) {
sym := w.table.sym(node.left_type)
if sym.kind == .struct_ {
if opmethod := sym.find_method(node.op.str()) {
w.fn_decl(mut &ast.FnDecl(opmethod.source_fn))
unsafe {
w.fn_decl(mut &ast.FnDecl(opmethod.source_fn))
}
}
}
if node.right_type == 0 {