From 115f83d2b94d986655af791bde9c452fe9303174 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Mon, 4 Mar 2024 16:56:44 -0300 Subject: [PATCH] checker: fix missing check for interface cast of option type (#20961) --- vlib/v/checker/checker.v | 4 ++-- .../tests/interface_option_cast_err.out | 19 +++++++++++++++++++ .../tests/interface_option_cast_err.vv | 14 ++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) create mode 100644 vlib/v/checker/tests/interface_option_cast_err.out create mode 100644 vlib/v/checker/tests/interface_option_cast_err.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index e035865a6..e6d794ea1 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3148,7 +3148,7 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { tt := c.table.type_to_str(to_type) c.error('cannot cast `${ft}` to `${tt}`', node.pos) } - } else if mut to_sym.info is ast.Interface { + } else if !from_type.has_option_or_result() && mut to_sym.info is ast.Interface { if c.type_implements(from_type, to_type, node.pos) { if !from_type.is_any_kind_of_pointer() && from_sym.kind != .interface_ && !c.inside_unsafe { @@ -3174,7 +3174,7 @@ fn (mut c Checker) cast_expr(mut node ast.CastExpr) ast.Type { } else if from_type == ast.none_type && !to_type.has_flag(.option) && !to_type.has_flag(.result) { type_name := c.table.type_to_str(to_type) c.error('cannot cast `none` to `${type_name}`', node.pos) - } else if from_sym.kind == .struct_ && !from_type.is_ptr() { + } else if !from_type.has_option_or_result() && from_sym.kind == .struct_ && !from_type.is_ptr() { if (final_to_is_ptr || to_sym.kind !in [.sum_type, .interface_]) && !c.is_builtin_mod { from_type_name := c.table.type_to_str(from_type) type_name := c.table.type_to_str(to_type) diff --git a/vlib/v/checker/tests/interface_option_cast_err.out b/vlib/v/checker/tests/interface_option_cast_err.out new file mode 100644 index 000000000..ca19d73de --- /dev/null +++ b/vlib/v/checker/tests/interface_option_cast_err.out @@ -0,0 +1,19 @@ +vlib/v/checker/tests/interface_option_cast_err.vv:12:2: warning: unused variable: `b` + 10 | a := ?Foo{} + 11 | dump(a) + 12 | b := IFoo(a?) + | ^ + 13 | c := IFoo(a) + 14 | } +vlib/v/checker/tests/interface_option_cast_err.vv:13:2: warning: unused variable: `c` + 11 | dump(a) + 12 | b := IFoo(a?) + 13 | c := IFoo(a) + | ^ + 14 | } +vlib/v/checker/tests/interface_option_cast_err.vv:13:7: error: cannot type cast an Option + 11 | dump(a) + 12 | b := IFoo(a?) + 13 | c := IFoo(a) + | ~~~~~~~ + 14 | } diff --git a/vlib/v/checker/tests/interface_option_cast_err.vv b/vlib/v/checker/tests/interface_option_cast_err.vv new file mode 100644 index 000000000..0fb0fbfed --- /dev/null +++ b/vlib/v/checker/tests/interface_option_cast_err.vv @@ -0,0 +1,14 @@ +interface IFoo { + a int +} + +struct Foo { + a int +} + +fn main() { + a := ?Foo{} + dump(a) + b := IFoo(a?) + c := IFoo(a) +} \ No newline at end of file -- 2.39.5