Skip to content
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

Add ability to determine if we are currently executing at compile time #868

Closed
tiehuis opened this issue Mar 30, 2018 · 5 comments · Fixed by #15290
Closed

Add ability to determine if we are currently executing at compile time #868

tiehuis opened this issue Mar 30, 2018 · 5 comments · Fixed by #15290
Labels
accepted This proposal is planned. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Milestone

Comments

@tiehuis
Copy link
Member

tiehuis commented Mar 30, 2018

I'm sure this was mentioned somewhere but could not find an issue: The gist is as follows:

if (@areWeInComptime()) {
   // use a slow fallback which we can compute in zig
} else {
   // use a fast runtime version that uses assembly (or features not supported at comptime)
}

This is present in D for example via the __ctfe variable. The current reason I need this is that I want to call sqrt at compile-time but on x86_64 this uses an assembly routine which can not be evaluated at compile-time.

@tiehuis tiehuis added the proposal This issue suggests modifications. If it also has the "accepted" label then it is planned. label Mar 30, 2018
@andrewrk
Copy link
Member

I think this makes sense. One thing I want to avoid though is over-reliance on this. In most cases we should strive to make the runtime and comptime representation the same. Something that I never want to see is a function that could have been perfectly fine executing in both comptime and runtime contexts, but somebody didn't think that was possible and did something like if (@areWeInComptime()) @compileError("unsupported").

In the case of inline assembly for sqrt, see #767

@andrewrk andrewrk added this to the 0.4.0 milestone Mar 30, 2018
@tiehuis
Copy link
Member Author

tiehuis commented Mar 30, 2018

Completely agree on not over-relying on this. I did forget about the llvm math intrinsics. I'm happy enough to hold of on this for now until we get other possible use cases that require something of this sort.

@andrewrk
Copy link
Member

andrewrk commented Oct 4, 2018

It's kind of a dirty secret that this is possible, but...

const std = @import("std");

test "detect comptime" {
    std.debug.warn("\n");
    std.debug.warn("1={}\n", isCompTime());
    std.debug.warn("2={}\n", comptime isCompTime());
    std.debug.warn("3={}\n", comptime isCompTime());
    std.debug.warn("4={}\n", isCompTime());
}

fn isCompTime() bool {
    var t: bool = true;
    const x = if (t) u7(0) else u8(0);
    return @typeOf(x) == u7;
}

Don't rely on this - zig reserves the right to make the if static if it can prove the value is compile-time known (which it should be able to do in this example with more sophisticated semantic analysis).

@jibal
Copy link

jibal commented Mar 26, 2022

Don't rely on this - zig reserves the right to make the if static if it can prove the value is compile-time known (which it should be able to do in this example with more sophisticated semantic analysis).

Having to rely on it is even worse than the possibility of abusing @areWeInComptime().
(And now it doesn't work but there's no apparent workaround. I think that it would have been a really good idea to add @areWeInComptime to the language when this stopped working.)

In most cases we should strive to make the runtime and comptime representation the same.

Sure, but there are things that are ok at comptime but produce errors or even crashes at runtime and v.v. (consider the existence of comptimePrint), and one needs to detect them in order to write complex generic code (which I'm in the process of doing and finding a number of roadblocks, like the lack of implementation of #425, which is forcing extreme awkwardness in my API; I have dozens of functions that always operate at comptime and they all have to be explicitly qualified with comptime at the call site and every one is a potential bug ... so I have changed them to return a type (a struct with a const containing the actual value) or comptime_int rather than bool (mostly) ... why can't we simply declare a function to return comptime bool?

Another example, pointed out in #5672, is the error message "error: variable of type 'T' must be const or comptime". The existence of such errors makes it necessary to be able to detect whether they will occur in generic functions. Personally I would prefer if there were no such errors ... if the type makes the variable comptime then the compiler should just make it comptime. Write enough generic code and you'll see why this should be the case. And if that requires a while or for to be inline, then the compiler should just make it so. Otherwise you have to write two (or more) versions of generic functions, one for comptime arguments and one for runtime arguments. Either do this always or allow an explicit declaration saying that this is generic code that should work in either case.

Edit: example: functions like std.mem.copy don't work on a slice of comptime_int or other comptime types. ("error: values of type 'comptime_int' must be comptime known, but index value is runtime known")

There's tension/conflict between generic functions and Zig's principle of being explicit. Generic functions may operate very differently and produce code with very different characteristics depending on the types of its arguments. Requiring explicit comptime and inline qualifiers rather than inferring them may be fine for forcing end-users to know what's going on, but this approach doesn't apply or work correctly for generic functions,

@topolarity
Copy link
Contributor

topolarity commented Aug 1, 2022

There's another dirty trick possible with stage2's inline semantics:

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

test {
    const a: i32 = 15;
    @compileLog(isComptime(a)); // true
    
    var x: u64 = 15;
    @compileLog(isComptime(x)); // false
    @compileLog(isComptime(x >= 0)); // true
}

Compared to the code above, this one seems guaranteed to work as expected even as semantic analysis improves.

If we don't want this to work, that probably requires a solution to #12261

topolarity added a commit to topolarity/zig that referenced this issue Oct 28, 2022
Comptime code can't execute assembly code, so we need some way to
force comptime code to use the generic path. This should be replaced
with whatever is implemented for ziglang#868, when that day comes.

I am seeing that the result for the hash is incorrect in stage1 and
crashes stage2, so presumably this never worked correctly. I will follow
up on that soon.
topolarity added a commit to topolarity/zig that referenced this issue Oct 28, 2022
Comptime code can't execute assembly code, so we need some way to
force comptime code to use the generic path. This should be replaced
with whatever is implemented for ziglang#868, when that day comes.

I am seeing that the result for the hash is incorrect in stage1 and
crashes stage2, so presumably this never worked correctly. I will follow
up on that soon.
@andrewrk andrewrk modified the milestones: 0.11.0, 0.12.0 Apr 9, 2023
mlugg added a commit to mlugg/zig that referenced this issue Apr 14, 2023
mlugg added a commit to mlugg/zig that referenced this issue Apr 15, 2023
mlugg added a commit to mlugg/zig that referenced this issue Apr 15, 2023
mlugg added a commit to mlugg/zig that referenced this issue Apr 15, 2023
mlugg added a commit to mlugg/zig that referenced this issue Apr 15, 2023
mlugg added a commit to mlugg/zig that referenced this issue Apr 17, 2023
mlugg added a commit to mlugg/zig that referenced this issue Apr 21, 2023
@andrewrk andrewrk added the accepted This proposal is planned. label Apr 22, 2023
@andrewrk andrewrk modified the milestones: 0.12.0, 0.11.0 Apr 22, 2023
andrewrk pushed a commit to mlugg/zig that referenced this issue Apr 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
accepted This proposal is planned. proposal This issue suggests modifications. If it also has the "accepted" label then it is planned.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants