mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
cgen: fix typeof with comptime var (#16816)
This commit is contained in:
parent
15c9153f1d
commit
5daf39bc6a
@ -3549,6 +3549,22 @@ fn (mut g Gen) typeof_expr(node ast.TypeOf) {
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut g Gen) comptime_typeof(node ast.TypeOf, default_type ast.Type) ast.Type {
|
||||
if node.expr is ast.ComptimeSelector {
|
||||
if node.expr.field_expr is ast.SelectorExpr {
|
||||
if node.expr.field_expr.expr is ast.Ident {
|
||||
key_str := '${node.expr.field_expr.expr.name}.typ'
|
||||
return g.comptime_var_type_map[key_str] or { default_type }
|
||||
}
|
||||
}
|
||||
} else if g.inside_comptime_for_field && node.expr is ast.Ident
|
||||
&& (node.expr as ast.Ident).obj is ast.Var && ((node.expr as ast.Ident).obj as ast.Var).is_comptime_field == true {
|
||||
// typeof(var) from T.fields
|
||||
return g.comptime_for_field_type
|
||||
}
|
||||
return default_type
|
||||
}
|
||||
|
||||
fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
||||
prevent_sum_type_unwrapping_once := g.prevent_sum_type_unwrapping_once
|
||||
g.prevent_sum_type_unwrapping_once = false
|
||||
@ -3568,20 +3584,17 @@ fn (mut g Gen) selector_expr(node ast.SelectorExpr) {
|
||||
// typeof(expr).name
|
||||
mut name_type := node.name_type
|
||||
if node.expr is ast.TypeOf {
|
||||
if node.expr.expr is ast.ComptimeSelector {
|
||||
if node.expr.expr.field_expr is ast.SelectorExpr {
|
||||
if node.expr.expr.field_expr.expr is ast.Ident {
|
||||
key_str := '${node.expr.expr.field_expr.expr.name}.typ'
|
||||
name_type = g.comptime_var_type_map[key_str] or { name_type }
|
||||
}
|
||||
}
|
||||
}
|
||||
name_type = g.comptime_typeof(node.expr, name_type)
|
||||
}
|
||||
g.type_name(name_type)
|
||||
return
|
||||
} else if node.field_name == 'idx' {
|
||||
mut name_type := node.name_type
|
||||
if node.expr is ast.TypeOf {
|
||||
name_type = g.comptime_typeof(node.expr, name_type)
|
||||
}
|
||||
// `typeof(expr).idx`
|
||||
g.write(int(g.unwrap_generic(node.name_type)).str())
|
||||
g.write(int(g.unwrap_generic(name_type)).str())
|
||||
return
|
||||
}
|
||||
g.error('unknown generic field', node.pos)
|
||||
|
41
vlib/v/tests/comptime_for_in_field_typeof_test.v
Normal file
41
vlib/v/tests/comptime_for_in_field_typeof_test.v
Normal file
@ -0,0 +1,41 @@
|
||||
struct Ab {
|
||||
a []int
|
||||
}
|
||||
|
||||
struct ComplexStruct {
|
||||
a int
|
||||
b []Ab
|
||||
c string
|
||||
d map[string]int
|
||||
}
|
||||
|
||||
fn test_typeof_in_comptime_for_in_fields() {
|
||||
out := encode_struct(ComplexStruct{})
|
||||
dump(out)
|
||||
assert out[0] == 'a'
|
||||
assert out[1] == typeof[int]().idx.str()
|
||||
assert out[2] == 'int'
|
||||
|
||||
assert out[3] == 'b'
|
||||
assert out[4] == typeof[[]Ab]().idx.str()
|
||||
assert out[5] == '[]Ab'
|
||||
|
||||
assert out[6] == 'c'
|
||||
assert out[7] == typeof[string]().idx.str()
|
||||
assert out[8] == 'string'
|
||||
|
||||
assert out[9] == 'd'
|
||||
assert out[10] == typeof[map[string]int]().idx.str()
|
||||
assert out[11] == 'map[string]int'
|
||||
}
|
||||
|
||||
fn encode_struct[T](val T) []string {
|
||||
mut out := []string{}
|
||||
$for field in T.fields {
|
||||
value := val.$(field.name)
|
||||
out << field.name
|
||||
out << typeof(value).idx.str()
|
||||
out << typeof(value).name
|
||||
}
|
||||
return out
|
||||
}
|
Loading…
Reference in New Issue
Block a user