Skip to content

closure defined inside comptime $for uses first iterations value for every iteration #25513

Description

@choltreppe

Describe the bug

when you write a $for loop over e.g. a structs fields and there is a closure definition which uses the field in its body it will always use the first field for every iteration

Reproduction Steps

a kinda stupid example just to keep it simple:

struct TestObj {
mut:
  a int
  b int
}

fn main() {
  x := &TestObj{a: 1, b: 1}
  $for field in TestObj.fields {
    run_fn(fn[x, field] () {
      (*x).$(field.name) += 1
    })
  }
  println(x)
}

fn run_fn(f fn()) {
  f()
}

Expected Behavior

&TestObj{
    a: 2
    b: 2
}

Current Behavior

&TestObj{
    a: 3
    b: 1
}

Possible Solution

I inspected the generated c code, and I think the problem is that every iterations closure uses the same function. which is that of the first iteration (that updates the first field)

the closure defs:

/* field 0 : a */ {
	...
	main__run_fn((voidptr)			builtin__closure__closure_create(anon_fn_8ce6aadc8523cb25__141, (struct _V_anon_fn_8ce6aadc8523cb25__141_Ctx*) builtin__memdup_uncollectable(&(struct _V_anon_fn_8ce6aadc8523cb25__141_Ctx){.x = x,
		.field = field,
	}, sizeof(struct _V_anon_fn_8ce6aadc8523cb25__141_Ctx))));
}
...
/* field 1 : b */ {
	...
	main__run_fn((voidptr)builtin__closure__closure_create(anon_fn_8ce6aadc8523cb25__141, (struct _V_anon_fn_8ce6aadc8523cb25__141_Ctx*) builtin__memdup_uncollectable(&(struct _V_anon_fn_8ce6aadc8523cb25__141_Ctx){.x = x,
		.field = field,
	}, sizeof(struct _V_anon_fn_8ce6aadc8523cb25__141_Ctx))));
}

both reference:

// V anon functions:
VV_LOC void anon_fn_8ce6aadc8523cb25__141(void) {
			struct _V_anon_fn_8ce6aadc8523cb25__141_Ctx* _V_closure_ctx = g_closure.closure_get_data();
	(*_V_closure_ctx->x).a += 1;
}

which updates field a

Additional Information/Context

No response

V version

V 0.4.12 e5a5f02

Environment details (OS name and version, etc.)

V full version V 0.4.12 8342968.e5a5f02
OS linux, "Arch Linux"
Processor 16 cpus, 64bit, little endian, AMD Ryzen 7 5800X 8-Core Processor
Memory 54.92GB/62.71GB
V executable /home/chol/bin/vlang/v
V last modified time 2025-10-16 00:10:49
V home dir OK, value: /home/chol/bin/vlang
VMODULES OK, value: /home/chol/.vmodules
VTMP OK, value: /tmp/v_1003
Current working dir OK, value: /home/chol/Documents
Git version git version 2.51.0
V git status weekly.2025.42-13-ge5a5f027
.git/config present true
cc version cc (GCC) 15.2.1 20250813
gcc version gcc (GCC) 15.2.1 20250813
clang version clang version 20.1.8
tcc version tcc version 0.9.28rc 2025-02-13 HEAD@f8bd136d (x86_64 Linux)
tcc git status thirdparty-linux-amd64 696c1d84
emcc version N/A
glibc version ldd (GNU libc) 2.42

Note

You can use the 👍 reaction to increase the issue's priority for developers.

Please note that only the 👍 reaction to the issue itself counts as a vote.
Other reactions and those to comments will not be taken into account.

Metadata

Metadata

Assignees

Labels

BugThis tag is applied to issues which reports bugs.ComptimeFeatures processed during compile time, like $if, $for, $env etcStatus: ConfirmedThis bug has been confirmed to be valid by a contributor.Unit: CompilerBugs/feature requests, that are related to the V compiler in general.Unit: cgenBugs/feature requests, that are related to the default C generating backend.

Type

No fields configured for Bug.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions