diff --git a/vlib/v/checker/infix.v b/vlib/v/checker/infix.v index 4466525eac1897..25f62660768fc6 100644 --- a/vlib/v/checker/infix.v +++ b/vlib/v/checker/infix.v @@ -781,6 +781,10 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { if typ != ast.no_type { typ_sym := c.table.sym(typ) op := node.op.str() + if left_type.has_flag(.option) && !c.inside_sql { + c.error('${node.left} is an Optional, it needs to be unwrapped first', + node.left.pos()) + } if typ_sym.kind == .placeholder { c.error('${op}: type `${typ_sym.name}` does not exist', right_expr.pos()) } diff --git a/vlib/v/checker/tests/opt_is_op_check_err.out b/vlib/v/checker/tests/opt_is_op_check_err.out new file mode 100644 index 00000000000000..f10ce93db2bbfa --- /dev/null +++ b/vlib/v/checker/tests/opt_is_op_check_err.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/opt_is_op_check_err.vv:13:7: error: t.a is an Optional, it needs to be unwrapped first + 11 | a: s + 12 | } + 13 | if t.a is string { + | ^ + 14 | r(t.a) + 15 | } diff --git a/vlib/v/checker/tests/opt_is_op_check_err.vv b/vlib/v/checker/tests/opt_is_op_check_err.vv new file mode 100644 index 00000000000000..917bdacba26ff4 --- /dev/null +++ b/vlib/v/checker/tests/opt_is_op_check_err.vv @@ -0,0 +1,21 @@ +type Foo = int | string + +struct Struct { + a ?Foo +} + +fn r(a string) {} + +fn t(s ?Foo) { + mut t := Struct{ + a: s + } + if t.a is string { + r(t.a) + } +} + +fn main() { + s := ?Foo('hello') + t(s) +} diff --git a/vlib/v/debug/tests/sumtype.vv b/vlib/v/debug/tests/sumtype.vv index 66ffe8bcfdcfea..21b7115df4b5e4 100644 --- a/vlib/v/debug/tests/sumtype.vv +++ b/vlib/v/debug/tests/sumtype.vv @@ -20,9 +20,11 @@ fn sumtype() { b := ?MySum(Test{ a: 1 }) - if b is Test { - dump(b) - $dbg; + if b != none { + if b is Test { + dump(b) + $dbg; + } } } diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 36830e82cac738..a7f7254bbafb94 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -4347,17 +4347,20 @@ fn (mut g Gen) debugger_stmt(node ast.DebuggerStmt) { cast_sym := g.table.sym(var_typ) mut param_var := strings.new_builder(50) - is_option := obj.typ.has_flag(.option) + is_option := obj.orig_type.has_flag(.option) var_typ_is_option := var_typ.has_flag(.option) if obj.smartcasts.len > 0 { - is_option_unwrap := is_option && var_typ == obj.typ.clear_flag(.option) + is_option_unwrap := is_option && !obj.typ.has_flag(.option) + && obj.orig_type.has_flag(.option) mut opt_cast := false mut func := if cast_sym.info is ast.Aggregate { '' } else { g.get_str_fn(var_typ) } - + if obj.smartcasts.len > 1 && obj_sym.kind == .sum_type { + param_var.write_string('*(') + } param_var.write_string('(') if obj_sym.kind == .sum_type && !obj.is_auto_heap { if is_option { diff --git a/vlib/v/tests/options/option_sumtype_test.v b/vlib/v/tests/options/option_sumtype_test.v index f17b78733600e0..9190634c64ab15 100644 --- a/vlib/v/tests/options/option_sumtype_test.v +++ b/vlib/v/tests/options/option_sumtype_test.v @@ -6,11 +6,13 @@ pub fn teste() ?TType { fn test_main() { x := teste() - if x is []int { - dump(x) - y := x as []int - assert y == [1, 2] - return + if x != none { + if x is []int { + dump(x) + y := x as []int + assert y == [1, 2] + return + } } assert false }