繁体   English   中英

遇到 `zig 编译器错误:GenericPoison`?

[英]encountered `zig compiler bug: GenericPoison`?

平台详情

  • macOS(苹果硅)
  • 之字形版本(所有行为都相同)
    • 0.10.0 aarch64
    • 0.11-dev824 aarch64

问题

我为基本的可组合迭代器编写了这段代码:

pub fn RangeIterator(comptime NumberType: type) type {
    return struct {
        const This = @This();
        const Item = NumberType;

        start: NumberType,
        step: NumberType,
        len: usize,
        _index: usize = 0,

        fn next(this: *This) !?Item {
            if (this._index >= this.len) {
                return null;
            }
            defer this._index += 1;
            return this.start + (this.step * @intCast(NumberType, this._index));
        }
    };
}

test "range iterator" {
    // these tests pass!
    var iterator = RangeIterator(u32){.start = 1, .step = 3, .len = 5};
    
    try std.testing.expectEqual(iterator.next(), 1);
    try std.testing.expectEqual(iterator.next(), 4);
    try std.testing.expectEqual(iterator.next(), 7);
    try std.testing.expectEqual(iterator.next(), 10);
    try std.testing.expectEqual(iterator.next(), 13);
    try std.testing.expectEqual(iterator.next(), null);
}

// based on pattern used for BufferedWriter & bufferedWriter
// https://github.com/ziglang/zig/blob/master/lib/std/io/buffered_writer.zig

pub fn IterWhile(
    comptime IteratorType: type,
    comptime ItemType: type,
    comptime include_last: bool,
) type {
    return struct {
        const This = @This();
        const Item = ItemType;

        iterator: IteratorType,
        predicate: fn (ItemType) bool,
        _is_spent: bool = false,

        pub fn next(this: *This) ?ItemType {
            if (this._is_spent) {
                return null;
            }

            const result = try this.iterator.next();
            if (result == null) {
                return null;
            }
            if (!this.predicate(result)) {
                this._is_spent = true;
                if (!include_last) return null;
            }
            return result;
        }
    };
}

pub fn iterWhile(
    iterator: anytype,
    predicate: fn (anytype) bool,
    comptime include_last: bool,
) IterWhile(
    @TypeOf(iterator),
    @typeInfo(predicate).Fn.args[0].arg_type,
    include_last,
) {
    return .{ .iterator = iterator, .predicate = predicate };
}

test "iter while" {
    // these tests generate a compiler error :S
    var range = RangeIterator(u32){.start = 1, .step = 3, .len = 5};
    var iterator = iterWhile(range, TestUtils.isOneDigit, false);

    try std.testing.expectEqual(iterator.next(), 1);
    try std.testing.expectEqual(iterator.next(), 4);
    try std.testing.expectEqual(iterator.next(), 7);
    try std.testing.expectEqual(iterator.next(), null);
}

const TestUtils = struct {
    fn isOneDigit(value: u32) bool {
        return value < 10;
    }
};

如果我注释掉第二个测试块"iter while" ,则测试通过。 但是如果我把它们留在里面,我会收到以下错误:

thread 1531026 panic: zig compiler bug: GenericPoison
Unable to dump stack trace: debug info stripped
zsh: abort      zig test src/utils/iterator.zig

问题

  1. 关于代码有什么问题的任何想法? 编辑:或者这是编译器的问题?
  2. debug info stripped -> 为什么会这样? 我不是通过不传递任何发布构建标志在调试模式下运行它吗?

虽然错误消息是由于编译器中的错误引起的,但您的代码中存在一些错误,解决后允许代码按预期编译和运行:

  1. (导致 GenericPoison 编译器错误): fn(u32) bool不可分配给fn(anytype) bool anytype是一个特殊值,可以在参数中使用以指定参数应该是通用的,并为传入的每个不同类型制作函数的新副本。更改predicate: fn(anytype) boolpredicate: anytype修复了这个问题

在此之后,其余问题都有正确的错误消息(尽管接下来的一些问题不会以颜色显示,并注意存在与其显示相关的 zig 编译器错误: Zig compiler bug: attempted to destroy declaration with an attached error )

  1. @typeInfo(predicate) - 这里的 predicate 是fn(u32) bool类型,所以你需要使用@TypeOf@typeInfo(@TypeOf(predicate))

  2. .arg_type - 这是一个可选的。 null 值表示参数类型设置为anytype 使用.arg_type.? 这里。 请注意,在较新版本的 zig 中,它已更改为.Fn.params[0].type.?

  3. predicate: fn(ItemType) bool - 这导致结构成为仅编译时间。 要使其在运行时可用,请使用函数指针: *const fn(ItemType) bool.predicate = &predicate 这个错误消息不是很有帮助——它说函数在 comptime 被调用,因为它的返回类型是 comptime-only,但没有解释为什么会这样。

  4. this.predicate(result) - 这里的 result 是可选的。 由于您在上面测试了 null,因此您可以安全地使用result.? 在这里或者您可以更改代码,因此 result 不再是orelse的可选项:

     const result = (try this.iterator.next()) orelse return null;

现在测试将通过


有关编译器错误的信息:

thread 1531026 panic: zig compiler bug: GenericPoison
Unable to dump stack trace: debug info stripped
zsh: abort      zig test src/utils/iterator.zig

zig 编译器错误

此消息表明该错误是 zig 编译器中的错误; 你不应该看到它。 编译器错误可能表明:

  • 不应编译的代码,但错误未被正确捕获和显示 - 这是编译器中的错误
  • 应该编译的代码,但编译器中有一个错误阻止它编译

在这里,代码应该导致关于fn(u32) bool not being assignable to fn(anytype) bool的编译错误,但是编译器某处存在错误导致它说GenericPoison

预期的错误消息:

a.zig:xx:xx: error: expected type 'fn(anytype) bool', found 'fn(u32) bool'

最小复制:

const std = @import("std");

pub fn iterWhile(
    predicate: fn (anytype) bool,
) void {
    _ = predicate;
}

test "iter while" {
    iterWhile(isOneDigit);
}

fn isOneDigit(value: u32) bool {
    return value < 10;
}

问题报告: #14052 ,可能与#12373的评论有关

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM