authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-19 03:50:38-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-19 03:50:38-04:00
loga3ddd0826bd9c799768c0c707de72c21befa742a
tree685b621eb041c178af40c0044c74f689d8d6af7b
parent626b73e8beeaae1cab23f883f877d89d64bbfa39

remove enum to/from int casting syntax; add `@enumToInt`/`@intToEnum`

see #1061

9 files changed, 174 insertions(+), 51 deletions(-)

doc/langref.html.in+27-7
...@@ -1900,9 +1900,9 @@ const Value = enum(u2) {...@@ -1900,9 +1900,9 @@ const Value = enum(u2) {
1900// Now you can cast between u2 and Value.1900// Now you can cast between u2 and Value.
1901// The ordinal value starts from 0, counting up for each member.1901// The ordinal value starts from 0, counting up for each member.
1902test "enum ordinal value" {1902test "enum ordinal value" {
1903 assert(u2(Value.Zero) == 0);1903 assert(@enumToInt(Value.Zero) == 0);
1904 assert(u2(Value.One) == 1);1904 assert(@enumToInt(Value.One) == 1);
1905 assert(u2(Value.Two) == 2);1905 assert(@enumToInt(Value.Two) == 2);
1906}1906}
19071907
1908// You can override the ordinal value for an enum.1908// You can override the ordinal value for an enum.
...@@ -1912,9 +1912,9 @@ const Value2 = enum(u32) {...@@ -1912,9 +1912,9 @@ const Value2 = enum(u32) {
1912 Million = 1000000,1912 Million = 1000000,
1913};1913};
1914test "set enum ordinal value" {1914test "set enum ordinal value" {
1915 assert(u32(Value2.Hundred) == 100);1915 assert(@enumToInt(Value2.Hundred) == 100);
1916 assert(u32(Value2.Thousand) == 1000);1916 assert(@enumToInt(Value2.Thousand) == 1000);
1917 assert(u32(Value2.Million) == 1000000);1917 assert(@enumToInt(Value2.Million) == 1000000);
1918}1918}
19191919
1920// Enums can have methods, the same as structs and unions.1920// Enums can have methods, the same as structs and unions.
...@@ -4931,6 +4931,14 @@ test "main" {...@@ -4931,6 +4931,14 @@ test "main" {
4931 {#see_also|@import#}4931 {#see_also|@import#}
4932 {#header_close#}4932 {#header_close#}
49334933
4934 {#header_open|@enumToInt#}
4935 <pre><code class="zig">@enumToInt(enum_value: var) var</code></pre>
4936 <p>
4937 Converts an enumeration value into its integer tag type.
4938 </p>
4939 {#see_also|@intToEnum#}
4940 {#header_close#}
4941
4934 {#header_open|@errSetCast#}4942 {#header_open|@errSetCast#}
4935 <pre><code class="zig">@errSetCast(comptime T: DestType, value: var) DestType</code></pre>4943 <pre><code class="zig">@errSetCast(comptime T: DestType, value: var) DestType</code></pre>
4936 <p>4944 <p>
...@@ -5095,6 +5103,18 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -5095,6 +5103,18 @@ fn add(a: i32, b: i32) i32 { return a + b; }
5095 </p>5103 </p>
5096 {#header_close#}5104 {#header_close#}
50975105
5106 {#header_open|@intToEnum#}
5107 <pre><code class="zig">@intToEnum(comptime DestType: type, int_value: @TagType(DestType)) DestType</code></pre>
5108 <p>
5109 Converts an integer into an {#link|enum#} value.
5110 </p>
5111 <p>
5112 Attempting to convert an integer which represents no value in the chosen enum type invokes
5113 safety-checked {#link|Undefined Behavior#}.
5114 </p>
5115 {#see_also|@enumToInt#}
5116 {#header_close#}
5117
5098 {#header_open|@intToError#}5118 {#header_open|@intToError#}
5099 <pre><code class="zig">@intToError(value: @IntType(false, @sizeOf(error) * 8)) error</code></pre>5119 <pre><code class="zig">@intToError(value: @IntType(false, @sizeOf(error) * 8)) error</code></pre>
5100 <p>5120 <p>
...@@ -6867,7 +6887,7 @@ hljs.registerLanguage("zig", function(t) {...@@ -6867,7 +6887,7 @@ hljs.registerLanguage("zig", function(t) {
6867 a = t.IR + "\\s*\\(",6887 a = t.IR + "\\s*\\(",
6868 c = {6888 c = {
6869 keyword: "const align var extern stdcallcc nakedcc volatile export pub noalias inline struct packed enum union break return try catch test continue unreachable comptime and or asm defer errdefer if else switch while for fn use bool f32 f64 void type noreturn error i8 u8 i16 u16 i32 u32 i64 u64 isize usize i8w u8w i16w i32w u32w i64w u64w isizew usizew c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong resume cancel await async orelse",6889 keyword: "const align var extern stdcallcc nakedcc volatile export pub noalias inline struct packed enum union break return try catch test continue unreachable comptime and or asm defer errdefer if else switch while for fn use bool f32 f64 void type noreturn error i8 u8 i16 u16 i32 u32 i64 u64 isize usize i8w u8w i16w i32w u32w i64w u64w isizew usizew c_short c_ushort c_int c_uint c_long c_ulong c_longlong c_ulonglong resume cancel await async orelse",
6870 built_in: "atomicLoad breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic ptrCast intCast floatCast intToFloat floatToInt boolToInt bytesToSlice sliceToBytes errSetCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchgStrong cmpxchgWeak fence divExact truncate atomicRmw sqrt field typeInfo typeName newStackCall errorToInt intToError",6890 built_in: "atomicLoad breakpoint returnAddress frameAddress fieldParentPtr setFloatMode IntType OpaqueType compileError compileLog setCold setRuntimeSafety setEvalBranchQuota offsetOf memcpy inlineCall setGlobalLinkage setGlobalSection divTrunc divFloor enumTagName intToPtr ptrToInt panic ptrCast intCast floatCast intToFloat floatToInt boolToInt bytesToSlice sliceToBytes errSetCast bitCast rem mod memset sizeOf alignOf alignCast maxValue minValue memberCount memberName memberType typeOf addWithOverflow subWithOverflow mulWithOverflow shlWithOverflow shlExact shrExact cInclude cDefine cUndef ctz clz import cImport errorName embedFile cmpxchgStrong cmpxchgWeak fence divExact truncate atomicRmw sqrt field typeInfo typeName newStackCall errorToInt intToError enumToInt intToEnum",
6871 literal: "true false null undefined"6891 literal: "true false null undefined"
6872 },6892 },
6873 n = [e, t.CLCM, t.CBCM, s, r];6893 n = [e, t.CLCM, t.CBCM, s, r];
src/all_types.hpp+10
...@@ -1378,6 +1378,8 @@ enum BuiltinFnId {...@@ -1378,6 +1378,8 @@ enum BuiltinFnId {
1378 BuiltinFnIdBoolToInt,1378 BuiltinFnIdBoolToInt,
1379 BuiltinFnIdErrToInt,1379 BuiltinFnIdErrToInt,
1380 BuiltinFnIdIntToErr,1380 BuiltinFnIdIntToErr,
1381 BuiltinFnIdEnumToInt,
1382 BuiltinFnIdIntToEnum,
1381 BuiltinFnIdIntType,1383 BuiltinFnIdIntType,
1382 BuiltinFnIdSetCold,1384 BuiltinFnIdSetCold,
1383 BuiltinFnIdSetRuntimeSafety,1385 BuiltinFnIdSetRuntimeSafety,
...@@ -2092,6 +2094,7 @@ enum IrInstructionId {...@@ -2092,6 +2094,7 @@ enum IrInstructionId {
2092 IrInstructionIdIntToPtr,2094 IrInstructionIdIntToPtr,
2093 IrInstructionIdPtrToInt,2095 IrInstructionIdPtrToInt,
2094 IrInstructionIdIntToEnum,2096 IrInstructionIdIntToEnum,
2097 IrInstructionIdEnumToInt,
2095 IrInstructionIdIntToErr,2098 IrInstructionIdIntToErr,
2096 IrInstructionIdErrToInt,2099 IrInstructionIdErrToInt,
2097 IrInstructionIdCheckSwitchProngs,2100 IrInstructionIdCheckSwitchProngs,
...@@ -2905,6 +2908,13 @@ struct IrInstructionIntToPtr {...@@ -2905,6 +2908,13 @@ struct IrInstructionIntToPtr {
2905struct IrInstructionIntToEnum {2908struct IrInstructionIntToEnum {
2906 IrInstruction base;2909 IrInstruction base;
29072910
2911 IrInstruction *dest_type;
2912 IrInstruction *target;
2913};
2914
2915struct IrInstructionEnumToInt {
2916 IrInstruction base;
2917
2908 IrInstruction *target;2918 IrInstruction *target;
2909};2919};
29102920
src/codegen.cpp+3
...@@ -4730,6 +4730,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,...@@ -4730,6 +4730,7 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
4730 case IrInstructionIdErrSetCast:4730 case IrInstructionIdErrSetCast:
4731 case IrInstructionIdFromBytes:4731 case IrInstructionIdFromBytes:
4732 case IrInstructionIdToBytes:4732 case IrInstructionIdToBytes:
4733 case IrInstructionIdEnumToInt:
4733 zig_unreachable();4734 zig_unreachable();
47344735
4735 case IrInstructionIdReturn:4736 case IrInstructionIdReturn:
...@@ -6325,6 +6326,8 @@ static void define_builtin_fns(CodeGen *g) {...@@ -6325,6 +6326,8 @@ static void define_builtin_fns(CodeGen *g) {
6325 create_builtin_fn(g, BuiltinFnIdBoolToInt, "boolToInt", 1);6326 create_builtin_fn(g, BuiltinFnIdBoolToInt, "boolToInt", 1);
6326 create_builtin_fn(g, BuiltinFnIdErrToInt, "errorToInt", 1);6327 create_builtin_fn(g, BuiltinFnIdErrToInt, "errorToInt", 1);
6327 create_builtin_fn(g, BuiltinFnIdIntToErr, "intToError", 1);6328 create_builtin_fn(g, BuiltinFnIdIntToErr, "intToError", 1);
6329 create_builtin_fn(g, BuiltinFnIdEnumToInt, "enumToInt", 1);
6330 create_builtin_fn(g, BuiltinFnIdIntToEnum, "intToEnum", 2);
6328 create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);6331 create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
6329 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);6332 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
6330 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int6333 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
src/ir.cpp+105-13
...@@ -600,6 +600,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToEnum *) {...@@ -600,6 +600,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToEnum *) {
600 return IrInstructionIdIntToEnum;600 return IrInstructionIdIntToEnum;
601}601}
602602
603static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumToInt *) {
604 return IrInstructionIdEnumToInt;
605}
606
603static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToErr *) {607static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToErr *) {
604 return IrInstructionIdIntToErr;608 return IrInstructionIdIntToErr;
605}609}
...@@ -2378,10 +2382,26 @@ static IrInstruction *ir_build_ptr_to_int(IrBuilder *irb, Scope *scope, AstNode...@@ -2378,10 +2382,26 @@ static IrInstruction *ir_build_ptr_to_int(IrBuilder *irb, Scope *scope, AstNode
2378}2382}
23792383
2380static IrInstruction *ir_build_int_to_enum(IrBuilder *irb, Scope *scope, AstNode *source_node,2384static IrInstruction *ir_build_int_to_enum(IrBuilder *irb, Scope *scope, AstNode *source_node,
2381 IrInstruction *target)2385 IrInstruction *dest_type, IrInstruction *target)
2382{2386{
2383 IrInstructionIntToEnum *instruction = ir_build_instruction<IrInstructionIntToEnum>(2387 IrInstructionIntToEnum *instruction = ir_build_instruction<IrInstructionIntToEnum>(
2384 irb, scope, source_node);2388 irb, scope, source_node);
2389 instruction->dest_type = dest_type;
2390 instruction->target = target;
2391
2392 if (dest_type) ir_ref_instruction(dest_type, irb->current_basic_block);
2393 ir_ref_instruction(target, irb->current_basic_block);
2394
2395 return &instruction->base;
2396}
2397
2398
2399
2400static IrInstruction *ir_build_enum_to_int(IrBuilder *irb, Scope *scope, AstNode *source_node,
2401 IrInstruction *target)
2402{
2403 IrInstructionEnumToInt *instruction = ir_build_instruction<IrInstructionEnumToInt>(
2404 irb, scope, source_node);
2385 instruction->target = target;2405 instruction->target = target;
23862406
2387 ir_ref_instruction(target, irb->current_basic_block);2407 ir_ref_instruction(target, irb->current_basic_block);
...@@ -4708,6 +4728,31 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4708,6 +4728,31 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4708 // this value does not mean anything since we passed non-null values for other arg4728 // this value does not mean anything since we passed non-null values for other arg
4709 AtomicOrderMonotonic);4729 AtomicOrderMonotonic);
4710 }4730 }
4731 case BuiltinFnIdIntToEnum:
4732 {
4733 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4734 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4735 if (arg0_value == irb->codegen->invalid_instruction)
4736 return arg0_value;
4737
4738 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4739 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
4740 if (arg1_value == irb->codegen->invalid_instruction)
4741 return arg1_value;
4742
4743 IrInstruction *result = ir_build_int_to_enum(irb, scope, node, arg0_value, arg1_value);
4744 return ir_lval_wrap(irb, scope, result, lval);
4745 }
4746 case BuiltinFnIdEnumToInt:
4747 {
4748 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4749 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4750 if (arg0_value == irb->codegen->invalid_instruction)
4751 return arg0_value;
4752
4753 IrInstruction *result = ir_build_enum_to_int(irb, scope, node, arg0_value);
4754 return ir_lval_wrap(irb, scope, result, lval);
4755 }
4711 }4756 }
4712 zig_unreachable();4757 zig_unreachable();
4713}4758}
...@@ -9951,7 +9996,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour...@@ -9951,7 +9996,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
9951 }9996 }
99529997
9953 IrInstruction *result = ir_build_int_to_enum(&ira->new_irb, source_instr->scope,9998 IrInstruction *result = ir_build_int_to_enum(&ira->new_irb, source_instr->scope,
9954 source_instr->source_node, target);9999 source_instr->source_node, nullptr, target);
9955 result->value.type = wanted_type;10000 result->value.type = wanted_type;
9956 return result;10001 return result;
9957}10002}
...@@ -10485,16 +10530,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10485,16 +10530,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10485 return ir_analyze_number_to_literal(ira, source_instr, value, wanted_type);10530 return ir_analyze_number_to_literal(ira, source_instr, value, wanted_type);
10486 }10531 }
1048710532
10488 // explicit cast from integer to enum type with no payload
10489 if (actual_type->id == TypeTableEntryIdInt && wanted_type->id == TypeTableEntryIdEnum) {
10490 return ir_analyze_int_to_enum(ira, source_instr, value, wanted_type);
10491 }
10492
10493 // explicit cast from enum type with no payload to integer
10494 if (wanted_type->id == TypeTableEntryIdInt && actual_type->id == TypeTableEntryIdEnum) {
10495 return ir_analyze_enum_to_int(ira, source_instr, value, wanted_type);
10496 }
10497
10498 // explicit cast from union to the enum type of the union10533 // explicit cast from union to the enum type of the union
10499 if (actual_type->id == TypeTableEntryIdUnion && wanted_type->id == TypeTableEntryIdEnum) {10534 if (actual_type->id == TypeTableEntryIdUnion && wanted_type->id == TypeTableEntryIdEnum) {
10500 type_ensure_zero_bits_known(ira->codegen, actual_type);10535 type_ensure_zero_bits_known(ira->codegen, actual_type);
...@@ -20262,11 +20297,63 @@ static TypeTableEntry *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstruction...@@ -20262,11 +20297,63 @@ static TypeTableEntry *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstruction
20262 return result->value.type;20297 return result->value.type;
20263}20298}
2026420299
20300static TypeTableEntry *ir_analyze_instruction_enum_to_int(IrAnalyze *ira, IrInstructionEnumToInt *instruction) {
20301 IrInstruction *target = instruction->target->other;
20302 if (type_is_invalid(target->value.type))
20303 return ira->codegen->builtin_types.entry_invalid;
20304
20305 if (target->value.type->id != TypeTableEntryIdEnum) {
20306 ir_add_error(ira, instruction->target,
20307 buf_sprintf("expected enum, found type '%s'", buf_ptr(&target->value.type->name)));
20308 return ira->codegen->builtin_types.entry_invalid;
20309 }
20310
20311 type_ensure_zero_bits_known(ira->codegen, target->value.type);
20312 if (type_is_invalid(target->value.type))
20313 return ira->codegen->builtin_types.entry_invalid;
20314
20315 TypeTableEntry *tag_type = target->value.type->data.enumeration.tag_int_type;
20316
20317 IrInstruction *result = ir_analyze_enum_to_int(ira, &instruction->base, target, tag_type);
20318 ir_link_new_instruction(result, &instruction->base);
20319 return result->value.type;
20320}
20321
20322static TypeTableEntry *ir_analyze_instruction_int_to_enum(IrAnalyze *ira, IrInstructionIntToEnum *instruction) {
20323 IrInstruction *dest_type_value = instruction->dest_type->other;
20324 TypeTableEntry *dest_type = ir_resolve_type(ira, dest_type_value);
20325 if (type_is_invalid(dest_type))
20326 return ira->codegen->builtin_types.entry_invalid;
20327
20328 if (dest_type->id != TypeTableEntryIdEnum) {
20329 ir_add_error(ira, instruction->dest_type,
20330 buf_sprintf("expected enum, found type '%s'", buf_ptr(&dest_type->name)));
20331 return ira->codegen->builtin_types.entry_invalid;
20332 }
20333
20334 type_ensure_zero_bits_known(ira->codegen, dest_type);
20335 if (type_is_invalid(dest_type))
20336 return ira->codegen->builtin_types.entry_invalid;
20337
20338 TypeTableEntry *tag_type = dest_type->data.enumeration.tag_int_type;
20339
20340 IrInstruction *target = instruction->target->other;
20341 if (type_is_invalid(target->value.type))
20342 return ira->codegen->builtin_types.entry_invalid;
20343
20344 IrInstruction *casted_target = ir_implicit_cast(ira, target, tag_type);
20345 if (type_is_invalid(casted_target->value.type))
20346 return ira->codegen->builtin_types.entry_invalid;
20347
20348 IrInstruction *result = ir_analyze_int_to_enum(ira, &instruction->base, casted_target, dest_type);
20349 ir_link_new_instruction(result, &instruction->base);
20350 return result->value.type;
20351}
20352
20265static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {20353static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
20266 switch (instruction->id) {20354 switch (instruction->id) {
20267 case IrInstructionIdInvalid:20355 case IrInstructionIdInvalid:
20268 case IrInstructionIdWidenOrShorten:20356 case IrInstructionIdWidenOrShorten:
20269 case IrInstructionIdIntToEnum:
20270 case IrInstructionIdStructInit:20357 case IrInstructionIdStructInit:
20271 case IrInstructionIdUnionInit:20358 case IrInstructionIdUnionInit:
20272 case IrInstructionIdStructFieldPtr:20359 case IrInstructionIdStructFieldPtr:
...@@ -20531,6 +20618,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -20531,6 +20618,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
20531 return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction);20618 return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction);
20532 case IrInstructionIdErrToInt:20619 case IrInstructionIdErrToInt:
20533 return ir_analyze_instruction_err_to_int(ira, (IrInstructionErrToInt *)instruction);20620 return ir_analyze_instruction_err_to_int(ira, (IrInstructionErrToInt *)instruction);
20621 case IrInstructionIdIntToEnum:
20622 return ir_analyze_instruction_int_to_enum(ira, (IrInstructionIntToEnum *)instruction);
20623 case IrInstructionIdEnumToInt:
20624 return ir_analyze_instruction_enum_to_int(ira, (IrInstructionEnumToInt *)instruction);
20534 }20625 }
20535 zig_unreachable();20626 zig_unreachable();
20536}20627}
...@@ -20754,6 +20845,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {...@@ -20754,6 +20845,7 @@ bool ir_has_side_effects(IrInstruction *instruction) {
20754 case IrInstructionIdBoolToInt:20845 case IrInstructionIdBoolToInt:
20755 case IrInstructionIdFromBytes:20846 case IrInstructionIdFromBytes:
20756 case IrInstructionIdToBytes:20847 case IrInstructionIdToBytes:
20848 case IrInstructionIdEnumToInt:
20757 return false;20849 return false;
2075820850
20759 case IrInstructionIdAsm:20851 case IrInstructionIdAsm:
src/ir_print.cpp+14
...@@ -928,6 +928,17 @@ static void ir_print_int_to_ptr(IrPrint *irp, IrInstructionIntToPtr *instruction...@@ -928,6 +928,17 @@ static void ir_print_int_to_ptr(IrPrint *irp, IrInstructionIntToPtr *instruction
928928
929static void ir_print_int_to_enum(IrPrint *irp, IrInstructionIntToEnum *instruction) {929static void ir_print_int_to_enum(IrPrint *irp, IrInstructionIntToEnum *instruction) {
930 fprintf(irp->f, "@intToEnum(");930 fprintf(irp->f, "@intToEnum(");
931 if (instruction->dest_type == nullptr) {
932 fprintf(irp->f, "(null)");
933 } else {
934 ir_print_other_instruction(irp, instruction->dest_type);
935 }
936 ir_print_other_instruction(irp, instruction->target);
937 fprintf(irp->f, ")");
938}
939
940static void ir_print_enum_to_int(IrPrint *irp, IrInstructionEnumToInt *instruction) {
941 fprintf(irp->f, "@enumToInt(");
931 ir_print_other_instruction(irp, instruction->target);942 ir_print_other_instruction(irp, instruction->target);
932 fprintf(irp->f, ")");943 fprintf(irp->f, ")");
933}944}
...@@ -1717,6 +1728,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {...@@ -1717,6 +1728,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
1717 case IrInstructionIdAtomicLoad:1728 case IrInstructionIdAtomicLoad:
1718 ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);1729 ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);
1719 break;1730 break;
1731 case IrInstructionIdEnumToInt:
1732 ir_print_enum_to_int(irp, (IrInstructionEnumToInt *)instruction);
1733 break;
1720 }1734 }
1721 fprintf(irp->f, "\n");1735 fprintf(irp->f, "\n");
1722}1736}
std/json.zig+1-1
...@@ -180,7 +180,7 @@ pub const StreamingParser = struct {...@@ -180,7 +180,7 @@ pub const StreamingParser = struct {
180 pub fn fromInt(x: var) State {180 pub fn fromInt(x: var) State {
181 debug.assert(x == 0 or x == 1);181 debug.assert(x == 0 or x == 1);
182 const T = @TagType(State);182 const T = @TagType(State);
183 return State(@intCast(T, x));183 return @intToEnum(State, @intCast(T, x));
184 }184 }
185 };185 };
186186
test/cases/enum.zig+8-8
...@@ -92,14 +92,14 @@ test "enum to int" {...@@ -92,14 +92,14 @@ test "enum to int" {
92}92}
9393
94fn shouldEqual(n: Number, expected: u3) void {94fn shouldEqual(n: Number, expected: u3) void {
95 assert(u3(n) == expected);95 assert(@enumToInt(n) == expected);
96}96}
9797
98test "int to enum" {98test "int to enum" {
99 testIntToEnumEval(3);99 testIntToEnumEval(3);
100}100}
101fn testIntToEnumEval(x: i32) void {101fn testIntToEnumEval(x: i32) void {
102 assert(IntToEnumNumber(@intCast(u3, x)) == IntToEnumNumber.Three);102 assert(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three);
103}103}
104const IntToEnumNumber = enum {104const IntToEnumNumber = enum {
105 Zero,105 Zero,
...@@ -768,7 +768,7 @@ test "casting enum to its tag type" {...@@ -768,7 +768,7 @@ test "casting enum to its tag type" {
768}768}
769769
770fn testCastEnumToTagType(value: Small2) void {770fn testCastEnumToTagType(value: Small2) void {
771 assert(u2(value) == 1);771 assert(@enumToInt(value) == 1);
772}772}
773773
774const MultipleChoice = enum(u32) {774const MultipleChoice = enum(u32) {
...@@ -784,7 +784,7 @@ test "enum with specified tag values" {...@@ -784,7 +784,7 @@ test "enum with specified tag values" {
784}784}
785785
786fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void {786fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void {
787 assert(u32(x) == 60);787 assert(@enumToInt(x) == 60);
788 assert(1234 == switch (x) {788 assert(1234 == switch (x) {
789 MultipleChoice.A => 1,789 MultipleChoice.A => 1,
790 MultipleChoice.B => 2,790 MultipleChoice.B => 2,
...@@ -811,7 +811,7 @@ test "enum with specified and unspecified tag values" {...@@ -811,7 +811,7 @@ test "enum with specified and unspecified tag values" {
811}811}
812812
813fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {813fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
814 assert(u32(x) == 1000);814 assert(@enumToInt(x) == 1000);
815 assert(1234 == switch (x) {815 assert(1234 == switch (x) {
816 MultipleChoice2.A => 1,816 MultipleChoice2.A => 1,
817 MultipleChoice2.B => 2,817 MultipleChoice2.B => 2,
...@@ -826,8 +826,8 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {...@@ -826,8 +826,8 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
826}826}
827827
828test "cast integer literal to enum" {828test "cast integer literal to enum" {
829 assert(MultipleChoice2(0) == MultipleChoice2.Unspecified1);829 assert(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);
830 assert(MultipleChoice2(40) == MultipleChoice2.B);830 assert(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B);
831}831}
832832
833const EnumWithOneMember = enum {833const EnumWithOneMember = enum {
...@@ -865,7 +865,7 @@ const EnumWithTagValues = enum(u4) {...@@ -865,7 +865,7 @@ const EnumWithTagValues = enum(u4) {
865 D = 1 << 3,865 D = 1 << 3,
866};866};
867test "enum with tag values don't require parens" {867test "enum with tag values don't require parens" {
868 assert(u4(EnumWithTagValues.C) == 0b0100);868 assert(@enumToInt(EnumWithTagValues.C) == 0b0100);
869}869}
870870
871test "enum with 1 field but explicit tag type should still have the tag type" {871test "enum with 1 field but explicit tag type should still have the tag type" {
test/cases/union.zig+2-2
...@@ -126,7 +126,7 @@ const MultipleChoice = union(enum(u32)) {...@@ -126,7 +126,7 @@ const MultipleChoice = union(enum(u32)) {
126test "simple union(enum(u32))" {126test "simple union(enum(u32))" {
127 var x = MultipleChoice.C;127 var x = MultipleChoice.C;
128 assert(x == MultipleChoice.C);128 assert(x == MultipleChoice.C);
129 assert(u32(@TagType(MultipleChoice)(x)) == 60);129 assert(@enumToInt(@TagType(MultipleChoice)(x)) == 60);
130}130}
131131
132const MultipleChoice2 = union(enum(u32)) {132const MultipleChoice2 = union(enum(u32)) {
...@@ -148,7 +148,7 @@ test "union(enum(u32)) with specified and unspecified tag values" {...@@ -148,7 +148,7 @@ test "union(enum(u32)) with specified and unspecified tag values" {
148}148}
149149
150fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: *const MultipleChoice2) void {150fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: *const MultipleChoice2) void {
151 assert(u32(@TagType(MultipleChoice2)(x.*)) == 60);151 assert(@enumToInt(@TagType(MultipleChoice2)(x.*)) == 60);
152 assert(1123 == switch (x.*) {152 assert(1123 == switch (x.*) {
153 MultipleChoice2.A => 1,153 MultipleChoice2.A => 1,
154 MultipleChoice2.B => 2,154 MultipleChoice2.B => 2,
test/compile_errors.zig+4-20
...@@ -3709,22 +3709,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3709,22 +3709,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3709 ".tmp_source.zig:9:22: error: expected type 'u2', found 'Small'",3709 ".tmp_source.zig:9:22: error: expected type 'u2', found 'Small'",
3710 );3710 );
37113711
3712 cases.add(
3713 "explicitly casting enum to non tag type",
3714 \\const Small = enum(u2) {
3715 \\ One,
3716 \\ Two,
3717 \\ Three,
3718 \\ Four,
3719 \\};
3720 \\
3721 \\export fn entry() void {
3722 \\ var x = u3(Small.Two);
3723 \\}
3724 ,
3725 ".tmp_source.zig:9:15: error: enum to integer cast to 'u3' instead of its tag type, 'u2'",
3726 );
3727
3728 cases.add(3712 cases.add(
3729 "explicitly casting non tag type to enum",3713 "explicitly casting non tag type to enum",
3730 \\const Small = enum(u2) {3714 \\const Small = enum(u2) {
...@@ -3736,10 +3720,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -3736,10 +3720,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
3736 \\3720 \\
3737 \\export fn entry() void {3721 \\export fn entry() void {
3738 \\ var y = u3(3);3722 \\ var y = u3(3);
3739 \\ var x = Small(y);3723 \\ var x = @intToEnum(Small, y);
3740 \\}3724 \\}
3741 ,3725 ,
3742 ".tmp_source.zig:10:18: error: integer to enum cast from 'u3' instead of its tag type, 'u2'",3726 ".tmp_source.zig:10:31: error: expected type 'u2', found 'u3'",
3743 );3727 );
37443728
3745 cases.add(3729 cases.add(
...@@ -4020,10 +4004,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -4020,10 +4004,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
4020 \\ B = 11,4004 \\ B = 11,
4021 \\};4005 \\};
4022 \\export fn entry() void {4006 \\export fn entry() void {
4023 \\ var x = Foo(0);4007 \\ var x = @intToEnum(Foo, 0);
4024 \\}4008 \\}
4025 ,4009 ,
4026 ".tmp_source.zig:6:16: error: enum 'Foo' has no tag matching integer value 0",4010 ".tmp_source.zig:6:13: error: enum 'Foo' has no tag matching integer value 0",
4027 ".tmp_source.zig:1:13: note: 'Foo' declared here",4011 ".tmp_source.zig:1:13: note: 'Foo' declared here",
4028 );4012 );
40294013