From 537b0015c40e31a875d70e02797e8bf8a966b0ee Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sun, 24 May 2026 16:23:00 +0300 Subject: [PATCH] cgen: fix string interpolation of `for mut item in []string` (fix #27122) (#27232) --- vlib/v/gen/c/str_intp.v | 19 +++++++++++++++++++ .../inout/printing_for_mut_string_27122.out | 9 +++++++++ .../inout/printing_for_mut_string_27122.vv | 11 +++++++++++ 3 files changed, 39 insertions(+) create mode 100644 vlib/v/slow_tests/inout/printing_for_mut_string_27122.out create mode 100644 vlib/v/slow_tests/inout/printing_for_mut_string_27122.vv diff --git a/vlib/v/gen/c/str_intp.v b/vlib/v/gen/c/str_intp.v index 93911faaf..0785649d1 100644 --- a/vlib/v/gen/c/str_intp.v +++ b/vlib/v/gen/c/str_intp.v @@ -726,6 +726,25 @@ fn (mut g Gen) string_inter_literal(node ast.StringInterLiteral) { fmts[i] = g.get_default_fmt(field_typ, field_typ) } } + } else if g.expr_is_auto_deref_var(expr_) && field_typ.is_ptr() + && !field_typ.has_flag(.option) && !field_typ.has_flag(.shared_f) { + // `for mut x in arr` loop variables surface in C as pointers + // (e.g. `string*`), but `${x}` should interpolate the + // underlying value. Pick the format specifier from the + // dereferenced element type so it lands in the `%s` path + // instead of falling through to `%p`. The pointer type is + // preserved in expr_types so `str_val` still emits the + // required `*` when reading the value. + if !node_.need_fmts[i] { + deref_typ := field_typ.deref() + ftyp_sym := g.table.sym(deref_typ) + new_typ := if ftyp_sym.kind == .alias && !ftyp_sym.has_method('str') { + g.table.unalias_num_type(deref_typ) + } else { + deref_typ + } + fmts[i] = g.get_default_fmt(deref_typ, new_typ) + } } } else {} diff --git a/vlib/v/slow_tests/inout/printing_for_mut_string_27122.out b/vlib/v/slow_tests/inout/printing_for_mut_string_27122.out new file mode 100644 index 000000000..469d7baab --- /dev/null +++ b/vlib/v/slow_tests/inout/printing_for_mut_string_27122.out @@ -0,0 +1,9 @@ +item value: alpha +item after: CHANGED_alpha +item value: beta +item after: CHANGED_beta +item value: gamma +item after: CHANGED_gamma +CHANGED_alpha +CHANGED_beta +CHANGED_gamma diff --git a/vlib/v/slow_tests/inout/printing_for_mut_string_27122.vv b/vlib/v/slow_tests/inout/printing_for_mut_string_27122.vv new file mode 100644 index 000000000..b3d74fea6 --- /dev/null +++ b/vlib/v/slow_tests/inout/printing_for_mut_string_27122.vv @@ -0,0 +1,11 @@ +fn main() { + mut items := ['alpha', 'beta', 'gamma'] + for mut item in items { + println('item value: ${item}') + item = 'CHANGED_${item}' + println('item after: ${item}') + } + for item in items { + println(item) + } +} -- 2.39.5