authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-18 18:48:29-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-18 18:48:29-04:00
log626b73e8beeaae1cab23f883f877d89d64bbfa39
tree4ed0ee57e00134f34656e759282b5c0e771726b2
parenta430853a48a5e4dbcd0094c632957e28898159f3

remove error to/from int casting syntax; add `@errorToInt`/`@intToError`

See #1061

10 files changed, 138 insertions(+), 60 deletions(-)

doc/langref.html.in+42-6
...@@ -4658,7 +4658,7 @@ comptime {...@@ -4658,7 +4658,7 @@ comptime {
4658 </p>4658 </p>
4659 <p>4659 <p>
4660 Attempting to convert a number of bytes with a length that does not evenly divide into a slice of4660 Attempting to convert a number of bytes with a length that does not evenly divide into a slice of
4661 elements results in {#link|Undefined Behavior#}.4661 elements results in safety-protected {#link|Undefined Behavior#}.
4662 </p>4662 </p>
4663 {#header_close#}4663 {#header_close#}
46644664
...@@ -4935,7 +4935,7 @@ test "main" {...@@ -4935,7 +4935,7 @@ test "main" {
4935 <pre><code class="zig">@errSetCast(comptime T: DestType, value: var) DestType</code></pre>4935 <pre><code class="zig">@errSetCast(comptime T: DestType, value: var) DestType</code></pre>
4936 <p>4936 <p>
4937 Converts an error value from one error set to another error set. Attempting to convert an error4937 Converts an error value from one error set to another error set. Attempting to convert an error
4938 which is not in the destination error set results in {#link|Undefined Behavior#}.4938 which is not in the destination error set results in safety-protected {#link|Undefined Behavior#}.
4939 </p>4939 </p>
4940 {#header_close#}4940 {#header_close#}
49414941
...@@ -4955,6 +4955,7 @@ test "main" {...@@ -4955,6 +4955,7 @@ test "main" {
4955 error name table will be generated.4955 error name table will be generated.
4956 </p>4956 </p>
4957 {#header_close#}4957 {#header_close#}
4958
4958 {#header_open|@errorReturnTrace#}4959 {#header_open|@errorReturnTrace#}
4959 <pre><code class="zig">@errorReturnTrace() ?*builtin.StackTrace</code></pre>4960 <pre><code class="zig">@errorReturnTrace() ?*builtin.StackTrace</code></pre>
4960 <p>4961 <p>
...@@ -4964,6 +4965,25 @@ test "main" {...@@ -4964,6 +4965,25 @@ test "main" {
4964 </p>4965 </p>
4965 {#header_close#}4966 {#header_close#}
49664967
4968 {#header_open|@errorToInt#}
4969 <pre><code class="zig">@errorToInt(err: var) @IntType(false, @sizeOf(error) * 8)</code></pre>
4970 <p>
4971 Supports the following types:
4972 </p>
4973 <ul>
4974 <li>error unions</li>
4975 <li><code>E!void</code></li>
4976 </ul>
4977 <p>
4978 Converts an error to the integer representation of an error.
4979 </p>
4980 <p>
4981 It is generally recommended to avoid this
4982 cast, as the integer representation of an error is not stable across source code changes.
4983 </p>
4984 {#see_also|@intToError#}
4985 {#header_close#}
4986
4967 {#header_open|@export#}4987 {#header_open|@export#}
4968 <pre><code class="zig">@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8</code></pre>4988 <pre><code class="zig">@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8</code></pre>
4969 <p>4989 <p>
...@@ -5071,8 +5091,24 @@ fn add(a: i32, b: i32) i32 { return a + b; }...@@ -5071,8 +5091,24 @@ fn add(a: i32, b: i32) i32 { return a + b; }
5071 <p>5091 <p>
5072 Converts an integer to another integer while keeping the same numerical value.5092 Converts an integer to another integer while keeping the same numerical value.
5073 Attempting to convert a number which is out of range of the destination type results in5093 Attempting to convert a number which is out of range of the destination type results in
5074 {#link|Undefined Behavior#}.5094 safety-protected {#link|Undefined Behavior#}.
5095 </p>
5096 {#header_close#}
5097
5098 {#header_open|@intToError#}
5099 <pre><code class="zig">@intToError(value: @IntType(false, @sizeOf(error) * 8)) error</code></pre>
5100 <p>
5101 Converts from the integer representation of an error into the global error set type.
5102 </p>
5103 <p>
5104 It is generally recommended to avoid this
5105 cast, as the integer representation of an error is not stable across source code changes.
5106 </p>
5107 <p>
5108 Attempting to convert an integer that does not correspond to any error results in
5109 safety-protected {#link|Undefined Behavior#}.
5075 </p>5110 </p>
5111 {#see_also|@errorToInt#}
5076 {#header_close#}5112 {#header_close#}
50775113
5078 {#header_open|@intToFloat#}5114 {#header_open|@intToFloat#}
...@@ -6123,8 +6159,8 @@ fn getNumberOrFail() !i32 {...@@ -6123,8 +6159,8 @@ fn getNumberOrFail() !i32 {
6123 {#code_begin|test_err|integer value 11 represents no error#}6159 {#code_begin|test_err|integer value 11 represents no error#}
6124comptime {6160comptime {
6125 const err = error.AnError;6161 const err = error.AnError;
6126 const number = u32(err) + 10;6162 const number = @errorToInt(err) + 10;
6127 const invalid_err = error(number);6163 const invalid_err = @intToError(number);
6128}6164}
6129 {#code_end#}6165 {#code_end#}
6130 <p>At runtime crashes with the message <code>invalid error code</code> and a stack trace.</p>6166 <p>At runtime crashes with the message <code>invalid error code</code> and a stack trace.</p>
...@@ -6831,7 +6867,7 @@ hljs.registerLanguage("zig", function(t) {...@@ -6831,7 +6867,7 @@ hljs.registerLanguage("zig", function(t) {
6831 a = t.IR + "\\s*\\(",6867 a = t.IR + "\\s*\\(",
6832 c = {6868 c = {
6833 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",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",
6834 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",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",
6835 literal: "true false null undefined"6871 literal: "true false null undefined"
6836 },6872 },
6837 n = [e, t.CLCM, t.CBCM, s, r];6873 n = [e, t.CLCM, t.CBCM, s, r];
src/all_types.hpp+2
...@@ -1376,6 +1376,8 @@ enum BuiltinFnId {...@@ -1376,6 +1376,8 @@ enum BuiltinFnId {
1376 BuiltinFnIdIntToFloat,1376 BuiltinFnIdIntToFloat,
1377 BuiltinFnIdFloatToInt,1377 BuiltinFnIdFloatToInt,
1378 BuiltinFnIdBoolToInt,1378 BuiltinFnIdBoolToInt,
1379 BuiltinFnIdErrToInt,
1380 BuiltinFnIdIntToErr,
1379 BuiltinFnIdIntType,1381 BuiltinFnIdIntType,
1380 BuiltinFnIdSetCold,1382 BuiltinFnIdSetCold,
1381 BuiltinFnIdSetRuntimeSafety,1383 BuiltinFnIdSetRuntimeSafety,
src/codegen.cpp+2
...@@ -6323,6 +6323,8 @@ static void define_builtin_fns(CodeGen *g) {...@@ -6323,6 +6323,8 @@ static void define_builtin_fns(CodeGen *g) {
6323 create_builtin_fn(g, BuiltinFnIdIntToFloat, "intToFloat", 2);6323 create_builtin_fn(g, BuiltinFnIdIntToFloat, "intToFloat", 2);
6324 create_builtin_fn(g, BuiltinFnIdFloatToInt, "floatToInt", 2);6324 create_builtin_fn(g, BuiltinFnIdFloatToInt, "floatToInt", 2);
6325 create_builtin_fn(g, BuiltinFnIdBoolToInt, "boolToInt", 1);6325 create_builtin_fn(g, BuiltinFnIdBoolToInt, "boolToInt", 1);
6326 create_builtin_fn(g, BuiltinFnIdErrToInt, "errorToInt", 1);
6327 create_builtin_fn(g, BuiltinFnIdIntToErr, "intToError", 1);
6326 create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);6328 create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
6327 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);6329 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
6328 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int6330 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
src/ir.cpp+57-17
...@@ -4167,6 +4167,26 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo...@@ -4167,6 +4167,26 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
4167 IrInstruction *result = ir_build_float_to_int(irb, scope, node, arg0_value, arg1_value);4167 IrInstruction *result = ir_build_float_to_int(irb, scope, node, arg0_value, arg1_value);
4168 return ir_lval_wrap(irb, scope, result, lval);4168 return ir_lval_wrap(irb, scope, result, lval);
4169 }4169 }
4170 case BuiltinFnIdErrToInt:
4171 {
4172 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4173 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4174 if (arg0_value == irb->codegen->invalid_instruction)
4175 return arg0_value;
4176
4177 IrInstruction *result = ir_build_err_to_int(irb, scope, node, arg0_value);
4178 return ir_lval_wrap(irb, scope, result, lval);
4179 }
4180 case BuiltinFnIdIntToErr:
4181 {
4182 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4183 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4184 if (arg0_value == irb->codegen->invalid_instruction)
4185 return arg0_value;
4186
4187 IrInstruction *result = ir_build_int_to_err(irb, scope, node, arg0_value);
4188 return ir_lval_wrap(irb, scope, result, lval);
4189 }
4170 case BuiltinFnIdBoolToInt:4190 case BuiltinFnIdBoolToInt:
4171 {4191 {
4172 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);4192 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
...@@ -10465,21 +10485,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst...@@ -10465,21 +10485,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
10465 return ir_analyze_number_to_literal(ira, source_instr, value, wanted_type);10485 return ir_analyze_number_to_literal(ira, source_instr, value, wanted_type);
10466 }10486 }
1046710487
10468 // explicit cast from T!void to integer type which can fit it
10469 bool actual_type_is_void_err = actual_type->id == TypeTableEntryIdErrorUnion &&
10470 !type_has_bits(actual_type->data.error_union.payload_type);
10471 bool actual_type_is_err_set = actual_type->id == TypeTableEntryIdErrorSet;
10472 if ((actual_type_is_void_err || actual_type_is_err_set) && wanted_type->id == TypeTableEntryIdInt) {
10473 return ir_analyze_err_to_int(ira, source_instr, value, wanted_type);
10474 }
10475
10476 // explicit cast from integer to error set
10477 if (wanted_type->id == TypeTableEntryIdErrorSet && actual_type->id == TypeTableEntryIdInt &&
10478 !actual_type->data.integral.is_signed)
10479 {
10480 return ir_analyze_int_to_err(ira, source_instr, value, wanted_type);
10481 }
10482
10483 // explicit cast from integer to enum type with no payload10488 // explicit cast from integer to enum type with no payload
10484 if (actual_type->id == TypeTableEntryIdInt && wanted_type->id == TypeTableEntryIdEnum) {10489 if (actual_type->id == TypeTableEntryIdInt && wanted_type->id == TypeTableEntryIdEnum) {
10485 return ir_analyze_int_to_enum(ira, source_instr, value, wanted_type);10490 return ir_analyze_int_to_enum(ira, source_instr, value, wanted_type);
...@@ -17785,6 +17790,39 @@ static TypeTableEntry *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrIns...@@ -17785,6 +17790,39 @@ static TypeTableEntry *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrIns
17785 return dest_type;17790 return dest_type;
17786}17791}
1778717792
17793static TypeTableEntry *ir_analyze_instruction_err_to_int(IrAnalyze *ira, IrInstructionErrToInt *instruction) {
17794 IrInstruction *target = instruction->target->other;
17795 if (type_is_invalid(target->value.type))
17796 return ira->codegen->builtin_types.entry_invalid;
17797
17798 IrInstruction *casted_target;
17799 if (target->value.type->id == TypeTableEntryIdErrorSet) {
17800 casted_target = target;
17801 } else {
17802 casted_target = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_global_error_set);
17803 if (type_is_invalid(casted_target->value.type))
17804 return ira->codegen->builtin_types.entry_invalid;
17805 }
17806
17807 IrInstruction *result = ir_analyze_err_to_int(ira, &instruction->base, casted_target, ira->codegen->err_tag_type);
17808 ir_link_new_instruction(result, &instruction->base);
17809 return result->value.type;
17810}
17811
17812static TypeTableEntry *ir_analyze_instruction_int_to_err(IrAnalyze *ira, IrInstructionIntToErr *instruction) {
17813 IrInstruction *target = instruction->target->other;
17814 if (type_is_invalid(target->value.type))
17815 return ira->codegen->builtin_types.entry_invalid;
17816
17817 IrInstruction *casted_target = ir_implicit_cast(ira, target, ira->codegen->err_tag_type);
17818 if (type_is_invalid(casted_target->value.type))
17819 return ira->codegen->builtin_types.entry_invalid;
17820
17821 IrInstruction *result = ir_analyze_int_to_err(ira, &instruction->base, casted_target, ira->codegen->builtin_types.entry_global_error_set);
17822 ir_link_new_instruction(result, &instruction->base);
17823 return result->value.type;
17824}
17825
17788static TypeTableEntry *ir_analyze_instruction_bool_to_int(IrAnalyze *ira, IrInstructionBoolToInt *instruction) {17826static TypeTableEntry *ir_analyze_instruction_bool_to_int(IrAnalyze *ira, IrInstructionBoolToInt *instruction) {
17789 IrInstruction *target = instruction->target->other;17827 IrInstruction *target = instruction->target->other;
17790 if (type_is_invalid(target->value.type))17828 if (type_is_invalid(target->value.type))
...@@ -20229,8 +20267,6 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -20229,8 +20267,6 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
20229 case IrInstructionIdInvalid:20267 case IrInstructionIdInvalid:
20230 case IrInstructionIdWidenOrShorten:20268 case IrInstructionIdWidenOrShorten:
20231 case IrInstructionIdIntToEnum:20269 case IrInstructionIdIntToEnum:
20232 case IrInstructionIdIntToErr:
20233 case IrInstructionIdErrToInt:
20234 case IrInstructionIdStructInit:20270 case IrInstructionIdStructInit:
20235 case IrInstructionIdUnionInit:20271 case IrInstructionIdUnionInit:
20236 case IrInstructionIdStructFieldPtr:20272 case IrInstructionIdStructFieldPtr:
...@@ -20491,6 +20527,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi...@@ -20491,6 +20527,10 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
20491 return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);20527 return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);
20492 case IrInstructionIdSqrt:20528 case IrInstructionIdSqrt:
20493 return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction);20529 return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction);
20530 case IrInstructionIdIntToErr:
20531 return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction);
20532 case IrInstructionIdErrToInt:
20533 return ir_analyze_instruction_err_to_int(ira, (IrInstructionErrToInt *)instruction);
20494 }20534 }
20495 zig_unreachable();20535 zig_unreachable();
20496}20536}
std/os/child_process.zig+2-2
...@@ -318,7 +318,7 @@ pub const ChildProcess = struct {...@@ -318,7 +318,7 @@ pub const ChildProcess = struct {
318 // Here we potentially return the fork child's error318 // Here we potentially return the fork child's error
319 // from the parent pid.319 // from the parent pid.
320 if (err_int != @maxValue(ErrInt)) {320 if (err_int != @maxValue(ErrInt)) {
321 return SpawnError(err_int);321 return @errSetCast(SpawnError, @intToError(err_int));
322 }322 }
323323
324 return statusToTerm(status);324 return statusToTerm(status);
...@@ -756,7 +756,7 @@ fn destroyPipe(pipe: *const [2]i32) void {...@@ -756,7 +756,7 @@ fn destroyPipe(pipe: *const [2]i32) void {
756// Child of fork calls this to report an error to the fork parent.756// Child of fork calls this to report an error to the fork parent.
757// Then the child exits.757// Then the child exits.
758fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {758fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
759 _ = writeIntFd(fd, ErrInt(err));759 _ = writeIntFd(fd, ErrInt(@errorToInt(err)));
760 posix.exit(1);760 posix.exit(1);
761}761}
762762
test/cases/cast.zig+2-2
...@@ -140,8 +140,8 @@ test "explicit cast from integer to error type" {...@@ -140,8 +140,8 @@ test "explicit cast from integer to error type" {
140 comptime testCastIntToErr(error.ItBroke);140 comptime testCastIntToErr(error.ItBroke);
141}141}
142fn testCastIntToErr(err: error) void {142fn testCastIntToErr(err: error) void {
143 const x = usize(err);143 const x = @errorToInt(err);
144 const y = error(x);144 const y = @intToError(x);
145 assert(error.ItBroke == y);145 assert(error.ItBroke == y);
146}146}
147147
test/cases/error.zig+5-5
...@@ -31,8 +31,8 @@ test "@errorName" {...@@ -31,8 +31,8 @@ test "@errorName" {
31}31}
3232
33test "error values" {33test "error values" {
34 const a = i32(error.err1);34 const a = @errorToInt(error.err1);
35 const b = i32(error.err2);35 const b = @errorToInt(error.err2);
36 assert(a != b);36 assert(a != b);
37}37}
3838
...@@ -147,14 +147,14 @@ test "syntax: optional operator in front of error union operator" {...@@ -147,14 +147,14 @@ test "syntax: optional operator in front of error union operator" {
147}147}
148148
149test "comptime err to int of error set with only 1 possible value" {149test "comptime err to int of error set with only 1 possible value" {
150 testErrToIntWithOnePossibleValue(error.A, u32(error.A));150 testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
151 comptime testErrToIntWithOnePossibleValue(error.A, u32(error.A));151 comptime testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
152}152}
153fn testErrToIntWithOnePossibleValue(153fn testErrToIntWithOnePossibleValue(
154 x: error{A},154 x: error{A},
155 comptime value: u32,155 comptime value: u32,
156) void {156) void {
157 if (u32(x) != value) {157 if (@errorToInt(x) != value) {
158 @compileError("bad");158 @compileError("bad");
159 }159 }
160}160}
test/cases/type_info.zig+1-1
...@@ -130,7 +130,7 @@ fn testErrorSet() void {...@@ -130,7 +130,7 @@ fn testErrorSet() void {
130 assert(TypeId(error_set_info) == TypeId.ErrorSet);130 assert(TypeId(error_set_info) == TypeId.ErrorSet);
131 assert(error_set_info.ErrorSet.errors.len == 3);131 assert(error_set_info.ErrorSet.errors.len == 3);
132 assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));132 assert(mem.eql(u8, error_set_info.ErrorSet.errors[0].name, "First"));
133 assert(error_set_info.ErrorSet.errors[2].value == usize(TestErrorSet.Third));133 assert(error_set_info.ErrorSet.errors[2].value == @errorToInt(TestErrorSet.Third));
134134
135 const error_union_info = @typeInfo(TestErrorSet!usize);135 const error_union_info = @typeInfo(TestErrorSet!usize);
136 assert(TypeId(error_union_info) == TypeId.ErrorUnion);136 assert(TypeId(error_union_info) == TypeId.ErrorUnion);
test/compile_errors.zig+18-20
...@@ -467,25 +467,34 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -467,25 +467,34 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
467467
468 cases.add(468 cases.add(
469 "int to err global invalid number",469 "int to err global invalid number",
470 \\const Set1 = error{A, B};470 \\const Set1 = error{
471 \\ A,
472 \\ B,
473 \\};
471 \\comptime {474 \\comptime {
472 \\ var x: usize = 3;475 \\ var x: u16 = 3;
473 \\ var y = error(x);476 \\ var y = @intToError(x);
474 \\}477 \\}
475 ,478 ,
476 ".tmp_source.zig:4:18: error: integer value 3 represents no error",479 ".tmp_source.zig:7:13: error: integer value 3 represents no error",
477 );480 );
478481
479 cases.add(482 cases.add(
480 "int to err non global invalid number",483 "int to err non global invalid number",
481 \\const Set1 = error{A, B};484 \\const Set1 = error{
482 \\const Set2 = error{A, C};485 \\ A,
486 \\ B,
487 \\};
488 \\const Set2 = error{
489 \\ A,
490 \\ C,
491 \\};
483 \\comptime {492 \\comptime {
484 \\ var x = usize(Set1.B);493 \\ var x = @errorToInt(Set1.B);
485 \\ var y = Set2(x);494 \\ var y = @errSetCast(Set2, @intToError(x));
486 \\}495 \\}
487 ,496 ,
488 ".tmp_source.zig:5:17: error: integer value 2 represents no error in 'Set2'",497 ".tmp_source.zig:11:13: error: error.B not a member of error set 'Set2'",
489 );498 );
490499
491 cases.add(500 cases.add(
...@@ -2612,17 +2621,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -2612,17 +2621,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
2612 ".tmp_source.zig:2:21: error: expected pointer, found 'usize'",2621 ".tmp_source.zig:2:21: error: expected pointer, found 'usize'",
2613 );2622 );
26142623
2615 cases.add(
2616 "too many error values to cast to small integer",
2617 \\const Error = error { A, B, C, D, E, F, G, H };
2618 \\fn foo(e: Error) u2 {
2619 \\ return u2(e);
2620 \\}
2621 \\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
2622 ,
2623 ".tmp_source.zig:3:14: error: too many error values to fit in 'u2'",
2624 );
2625
2626 cases.add(2624 cases.add(
2627 "asm at compile time",2625 "asm at compile time",
2628 \\comptime {2626 \\comptime {
test/runtime_safety.zig+7-7
...@@ -175,7 +175,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -175,7 +175,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
175 \\ if (x.len == 0) return error.Whatever;175 \\ if (x.len == 0) return error.Whatever;
176 \\}176 \\}
177 \\fn widenSlice(slice: []align(1) const u8) []align(1) const i32 {177 \\fn widenSlice(slice: []align(1) const u8) []align(1) const i32 {
178 \\ return ([]align(1) const i32)(slice);178 \\ return @bytesToSlice(i32, slice);
179 \\}179 \\}
180 );180 );
181181
...@@ -227,12 +227,12 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -227,12 +227,12 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
227 \\pub fn main() void {227 \\pub fn main() void {
228 \\ _ = bar(9999);228 \\ _ = bar(9999);
229 \\}229 \\}
230 \\fn bar(x: u32) error {230 \\fn bar(x: u16) error {
231 \\ return error(x);231 \\ return @intToError(x);
232 \\}232 \\}
233 );233 );
234234
235 cases.addRuntimeSafety("cast integer to non-global error set and no match",235 cases.addRuntimeSafety("@errSetCast error not present in destination",
236 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {236 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
237 \\ @import("std").os.exit(126);237 \\ @import("std").os.exit(126);
238 \\}238 \\}
...@@ -242,7 +242,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -242,7 +242,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
242 \\ _ = foo(Set1.B);242 \\ _ = foo(Set1.B);
243 \\}243 \\}
244 \\fn foo(set1: Set1) Set2 {244 \\fn foo(set1: Set1) Set2 {
245 \\ return Set2(set1);245 \\ return @errSetCast(Set2, set1);
246 \\}246 \\}
247 );247 );
248248
...@@ -252,12 +252,12 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {...@@ -252,12 +252,12 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
252 \\}252 \\}
253 \\pub fn main() !void {253 \\pub fn main() !void {
254 \\ var array align(4) = []u32{0x11111111, 0x11111111};254 \\ var array align(4) = []u32{0x11111111, 0x11111111};
255 \\ const bytes = ([]u8)(array[0..]);255 \\ const bytes = @sliceToBytes(array[0..]);
256 \\ if (foo(bytes) != 0x11111111) return error.Wrong;256 \\ if (foo(bytes) != 0x11111111) return error.Wrong;
257 \\}257 \\}
258 \\fn foo(bytes: []u8) u32 {258 \\fn foo(bytes: []u8) u32 {
259 \\ const slice4 = bytes[1..5];259 \\ const slice4 = bytes[1..5];
260 \\ const int_slice = ([]u32)(@alignCast(4, slice4));260 \\ const int_slice = @bytesToSlice(u32, @alignCast(4, slice4));
261 \\ return int_slice[0];261 \\ return int_slice[0];
262 \\}262 \\}
263 );263 );