mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen, checker: fix comptime assigning to sumtype or indexexpr (#18240)
This commit is contained in:
parent
e2f18fc9cc
commit
37618c9465
@ -336,8 +336,10 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
||||
}
|
||||
}
|
||||
if right is ast.ComptimeSelector {
|
||||
left.obj.ct_type_var = .field_var
|
||||
left.obj.typ = c.comptime_fields_default_type
|
||||
if is_decl {
|
||||
left.obj.ct_type_var = .field_var
|
||||
left.obj.typ = c.comptime_fields_default_type
|
||||
}
|
||||
} else if right is ast.Ident
|
||||
&& (right as ast.Ident).obj is ast.Var && (right as ast.Ident).or_expr.kind == .absent {
|
||||
if ((right as ast.Ident).obj as ast.Var).ct_type_var != .no_comptime {
|
||||
|
@ -238,9 +238,13 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
||||
} else if val is ast.ComptimeSelector {
|
||||
key_str := g.get_comptime_selector_key_type(val)
|
||||
if key_str != '' {
|
||||
var_type = g.comptime_var_type_map[key_str] or { var_type }
|
||||
val_type = var_type
|
||||
left.obj.typ = var_type
|
||||
if is_decl {
|
||||
var_type = g.comptime_var_type_map[key_str] or { var_type }
|
||||
val_type = var_type
|
||||
left.obj.typ = var_type
|
||||
} else {
|
||||
val_type = g.comptime_var_type_map[key_str] or { var_type }
|
||||
}
|
||||
}
|
||||
} else if val is ast.ComptimeCall {
|
||||
key_str := '${val.method_name}.return_type'
|
||||
@ -283,6 +287,11 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
||||
val_type = g.comptime_var_type_map[key_str_right] or { var_type }
|
||||
}
|
||||
}
|
||||
} else if mut left is ast.IndexExpr && val is ast.ComptimeSelector {
|
||||
key_str := g.get_comptime_selector_key_type(val)
|
||||
if key_str != '' {
|
||||
val_type = g.comptime_var_type_map[key_str] or { var_type }
|
||||
}
|
||||
}
|
||||
mut styp := g.typ(var_type)
|
||||
mut is_fixed_array_init := false
|
||||
|
@ -4263,7 +4263,7 @@ fn (mut g Gen) cast_expr(node ast.CastExpr) {
|
||||
node_typ := g.unwrap_generic(node.typ)
|
||||
mut expr_type := node.expr_type
|
||||
sym := g.table.sym(node_typ)
|
||||
if node.expr is ast.Ident && g.is_comptime_var(node.expr) {
|
||||
if (node.expr is ast.Ident && g.is_comptime_var(node.expr)) || node.expr is ast.ComptimeSelector {
|
||||
expr_type = g.unwrap_generic(g.get_comptime_var_type(node.expr))
|
||||
}
|
||||
if sym.kind in [.sum_type, .interface_] {
|
||||
|
38
vlib/v/tests/comptime_sumtype_cast_2_test.v
Normal file
38
vlib/v/tests/comptime_sumtype_cast_2_test.v
Normal file
@ -0,0 +1,38 @@
|
||||
pub type Any = bool | int | map[string]Any | string
|
||||
|
||||
struct StructType[T] {
|
||||
mut:
|
||||
val T
|
||||
}
|
||||
|
||||
fn map_from[T](t T) Any {
|
||||
mut value := Any{}
|
||||
$if T is $struct {
|
||||
$for field in T.fields {
|
||||
println(t.$(field.name))
|
||||
value = t.$(field.name)
|
||||
value = Any(t.$(field.name))
|
||||
}
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
fn test_generic_struct_with_sumtype() {
|
||||
struct_type := StructType[string]{
|
||||
val: 'true'
|
||||
}
|
||||
struct_type2 := StructType[int]{
|
||||
val: 1
|
||||
}
|
||||
array_of_struct := [struct_type, struct_type]
|
||||
|
||||
for variable in array_of_struct {
|
||||
assert map_from(variable) == Any('true')
|
||||
}
|
||||
|
||||
array_of_struct2 := [struct_type2, struct_type2]
|
||||
|
||||
for variable in array_of_struct2 {
|
||||
assert map_from(variable) == Any(1)
|
||||
}
|
||||
}
|
61
vlib/v/tests/comptime_sumtype_cast_3_test.v
Normal file
61
vlib/v/tests/comptime_sumtype_cast_3_test.v
Normal file
@ -0,0 +1,61 @@
|
||||
pub type Any = bool | int | map[string]Any | string
|
||||
|
||||
struct StructType[T] {
|
||||
mut:
|
||||
val T
|
||||
}
|
||||
|
||||
fn map_from[T](t T) map[string]Any {
|
||||
mut m := map[string]Any{}
|
||||
$if T is $struct {
|
||||
$for field in T.fields {
|
||||
key := field.name
|
||||
m[key] = t.$(field.name)
|
||||
}
|
||||
}
|
||||
return m
|
||||
}
|
||||
|
||||
fn test_struct_to_map_string() {
|
||||
array_of_struct := [StructType[string]{
|
||||
val: 'true'
|
||||
}, StructType[string]{
|
||||
val: 'false'
|
||||
}]
|
||||
|
||||
mut array_of_map := []Any{}
|
||||
|
||||
for variable in array_of_struct {
|
||||
array_of_map << map_from(variable)
|
||||
}
|
||||
|
||||
println(array_of_map)
|
||||
assert array_of_map[0] == Any({
|
||||
'val': Any('true')
|
||||
})
|
||||
assert array_of_map[1] == Any({
|
||||
'val': Any('false')
|
||||
})
|
||||
}
|
||||
|
||||
fn test_struct_to_map_bool() {
|
||||
array_of_struct := [StructType[bool]{
|
||||
val: true
|
||||
}, StructType[bool]{
|
||||
val: false
|
||||
}]
|
||||
|
||||
mut array_of_map := []Any{}
|
||||
|
||||
for variable in array_of_struct {
|
||||
array_of_map << map_from(variable)
|
||||
}
|
||||
|
||||
println(array_of_map)
|
||||
assert array_of_map[0] == Any({
|
||||
'val': Any(true)
|
||||
})
|
||||
assert array_of_map[1] == Any({
|
||||
'val': Any(false)
|
||||
})
|
||||
}
|
Loading…
Reference in New Issue
Block a user