diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 27ac7ec3ee12cd..36830e82cac738 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -3995,13 +3995,17 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) { // check first if field is sum type because scope searching is expensive scope := g.file.scope.innermost(node.pos.pos) if field := scope.find_struct_field(node.expr.str(), node.expr_type, node.field_name) { + nested_unwrap := is_option && field.smartcasts.len > 1 is_option_unwrap = is_option && field.smartcasts.len > 0 && field.typ.clear_flag(.option) == field.smartcasts.last() if field.orig_type.is_ptr() { sum_type_dot = '->' } + if nested_unwrap && field_sym.kind == .sum_type { + g.write('*(') + } for i, typ in field.smartcasts { - if i == 0 && is_option_unwrap { + if i == 0 && (is_option_unwrap || nested_unwrap) { deref := if g.inside_selector { '*'.repeat(field.smartcasts.last().nr_muls() + 1) } else { @@ -4009,7 +4013,9 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) { } g.write('(${deref}(${g.styp(typ)}*)') } - g.write('(') + if i == 0 || !nested_unwrap { + g.write('(') + } if field_sym.kind == .sum_type && !is_option { g.write('*') } @@ -4029,7 +4035,11 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) { agg_sym := g.table.sym(cast_sym.info.types[g.aggregate_type_idx]) sum_type_deref_field += '_${agg_sym.cname}' } else { - sum_type_deref_field += '_${cast_sym.cname}' + if i == 0 && nested_unwrap { + sum_type_deref_field += 'data)' + } else { + sum_type_deref_field += '_${cast_sym.cname}' + } } } } diff --git a/vlib/v/tests/options/option_nested_selector_unwrap_test.v b/vlib/v/tests/options/option_nested_selector_unwrap_test.v new file mode 100644 index 00000000000000..5cf86f152f53c3 --- /dev/null +++ b/vlib/v/tests/options/option_nested_selector_unwrap_test.v @@ -0,0 +1,22 @@ +type Foo = string | int | f32 + +struct Bar { + log ?Foo +} + +fn Bar.init(log ?Foo) { + mut bar := Bar{ + log: log + } + if bar.log != none { + if bar.log is string { + assert bar.log == 'foobar' + return + } + } + assert false +} + +fn test_main() { + Bar.init('foobar') +}