Skip to content

proposal: isComptime builtin. #7539

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
lolbinarycat opened this issue Dec 24, 2020 · 17 comments
Closed

proposal: isComptime builtin. #7539

lolbinarycat opened this issue Dec 24, 2020 · 17 comments
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@lolbinarycat
Copy link

currently (as far as I know), there is no simple to get whether a value is known at compile time. For integer types, you can do @TypeOf(@clz(u8, val)) == comptime_int, but this is really more of a hack. Since this check already exists as part of @clz, it shouldn't be hard to implement into zig.

@lolbinarycat
Copy link
Author

originally I had the idea for a function that would take a value of type T and return a comptime ?T (which would be null if the value isn't comptime), but it turns out this isn't necessary, as this works:

    const foo = try std.io.getStdIn().reader().readByte();
    comptime {
        if (@TypeOf(@clz(u8, foo)) == comptime_int) {
            const bar = foo + 6;
        }
}

@Vexu
Copy link
Member

Vexu commented Dec 24, 2020

Duplicate of #868.

@Vexu Vexu closed this as completed Dec 24, 2020
@lolbinarycat
Copy link
Author

@Vexu that issue is about whether the function is being a called from a comptime block, while this issue is about telling whether a value is available at comptime, which aren't the same. while this proposal might help with the other issue, the opposite is not true.

@Vexu
Copy link
Member

Vexu commented Dec 24, 2020

A value will only be comptime if you explicitly make it so or the function is being executed at comptime when all values will be comptime meaning that an @areWeInComptime would also solve this.

@lolbinarycat
Copy link
Author

lolbinarycat commented Dec 24, 2020

@Vexu

A value will only be comptime if you explicitly make it so or the function is being executed at comptime when all values will be comptime meaning that an @areWeInComptime would also solve this.

This just isn't true at all...

const std = @import("std");

fn isComptime(val: anytype) bool {
    return @TypeOf(@clz(usize, val)) == comptime_int;
}

test "" {
    const foo = 4;
    comptime {
        std.testing.expect(isComptime(foo));
        _ = bar(foo);
    }
}

fn bar(val: usize) type {
    return [val]u8;
}

@Vexu
Copy link
Member

Vexu commented Dec 24, 2020

const foo = 4;is the same as const foo: comptime_int = 4, which makes it always comptime as does making a variable of type comptime_float or type.

@lolbinarycat
Copy link
Author

@Vexu Perhaps, but how do you explain this?

const std = @import("std");

fn isComptime(val: anytype) bool {
    return @TypeOf(@clz(usize, val)) == comptime_int;
}

test "" {
    const foo: usize = 4;
    comptime {
        std.testing.expect(isComptime(foo));
        _ = bar(foo);
    }
    _ = bar(foo);
}

fn bar(val: usize) type {
    return [val]u8;
}

@Vexu
Copy link
Member

Vexu commented Dec 24, 2020

If you declare a const variable with a comptime value, the variable will be comptime known since the compiler knows that you cannot change it to a non-comptime value. If you make it a var then it will be runtime known unless the function is running at comptime, same happens at container level except all values have to be initiated with comptime values.

@lolbinarycat
Copy link
Author

@Vexu, ok, but that doesn't change the fact that your original statement was wrong. My point is that in this case @areWeInComptime would be fairly unhelpful. It becomes even less helpful if you use multiple parameters in your function. They are separate issues, as they address separate problems.

@Vexu
Copy link
Member

Vexu commented Dec 24, 2020

bar not requiring comptime on val is a bug what would be fixed #5672.

@lolbinarycat
Copy link
Author

@Vexu usize is not a compile-only type though. Can you please just reopen the issue, these are clearly not the same thing.

@Vexu
Copy link
Member

Vexu commented Dec 24, 2020

I got that wrong but @areWeInComptime would tell that val is comptime.

@Vexu Vexu reopened this Dec 24, 2020
@Vexu Vexu added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Dec 24, 2020
@Vexu Vexu added this to the 0.9.0 milestone Dec 24, 2020
@andrewrk andrewrk modified the milestones: 0.9.0, 0.8.0 Dec 24, 2020
@andrewrk
Copy link
Member

Thanks for the proposal. It is planned to not have this builtin because the language intends for Zig programmers to write code that works both at comptime and runtime values. There is no need to explicitly check, and having such a builtin would lead to its use, making code needlessly more complex.

@lolbinarycat
Copy link
Author

@andrewrk

language intends for Zig programmers to write code that works both at comptime and runtime values.

The language also has operators that only work on comptime values, as well as lots of stuff that only works at runtime. Add to this the fact that it is already possible to tell if values are comptime by abusing @clz, and that plenty of builtins come with disclaimers discouraging their use. and I feel like this is a somewhat arbitrary line to draw.

@windows-h8r
Copy link

windows-h8r commented Jun 25, 2021

Possible use case: A more user-friendly implementation of std.debug.assert:

pub fn assert(condition: bool) void {
    if (!condition) {
        if (@isComptime()) {
            // because @panic(...) doesn't show the message at compile time
            @compileError("assertion failed");
        }

        switch (comptime std.builtin.mode) {
            .Debug, .ReleaseSafe => @panic("assertion failed"),
            .ReleaseFast, .ReleaseSmall => unreachable,
        }
    }
}

However, this could also be implemented using the @clz hack.

@gooncreeper

This comment was marked as off-topic.

@castholm
Copy link
Contributor

castholm commented Aug 12, 2024

@gooncreeper Just for the record, it's currently possible to discover whether or not a value is comptime-known by instantiating an anonymous tuple and reflecting on its fields, which in turn makes it possible to implement an isComptimeKnown function in user code like this:

const std = @import("std");
const expectEqual = std.testing.expectEqual;

inline fn isComptimeKnown(val: anytype) bool {
    return @typeInfo(@TypeOf(.{val})).Struct.fields[0].is_comptime;
}

test {
    const a: i32 = 15;
    try expectEqual(true, isComptimeKnown(a));

    var x: u64 = undefined;
    x = 15;
    try expectEqual(false, isComptimeKnown(x));
    try expectEqual(true, isComptimeKnown(x >= 0));
}

(Adapted from #868 (comment))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

No branches or pull requests

6 participants