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 {
|
if right is ast.ComptimeSelector {
|
||||||
left.obj.ct_type_var = .field_var
|
if is_decl {
|
||||||
left.obj.typ = c.comptime_fields_default_type
|
left.obj.ct_type_var = .field_var
|
||||||
|
left.obj.typ = c.comptime_fields_default_type
|
||||||
|
}
|
||||||
} else if right is ast.Ident
|
} else if right is ast.Ident
|
||||||
&& (right as ast.Ident).obj is ast.Var && (right as ast.Ident).or_expr.kind == .absent {
|
&& (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 {
|
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 {
|
} else if val is ast.ComptimeSelector {
|
||||||
key_str := g.get_comptime_selector_key_type(val)
|
key_str := g.get_comptime_selector_key_type(val)
|
||||||
if key_str != '' {
|
if key_str != '' {
|
||||||
var_type = g.comptime_var_type_map[key_str] or { var_type }
|
if is_decl {
|
||||||
val_type = var_type
|
var_type = g.comptime_var_type_map[key_str] or { var_type }
|
||||||
left.obj.typ = 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 {
|
} else if val is ast.ComptimeCall {
|
||||||
key_str := '${val.method_name}.return_type'
|
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 }
|
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 styp := g.typ(var_type)
|
||||||
mut is_fixed_array_init := false
|
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)
|
node_typ := g.unwrap_generic(node.typ)
|
||||||
mut expr_type := node.expr_type
|
mut expr_type := node.expr_type
|
||||||
sym := g.table.sym(node_typ)
|
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))
|
expr_type = g.unwrap_generic(g.get_comptime_var_type(node.expr))
|
||||||
}
|
}
|
||||||
if sym.kind in [.sum_type, .interface_] {
|
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…
x
Reference in New Issue
Block a user