From 6f46fc217021a8351263659c1066b2866aa5e8d8 Mon Sep 17 00:00:00 2001 From: yuyi Date: Wed, 24 Nov 2021 20:43:37 +0800 Subject: [PATCH] checker, cgen: fix for_in_mut iterator val (#12563) --- vlib/v/checker/checker.v | 14 +++++- vlib/v/gen/c/cgen.v | 2 +- vlib/v/tests/for_in_mut_iterator_val_test.v | 50 +++++++++++++++++++++ 3 files changed, 63 insertions(+), 3 deletions(-) create mode 100644 vlib/v/tests/for_in_mut_iterator_val_test.v diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index b7bd3e4320..74368d7ee8 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3395,7 +3395,14 @@ pub fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type { old_selector_expr := c.inside_selector_expr c.inside_selector_expr = true - typ := c.expr(node.expr) + mut typ := c.expr(node.expr) + if node.expr.is_auto_deref_var() { + if mut node.expr is ast.Ident { + if mut node.expr.obj is ast.Var { + typ = node.expr.obj.typ + } + } + } c.inside_selector_expr = old_selector_expr c.using_new_err_struct = using_new_err_struct_save if typ == ast.void_type_idx { @@ -4857,7 +4864,10 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) { if next_fn.params.len != 1 { c.error('iterator method `next()` must have 0 parameters', node.cond.position()) } - val_type := next_fn.return_type.clear_flag(.optional) + mut val_type := next_fn.return_type.clear_flag(.optional) + if node.val_is_mut { + val_type = val_type.ref() + } node.cond_type = typ node.kind = sym.kind node.val_type = val_type diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index bed5065f31..1a06979ca1 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -2183,7 +2183,7 @@ fn (mut g Gen) for_in_stmt(node ast.ForInStmt) { val := if node.val_var in ['', '_'] { g.new_tmp_var() } else { node.val_var } val_styp := g.typ(node.val_type) if node.val_is_mut { - g.writeln('\t$val_styp* $val = ($val_styp*)${t_var}.data;') + g.writeln('\t$val_styp $val = ($val_styp)${t_var}.data;') } else { g.writeln('\t$val_styp $val = *($val_styp*)${t_var}.data;') } diff --git a/vlib/v/tests/for_in_mut_iterator_val_test.v b/vlib/v/tests/for_in_mut_iterator_val_test.v new file mode 100644 index 0000000000..bce8752770 --- /dev/null +++ b/vlib/v/tests/for_in_mut_iterator_val_test.v @@ -0,0 +1,50 @@ +const ( + packets = { + 0: &Packet{ + pid: 2 + } + 1: &Packet{ + pid: 1 + } + } +) + +struct Packet { + pid int + handle fn () string + restricted bool +} + +struct Reader { + foo int + bar string +mut: + index int +} + +fn (mut p Reader) next() ?&Packet { + if p.index + 1 > packets.len { + return error('') + } + if p.index !in packets { + return error('') + } + + p.index++ + return packets[p.index - 1] +} + +fn test_for_in_mut_interator_val() { + r := Reader{} + mut rets := []string{} + + for mut packet in r { + println(packet.pid) + rets << '$packet.pid' + } + + println(rets) + assert rets.len == 2 + assert rets[0] == '2' + assert rets[1] == '1' +}