mirror of
https://github.com/ziglang/zig.git
synced 2026-02-21 00:35:10 +00:00
stage1: @intToEnum implicitly does an @intCast
This is a backwards-compatible language change. Previously, `@intToEnum` coerced its integer operand to the integer tag type of the destination enum type, often requiring the callsite to additionally wrap the operand in an `@intCast`. Now, the `@intCast` is implicit, and any integer operand can be passed to `@intToEnum`. The same as before, it is illegal behavior to pass any integer which does not have a corresponding enum tag.
This commit is contained in:
parent
d5ef5da594
commit
bb38931c71
@ -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>
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user