Skip to content

Commit

Permalink
checker: disallow expr is Type if expr is Optional (fix #23486) (#2…
Browse files Browse the repository at this point in the history
  • Loading branch information
Delta456 authored Jan 25, 2025
1 parent fac8bb8 commit 89089ab
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 11 deletions.
4 changes: 4 additions & 0 deletions vlib/v/checker/infix.v
Original file line number Diff line number Diff line change
Expand Up @@ -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())
}
Expand Down
7 changes: 7 additions & 0 deletions vlib/v/checker/tests/opt_is_op_check_err.out
Original file line number Diff line number Diff line change
@@ -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 | }
21 changes: 21 additions & 0 deletions vlib/v/checker/tests/opt_is_op_check_err.vv
Original file line number Diff line number Diff line change
@@ -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)
}
8 changes: 5 additions & 3 deletions vlib/v/debug/tests/sumtype.vv
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}
}

Expand Down
9 changes: 6 additions & 3 deletions vlib/v/gen/c/cgen.v
Original file line number Diff line number Diff line change
Expand Up @@ -4370,17 +4370,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 {
Expand Down
12 changes: 7 additions & 5 deletions vlib/v/tests/options/option_sumtype_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

0 comments on commit 89089ab

Please sign in to comment.