Skip to content

Commit

Permalink
checker: fix missing option variable checking when casting using as
Browse files Browse the repository at this point in the history
… operator (fix #23349) (#23358)
  • Loading branch information
felipensp authored Jan 4, 2025
1 parent d8422c7 commit 0763ae7
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 7 deletions.
14 changes: 14 additions & 0 deletions vlib/v/checker/checker.v
Original file line number Diff line number Diff line change
Expand Up @@ -2962,6 +2962,20 @@ pub fn (mut c Checker) expr(mut node ast.Expr) ast.Type {
if !c.is_builtin_mod {
c.table.used_features.as_cast = true
}
if mut node.expr is ast.Ident {
if mut node.expr.obj is ast.Var {
ident_typ := if node.expr.obj.smartcasts.len > 0 {
node.expr.obj.smartcasts.last()
} else {
node.expr.obj.typ
}
if !node.typ.has_flag(.option) && ident_typ.has_flag(.option)
&& node.expr.or_expr.kind == .absent {
c.error('variable `${node.expr.name}` is an Option, it must be unwrapped first',
node.expr.pos)
}
}
}
if expr_type_sym.kind == .sum_type {
c.ensure_type_exists(node.typ, node.pos)
if !c.table.sumtype_has_variant(c.unwrap_generic(node.expr_type), c.unwrap_generic(node.typ),
Expand Down
5 changes: 5 additions & 0 deletions vlib/v/checker/tests/option_as_cast_err.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
vlib/v/checker/tests/option_as_cast_err.vv:12:9: error: variable `b` is an Option, it must be unwrapped first
10 | println(b)
11 | println(b? as int)
12 | println(b as int)
| ^
12 changes: 12 additions & 0 deletions vlib/v/checker/tests/option_as_cast_err.vv
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
type Sum = int | string

fn sum() ?Sum {
return Sum(5)
}

a := sum()?
println(a as int)
b := sum()
println(b)
println(b? as int)
println(b as int)
6 changes: 3 additions & 3 deletions vlib/v/tests/options/option_concatexpr_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ fn foo(f int) !(int, ?int) {

fn test_main() {
a, b := foo(-1) or { 2, 2 }
c := b as int
c := b? as int
assert a == 2
assert c == 2

a2, b2 := foo(0) or { 2, 2 }
c2 := b2 as int
c2 := b2? as int
assert a2 == 0
assert c2 == 0

a3, b3 := foo(1) or { 2, 2 }
c3 := b3 as int
c3 := b3? as int
assert a3 == 1
assert c3 == 1
}
8 changes: 4 additions & 4 deletions vlib/v/tests/options/option_unwrap_as_cast_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ fn get_opt_int(a int) ?int {
fn test_option_unwrap_as_cast() {
x := get_opt(1)
d := get_opt_int(12)
dump(d as int == 12)
dump('${x as string}' == 'success')
dump(d? as int == 12)
dump('${x? as string}' == 'success')

assert d as int == 12
assert x as string == 'success'
assert d? as int == 12
assert x? as string == 'success'
}

0 comments on commit 0763ae7

Please sign in to comment.