mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen: fix code generated for optional comptime var (#16854)
This commit is contained in:
@ -4247,6 +4247,22 @@ fn (mut g Gen) ident(node ast.Ident) {
|
||||
}
|
||||
mut is_auto_heap := false
|
||||
if node.info is ast.IdentVar {
|
||||
if node.obj is ast.Var {
|
||||
if !g.is_assign_lhs && node.obj.is_comptime_field {
|
||||
if g.comptime_for_field_type.has_flag(.optional) {
|
||||
if g.inside_opt_or_res {
|
||||
g.write('${name}')
|
||||
} else {
|
||||
g.write('/*opt*/')
|
||||
styp := g.base_type(g.comptime_for_field_type)
|
||||
g.write('(*(${styp}*)${name}.data)')
|
||||
}
|
||||
} else {
|
||||
g.write('${name}')
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
// x ?int
|
||||
// `x = 10` => `x.data = 10` (g.right_is_opt == false)
|
||||
// `x = new_opt()` => `x = new_opt()` (g.right_is_opt == true)
|
||||
|
34
vlib/v/tests/optional_compvar_types_test.v
Normal file
34
vlib/v/tests/optional_compvar_types_test.v
Normal file
@ -0,0 +1,34 @@
|
||||
struct FixedStruct1 {
|
||||
a int
|
||||
b string
|
||||
}
|
||||
|
||||
struct FixedStruct2 {
|
||||
c ?int
|
||||
d ?string
|
||||
}
|
||||
|
||||
struct Writer {}
|
||||
|
||||
fn write1[T](val T) {
|
||||
println(val)
|
||||
}
|
||||
|
||||
fn (wr &Writer) write2[T](val T) {
|
||||
println(val)
|
||||
}
|
||||
|
||||
fn encode_struct[T](val T) bool {
|
||||
wr := Writer{}
|
||||
$for field in T.fields {
|
||||
value := val.$(field.name)
|
||||
write1(value)
|
||||
wr.write2(value)
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
fn test_main() {
|
||||
assert encode_struct(FixedStruct1{}) == true
|
||||
assert encode_struct(FixedStruct2{}) == true
|
||||
}
|
60
vlib/v/tests/optional_compvar_val_test.v
Normal file
60
vlib/v/tests/optional_compvar_val_test.v
Normal file
@ -0,0 +1,60 @@
|
||||
struct FixedStruct1 {
|
||||
a int
|
||||
b ?int
|
||||
c ?int = 4
|
||||
}
|
||||
|
||||
// struct FixedStruct2 {
|
||||
// b ?int
|
||||
// }
|
||||
|
||||
struct Encoder {}
|
||||
|
||||
struct Writer {}
|
||||
|
||||
fn write1[T](val T) {
|
||||
println(val)
|
||||
}
|
||||
|
||||
fn (wr &Writer) write2[T](val T) {
|
||||
println(val)
|
||||
}
|
||||
|
||||
fn encode_struct[T](val T) map[string][]string {
|
||||
wr := Writer{}
|
||||
mut out := map[string][]string{}
|
||||
$if T is $Struct {
|
||||
$for field in T.fields {
|
||||
value := val.$(field.name)
|
||||
$if field.typ is ?int {
|
||||
// work if comment lines 27 and 28
|
||||
write1(value)
|
||||
wr.write2(value)
|
||||
out[field.name] << '${value}'
|
||||
} $else {
|
||||
write1(value)
|
||||
wr.write2(value)
|
||||
out[field.name] << value.str()
|
||||
}
|
||||
// This work well
|
||||
$if field.is_optional {
|
||||
write1(value)
|
||||
wr.write2(value)
|
||||
out[field.name] << '${value}'
|
||||
} $else {
|
||||
write1(value)
|
||||
wr.write2(value)
|
||||
out[field.name] << value.str()
|
||||
}
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
fn test_main() {
|
||||
// cgen error: cannot convert 'struct _option_int' to 'int'
|
||||
out := encode_struct(FixedStruct1{})
|
||||
assert out['a'] == ['0', '0']
|
||||
assert out['b'] == ['0', '0']
|
||||
assert out['c'] == ['4', '4']
|
||||
}
|
Reference in New Issue
Block a user