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:
parent
f57b16a843
commit
1302dbf02f
@ -31,11 +31,19 @@ fn (mut c Checker) for_c_stmt(node ast.ForCStmt) {
|
|||||||
c.in_for_count--
|
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) {
|
fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) {
|
||||||
c.in_for_count++
|
c.in_for_count++
|
||||||
prev_loop_label := c.loop_label
|
prev_loop_label := c.loop_label
|
||||||
typ := c.expr(node.cond)
|
mut typ := c.expr(node.cond)
|
||||||
typ_idx := typ.idx()
|
|
||||||
if node.key_var.len > 0 && node.key_var != '_' {
|
if node.key_var.len > 0 && node.key_var != '_' {
|
||||||
c.check_valid_snake_case(node.key_var, 'variable name', node.pos)
|
c.check_valid_snake_case(node.key_var, 'variable name', node.pos)
|
||||||
if reserved_type_names_chk.matches(node.key_var) {
|
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 {
|
if node.is_range {
|
||||||
|
typ_idx := typ.idx()
|
||||||
high_type := c.expr(node.high)
|
high_type := c.expr(node.high)
|
||||||
high_type_idx := high_type.idx()
|
high_type_idx := high_type.idx()
|
||||||
if typ_idx in ast.integer_type_idxs && high_type_idx !in ast.integer_type_idxs
|
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.high_type = high_type
|
||||||
node.scope.update_var_type(node.val_var, node.val_type)
|
node.scope.update_var_type(node.val_var, node.val_type)
|
||||||
} else {
|
} else {
|
||||||
sym := c.table.final_sym(typ)
|
mut sym := c.table.final_sym(typ)
|
||||||
if sym.kind != .string {
|
if sym.kind != .string {
|
||||||
match mut node.cond {
|
match mut node.cond {
|
||||||
ast.PrefixExpr {
|
ast.PrefixExpr {
|
||||||
node.val_is_ref = node.cond.op == .amp
|
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 {
|
ast.Ident {
|
||||||
match mut node.cond.info {
|
match mut node.cond.info {
|
||||||
ast.IdentVar {
|
ast.IdentVar {
|
||||||
|
23
vlib/v/tests/for_comptime_selector_test.v
Normal file
23
vlib/v/tests/for_comptime_selector_test.v
Normal 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
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user