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

comptime keyword used with runtime-known identifier fails to produce a compile error #2471

Closed
ghost opened this issue May 11, 2019 · 4 comments
Labels
bug Observed behavior contradicts documented or intended behavior frontend Tokenization, parsing, AstGen, Sema, and Liveness.
Milestone

Comments

@ghost
Copy link

ghost commented May 11, 2019

fn hasField() bool {
    return false;
}

test "" {
    var x: u32 = 123; // runtime value

    // what i'm trying to do:
    if (comptime hasField()) {
      if (x == 123) {
        @compileError("A"); // this won't happen
      }
    }

    // this works as above, although it's weird and ambiguous to read
    if (comptime hasField() and x == 123) {
        @compileError("B"); // this won't happen
    }

    // this does not work as above. `comptime` seems to be ignored.
    if (x == 123 and comptime hasField()) {
        @compileError("C"); // this happens
    }
}

Output:

/home/dbandstra/zang/test.zig:22:9: error: C
        @compileError("C"); // this happens
        ^

Disclaimer: I don't actually know how this comptime thing works. I don't think it's even documented? Is it an official feature? (I find it useful.)

In the above test, I'm not sure what I expect to happen. In the first condition, comptime hasField() and x == 123, I don't whether comptime is supposed to apply to the first term or to the whole expression.

But in any case, I think there should be a compile error if a comptime is not going to be applied.

    var x: u32 = 123; // runtime value

    if (comptime x == 123) {
        std.debug.warn("why am i allowed to do this? what does it mean?\n");
    }
    var x: u32 = 123; // runtime value

    if (comptime x == 123 and comptime hasField()) {
        @compileError("huh?"); // this happens
    }
/home/dbandstra/zang/test.zig:9:20: error: unable to evaluate constant expression
    if (comptime x == 123 and comptime hasField()) {
                   ^
@andrewrk andrewrk added this to the 0.5.0 milestone May 12, 2019
@andrewrk andrewrk modified the milestones: 0.5.0, 0.6.0 Sep 20, 2019
@andrewrk
Copy link
Member

andrewrk commented Jan 5, 2020

Here's what's happening in each of your examples:

    if (comptime hasField()) {

comptime causes hasField to be evaluated at compile-time. Result is a compile-time known bool. The if is evaluated at compile-time.

    if (comptime hasField() and x == 123) {

Perhaps related to #114, this is parsed as (comptime hasField()) and x == 123 and not comptime (hasField() and x == 123). However because and does not evaluate the right-hand side if the left-hand side is comptime-known, the x == 123 is never evaluated.

    if (x == 123 and comptime hasField()) {

x == 123 is a runtime-known value, so even though comptime hasField() is evaluated to false, both sides of the if statement must be generated, which means that @compileError("C"); is reachable.

const std = @import("std");

test "aoeu" {
    var x: u32 = 123; // runtime value

    if (comptime x == 123) {
        std.debug.warn("why am i allowed to do this? what does it mean?\n", .{});
    }
}

This is a bug. If the expression is used in another context where a comptime value is required, you get a compilation error as expected:

const std = @import("std");

test "aoeu" {
    var x: u32 = 123; // runtime value
    var y: [@boolToInt(x == 123)]u8 = undefined;
}
/home/andy/dev/zig/build/test.zig:5:13: error: unable to evaluate constant expression
    var y: [@boolToInt(x == 123)]u8 = undefined;
            ^

This compile error is correct; the other case is incorrectly missing the compile error.

@andrewrk andrewrk added bug Observed behavior contradicts documented or intended behavior stage1 The process of building from source via WebAssembly and the C backend. labels Jan 5, 2020
@andrewrk andrewrk modified the milestones: 0.6.0, 0.7.0 Jan 5, 2020
@andrewrk andrewrk modified the milestones: 0.7.0, 0.8.0 Aug 13, 2020
@andrewrk andrewrk modified the milestones: 0.8.0, 0.9.0 Nov 6, 2020
@andrewrk andrewrk modified the milestones: 0.9.0, 0.10.0 May 19, 2021
@nektro
Copy link
Contributor

nektro commented Oct 16, 2022

this affects stage2 as well

@andrewrk
Copy link
Member

andrewrk commented Dec 27, 2022

The only issue here is this:

const std = @import("std");

test "comptime keyword used on runtime-known variable" {
    var x: u32 = 123; // runtime value

    if (comptime x == 123) { // should be a compile error because `x` is runtime-known
        return error.TestFailed;
    }
}
$ stage4/bin/zig test test.zig 
Test [1/1] test.comptime keyword used on runtime-known variable... FAIL (TestFailed)
/home/andy/dev/zig/build-release/test.zig:7:9: 0x20bed1 in test.comptime keyword used on runtime-known variable (test)
        return error.TestFailed;
        ^
0 passed; 0 skipped; 1 failed.
error: the following test command failed with exit code 1:
/home/andy/dev/zig/zig-cache/o/946dc69dfede9bc2cbf0db64615fb63d/test

@andrewrk andrewrk added frontend Tokenization, parsing, AstGen, Sema, and Liveness. and removed stage1 The process of building from source via WebAssembly and the C backend. labels Dec 27, 2022
@andrewrk andrewrk modified the milestones: 0.12.0, 0.11.0 Dec 27, 2022
@andrewrk andrewrk changed the title comptime expression prefix is ignored in some cases comptime keyword used with runtime-known identifier fails to produce a compile error Dec 27, 2022
@Vexu
Copy link
Member

Vexu commented Apr 23, 2023

Fixed by #13360 and #14819

@Vexu Vexu closed this as completed Apr 23, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior frontend Tokenization, parsing, AstGen, Sema, and Liveness.
Projects
None yet
Development

No branches or pull requests

3 participants