1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: fix for..in statement with ComptimeSelector (#16997)

This commit is contained in:
Felipe Pena 2023-01-17 01:49:45 -03:00 committed by GitHub
parent f57b16a843
commit 1302dbf02f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 42 additions and 3 deletions

View File

@ -31,11 +31,19 @@ fn (mut c Checker) for_c_stmt(node ast.ForCStmt) {
c.in_for_count--
}
fn (mut c Checker) get_compselector_type_from_selector_name(node ast.ComptimeSelector) (bool, ast.Type) {
if c.inside_comptime_for_field && node.field_expr is ast.SelectorExpr
&& (node.field_expr as ast.SelectorExpr).expr.str() in c.comptime_fields_type
&& (node.field_expr as ast.SelectorExpr).field_name == 'name' {
return true, c.unwrap_generic(c.comptime_fields_default_type)
}
return false, ast.void_type
}
fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
c.in_for_count++
prev_loop_label := c.loop_label
typ := c.expr(node.cond)
typ_idx := typ.idx()
mut typ := c.expr(node.cond)
if node.key_var.len > 0 && node.key_var != '_' {
c.check_valid_snake_case(node.key_var, 'variable name', node.pos)
if reserved_type_names_chk.matches(node.key_var) {
@ -49,6 +57,7 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
}
}
if node.is_range {
typ_idx := typ.idx()
high_type := c.expr(node.high)
high_type_idx := high_type.idx()
if typ_idx in ast.integer_type_idxs && high_type_idx !in ast.integer_type_idxs
@ -75,12 +84,19 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
node.high_type = high_type
node.scope.update_var_type(node.val_var, node.val_type)
} else {
sym := c.table.final_sym(typ)
mut sym := c.table.final_sym(typ)
if sym.kind != .string {
match mut node.cond {
ast.PrefixExpr {
node.val_is_ref = node.cond.op == .amp
}
ast.ComptimeSelector {
found, selector_type := c.get_compselector_type_from_selector_name(node.cond)
if found {
sym = c.table.final_sym(selector_type)
typ = selector_type
}
}
ast.Ident {
match mut node.cond.info {
ast.IdentVar {

View File

@ -0,0 +1,23 @@
struct Test {
b ?[]int
}
fn call_generic[U](val U) int {
mut out := 0
$for field in U.fields {
variable := val.$(field.name)
println(variable)
for element in val.$(field.name) {
dump(element)
out += element
}
}
return out
}
fn test_main() {
test := Test{
b: [1, 2, 3]
}
assert call_generic(test) == 6
}