Skip to content

Commit 496451e

Browse files
authored
cgen: fix nested option selector unwrapping (fix #23500) (#23497)
1 parent c98295b commit 496451e

File tree

2 files changed

+35
-3
lines changed

2 files changed

+35
-3
lines changed

vlib/v/gen/c/cgen.v

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3995,21 +3995,27 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
39953995
// check first if field is sum type because scope searching is expensive
39963996
scope := g.file.scope.innermost(node.pos.pos)
39973997
if field := scope.find_struct_field(node.expr.str(), node.expr_type, node.field_name) {
3998+
nested_unwrap := is_option && field.smartcasts.len > 1
39983999
is_option_unwrap = is_option && field.smartcasts.len > 0
39994000
&& field.typ.clear_flag(.option) == field.smartcasts.last()
40004001
if field.orig_type.is_ptr() {
40014002
sum_type_dot = '->'
40024003
}
4004+
if nested_unwrap && field_sym.kind == .sum_type {
4005+
g.write('*(')
4006+
}
40034007
for i, typ in field.smartcasts {
4004-
if i == 0 && is_option_unwrap {
4008+
if i == 0 && (is_option_unwrap || nested_unwrap) {
40054009
deref := if g.inside_selector {
40064010
'*'.repeat(field.smartcasts.last().nr_muls() + 1)
40074011
} else {
40084012
'*'
40094013
}
40104014
g.write('(${deref}(${g.styp(typ)}*)')
40114015
}
4012-
g.write('(')
4016+
if i == 0 || !nested_unwrap {
4017+
g.write('(')
4018+
}
40134019
if field_sym.kind == .sum_type && !is_option {
40144020
g.write('*')
40154021
}
@@ -4029,7 +4035,11 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
40294035
agg_sym := g.table.sym(cast_sym.info.types[g.aggregate_type_idx])
40304036
sum_type_deref_field += '_${agg_sym.cname}'
40314037
} else {
4032-
sum_type_deref_field += '_${cast_sym.cname}'
4038+
if i == 0 && nested_unwrap {
4039+
sum_type_deref_field += 'data)'
4040+
} else {
4041+
sum_type_deref_field += '_${cast_sym.cname}'
4042+
}
40334043
}
40344044
}
40354045
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
type Foo = string | int | f32
2+
3+
struct Bar {
4+
log ?Foo
5+
}
6+
7+
fn Bar.init(log ?Foo) {
8+
mut bar := Bar{
9+
log: log
10+
}
11+
if bar.log != none {
12+
if bar.log is string {
13+
assert bar.log == 'foobar'
14+
return
15+
}
16+
}
17+
assert false
18+
}
19+
20+
fn test_main() {
21+
Bar.init('foobar')
22+
}

0 commit comments

Comments
 (0)