From 6ba6a22a775a649ed086489e619d826c7929589a Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Mon, 17 Aug 2020 10:19:44 +0100 Subject: [PATCH] checker: prevent from casting non-struct to struct (#6143) --- vlib/v/checker/checker.v | 16 +++++++---- .../v/checker/tests/cannot_cast_to_struct.out | 27 +++++++++++++++++++ vlib/v/checker/tests/cannot_cast_to_struct.vv | 16 +++++++++++ 3 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 vlib/v/checker/tests/cannot_cast_to_struct.out create mode 100644 vlib/v/checker/tests/cannot_cast_to_struct.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 10ae77d37a..dffab588f0 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2333,11 +2333,17 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type { type_name := c.table.type_to_str(node.expr_type) c.error('cannot cast type `$type_name` to `byte`', node.pos) } else if to_type_sym.kind == .struct_ && !node.typ.is_ptr() && !(to_type_sym.info as table.Struct).is_typedef { - from_type_info := from_type_sym.info as table.Struct - to_type_info := to_type_sym.info as table.Struct - if !c.check_struct_signature(from_type_info, to_type_info) { - c.error('cannot convert struct `$from_type_sym.name` to struct `$to_type_sym.name`', - node.pos) + // For now we ignore C typedef because of `C.Window(C.None)` in vlib/clipboard + if from_type_sym.kind == .struct_ && !node.expr_type.is_ptr() { + from_type_info := from_type_sym.info as table.Struct + to_type_info := to_type_sym.info as table.Struct + if !c.check_struct_signature(from_type_info, to_type_info) { + c.error('cannot convert struct `$from_type_sym.name` to struct `$to_type_sym.name`', + node.pos) + } + } else { + type_name := c.table.type_to_str(node.expr_type) + c.error('cannot cast `$type_name` to struct', node.pos) } } if node.has_arg { diff --git a/vlib/v/checker/tests/cannot_cast_to_struct.out b/vlib/v/checker/tests/cannot_cast_to_struct.out new file mode 100644 index 0000000000..b83e27bd21 --- /dev/null +++ b/vlib/v/checker/tests/cannot_cast_to_struct.out @@ -0,0 +1,27 @@ +vlib/v/checker/tests/cannot_cast_to_struct.v:10:12: error: cannot convert struct `Abc` to struct `Test` + 8 | + 9 | fn main() { + 10 | _ := Test(Abc{}) + | ~~~~~ + 11 | sum := Alphabet(Xyz{}) + 12 | _ = Xyz(sum) +vlib/v/checker/tests/cannot_cast_to_struct.v:12:10: error: cannot cast `Alphabet` to struct + 10 | _ := Test(Abc{}) + 11 | sum := Alphabet(Xyz{}) + 12 | _ = Xyz(sum) + | ~~~ + 13 | _ = Xyz(5) + 14 | s := Abc{} +vlib/v/checker/tests/cannot_cast_to_struct.v:13:10: error: cannot cast `any_int` to struct + 11 | sum := Alphabet(Xyz{}) + 12 | _ = Xyz(sum) + 13 | _ = Xyz(5) + | ^ + 14 | s := Abc{} + 15 | _ = Xyz(&s) +vlib/v/checker/tests/cannot_cast_to_struct.v:15:10: error: cannot cast `&Abc` to struct + 13 | _ = Xyz(5) + 14 | s := Abc{} + 15 | _ = Xyz(&s) + | ^ + 16 | } diff --git a/vlib/v/checker/tests/cannot_cast_to_struct.vv b/vlib/v/checker/tests/cannot_cast_to_struct.vv new file mode 100644 index 0000000000..64cf7faa04 --- /dev/null +++ b/vlib/v/checker/tests/cannot_cast_to_struct.vv @@ -0,0 +1,16 @@ +struct Abc {} +struct Xyz {} +type Alphabet = Abc | Xyz + +struct Test { + abc Alphabet +} + +fn main() { + _ := Test(Abc{}) + sum := Alphabet(Xyz{}) + _ = Xyz(sum) + _ = Xyz(5) + s := Abc{} + _ = Xyz(&s) +}