1
0
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:
Felipe Pena 2022-12-31 10:57:55 -03:00 committed by GitHub
parent 15c9153f1d
commit 5daf39bc6a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 63 additions and 9 deletions

View File

@ -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)

View 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
}