From 20294fab5d934a4cb4178e651ef51f8e6671762e Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Tue, 3 Dec 2024 20:00:17 -0300 Subject: [PATCH] checker: fix missing checker for cast from mut var to non-ptr type (fix #23017) (#23056) --- vlib/v/checker/checker.v | 10 ++++ .../tests/cast_to_concrete_mut_err.out | 14 +++++ .../checker/tests/cast_to_concrete_mut_err.vv | 58 +++++++++++++++++++ 3 files changed, 82 insertions(+) create mode 100644 vlib/v/checker/tests/cast_to_concrete_mut_err.out create mode 100644 vlib/v/checker/tests/cast_to_concrete_mut_err.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index dc752671d..699b21d72 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3614,6 +3614,16 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { c.error('cannot cast `${ft}` ${kind_name} value to `${tt}`, use `${node.expr} as ${tt}` instead', node.pos) } + if from_sym.language == .v && from_type.is_ptr() && !to_type.is_ptr() && !final_to_type.is_ptr() + && !node.expr.is_auto_deref_var() && final_to_sym.kind == .struct + && final_from_sym.kind == .struct { + if c.check_struct_signature(final_from_sym.info as ast.Struct, final_to_sym.info as ast.Struct) { + ft := c.table.type_to_str(from_type) + tt := c.table.type_to_str(to_type) + c.error('cannot cast `${ft}` to `${tt}`, you must dereference it first (e.g. ${tt}(*var))', + node.pos) + } + } if node.has_arg { c.expr(mut node.arg) diff --git a/vlib/v/checker/tests/cast_to_concrete_mut_err.out b/vlib/v/checker/tests/cast_to_concrete_mut_err.out new file mode 100644 index 000000000..ef940f364 --- /dev/null +++ b/vlib/v/checker/tests/cast_to_concrete_mut_err.out @@ -0,0 +1,14 @@ +vlib/v/checker/tests/cast_to_concrete_mut_err.vv:37:12: warning: casting `&Message` to `&LocalMessageType` is only allowed in `unsafe` code + 35 | if mut mdef is Message { + 36 | mut a := LocalMessageType(*mdef) + 37 | mut b := &LocalMessageType(mdef) + | ~~~~~~~~~~~~~~~~~~~~~~~ + 38 | mut c := LocalMessageType(mdef) + 39 | +vlib/v/checker/tests/cast_to_concrete_mut_err.vv:38:12: error: cannot cast `&Message` to `LocalMessageType`, you must dereference it first (e.g. LocalMessageType(*var)) + 36 | mut a := LocalMessageType(*mdef) + 37 | mut b := &LocalMessageType(mdef) + 38 | mut c := LocalMessageType(mdef) + | ~~~~~~~~~~~~~~~~~~~~~~ + 39 | + 40 | dump(a) diff --git a/vlib/v/checker/tests/cast_to_concrete_mut_err.vv b/vlib/v/checker/tests/cast_to_concrete_mut_err.vv new file mode 100644 index 000000000..f911d8558 --- /dev/null +++ b/vlib/v/checker/tests/cast_to_concrete_mut_err.vv @@ -0,0 +1,58 @@ +module main + +pub struct Message { +pub mut: + text string = 'Init' + m2 ?&Message +} + +pub fn (mut m Message) update_text(new_text string) { + m.text = new_text +} + +pub fn (mut m Message) update_ext_text(new_text string) { + m.m2?.text = new_text +} + +type LocalMessageType = Message + +interface IMessage { +mut: + text string + update_text(new_text string) +} + +struct App { +mut: + message &IMessage +} + +pub fn (mut m LocalMessageType) update_text_externally(new_text string) { + m.text = new_text +} + +fn print_message(mut mdef IMessage) { + if mut mdef is Message { + mut a := LocalMessageType(*mdef) + mut b := &LocalMessageType(mdef) + mut c := LocalMessageType(mdef) + + dump(a) + dump(b) + dump(c) + } +} + +fn test_main() { + mut m2 := &Message{ + text: 'Init External' + } + mut mdef := &Message{ + text: 'Init' + m2: m2 + } + mut app := &App{ + message: mdef + } + print_message(mut app.message) +} -- 2.39.5