Commit bb38931c71
Changed files (4)
doc/langref.html.in
@@ -3163,7 +3163,9 @@ test "switch using enum literals" {
It must specify a tag type and cannot consume every enumeration value.
</p>
<p>
- {#link|@intToEnum#} on a non-exhaustive enum cannot fail.
+ {#link|@intToEnum#} on a non-exhaustive enum involves the safety semantics
+ of {#link|@intCast#} to the integer tag type, but beyond that always results in
+ a well-defined enum value.
</p>
<p>
A switch on a non-exhaustive enum can include a '_' prong as an alternative to an {#syntax#}else{#endsyntax#} prong
@@ -7972,7 +7974,7 @@ test "@hasDecl" {
{#header_close#}
{#header_open|@intToEnum#}
- <pre>{#syntax#}@intToEnum(comptime DestType: type, int_value: std.meta.Tag(DestType)) DestType{#endsyntax#}</pre>
+ <pre>{#syntax#}@intToEnum(comptime DestType: type, integer: anytype) DestType{#endsyntax#}</pre>
<p>
Converts an integer into an {#link|enum#} value.
</p>
src/stage1/ir.cpp
@@ -20007,29 +20007,24 @@ static Stage1AirInst *ir_analyze_instruction_truncate(IrAnalyze *ira, Stage1ZirI
return ir_build_truncate_gen(ira, instruction->base.scope, instruction->base.source_node, dest_type, target);
}
-static Stage1AirInst *ir_analyze_instruction_int_cast(IrAnalyze *ira, Stage1ZirInstIntCast *instruction) {
- ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
- if (type_is_invalid(dest_type))
- return ira->codegen->invalid_inst_gen;
-
+static Stage1AirInst *ir_analyze_int_cast(IrAnalyze *ira, Scope *scope, AstNode *source_node,
+ ZigType *dest_type, AstNode *dest_type_src_node,
+ Stage1AirInst *target, AstNode *target_src_node)
+{
ZigType *scalar_dest_type = (dest_type->id == ZigTypeIdVector) ?
dest_type->data.vector.elem_type : dest_type;
if (scalar_dest_type->id != ZigTypeIdInt && scalar_dest_type->id != ZigTypeIdComptimeInt) {
- ir_add_error_node(ira, instruction->dest_type->source_node,
+ ir_add_error_node(ira, dest_type_src_node,
buf_sprintf("expected integer type, found '%s'", buf_ptr(&scalar_dest_type->name)));
return ira->codegen->invalid_inst_gen;
}
- Stage1AirInst *target = instruction->target->child;
- if (type_is_invalid(target->value->type))
- return ira->codegen->invalid_inst_gen;
-
ZigType *scalar_target_type = (target->value->type->id == ZigTypeIdVector) ?
target->value->type->data.vector.elem_type : target->value->type;
if (scalar_target_type->id != ZigTypeIdInt && scalar_target_type->id != ZigTypeIdComptimeInt) {
- ir_add_error_node(ira, instruction->target->source_node, buf_sprintf("expected integer type, found '%s'",
+ ir_add_error_node(ira, target_src_node, buf_sprintf("expected integer type, found '%s'",
buf_ptr(&scalar_target_type->name)));
return ira->codegen->invalid_inst_gen;
}
@@ -20039,10 +20034,24 @@ static Stage1AirInst *ir_analyze_instruction_int_cast(IrAnalyze *ira, Stage1ZirI
if (val == nullptr)
return ira->codegen->invalid_inst_gen;
- return ir_implicit_cast2(ira, instruction->target->scope, instruction->target->source_node, target, dest_type);
+ return ir_implicit_cast2(ira, scope, target_src_node, target, dest_type);
}
- return ir_analyze_widen_or_shorten(ira, instruction->base.scope, instruction->base.source_node, target, dest_type);
+ return ir_analyze_widen_or_shorten(ira, scope, source_node, target, dest_type);
+}
+
+static Stage1AirInst *ir_analyze_instruction_int_cast(IrAnalyze *ira, Stage1ZirInstIntCast *instruction) {
+ ZigType *dest_type = ir_resolve_type(ira, instruction->dest_type->child);
+ if (type_is_invalid(dest_type))
+ return ira->codegen->invalid_inst_gen;
+
+ Stage1AirInst *target = instruction->target->child;
+ if (type_is_invalid(target->value->type))
+ return ira->codegen->invalid_inst_gen;
+
+ return ir_analyze_int_cast(ira, instruction->base.scope, instruction->base.source_node,
+ dest_type, instruction->dest_type->source_node,
+ target, instruction->target->source_node);
}
static Stage1AirInst *ir_analyze_instruction_float_cast(IrAnalyze *ira, Stage1ZirInstFloatCast *instruction) {
@@ -24282,7 +24291,9 @@ static Stage1AirInst *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, Stage1Z
if (type_is_invalid(target->value->type))
return ira->codegen->invalid_inst_gen;
- Stage1AirInst *casted_target = ir_implicit_cast(ira, target, tag_type);
+ Stage1AirInst *casted_target = ir_analyze_int_cast(ira, instruction->base.scope,
+ instruction->base.source_node, tag_type, instruction->dest_type->source_node,
+ target, instruction->target->source_node);
if (type_is_invalid(casted_target->value->type))
return ira->codegen->invalid_inst_gen;
test/behavior/enum.zig
@@ -203,7 +203,7 @@ test "int to enum" {
try testIntToEnumEval(3);
}
fn testIntToEnumEval(x: i32) !void {
- try expect(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three);
+ try expect(@intToEnum(IntToEnumNumber, x) == IntToEnumNumber.Three);
}
const IntToEnumNumber = enum {
Zero,
test/compile_errors.zig
@@ -7691,12 +7691,12 @@ pub fn addCases(ctx: *TestContext) !void {
\\};
\\
\\export fn entry() void {
- \\ var y = @as(u3, 3);
+ \\ var y = @as(f32, 3);
\\ var x = @intToEnum(Small, y);
\\ _ = x;
\\}
, &[_][]const u8{
- "tmp.zig:10:31: error: expected type 'u2', found 'u3'",
+ "tmp.zig:10:31: error: expected integer type, found 'f32'",
});
ctx.objErrStage1("union fields with value assignments",