zig icon indicating copy to clipboard operation
zig copied to clipboard

inline compile error: indexing into empty slice is not allowed

Open zedongh opened this issue 1 year ago • 3 comments

Zig Version

0.13.0

Steps to Reproduce and Observed Behavior

inline function bisect_right cause error: indexing into empty slice is not allowed

pub fn bisect_right(arr: []const u8, target: usize) usize {
    var start: usize = 0;
    var end: usize = arr.len;
    while (start < end) {
        const mid = (start + end) / 2;
        if (arr[mid] < target) {
            start = mid + 1;
        } else {
            end = mid;
        }
    }
    return start;
}

pub inline fn inline_bisect_right(arr: []const u8, target: usize) usize {
    var start: usize = 0;
    var end: usize = arr.len;
    while (start < end) {
        const mid = (start + end) / 2;
        if (arr[mid] < target) {
            start = mid + 1;
        } else {
            end = mid;
        }
    }
    return start;
}

test "inline bisect const compile failed" {
    const s = [_]u8{};
    _ = inline_bisect_right(&s, 1);
}

test "inline bisect var compile success" {
    var s = [_]u8{};
    _ = inline_bisect_right(&s, 1);
}

test "inline bisect ok" {
    const s = [_]u8{1};
    _ = inline_bisect_right(&s, 1);
}

test "bisect ok" {
    const s0 = [_]u8{0};
    _ = bisect_right(&s0, 1);
    const s1 = [_]u8{1};
    _ = bisect_right(&s1, 1);
}

Expected Behavior

should not all of this behavior same as not inline annotated?

zedongh avatar Jul 31 '24 03:07 zedongh

As documented in https://ziglang.org/documentation/master/#inline-fn, "arguments at an inline function callsite which are compile-time known are treated as Compile Time Parameters." s0 is comptime-known in test "bisect ok", however the variables start and end in inline_bisect_right are var, so the condition in while (start < end) is only resolved at runtime. Therefore the loop body is analyzed and arr[mid] is found, which triggers the compile error. This seems not like a bug, but like the intended semantics to me. Note that if you're unsure whether something is a bug, you can also ask in one of the community spaces.

rohlem avatar Jul 31 '24 15:07 rohlem

As documented in https://ziglang.org/documentation/master/#inline-fn, "arguments at an inline function callsite which are compile-time known are treated as Compile Time Parameters." s0 is comptime-known in test "bisect ok", however the variables start and end in inline_bisect_right are var, so the condition in while (start < end) is only resolved at runtime. Therefore the loop body is analyzed and arr[mid] is found, which triggers the compile error. This seems not like a bug, but like the intended semantics to me. Note that if you're unsure whether something is a bug, you can also ask in one of the community spaces.

Yeah, when i analyzed the code, found the compiler don't know it's impossible go into loop when passing zero length slice. But is possible to provide some information to tell compiler to make code perform consistently?

zedongh avatar Aug 05 '24 07:08 zedongh

But is possible to provide some information to tell compiler to make code perform consistently?

For your concrete example you can explicitly tell the compiler by adding an early return if (arr.len == 0) return start; before the loop. If arr is comptime-known, then arr.len is as well. In the general case, the compiler doesn't want to try doing runtime work at comptime, and so it "gives up" and demotes code to runtime as soon as a runtime value is involved. If you really want to use the inline keyword, you'll probably have to bend your code around this limitation. Note that the inline keyword is discouraged in general:

It is generally better to let the compiler decide when to inline a function [...] Note that inline actually restricts what the compiler is allowed to do. This can harm binary size, compilation speed, and even runtime performance.

rohlem avatar Aug 05 '24 13:08 rohlem