Zig 0.8.0 error: values of type '(enum literal)' must be comptime known
Zig 0.8.0 error: values of type '(enum literal)' must be comptime known
在 Zig 0.8.0 中,当切换 u8 字符以获取枚举类型时,我遇到了一个奇怪的编译器错误,代码如下:
.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
在 Zig 0.8.0 中,当切换 u8 字符以获取枚举类型时,我遇到了一个奇怪的编译器错误,代码如下:
.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