微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Zig 0.8.0 错误:“枚举文字”类型的值必须是已知的

如何解决Zig 0.8.0 错误:“枚举文字”类型的值必须是已知的

在 Zig 0.8.0 中,在切换 u8 字符以获取 enum 类型时,我遇到了以下代码的奇怪编译器错误

.op_type = switch(c1) {
    '+' => .add,'-' => .sub,'*' => .mul,'/' => .div,'%' => .mod,'^' => .exp,'|' => .bor,'~' => .bxor,'&' => .band,'<' => if (is_long) .lte else .lt,'>' => if (is_long) .gte else .gt,'=' => if (is_long) .eq  else .nop,'!' => if (is_long) .neq else return TokenError.NotAToken,else => unreachable
}

错误是:

.\lib.zig:137:36: error: values of type '(enum literal)' must be comptime kNown
                        '<' => if (is_long) .lte else .lt,^

通常在 zig 中,“must be comptime kNown”消息意味着我在运行时值上留下了类型签名,例如 const x = 3;。但是,switch 表达式中没有签名,而且编译器无论如何都应该知道类型是什么,因为字段 .op_type 采用 Op 类型枚举。

我能够通过使用 switch 语句而不是表达式来解决这个问题,我曾经用它来分配占位符值。结果很惨:

var op_type: Op = undefined;
switch(c1) {
    '+' => op_type = .add,'-' => op_type = .sub,'*' => op_type = .mul,'/' => op_type = .div,'%' => op_type = .mod,'^' => op_type = .exp,'|' => op_type = .bor,'~' => op_type = .bxor,'&' => op_type = .band,'<' => if (is_long) {op_type = .lte;} else {op_type = .lt;},'>' => if (is_long) {op_type = .gte;} else {op_type = .gt;},'=' => if (is_long) {op_type = .eq ;} else {op_type = .nop;},'!' => if (is_long) {op_type = .neq;} else return TokenError.NotAToken,else => unreachable
}
...
... {
    ...
    .op_type = op_type
}

我发布这个问题的原因是我并不真正理解第一个实现的问题,我想看看是否有比我想出的更好的解决方案。

解决方法

您遇到的是枚举文字的怪癖。当您编写 .sub 时,首先这是一个尚未强制转换为实际枚举类型的枚举文字。通常这个过程是透明的,但在这种情况下,类型系统似乎无法通过您的 if 表达式“推理”。

这可能会在自托管编译器中得到改进,但与此同时,解决方案是在遇到此问题时简单地明确枚举类型。

这是您编译的代码片段的简化版本:https://zig.godbolt.org/z/zeTnf3a67

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。