diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index a6f1d7571e1bff..7375f82872e979 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1386,6 +1386,13 @@ fn (mut c Checker) check_expr_option_or_result_call(expr ast.Expr, ret_type ast. c.check_expr_option_or_result_call(expr.expr, ret_type) } ast.AsCast { + if expr.expr is ast.Ident { + if !ret_type.has_flag(.option) && expr.expr.obj.typ.has_flag(.option) + && expr.expr.or_expr.kind == .absent { + c.error('variable `${expr.expr.name}` is an Option, it must be unwrapped first', + expr.expr.pos) + } + } c.check_expr_option_or_result_call(expr.expr, ret_type) } ast.ParExpr { @@ -2958,6 +2965,7 @@ pub fn (mut c Checker) expr(mut node ast.Expr) ast.Type { if !c.is_builtin_mod { c.table.used_features.as_cast = true } + c.check_expr_option_or_result_call(node.expr, node.typ) 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), diff --git a/vlib/v/checker/tests/option_as_cast_err.out b/vlib/v/checker/tests/option_as_cast_err.out new file mode 100644 index 00000000000000..e7973ab4ba0ebd --- /dev/null +++ b/vlib/v/checker/tests/option_as_cast_err.out @@ -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) + | ^ diff --git a/vlib/v/checker/tests/option_as_cast_err.vv b/vlib/v/checker/tests/option_as_cast_err.vv new file mode 100644 index 00000000000000..c57cd3f7348058 --- /dev/null +++ b/vlib/v/checker/tests/option_as_cast_err.vv @@ -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)