Skip to content

comptime-evaluated functions #26475

@dy-tea

Description

@dy-tea

Describe the feature

I would like functions that can be evaluated at comptime, designated by a @[comptime] attribute.

@[comptime]
fn color(r u8, g u8, b u8, a u8) u32 {
    return u32(r) << 24 + u32(r) << 16 + u32(b) << 8 + u32(a)
}

enum Colors : u32 {
    red = color(255, 0, 0, 255)
    green = color(0, 255, 0, 255)
    blue = color(0, 0, 255, 255)
}

Could allow something like the above.

Use Case

Another use case is in comptime, for example the current way you could emulate the container_of macro in V is the following:

pub fn container_of[T](ptr voidptr, member_name string) &T {
	$if T is $struct && T !is $string {
		return unsafe { &T(&char(ptr) - offsetof[T](member_name)) }
	} $else {
		$compile_error('T is not of type struct')
	}
}

pub fn offsetof[T](member_name string) int {
	tmp := &T{}
	$if T is $struct {
		$for field in T.fields {
			if field.name == member_name {
				access := int(voidptr(&tmp.$(field.name)))
				return access - int(tmp)
			}
		}
	} $else {
		$compile_error('offsetof only accepts struct types')
	}
	return 0
}

Notice that offsetof needs to loop for all fields in T in order to find the one that matches member_name which adds unnecessary runtime. Since we need to call offsetof inside this function with different types, we cannot have a fixed member name, as this may differ depending on where you call container_of from.

Below is how it could look with @[comptime]:

@[comptime]
pub fn offsetof[T](member_name string) usize {
	unsafe {
		return usize(
			&char(&T{}.$(member_name)) - &char(0)
		)
	}
}

Notice that member_name is used as a constant and replaced as the member name of T. We are calculating the offset of the member named member_name from the start of the pointer. There is no need to loop here as this can be checked at compile-time anyway (given that member_name is a constant).

Proposed Solution

I quick way to implement this would be to "simulate" each function in V repl and insert the constant output in place of the function call.

Other Information

For my second example you could probably implement something comptime if in like:

struct Foo {
    bar string
    member int
}

const a := 'member'

foo := Foo{
    bar: 'hello'
    member: 42
}

$if field := a $in Foo.fields {
    println(foo.$(field.name))
}

Acknowledgements

  • I may be able to implement this feature request
  • This feature might incur a breaking change

Version used

V 0.5.0 50a7d53

Environment details (OS name and version, etc.)

V full version V 0.5.0 a965a39.50a7d53
OS linux, "CachyOS"
Processor 12 cpus, 64bit, little endian, 13th Gen Intel(R) Core(TM) i5-1335U
Memory 5.32GB/15.31GB
V executable /home/dylan/Repos/v/v
V last modified time 2026-01-28 17:56:57
V home dir OK, value: /home/dylan/Repos/v
VMODULES OK, value: /home/dylan/.vmodules
VTMP OK, value: /tmp/v_1000
Current working dir OK, value: /home/dylan
Git version git version 2.52.0
V git status weekly.2026.02-182-g50a7d536
.git/config present true
cc version cc (GCC) 15.2.1 20260103
gcc version gcc (GCC) 15.2.1 20260103
clang version clang version 21.1.6
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

No one assigned

    Labels

    Feature/Enhancement RequestThis issue is made to request a feature or an enhancement to an existing one.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions