diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 33e11919e1a6d9..bce15f34443a4d 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -4996,26 +4996,7 @@ fn (mut g Gen) ident(node ast.Ident) { g.write(name) } } else { - g.write('/*opt*/') - styp := g.base_type(node.info.typ) - if is_auto_heap { - g.write('(*(${styp}*)${name}->data)') - } else { - type_sym := g.table.sym(node.info.typ) - if type_sym.kind == .alias { - // Alias to Option type - parent_typ := (type_sym.info as ast.Alias).parent_type - if parent_typ.has_flag(.option) { - g.write('*((${g.base_type(parent_typ)}*)') - } - g.write('(*(${styp}*)${name}.data)') - if parent_typ.has_flag(.option) { - g.write('.data)') - } - } else { - g.write('(*(${styp}*)${name}.data)') - } - } + g.unwrap_option_type(node.info.typ, name, is_auto_heap) } if node.or_expr.kind != .absent && !(g.inside_opt_or_res && g.inside_assign && !g.is_assign_lhs) { @@ -7801,7 +7782,17 @@ fn (mut g Gen) as_cast(node ast.AsCast) { g.as_cast_type_names[idx] = variant_sym.name } } else { - g.expr(node.expr) + if node.expr is ast.Ident { + if node.expr.info is ast.IdentVar { + if node.expr.info.is_option { + g.unwrap_option_type(unwrapped_node_typ, node.expr.name, node.expr.is_auto_heap()) + } else { + g.expr(node.expr) + } + } + } else { + g.expr(node.expr) + } } } diff --git a/vlib/v/gen/c/utils.v b/vlib/v/gen/c/utils.v index bd88216c170ea0..57bc34866cdf50 100644 --- a/vlib/v/gen/c/utils.v +++ b/vlib/v/gen/c/utils.v @@ -32,7 +32,7 @@ fn (mut g Gen) unwrap_generic(typ ast.Type) ast.Type { } } } else if g.table.sym(typ).kind == .struct { - // resolve selector `a.foo` where `a` is struct[T] on non generic function + // resolve selector `a.foo` where `a` is struct[T] on non generic function sym := g.table.sym(typ) if sym.info is ast.Struct { if sym.info.generic_types.len > 0 { @@ -145,3 +145,27 @@ fn (mut g Gen) dot_or_ptr(val_type ast.Type) string { '.' } } + +@[inline] +fn (mut g Gen) unwrap_option_type(typ ast.Type, name string, is_auto_heap bool) { + g.write('/*opt*/') + styp := g.base_type(typ) + if is_auto_heap { + g.write('(*(${styp}*)${name}->data)') + } else { + type_sym := g.table.sym(typ) + if type_sym.kind == .alias { + // Alias to Option type + parent_typ := (type_sym.info as ast.Alias).parent_type + if parent_typ.has_flag(.option) { + g.write('*((${g.base_type(parent_typ)}*)') + } + g.write('(*(${styp}*)${name}.data)') + if parent_typ.has_flag(.option) { + g.write('.data)') + } + } else { + g.write('(*(${styp}*)${name}.data)') + } + } +} diff --git a/vlib/v/tests/option_unwrap_as_cast_test.v b/vlib/v/tests/option_unwrap_as_cast_test.v new file mode 100644 index 00000000000000..6bf6879a9f74d4 --- /dev/null +++ b/vlib/v/tests/option_unwrap_as_cast_test.v @@ -0,0 +1,23 @@ +fn get_opt(a int) ?string { + if a < 0 { + return none + } + return 'success' +} + +fn get_opt_int(a int) ?int { + if a < 0 { + return none + } + return 12 +} + +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') + + assert d as int == 12 + assert x as string == 'success' +}