Skip to content

Commit 65098b2

Browse files
authored
cgen: fix auto eq method for option fields (fix #20314) (#20424)
1 parent d78adb0 commit 65098b2

File tree

2 files changed

+107
-1
lines changed

2 files changed

+107
-1
lines changed

vlib/v/gen/c/auto_eq_methods.v

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,9 @@ fn (mut g Gen) gen_struct_equality_fn(left_type ast.Type) string {
205205
left_arg := g.read_field(left_type, field_name, 'a')
206206
right_arg := g.read_field(left_type, field_name, 'b')
207207

208+
if field.typ.has_flag(.option) {
209+
fn_builder.write_string('(${left_arg}.state == ${right_arg}.state && ${right_arg}.state == 2 || ')
210+
}
208211
if field_type.sym.kind == .string {
209212
if field.typ.has_flag(.option) {
210213
left_arg_opt := g.read_opt_field(left_type, field_name, 'a', field.typ)
@@ -241,10 +244,13 @@ fn (mut g Gen) gen_struct_equality_fn(left_type ast.Type) string {
241244
eq_fn := g.gen_interface_equality_fn(field.typ)
242245
fn_builder.write_string('${eq_fn}_interface_eq(${ptr}${left_arg}, ${ptr}${right_arg})')
243246
} else if field.typ.has_flag(.option) {
244-
fn_builder.write_string('${left_arg}.state == ${right_arg}.state && !memcmp(&${left_arg}.data, &${right_arg}.data, sizeof(${g.base_type(field.typ)}))')
247+
fn_builder.write_string('!memcmp(&${left_arg}.data, &${right_arg}.data, sizeof(${g.base_type(field.typ)}))')
245248
} else {
246249
fn_builder.write_string('${left_arg} == ${right_arg}')
247250
}
251+
if field.typ.has_flag(.option) {
252+
fn_builder.write_string(')')
253+
}
248254
}
249255
} else {
250256
fn_builder.write_string('true')

vlib/v/tests/option_auto_eq_test.v

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
import x.json2
2+
3+
pub struct PartialEmoji {
4+
pub:
5+
id ?int
6+
name string
7+
animated bool
8+
}
9+
10+
pub fn PartialEmoji.parse(j json2.Any) !PartialEmoji {
11+
match j {
12+
map[string]json2.Any {
13+
return PartialEmoji{
14+
id: if s := j['id'] {
15+
if s !is json2.Null {
16+
?int(s.int())
17+
} else {
18+
none
19+
}
20+
} else {
21+
none
22+
}
23+
name: j['name']! as string
24+
animated: if b := j['animated'] {
25+
b as bool
26+
} else {
27+
false
28+
}
29+
}
30+
}
31+
else {
32+
return error('expected partial emoji to be object, got ${j.type_name()}')
33+
}
34+
}
35+
}
36+
37+
pub enum ButtonStyle {
38+
primary = 1
39+
secondary
40+
success
41+
danger
42+
link
43+
}
44+
45+
pub struct Button {
46+
pub:
47+
style ButtonStyle = .secondary
48+
label ?string
49+
emoji ?PartialEmoji
50+
custom_id ?string
51+
url ?string
52+
disabled ?bool
53+
}
54+
55+
pub fn Button.parse(j json2.Any) !Button {
56+
match j {
57+
map[string]json2.Any {
58+
return Button{
59+
style: unsafe { ButtonStyle(j['style']!.int()) }
60+
label: if s := j['label'] {
61+
?string(s as string)
62+
} else {
63+
none
64+
}
65+
emoji: if o := j['emoji'] {
66+
dump(PartialEmoji.parse(o)!)
67+
?PartialEmoji(PartialEmoji.parse(o)!)
68+
} else {
69+
none
70+
}
71+
custom_id: if s := j['custom_id'] {
72+
?string(s as string)
73+
} else {
74+
none
75+
}
76+
url: if s := j['url'] {
77+
?string(s as string)
78+
} else {
79+
none
80+
}
81+
disabled: if b := j['disabled'] {
82+
?bool(b as bool)
83+
} else {
84+
none
85+
}
86+
}
87+
}
88+
else {
89+
return error('expected button to be object, got ${j.type_name()}')
90+
}
91+
}
92+
}
93+
94+
fn test_main() {
95+
assert Button.parse({
96+
'style': json2.Any(2)
97+
}) or { panic('That case should not return error: ${err}') } == Button{
98+
style: .secondary
99+
}
100+
}

0 commit comments

Comments
 (0)