authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2018-06-19 11:40:21-04:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2018-06-19 11:40:21-04:00
log9f2324389d4aec5d38e840ab09fd9af558a77913
tree685b621eb041c178af40c0044c74f689d8d6af7b
parent1ca90b585692c9611c64412844d2f3a7b3e11340
parenta3ddd0826bd9c799768c0c707de72c21befa742a
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #1134 from ziglang/no-explicit-casting

remove "cast harder" casting syntax; add new casting builtins

24 files changed, 697 insertions(+), 222 deletions(-)

doc/langref.html.in+122-28
......@@ -1456,8 +1456,7 @@ test "pointer array access" {
14561456 // Taking an address of an individual element gives a
14571457 // pointer to a single item. This kind of pointer
14581458 // does not support pointer arithmetic.
1459
1460 var array = []u8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
1459 var array = []u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
14611460 const ptr = &array[2];
14621461 assert(@typeOf(ptr) == *u8);
14631462
......@@ -1469,7 +1468,7 @@ test "pointer array access" {
14691468test "pointer slicing" {
14701469 // In Zig, we prefer using slices over null-terminated pointers.
14711470 // You can turn an array into a slice using slice syntax:
1472 var array = []u8{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
1471 var array = []u8{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
14731472 const slice = array[2..4];
14741473 assert(slice.len == 2);
14751474
......@@ -1541,13 +1540,13 @@ test "pointer casting" {
15411540 // To convert one pointer type to another, use @ptrCast. This is an unsafe
15421541 // operation that Zig cannot protect you against. Use @ptrCast only when other
15431542 // conversions are not possible.
1544 const bytes align(@alignOf(u32)) = []u8{0x12, 0x12, 0x12, 0x12};
1543 const bytes align(@alignOf(u32)) = []u8{ 0x12, 0x12, 0x12, 0x12 };
15451544 const u32_ptr = @ptrCast(*const u32, &bytes[0]);
15461545 assert(u32_ptr.* == 0x12121212);
15471546
15481547 // Even this example is contrived - there are better ways to do the above than
15491548 // pointer casting. For example, using a slice narrowing cast:
1550 const u32_value = ([]const u32)(bytes[0..])[0];
1549 const u32_value = @bytesToSlice(u32, bytes[0..])[0];
15511550 assert(u32_value == 0x12121212);
15521551
15531552 // And even another way, the most straightforward way to do it:
......@@ -1630,13 +1629,13 @@ test "function alignment" {
16301629const assert = @import("std").debug.assert;
16311630
16321631test "pointer alignment safety" {
1633 var array align(4) = []u32{0x11111111, 0x11111111};
1634 const bytes = ([]u8)(array[0..]);
1632 var array align(4) = []u32{ 0x11111111, 0x11111111 };
1633 const bytes = @sliceToBytes(array[0..]);
16351634 assert(foo(bytes) == 0x11111111);
16361635}
16371636fn foo(bytes: []u8) u32 {
16381637 const slice4 = bytes[1..5];
1639 const int_slice = ([]u32)(@alignCast(4, slice4));
1638 const int_slice = @bytesToSlice(u32, @alignCast(4, slice4));
16401639 return int_slice[0];
16411640}
16421641 {#code_end#}
......@@ -1728,8 +1727,8 @@ test "slice pointer" {
17281727test "slice widening" {
17291728 // Zig supports slice widening and slice narrowing. Cast a slice of u8
17301729 // to a slice of anything else, and Zig will perform the length conversion.
1731 const array align(@alignOf(u32)) = []u8{0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13};
1732 const slice = ([]const u32)(array[0..]);
1730 const array align(@alignOf(u32)) = []u8{ 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13 };
1731 const slice = @bytesToSlice(u32, array[0..]);
17331732 assert(slice.len == 2);
17341733 assert(slice[0] == 0x12121212);
17351734 assert(slice[1] == 0x13131313);
......@@ -1901,9 +1900,9 @@ const Value = enum(u2) {
19011900// Now you can cast between u2 and Value.
19021901// The ordinal value starts from 0, counting up for each member.
19031902test "enum ordinal value" {
1904 assert(u2(Value.Zero) == 0);
1905 assert(u2(Value.One) == 1);
1906 assert(u2(Value.Two) == 2);
1903 assert(@enumToInt(Value.Zero) == 0);
1904 assert(@enumToInt(Value.One) == 1);
1905 assert(@enumToInt(Value.Two) == 2);
19071906}
19081907
19091908// You can override the ordinal value for an enum.
......@@ -1913,9 +1912,9 @@ const Value2 = enum(u32) {
19131912 Million = 1000000,
19141913};
19151914test "set enum ordinal value" {
1916 assert(u32(Value2.Hundred) == 100);
1917 assert(u32(Value2.Thousand) == 1000);
1918 assert(u32(Value2.Million) == 1000000);
1915 assert(@enumToInt(Value2.Hundred) == 100);
1916 assert(@enumToInt(Value2.Thousand) == 1000);
1917 assert(@enumToInt(Value2.Million) == 1000000);
19191918}
19201919
19211920// Enums can have methods, the same as structs and unions.
......@@ -4651,6 +4650,18 @@ comptime {
46514650 </p>
46524651 {#header_close#}
46534652
4653 {#header_open|@bytesToSlice#}
4654 <pre><code class="zig">@bytesToSlice(comptime Element: type, bytes: []u8) []Element</code></pre>
4655 <p>
4656 Converts a slice of bytes or array of bytes into a slice of <code>Element</code>.
4657 The resulting slice has the same {#link|pointer|Pointers#} properties as the parameter.
4658 </p>
4659 <p>
4660 Attempting to convert a number of bytes with a length that does not evenly divide into a slice of
4661 elements results in safety-protected {#link|Undefined Behavior#}.
4662 </p>
4663 {#header_close#}
4664
46544665 {#header_open|@cDefine#}
46554666 <pre><code class="zig">@cDefine(comptime name: []u8, value)</code></pre>
46564667 <p>
......@@ -4919,12 +4930,23 @@ test "main" {
49194930 </p>
49204931 {#see_also|@import#}
49214932 {#header_close#}
4922 {#header_open|@export#}
4923 <pre><code class="zig">@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8</code></pre>
4933
4934 {#header_open|@enumToInt#}
4935 <pre><code class="zig">@enumToInt(enum_value: var) var</code></pre>
49244936 <p>
4925 Creates a symbol in the output object file.
4937 Converts an enumeration value into its integer tag type.
4938 </p>
4939 {#see_also|@intToEnum#}
4940 {#header_close#}
4941
4942 {#header_open|@errSetCast#}
4943 <pre><code class="zig">@errSetCast(comptime T: DestType, value: var) DestType</code></pre>
4944 <p>
4945 Converts an error value from one error set to another error set. Attempting to convert an error
4946 which is not in the destination error set results in safety-protected {#link|Undefined Behavior#}.
49264947 </p>
49274948 {#header_close#}
4949
49284950 {#header_open|@errorName#}
49294951 <pre><code class="zig">@errorName(err: error) []u8</code></pre>
49304952 <p>
......@@ -4941,6 +4963,7 @@ test "main" {
49414963 error name table will be generated.
49424964 </p>
49434965 {#header_close#}
4966
49444967 {#header_open|@errorReturnTrace#}
49454968 <pre><code class="zig">@errorReturnTrace() ?*builtin.StackTrace</code></pre>
49464969 <p>
......@@ -4949,6 +4972,33 @@ test "main" {
49494972 stack trace object. Otherwise returns `null`.
49504973 </p>
49514974 {#header_close#}
4975
4976 {#header_open|@errorToInt#}
4977 <pre><code class="zig">@errorToInt(err: var) @IntType(false, @sizeOf(error) * 8)</code></pre>
4978 <p>
4979 Supports the following types:
4980 </p>
4981 <ul>
4982 <li>error unions</li>
4983 <li><code>E!void</code></li>
4984 </ul>
4985 <p>
4986 Converts an error to the integer representation of an error.
4987 </p>
4988 <p>
4989 It is generally recommended to avoid this
4990 cast, as the integer representation of an error is not stable across source code changes.
4991 </p>
4992 {#see_also|@intToError#}
4993 {#header_close#}
4994
4995 {#header_open|@export#}
4996 <pre><code class="zig">@export(comptime name: []const u8, target: var, linkage: builtin.GlobalLinkage) []const u8</code></pre>
4997 <p>
4998 Creates a symbol in the output object file.
4999 </p>
5000 {#header_close#}
5001
49525002 {#header_open|@fence#}
49535003 <pre><code class="zig">@fence(order: AtomicOrder)</code></pre>
49545004 <p>
......@@ -5049,8 +5099,36 @@ fn add(a: i32, b: i32) i32 { return a + b; }
50495099 <p>
50505100 Converts an integer to another integer while keeping the same numerical value.
50515101 Attempting to convert a number which is out of range of the destination type results in
5052 {#link|Undefined Behavior#}.
5102 safety-protected {#link|Undefined Behavior#}.
5103 </p>
5104 {#header_close#}
5105
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
5118 {#header_open|@intToError#}
5119 <pre><code class="zig">@intToError(value: @IntType(false, @sizeOf(error) * 8)) error</code></pre>
5120 <p>
5121 Converts from the integer representation of an error into the global error set type.
50535122 </p>
5123 <p>
5124 It is generally recommended to avoid this
5125 cast, as the integer representation of an error is not stable across source code changes.
5126 </p>
5127 <p>
5128 Attempting to convert an integer that does not correspond to any error results in
5129 safety-protected {#link|Undefined Behavior#}.
5130 </p>
5131 {#see_also|@errorToInt#}
50545132 {#header_close#}
50555133
50565134 {#header_open|@intToFloat#}
......@@ -5456,8 +5534,9 @@ pub const FloatMode = enum {
54565534 </p>
54575535 {#see_also|@shlExact|@shlWithOverflow#}
54585536 {#header_close#}
5537
54595538 {#header_open|@sizeOf#}
5460 <pre><code class="zig">@sizeOf(comptime T: type) (number literal)</code></pre>
5539 <pre><code class="zig">@sizeOf(comptime T: type) comptime_int</code></pre>
54615540 <p>
54625541 This function returns the number of bytes it takes to store <code>T</code> in memory.
54635542 </p>
......@@ -5465,6 +5544,15 @@ pub const FloatMode = enum {
54655544 The result is a target-specific compile time constant.
54665545 </p>
54675546 {#header_close#}
5547
5548 {#header_open|@sliceToBytes#}
5549 <pre><code class="zig">@sliceToBytes(value: var) []u8</code></pre>
5550 <p>
5551 Converts a slice or array to a slice of <code>u8</code>. The resulting slice has the same
5552 {#link|pointer|Pointers#} properties as the parameter.
5553 </p>
5554 {#header_close#}
5555
54685556 {#header_open|@sqrt#}
54695557 <pre><code class="zig">@sqrt(comptime T: type, value: T) T</code></pre>
54705558 <p>
......@@ -5817,10 +5905,10 @@ pub fn build(b: &Builder) void {
58175905 {#header_open|Undefined Behavior#}
58185906 <p>
58195907 Zig has many instances of undefined behavior. If undefined behavior is
5820 detected at compile-time, Zig emits an error. Most undefined behavior that
5821 cannot be detected at compile-time can be detected at runtime. In these cases,
5822 Zig has safety checks. Safety checks can be disabled on a per-block basis
5823 with {#link|setRuntimeSafety#}. The {#link|ReleaseFast#}
5908 detected at compile-time, Zig emits a compile error and refuses to continue.
5909 Most undefined behavior that cannot be detected at compile-time can be detected
5910 at runtime. In these cases, Zig has safety checks. Safety checks can be disabled
5911 on a per-block basis with {#link|setRuntimeSafety#}. The {#link|ReleaseFast#}
58245912 build mode disables all safety checks in order to facilitate optimizations.
58255913 </p>
58265914 <p>
......@@ -6091,8 +6179,8 @@ fn getNumberOrFail() !i32 {
60916179 {#code_begin|test_err|integer value 11 represents no error#}
60926180comptime {
60936181 const err = error.AnError;
6094 const number = u32(err) + 10;
6095 const invalid_err = error(number);
6182 const number = @errorToInt(err) + 10;
6183 const invalid_err = @intToError(number);
60966184}
60976185 {#code_end#}
60986186 <p>At runtime crashes with the message <code>invalid error code</code> and a stack trace.</p>
......@@ -6101,6 +6189,11 @@ comptime {
61016189 <p>TODO</p>
61026190
61036191 {#header_close#}
6192
6193 {#header_open|Invalid Error Set Cast#}
6194 <p>TODO</p>
6195 {#header_close#}
6196
61046197 {#header_open|Incorrect Pointer Alignment#}
61056198 <p>TODO</p>
61066199
......@@ -6109,6 +6202,7 @@ comptime {
61096202 <p>TODO</p>
61106203
61116204 {#header_close#}
6205
61126206 {#header_close#}
61136207 {#header_open|Memory#}
61146208 <p>TODO: explain no default allocator in zig</p>
......@@ -6793,7 +6887,7 @@ hljs.registerLanguage("zig", function(t) {
67936887 a = t.IR + "\\s*\\(",
67946888 c = {
67956889 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",
6796 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 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",
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",
67976891 literal: "true false null undefined"
67986892 },
67996893 n = [e, t.CLCM, t.CBCM, s, r];
src/all_types.hpp+49
......@@ -234,6 +234,16 @@ enum RuntimeHintPtr {
234234 RuntimeHintPtrNonStack,
235235};
236236
237enum RuntimeHintSliceId {
238 RuntimeHintSliceIdUnknown,
239 RuntimeHintSliceIdLen,
240};
241
242struct RuntimeHintSlice {
243 enum RuntimeHintSliceId id;
244 uint64_t len;
245};
246
237247struct ConstGlobalRefs {
238248 LLVMValueRef llvm_value;
239249 LLVMValueRef llvm_global;
......@@ -270,6 +280,7 @@ struct ConstExprValue {
270280 RuntimeHintErrorUnion rh_error_union;
271281 RuntimeHintOptional rh_maybe;
272282 RuntimeHintPtr rh_ptr;
283 RuntimeHintSlice rh_slice;
273284 } data;
274285};
275286
......@@ -1359,9 +1370,16 @@ enum BuiltinFnId {
13591370 BuiltinFnIdTruncate,
13601371 BuiltinFnIdIntCast,
13611372 BuiltinFnIdFloatCast,
1373 BuiltinFnIdErrSetCast,
1374 BuiltinFnIdToBytes,
1375 BuiltinFnIdFromBytes,
13621376 BuiltinFnIdIntToFloat,
13631377 BuiltinFnIdFloatToInt,
13641378 BuiltinFnIdBoolToInt,
1379 BuiltinFnIdErrToInt,
1380 BuiltinFnIdIntToErr,
1381 BuiltinFnIdEnumToInt,
1382 BuiltinFnIdIntToEnum,
13651383 BuiltinFnIdIntType,
13661384 BuiltinFnIdSetCold,
13671385 BuiltinFnIdSetRuntimeSafety,
......@@ -2076,6 +2094,7 @@ enum IrInstructionId {
20762094 IrInstructionIdIntToPtr,
20772095 IrInstructionIdPtrToInt,
20782096 IrInstructionIdIntToEnum,
2097 IrInstructionIdEnumToInt,
20792098 IrInstructionIdIntToErr,
20802099 IrInstructionIdErrToInt,
20812100 IrInstructionIdCheckSwitchProngs,
......@@ -2121,6 +2140,9 @@ enum IrInstructionId {
21212140 IrInstructionIdMergeErrRetTraces,
21222141 IrInstructionIdMarkErrRetTracePtr,
21232142 IrInstructionIdSqrt,
2143 IrInstructionIdErrSetCast,
2144 IrInstructionIdToBytes,
2145 IrInstructionIdFromBytes,
21242146};
21252147
21262148struct IrInstruction {
......@@ -2656,6 +2678,26 @@ struct IrInstructionFloatCast {
26562678 IrInstruction *target;
26572679};
26582680
2681struct IrInstructionErrSetCast {
2682 IrInstruction base;
2683
2684 IrInstruction *dest_type;
2685 IrInstruction *target;
2686};
2687
2688struct IrInstructionToBytes {
2689 IrInstruction base;
2690
2691 IrInstruction *target;
2692};
2693
2694struct IrInstructionFromBytes {
2695 IrInstruction base;
2696
2697 IrInstruction *dest_child_type;
2698 IrInstruction *target;
2699};
2700
26592701struct IrInstructionIntToFloat {
26602702 IrInstruction base;
26612703
......@@ -2866,6 +2908,13 @@ struct IrInstructionIntToPtr {
28662908struct IrInstructionIntToEnum {
28672909 IrInstruction base;
28682910
2911 IrInstruction *dest_type;
2912 IrInstruction *target;
2913};
2914
2915struct IrInstructionEnumToInt {
2916 IrInstruction base;
2917
28692918 IrInstruction *target;
28702919};
28712920
src/codegen.cpp+11
......@@ -4727,6 +4727,10 @@ static LLVMValueRef ir_render_instruction(CodeGen *g, IrExecutable *executable,
47274727 case IrInstructionIdIntToFloat:
47284728 case IrInstructionIdFloatToInt:
47294729 case IrInstructionIdBoolToInt:
4730 case IrInstructionIdErrSetCast:
4731 case IrInstructionIdFromBytes:
4732 case IrInstructionIdToBytes:
4733 case IrInstructionIdEnumToInt:
47304734 zig_unreachable();
47314735
47324736 case IrInstructionIdReturn:
......@@ -6320,6 +6324,10 @@ static void define_builtin_fns(CodeGen *g) {
63206324 create_builtin_fn(g, BuiltinFnIdIntToFloat, "intToFloat", 2);
63216325 create_builtin_fn(g, BuiltinFnIdFloatToInt, "floatToInt", 2);
63226326 create_builtin_fn(g, BuiltinFnIdBoolToInt, "boolToInt", 1);
6327 create_builtin_fn(g, BuiltinFnIdErrToInt, "errorToInt", 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);
63236331 create_builtin_fn(g, BuiltinFnIdCompileErr, "compileError", 1);
63246332 create_builtin_fn(g, BuiltinFnIdCompileLog, "compileLog", SIZE_MAX);
63256333 create_builtin_fn(g, BuiltinFnIdIntType, "IntType", 2); // TODO rename to Int
......@@ -6356,6 +6364,9 @@ static void define_builtin_fns(CodeGen *g) {
63566364 create_builtin_fn(g, BuiltinFnIdErrorReturnTrace, "errorReturnTrace", 0);
63576365 create_builtin_fn(g, BuiltinFnIdAtomicRmw, "atomicRmw", 5);
63586366 create_builtin_fn(g, BuiltinFnIdAtomicLoad, "atomicLoad", 3);
6367 create_builtin_fn(g, BuiltinFnIdErrSetCast, "errSetCast", 2);
6368 create_builtin_fn(g, BuiltinFnIdToBytes, "sliceToBytes", 1);
6369 create_builtin_fn(g, BuiltinFnIdFromBytes, "bytesToSlice", 2);
63596370}
63606371
63616372static const char *bool_to_str(bool b) {
src/ir.cpp+389-90
......@@ -468,6 +468,18 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionFloatCast *) {
468468 return IrInstructionIdFloatCast;
469469}
470470
471static constexpr IrInstructionId ir_instruction_id(IrInstructionErrSetCast *) {
472 return IrInstructionIdErrSetCast;
473}
474
475static constexpr IrInstructionId ir_instruction_id(IrInstructionToBytes *) {
476 return IrInstructionIdToBytes;
477}
478
479static constexpr IrInstructionId ir_instruction_id(IrInstructionFromBytes *) {
480 return IrInstructionIdFromBytes;
481}
482
471483static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToFloat *) {
472484 return IrInstructionIdIntToFloat;
473485}
......@@ -588,6 +600,10 @@ static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToEnum *) {
588600 return IrInstructionIdIntToEnum;
589601}
590602
603static constexpr IrInstructionId ir_instruction_id(IrInstructionEnumToInt *) {
604 return IrInstructionIdEnumToInt;
605}
606
591607static constexpr IrInstructionId ir_instruction_id(IrInstructionIntToErr *) {
592608 return IrInstructionIdIntToErr;
593609}
......@@ -1941,6 +1957,37 @@ static IrInstruction *ir_build_float_cast(IrBuilder *irb, Scope *scope, AstNode
19411957 return &instruction->base;
19421958}
19431959
1960static IrInstruction *ir_build_err_set_cast(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *target) {
1961 IrInstructionErrSetCast *instruction = ir_build_instruction<IrInstructionErrSetCast>(irb, scope, source_node);
1962 instruction->dest_type = dest_type;
1963 instruction->target = target;
1964
1965 ir_ref_instruction(dest_type, irb->current_basic_block);
1966 ir_ref_instruction(target, irb->current_basic_block);
1967
1968 return &instruction->base;
1969}
1970
1971static IrInstruction *ir_build_to_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *target) {
1972 IrInstructionToBytes *instruction = ir_build_instruction<IrInstructionToBytes>(irb, scope, source_node);
1973 instruction->target = target;
1974
1975 ir_ref_instruction(target, irb->current_basic_block);
1976
1977 return &instruction->base;
1978}
1979
1980static IrInstruction *ir_build_from_bytes(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_child_type, IrInstruction *target) {
1981 IrInstructionFromBytes *instruction = ir_build_instruction<IrInstructionFromBytes>(irb, scope, source_node);
1982 instruction->dest_child_type = dest_child_type;
1983 instruction->target = target;
1984
1985 ir_ref_instruction(dest_child_type, irb->current_basic_block);
1986 ir_ref_instruction(target, irb->current_basic_block);
1987
1988 return &instruction->base;
1989}
1990
19441991static IrInstruction *ir_build_int_to_float(IrBuilder *irb, Scope *scope, AstNode *source_node, IrInstruction *dest_type, IrInstruction *target) {
19451992 IrInstructionIntToFloat *instruction = ir_build_instruction<IrInstructionIntToFloat>(irb, scope, source_node);
19461993 instruction->dest_type = dest_type;
......@@ -2335,10 +2382,26 @@ static IrInstruction *ir_build_ptr_to_int(IrBuilder *irb, Scope *scope, AstNode
23352382}
23362383
23372384static IrInstruction *ir_build_int_to_enum(IrBuilder *irb, Scope *scope, AstNode *source_node,
2338 IrInstruction *target)
2385 IrInstruction *dest_type, IrInstruction *target)
23392386{
23402387 IrInstructionIntToEnum *instruction = ir_build_instruction<IrInstructionIntToEnum>(
23412388 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);
23422405 instruction->target = target;
23432406
23442407 ir_ref_instruction(target, irb->current_basic_block);
......@@ -4054,6 +4117,46 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
40544117 IrInstruction *result = ir_build_float_cast(irb, scope, node, arg0_value, arg1_value);
40554118 return ir_lval_wrap(irb, scope, result, lval);
40564119 }
4120 case BuiltinFnIdErrSetCast:
4121 {
4122 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4123 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4124 if (arg0_value == irb->codegen->invalid_instruction)
4125 return arg0_value;
4126
4127 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4128 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
4129 if (arg1_value == irb->codegen->invalid_instruction)
4130 return arg1_value;
4131
4132 IrInstruction *result = ir_build_err_set_cast(irb, scope, node, arg0_value, arg1_value);
4133 return ir_lval_wrap(irb, scope, result, lval);
4134 }
4135 case BuiltinFnIdFromBytes:
4136 {
4137 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4138 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4139 if (arg0_value == irb->codegen->invalid_instruction)
4140 return arg0_value;
4141
4142 AstNode *arg1_node = node->data.fn_call_expr.params.at(1);
4143 IrInstruction *arg1_value = ir_gen_node(irb, arg1_node, scope);
4144 if (arg1_value == irb->codegen->invalid_instruction)
4145 return arg1_value;
4146
4147 IrInstruction *result = ir_build_from_bytes(irb, scope, node, arg0_value, arg1_value);
4148 return ir_lval_wrap(irb, scope, result, lval);
4149 }
4150 case BuiltinFnIdToBytes:
4151 {
4152 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4153 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4154 if (arg0_value == irb->codegen->invalid_instruction)
4155 return arg0_value;
4156
4157 IrInstruction *result = ir_build_to_bytes(irb, scope, node, arg0_value);
4158 return ir_lval_wrap(irb, scope, result, lval);
4159 }
40574160 case BuiltinFnIdIntToFloat:
40584161 {
40594162 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
......@@ -4084,6 +4187,26 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
40844187 IrInstruction *result = ir_build_float_to_int(irb, scope, node, arg0_value, arg1_value);
40854188 return ir_lval_wrap(irb, scope, result, lval);
40864189 }
4190 case BuiltinFnIdErrToInt:
4191 {
4192 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4193 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4194 if (arg0_value == irb->codegen->invalid_instruction)
4195 return arg0_value;
4196
4197 IrInstruction *result = ir_build_err_to_int(irb, scope, node, arg0_value);
4198 return ir_lval_wrap(irb, scope, result, lval);
4199 }
4200 case BuiltinFnIdIntToErr:
4201 {
4202 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
4203 IrInstruction *arg0_value = ir_gen_node(irb, arg0_node, scope);
4204 if (arg0_value == irb->codegen->invalid_instruction)
4205 return arg0_value;
4206
4207 IrInstruction *result = ir_build_int_to_err(irb, scope, node, arg0_value);
4208 return ir_lval_wrap(irb, scope, result, lval);
4209 }
40874210 case BuiltinFnIdBoolToInt:
40884211 {
40894212 AstNode *arg0_node = node->data.fn_call_expr.params.at(0);
......@@ -4605,6 +4728,31 @@ static IrInstruction *ir_gen_builtin_fn_call(IrBuilder *irb, Scope *scope, AstNo
46054728 // this value does not mean anything since we passed non-null values for other arg
46064729 AtomicOrderMonotonic);
46074730 }
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 }
46084756 }
46094757 zig_unreachable();
46104758}
......@@ -9073,11 +9221,6 @@ static bool is_container(TypeTableEntry *type) {
90739221 type->id == TypeTableEntryIdUnion;
90749222}
90759223
9076static bool is_u8(TypeTableEntry *type) {
9077 return type->id == TypeTableEntryIdInt &&
9078 !type->data.integral.is_signed && type->data.integral.bit_count == 8;
9079}
9080
90819224static IrBasicBlock *ir_get_new_bb(IrAnalyze *ira, IrBasicBlock *old_bb, IrInstruction *ref_old_instruction) {
90829225 assert(old_bb);
90839226
......@@ -9631,6 +9774,8 @@ static IrInstruction *ir_analyze_array_to_slice(IrAnalyze *ira, IrInstruction *s
96319774 IrInstruction *result = ir_build_slice(&ira->new_irb, source_instr->scope,
96329775 source_instr->source_node, array_ptr, start, end, false);
96339776 result->value.type = wanted_type;
9777 result->value.data.rh_slice.id = RuntimeHintSliceIdLen;
9778 result->value.data.rh_slice.len = array_type->data.array.len;
96349779 ir_add_alloca(ira, result, result->value.type);
96359780
96369781 return result;
......@@ -9851,7 +9996,7 @@ static IrInstruction *ir_analyze_int_to_enum(IrAnalyze *ira, IrInstruction *sour
98519996 }
98529997
98539998 IrInstruction *result = ir_build_int_to_enum(&ira->new_irb, source_instr->scope,
9854 source_instr->source_node, target);
9999 source_instr->source_node, nullptr, target);
985510000 result->value.type = wanted_type;
985610001 return result;
985710002}
......@@ -10073,7 +10218,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1007310218 return ira->codegen->invalid_instruction;
1007410219 }
1007510220
10076 // explicit match or non-const to const
10221 // perfect match or non-const to const
1007710222 if (types_match_const_cast_only(ira, wanted_type, actual_type, source_node, false).id == ConstCastResultIdOk) {
1007810223 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpNoop, false);
1007910224 }
......@@ -10104,13 +10249,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1010410249 }
1010510250
1010610251
10107 // explicit error set cast
10108 if (wanted_type->id == TypeTableEntryIdErrorSet &&
10109 actual_type->id == TypeTableEntryIdErrorSet)
10110 {
10111 return ir_analyze_err_set_cast(ira, source_instr, value, wanted_type);
10112 }
10113
1011410252 // explicit cast from [N]T to []const T
1011510253 if (is_slice(wanted_type) && actual_type->id == TypeTableEntryIdArray) {
1011610254 TypeTableEntry *ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
......@@ -10142,7 +10280,7 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1014210280 }
1014310281 }
1014410282
10145 // explicit cast from [N]T to &const []const N
10283 // explicit cast from [N]T to &const []const T
1014610284 if (wanted_type->id == TypeTableEntryIdPointer &&
1014710285 wanted_type->data.pointer.is_const &&
1014810286 is_slice(wanted_type->data.pointer.child_type) &&
......@@ -10191,52 +10329,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1019110329 }
1019210330 }
1019310331
10194 // explicit cast from []T to []u8 or []u8 to []T
10195 if (is_slice(wanted_type) && is_slice(actual_type)) {
10196 TypeTableEntry *wanted_ptr_type = wanted_type->data.structure.fields[slice_ptr_index].type_entry;
10197 TypeTableEntry *actual_ptr_type = actual_type->data.structure.fields[slice_ptr_index].type_entry;
10198 if ((is_u8(wanted_ptr_type->data.pointer.child_type) || is_u8(actual_ptr_type->data.pointer.child_type)) &&
10199 (wanted_ptr_type->data.pointer.is_const || !actual_ptr_type->data.pointer.is_const))
10200 {
10201 uint32_t src_align_bytes = get_ptr_align(actual_ptr_type);
10202 uint32_t dest_align_bytes = get_ptr_align(wanted_ptr_type);
10203
10204 if (dest_align_bytes > src_align_bytes) {
10205 ErrorMsg *msg = ir_add_error(ira, source_instr,
10206 buf_sprintf("cast increases pointer alignment"));
10207 add_error_note(ira->codegen, msg, source_instr->source_node,
10208 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&actual_type->name), src_align_bytes));
10209 add_error_note(ira->codegen, msg, source_instr->source_node,
10210 buf_sprintf("'%s' has alignment %" PRIu32, buf_ptr(&wanted_type->name), dest_align_bytes));
10211 return ira->codegen->invalid_instruction;
10212 }
10213
10214 if (!ir_emit_global_runtime_side_effect(ira, source_instr))
10215 return ira->codegen->invalid_instruction;
10216 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpResizeSlice, true);
10217 }
10218 }
10219
10220 // explicit cast from [N]u8 to []const T
10221 if (is_slice(wanted_type) &&
10222 wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.is_const &&
10223 actual_type->id == TypeTableEntryIdArray &&
10224 is_u8(actual_type->data.array.child_type))
10225 {
10226 if (!ir_emit_global_runtime_side_effect(ira, source_instr))
10227 return ira->codegen->invalid_instruction;
10228 uint64_t child_type_size = type_size(ira->codegen,
10229 wanted_type->data.structure.fields[slice_ptr_index].type_entry->data.pointer.child_type);
10230 if (actual_type->data.array.len % child_type_size == 0) {
10231 return ir_resolve_cast(ira, source_instr, value, wanted_type, CastOpBytesToSlice, true);
10232 } else {
10233 ir_add_error_node(ira, source_instr->source_node,
10234 buf_sprintf("unable to convert %s to %s: size mismatch",
10235 buf_ptr(&actual_type->name), buf_ptr(&wanted_type->name)));
10236 return ira->codegen->invalid_instruction;
10237 }
10238 }
10239
1024010332 // explicit *[N]T to [*]T
1024110333 if (wanted_type->id == TypeTableEntryIdPointer &&
1024210334 wanted_type->data.pointer.ptr_len == PtrLenUnknown &&
......@@ -10438,31 +10530,6 @@ static IrInstruction *ir_analyze_cast(IrAnalyze *ira, IrInstruction *source_inst
1043810530 return ir_analyze_number_to_literal(ira, source_instr, value, wanted_type);
1043910531 }
1044010532
10441 // explicit cast from T!void to integer type which can fit it
10442 bool actual_type_is_void_err = actual_type->id == TypeTableEntryIdErrorUnion &&
10443 !type_has_bits(actual_type->data.error_union.payload_type);
10444 bool actual_type_is_err_set = actual_type->id == TypeTableEntryIdErrorSet;
10445 if ((actual_type_is_void_err || actual_type_is_err_set) && wanted_type->id == TypeTableEntryIdInt) {
10446 return ir_analyze_err_to_int(ira, source_instr, value, wanted_type);
10447 }
10448
10449 // explicit cast from integer to error set
10450 if (wanted_type->id == TypeTableEntryIdErrorSet && actual_type->id == TypeTableEntryIdInt &&
10451 !actual_type->data.integral.is_signed)
10452 {
10453 return ir_analyze_int_to_err(ira, source_instr, value, wanted_type);
10454 }
10455
10456 // explicit cast from integer to enum type with no payload
10457 if (actual_type->id == TypeTableEntryIdInt && wanted_type->id == TypeTableEntryIdEnum) {
10458 return ir_analyze_int_to_enum(ira, source_instr, value, wanted_type);
10459 }
10460
10461 // explicit cast from enum type with no payload to integer
10462 if (wanted_type->id == TypeTableEntryIdInt && actual_type->id == TypeTableEntryIdEnum) {
10463 return ir_analyze_enum_to_int(ira, source_instr, value, wanted_type);
10464 }
10465
1046610533 // explicit cast from union to the enum type of the union
1046710534 if (actual_type->id == TypeTableEntryIdUnion && wanted_type->id == TypeTableEntryIdEnum) {
1046810535 type_ensure_zero_bits_known(ira->codegen, actual_type);
......@@ -17593,6 +17660,137 @@ static TypeTableEntry *ir_analyze_instruction_float_cast(IrAnalyze *ira, IrInstr
1759317660 return dest_type;
1759417661}
1759517662
17663static TypeTableEntry *ir_analyze_instruction_err_set_cast(IrAnalyze *ira, IrInstructionErrSetCast *instruction) {
17664 TypeTableEntry *dest_type = ir_resolve_type(ira, instruction->dest_type->other);
17665 if (type_is_invalid(dest_type))
17666 return ira->codegen->builtin_types.entry_invalid;
17667
17668 if (dest_type->id != TypeTableEntryIdErrorSet) {
17669 ir_add_error(ira, instruction->dest_type,
17670 buf_sprintf("expected error set type, found '%s'", buf_ptr(&dest_type->name)));
17671 return ira->codegen->builtin_types.entry_invalid;
17672 }
17673
17674 IrInstruction *target = instruction->target->other;
17675 if (type_is_invalid(target->value.type))
17676 return ira->codegen->builtin_types.entry_invalid;
17677
17678 if (target->value.type->id != TypeTableEntryIdErrorSet) {
17679 ir_add_error(ira, instruction->target,
17680 buf_sprintf("expected error set type, found '%s'", buf_ptr(&target->value.type->name)));
17681 return ira->codegen->builtin_types.entry_invalid;
17682 }
17683
17684 IrInstruction *result = ir_analyze_err_set_cast(ira, &instruction->base, target, dest_type);
17685 if (type_is_invalid(result->value.type))
17686 return ira->codegen->builtin_types.entry_invalid;
17687 ir_link_new_instruction(result, &instruction->base);
17688 return dest_type;
17689}
17690
17691static TypeTableEntry *ir_analyze_instruction_from_bytes(IrAnalyze *ira, IrInstructionFromBytes *instruction) {
17692 TypeTableEntry *dest_child_type = ir_resolve_type(ira, instruction->dest_child_type->other);
17693 if (type_is_invalid(dest_child_type))
17694 return ira->codegen->builtin_types.entry_invalid;
17695
17696 IrInstruction *target = instruction->target->other;
17697 if (type_is_invalid(target->value.type))
17698 return ira->codegen->builtin_types.entry_invalid;
17699
17700 bool src_ptr_const;
17701 bool src_ptr_volatile;
17702 uint32_t src_ptr_align;
17703 if (target->value.type->id == TypeTableEntryIdPointer) {
17704 src_ptr_const = target->value.type->data.pointer.is_const;
17705 src_ptr_volatile = target->value.type->data.pointer.is_volatile;
17706 src_ptr_align = target->value.type->data.pointer.alignment;
17707 } else if (is_slice(target->value.type)) {
17708 TypeTableEntry *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry;
17709 src_ptr_const = src_ptr_type->data.pointer.is_const;
17710 src_ptr_volatile = src_ptr_type->data.pointer.is_volatile;
17711 src_ptr_align = src_ptr_type->data.pointer.alignment;
17712 } else {
17713 src_ptr_const = true;
17714 src_ptr_volatile = false;
17715 src_ptr_align = get_abi_alignment(ira->codegen, target->value.type);
17716 }
17717
17718 TypeTableEntry *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, dest_child_type,
17719 src_ptr_const, src_ptr_volatile, PtrLenUnknown,
17720 src_ptr_align, 0, 0);
17721 TypeTableEntry *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);
17722
17723 TypeTableEntry *u8_ptr = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
17724 src_ptr_const, src_ptr_volatile, PtrLenUnknown,
17725 src_ptr_align, 0, 0);
17726 TypeTableEntry *u8_slice = get_slice_type(ira->codegen, u8_ptr);
17727
17728 IrInstruction *casted_value = ir_implicit_cast(ira, target, u8_slice);
17729 if (type_is_invalid(casted_value->value.type))
17730 return ira->codegen->builtin_types.entry_invalid;
17731
17732 bool have_known_len = false;
17733 uint64_t known_len;
17734
17735 if (instr_is_comptime(casted_value)) {
17736 ConstExprValue *val = ir_resolve_const(ira, casted_value, UndefBad);
17737 if (!val)
17738 return ira->codegen->builtin_types.entry_invalid;
17739
17740 ConstExprValue *len_val = &val->data.x_struct.fields[slice_len_index];
17741 if (value_is_comptime(len_val)) {
17742 known_len = bigint_as_unsigned(&len_val->data.x_bigint);
17743 have_known_len = true;
17744 }
17745 }
17746
17747 if (casted_value->value.data.rh_slice.id == RuntimeHintSliceIdLen) {
17748 known_len = casted_value->value.data.rh_slice.len;
17749 have_known_len = true;
17750 }
17751
17752 if (have_known_len) {
17753 uint64_t child_type_size = type_size(ira->codegen, dest_child_type);
17754 uint64_t remainder = known_len % child_type_size;
17755 if (remainder != 0) {
17756 ErrorMsg *msg = ir_add_error(ira, &instruction->base,
17757 buf_sprintf("unable to convert [%" ZIG_PRI_u64 "]u8 to %s: size mismatch",
17758 known_len, buf_ptr(&dest_slice_type->name)));
17759 add_error_note(ira->codegen, msg, instruction->dest_child_type->source_node,
17760 buf_sprintf("%s has size %" ZIG_PRI_u64 "; remaining bytes: %" ZIG_PRI_u64,
17761 buf_ptr(&dest_child_type->name), child_type_size, remainder));
17762 return ira->codegen->builtin_types.entry_invalid;
17763 }
17764 }
17765
17766 IrInstruction *result = ir_resolve_cast(ira, &instruction->base, casted_value, dest_slice_type, CastOpResizeSlice, true);
17767 ir_link_new_instruction(result, &instruction->base);
17768 return dest_slice_type;
17769}
17770
17771static TypeTableEntry *ir_analyze_instruction_to_bytes(IrAnalyze *ira, IrInstructionToBytes *instruction) {
17772 IrInstruction *target = instruction->target->other;
17773 if (type_is_invalid(target->value.type))
17774 return ira->codegen->builtin_types.entry_invalid;
17775
17776 if (!is_slice(target->value.type)) {
17777 ir_add_error(ira, instruction->target,
17778 buf_sprintf("expected slice, found '%s'", buf_ptr(&target->value.type->name)));
17779 return ira->codegen->builtin_types.entry_invalid;
17780 }
17781
17782 TypeTableEntry *src_ptr_type = target->value.type->data.structure.fields[slice_ptr_index].type_entry;
17783
17784 TypeTableEntry *dest_ptr_type = get_pointer_to_type_extra(ira->codegen, ira->codegen->builtin_types.entry_u8,
17785 src_ptr_type->data.pointer.is_const, src_ptr_type->data.pointer.is_volatile, PtrLenUnknown,
17786 src_ptr_type->data.pointer.alignment, 0, 0);
17787 TypeTableEntry *dest_slice_type = get_slice_type(ira->codegen, dest_ptr_type);
17788
17789 IrInstruction *result = ir_resolve_cast(ira, &instruction->base, target, dest_slice_type, CastOpResizeSlice, true);
17790 ir_link_new_instruction(result, &instruction->base);
17791 return dest_slice_type;
17792}
17793
1759617794static TypeTableEntry *ir_analyze_instruction_int_to_float(IrAnalyze *ira, IrInstructionIntToFloat *instruction) {
1759717795 TypeTableEntry *dest_type = ir_resolve_type(ira, instruction->dest_type->other);
1759817796 if (type_is_invalid(dest_type))
......@@ -17627,6 +17825,39 @@ static TypeTableEntry *ir_analyze_instruction_float_to_int(IrAnalyze *ira, IrIns
1762717825 return dest_type;
1762817826}
1762917827
17828static TypeTableEntry *ir_analyze_instruction_err_to_int(IrAnalyze *ira, IrInstructionErrToInt *instruction) {
17829 IrInstruction *target = instruction->target->other;
17830 if (type_is_invalid(target->value.type))
17831 return ira->codegen->builtin_types.entry_invalid;
17832
17833 IrInstruction *casted_target;
17834 if (target->value.type->id == TypeTableEntryIdErrorSet) {
17835 casted_target = target;
17836 } else {
17837 casted_target = ir_implicit_cast(ira, target, ira->codegen->builtin_types.entry_global_error_set);
17838 if (type_is_invalid(casted_target->value.type))
17839 return ira->codegen->builtin_types.entry_invalid;
17840 }
17841
17842 IrInstruction *result = ir_analyze_err_to_int(ira, &instruction->base, casted_target, ira->codegen->err_tag_type);
17843 ir_link_new_instruction(result, &instruction->base);
17844 return result->value.type;
17845}
17846
17847static TypeTableEntry *ir_analyze_instruction_int_to_err(IrAnalyze *ira, IrInstructionIntToErr *instruction) {
17848 IrInstruction *target = instruction->target->other;
17849 if (type_is_invalid(target->value.type))
17850 return ira->codegen->builtin_types.entry_invalid;
17851
17852 IrInstruction *casted_target = ir_implicit_cast(ira, target, ira->codegen->err_tag_type);
17853 if (type_is_invalid(casted_target->value.type))
17854 return ira->codegen->builtin_types.entry_invalid;
17855
17856 IrInstruction *result = ir_analyze_int_to_err(ira, &instruction->base, casted_target, ira->codegen->builtin_types.entry_global_error_set);
17857 ir_link_new_instruction(result, &instruction->base);
17858 return result->value.type;
17859}
17860
1763017861static TypeTableEntry *ir_analyze_instruction_bool_to_int(IrAnalyze *ira, IrInstructionBoolToInt *instruction) {
1763117862 IrInstruction *target = instruction->target->other;
1763217863 if (type_is_invalid(target->value.type))
......@@ -20066,13 +20297,63 @@ static TypeTableEntry *ir_analyze_instruction_sqrt(IrAnalyze *ira, IrInstruction
2006620297 return result->value.type;
2006720298}
2006820299
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
2006920353static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstruction *instruction) {
2007020354 switch (instruction->id) {
2007120355 case IrInstructionIdInvalid:
2007220356 case IrInstructionIdWidenOrShorten:
20073 case IrInstructionIdIntToEnum:
20074 case IrInstructionIdIntToErr:
20075 case IrInstructionIdErrToInt:
2007620357 case IrInstructionIdStructInit:
2007720358 case IrInstructionIdUnionInit:
2007820359 case IrInstructionIdStructFieldPtr:
......@@ -20193,6 +20474,12 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
2019320474 return ir_analyze_instruction_int_cast(ira, (IrInstructionIntCast *)instruction);
2019420475 case IrInstructionIdFloatCast:
2019520476 return ir_analyze_instruction_float_cast(ira, (IrInstructionFloatCast *)instruction);
20477 case IrInstructionIdErrSetCast:
20478 return ir_analyze_instruction_err_set_cast(ira, (IrInstructionErrSetCast *)instruction);
20479 case IrInstructionIdFromBytes:
20480 return ir_analyze_instruction_from_bytes(ira, (IrInstructionFromBytes *)instruction);
20481 case IrInstructionIdToBytes:
20482 return ir_analyze_instruction_to_bytes(ira, (IrInstructionToBytes *)instruction);
2019620483 case IrInstructionIdIntToFloat:
2019720484 return ir_analyze_instruction_int_to_float(ira, (IrInstructionIntToFloat *)instruction);
2019820485 case IrInstructionIdFloatToInt:
......@@ -20327,6 +20614,14 @@ static TypeTableEntry *ir_analyze_instruction_nocast(IrAnalyze *ira, IrInstructi
2032720614 return ir_analyze_instruction_mark_err_ret_trace_ptr(ira, (IrInstructionMarkErrRetTracePtr *)instruction);
2032820615 case IrInstructionIdSqrt:
2032920616 return ir_analyze_instruction_sqrt(ira, (IrInstructionSqrt *)instruction);
20617 case IrInstructionIdIntToErr:
20618 return ir_analyze_instruction_int_to_err(ira, (IrInstructionIntToErr *)instruction);
20619 case IrInstructionIdErrToInt:
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);
2033020625 }
2033120626 zig_unreachable();
2033220627}
......@@ -20544,9 +20839,13 @@ bool ir_has_side_effects(IrInstruction *instruction) {
2054420839 case IrInstructionIdAtomicLoad:
2054520840 case IrInstructionIdIntCast:
2054620841 case IrInstructionIdFloatCast:
20842 case IrInstructionIdErrSetCast:
2054720843 case IrInstructionIdIntToFloat:
2054820844 case IrInstructionIdFloatToInt:
2054920845 case IrInstructionIdBoolToInt:
20846 case IrInstructionIdFromBytes:
20847 case IrInstructionIdToBytes:
20848 case IrInstructionIdEnumToInt:
2055020849 return false;
2055120850
2055220851 case IrInstructionIdAsm:
src/ir_print.cpp+45
......@@ -664,6 +664,28 @@ static void ir_print_float_cast(IrPrint *irp, IrInstructionFloatCast *instructio
664664 fprintf(irp->f, ")");
665665}
666666
667static void ir_print_err_set_cast(IrPrint *irp, IrInstructionErrSetCast *instruction) {
668 fprintf(irp->f, "@errSetCast(");
669 ir_print_other_instruction(irp, instruction->dest_type);
670 fprintf(irp->f, ", ");
671 ir_print_other_instruction(irp, instruction->target);
672 fprintf(irp->f, ")");
673}
674
675static void ir_print_from_bytes(IrPrint *irp, IrInstructionFromBytes *instruction) {
676 fprintf(irp->f, "@bytesToSlice(");
677 ir_print_other_instruction(irp, instruction->dest_child_type);
678 fprintf(irp->f, ", ");
679 ir_print_other_instruction(irp, instruction->target);
680 fprintf(irp->f, ")");
681}
682
683static void ir_print_to_bytes(IrPrint *irp, IrInstructionToBytes *instruction) {
684 fprintf(irp->f, "@sliceToBytes(");
685 ir_print_other_instruction(irp, instruction->target);
686 fprintf(irp->f, ")");
687}
688
667689static void ir_print_int_to_float(IrPrint *irp, IrInstructionIntToFloat *instruction) {
668690 fprintf(irp->f, "@intToFloat(");
669691 ir_print_other_instruction(irp, instruction->dest_type);
......@@ -906,6 +928,17 @@ static void ir_print_int_to_ptr(IrPrint *irp, IrInstructionIntToPtr *instruction
906928
907929static void ir_print_int_to_enum(IrPrint *irp, IrInstructionIntToEnum *instruction) {
908930 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(");
909942 ir_print_other_instruction(irp, instruction->target);
910943 fprintf(irp->f, ")");
911944}
......@@ -1461,6 +1494,15 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
14611494 case IrInstructionIdFloatCast:
14621495 ir_print_float_cast(irp, (IrInstructionFloatCast *)instruction);
14631496 break;
1497 case IrInstructionIdErrSetCast:
1498 ir_print_err_set_cast(irp, (IrInstructionErrSetCast *)instruction);
1499 break;
1500 case IrInstructionIdFromBytes:
1501 ir_print_from_bytes(irp, (IrInstructionFromBytes *)instruction);
1502 break;
1503 case IrInstructionIdToBytes:
1504 ir_print_to_bytes(irp, (IrInstructionToBytes *)instruction);
1505 break;
14641506 case IrInstructionIdIntToFloat:
14651507 ir_print_int_to_float(irp, (IrInstructionIntToFloat *)instruction);
14661508 break;
......@@ -1686,6 +1728,9 @@ static void ir_print_instruction(IrPrint *irp, IrInstruction *instruction) {
16861728 case IrInstructionIdAtomicLoad:
16871729 ir_print_atomic_load(irp, (IrInstructionAtomicLoad *)instruction);
16881730 break;
1731 case IrInstructionIdEnumToInt:
1732 ir_print_enum_to_int(irp, (IrInstructionEnumToInt *)instruction);
1733 break;
16891734 }
16901735 fprintf(irp->f, "\n");
16911736}
std/cstr.zig+1-1
......@@ -79,7 +79,7 @@ pub const NullTerminated2DArray = struct {
7979 errdefer allocator.free(buf);
8080
8181 var write_index = index_size;
82 const index_buf = ([]?[*]u8)(buf);
82 const index_buf = @bytesToSlice(?[*]u8, buf);
8383
8484 var i: usize = 0;
8585 for (slices) |slice| {
std/heap.zig+1-1
......@@ -221,7 +221,7 @@ pub const ArenaAllocator = struct {
221221 if (len >= actual_min_size) break;
222222 }
223223 const buf = try self.child_allocator.alignedAlloc(u8, @alignOf(BufNode), len);
224 const buf_node_slice = ([]BufNode)(buf[0..@sizeOf(BufNode)]);
224 const buf_node_slice = @bytesToSlice(BufNode, buf[0..@sizeOf(BufNode)]);
225225 const buf_node = &buf_node_slice[0];
226226 buf_node.* = BufNode{
227227 .data = buf,
std/json.zig+1-1
......@@ -180,7 +180,7 @@ pub const StreamingParser = struct {
180180 pub fn fromInt(x: var) State {
181181 debug.assert(x == 0 or x == 1);
182182 const T = @TagType(State);
183 return State(@intCast(T, x));
183 return @intToEnum(State, @intCast(T, x));
184184 }
185185 };
186186
std/macho.zig+1-1
......@@ -161,7 +161,7 @@ pub fn loadSymbols(allocator: *mem.Allocator, in: *io.FileInStream) !SymbolTable
161161}
162162
163163fn readNoEof(in: *io.FileInStream, comptime T: type, result: []T) !void {
164 return in.stream.readNoEof(([]u8)(result));
164 return in.stream.readNoEof(@sliceToBytes(result));
165165}
166166fn readOneNoEof(in: *io.FileInStream, comptime T: type, result: *T) !void {
167167 return readNoEof(in, T, (*[1]T)(result)[0..]);
std/mem.zig+6-6
......@@ -70,7 +70,7 @@ pub const Allocator = struct {
7070 for (byte_slice) |*byte| {
7171 byte.* = undefined;
7272 }
73 return ([]align(alignment) T)(@alignCast(alignment, byte_slice));
73 return @bytesToSlice(T, @alignCast(alignment, byte_slice));
7474 }
7575
7676 pub fn realloc(self: *Allocator, comptime T: type, old_mem: []T, n: usize) ![]T {
......@@ -86,7 +86,7 @@ pub const Allocator = struct {
8686 return ([*]align(alignment) T)(undefined)[0..0];
8787 }
8888
89 const old_byte_slice = ([]u8)(old_mem);
89 const old_byte_slice = @sliceToBytes(old_mem);
9090 const byte_count = math.mul(usize, @sizeOf(T), n) catch return Error.OutOfMemory;
9191 const byte_slice = try self.reallocFn(self, old_byte_slice, byte_count, alignment);
9292 assert(byte_slice.len == byte_count);
......@@ -96,7 +96,7 @@ pub const Allocator = struct {
9696 byte.* = undefined;
9797 }
9898 }
99 return ([]T)(@alignCast(alignment, byte_slice));
99 return @bytesToSlice(T, @alignCast(alignment, byte_slice));
100100 }
101101
102102 /// Reallocate, but `n` must be less than or equal to `old_mem.len`.
......@@ -118,13 +118,13 @@ pub const Allocator = struct {
118118 // n <= old_mem.len and the multiplication didn't overflow for that operation.
119119 const byte_count = @sizeOf(T) * n;
120120
121 const byte_slice = self.reallocFn(self, ([]u8)(old_mem), byte_count, alignment) catch unreachable;
121 const byte_slice = self.reallocFn(self, @sliceToBytes(old_mem), byte_count, alignment) catch unreachable;
122122 assert(byte_slice.len == byte_count);
123 return ([]align(alignment) T)(@alignCast(alignment, byte_slice));
123 return @bytesToSlice(T, @alignCast(alignment, byte_slice));
124124 }
125125
126126 pub fn free(self: *Allocator, memory: var) void {
127 const bytes = ([]const u8)(memory);
127 const bytes = @sliceToBytes(memory);
128128 if (bytes.len == 0) return;
129129 const non_const_ptr = @intToPtr([*]u8, @ptrToInt(bytes.ptr));
130130 self.freeFn(self, non_const_ptr[0..bytes.len]);
std/net.zig+1-1
......@@ -68,7 +68,7 @@ pub const Address = struct {
6868
6969pub fn parseIp4(buf: []const u8) !u32 {
7070 var result: u32 = undefined;
71 const out_ptr = ([]u8)((*[1]u32)(&result)[0..]);
71 const out_ptr = @sliceToBytes((*[1]u32)(&result)[0..]);
7272
7373 var x: u8 = 0;
7474 var index: u8 = 0;
std/os/child_process.zig+2-2
......@@ -318,7 +318,7 @@ pub const ChildProcess = struct {
318318 // Here we potentially return the fork child's error
319319 // from the parent pid.
320320 if (err_int != @maxValue(ErrInt)) {
321 return SpawnError(err_int);
321 return @errSetCast(SpawnError, @intToError(err_int));
322322 }
323323
324324 return statusToTerm(status);
......@@ -756,7 +756,7 @@ fn destroyPipe(pipe: *const [2]i32) void {
756756// Child of fork calls this to report an error to the fork parent.
757757// Then the child exits.
758758fn forkChildErrReport(fd: i32, err: ChildProcess.SpawnError) noreturn {
759 _ = writeIntFd(fd, ErrInt(err));
759 _ = writeIntFd(fd, ErrInt(@errorToInt(err)));
760760 posix.exit(1);
761761}
762762
std/os/index.zig+1-1
......@@ -1805,7 +1805,7 @@ pub fn argsAlloc(allocator: *mem.Allocator) ![]const []u8 {
18051805 const buf = try allocator.alignedAlloc(u8, @alignOf([]u8), total_bytes);
18061806 errdefer allocator.free(buf);
18071807
1808 const result_slice_list = ([][]u8)(buf[0..slice_list_bytes]);
1808 const result_slice_list = @bytesToSlice([]u8, buf[0..slice_list_bytes]);
18091809 const result_contents = buf[slice_list_bytes..];
18101810 mem.copy(u8, result_contents, contents_slice);
18111811
std/os/windows/util.zig+1-1
......@@ -79,7 +79,7 @@ pub fn windowsIsCygwinPty(handle: windows.HANDLE) bool {
7979
8080 const name_info = @ptrCast(*const windows.FILE_NAME_INFO, &name_info_bytes[0]);
8181 const name_bytes = name_info_bytes[size .. size + usize(name_info.FileNameLength)];
82 const name_wide = ([]u16)(name_bytes);
82 const name_wide = @bytesToSlice(u16, name_bytes);
8383 return mem.indexOf(u16, name_wide, []u16{ 'm', 's', 'y', 's', '-' }) != null or
8484 mem.indexOf(u16, name_wide, []u16{ '-', 'p', 't', 'y' }) != null;
8585}
test/cases/align.zig+1-1
......@@ -90,7 +90,7 @@ fn testBytesAlignSlice(b: u8) void {
9090 b,
9191 b,
9292 };
93 const slice = ([]u32)(bytes[0..]);
93 const slice: []u32 = @bytesToSlice(u32, bytes[0..]);
9494 assert(slice[0] == 0x33333333);
9595}
9696
test/cases/cast.zig+9-3
......@@ -140,8 +140,8 @@ test "explicit cast from integer to error type" {
140140 comptime testCastIntToErr(error.ItBroke);
141141}
142142fn testCastIntToErr(err: error) void {
143 const x = usize(err);
144 const y = error(x);
143 const x = @errorToInt(err);
144 const y = @intToError(x);
145145 assert(error.ItBroke == y);
146146}
147147
......@@ -372,7 +372,7 @@ test "const slice widen cast" {
372372 0x12,
373373 };
374374
375 const u32_value = ([]const u32)(bytes[0..])[0];
375 const u32_value = @bytesToSlice(u32, bytes[0..])[0];
376376 assert(u32_value == 0x12121212);
377377
378378 assert(@bitCast(u32, bytes) == 0x12121212);
......@@ -420,3 +420,9 @@ test "comptime_int @intToFloat" {
420420 assert(@typeOf(result) == f32);
421421 assert(result == 1234.0);
422422}
423
424test "@bytesToSlice keeps pointer alignment" {
425 var bytes = []u8{ 0x01, 0x02, 0x03, 0x04 };
426 const numbers = @bytesToSlice(u32, bytes[0..]);
427 comptime assert(@typeOf(numbers) == []align(@alignOf(@typeOf(bytes))) u32);
428}
test/cases/enum.zig+8-8
......@@ -92,14 +92,14 @@ test "enum to int" {
9292}
9393
9494fn shouldEqual(n: Number, expected: u3) void {
95 assert(u3(n) == expected);
95 assert(@enumToInt(n) == expected);
9696}
9797
9898test "int to enum" {
9999 testIntToEnumEval(3);
100100}
101101fn testIntToEnumEval(x: i32) void {
102 assert(IntToEnumNumber(@intCast(u3, x)) == IntToEnumNumber.Three);
102 assert(@intToEnum(IntToEnumNumber, @intCast(u3, x)) == IntToEnumNumber.Three);
103103}
104104const IntToEnumNumber = enum {
105105 Zero,
......@@ -768,7 +768,7 @@ test "casting enum to its tag type" {
768768}
769769
770770fn testCastEnumToTagType(value: Small2) void {
771 assert(u2(value) == 1);
771 assert(@enumToInt(value) == 1);
772772}
773773
774774const MultipleChoice = enum(u32) {
......@@ -784,7 +784,7 @@ test "enum with specified tag values" {
784784}
785785
786786fn testEnumWithSpecifiedTagValues(x: MultipleChoice) void {
787 assert(u32(x) == 60);
787 assert(@enumToInt(x) == 60);
788788 assert(1234 == switch (x) {
789789 MultipleChoice.A => 1,
790790 MultipleChoice.B => 2,
......@@ -811,7 +811,7 @@ test "enum with specified and unspecified tag values" {
811811}
812812
813813fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
814 assert(u32(x) == 1000);
814 assert(@enumToInt(x) == 1000);
815815 assert(1234 == switch (x) {
816816 MultipleChoice2.A => 1,
817817 MultipleChoice2.B => 2,
......@@ -826,8 +826,8 @@ fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: MultipleChoice2) void {
826826}
827827
828828test "cast integer literal to enum" {
829 assert(MultipleChoice2(0) == MultipleChoice2.Unspecified1);
830 assert(MultipleChoice2(40) == MultipleChoice2.B);
829 assert(@intToEnum(MultipleChoice2, 0) == MultipleChoice2.Unspecified1);
830 assert(@intToEnum(MultipleChoice2, 40) == MultipleChoice2.B);
831831}
832832
833833const EnumWithOneMember = enum {
......@@ -865,7 +865,7 @@ const EnumWithTagValues = enum(u4) {
865865 D = 1 << 3,
866866};
867867test "enum with tag values don't require parens" {
868 assert(u4(EnumWithTagValues.C) == 0b0100);
868 assert(@enumToInt(EnumWithTagValues.C) == 0b0100);
869869}
870870
871871test "enum with 1 field but explicit tag type should still have the tag type" {
test/cases/error.zig+7-7
......@@ -31,8 +31,8 @@ test "@errorName" {
3131}
3232
3333test "error values" {
34 const a = i32(error.err1);
35 const b = i32(error.err2);
34 const a = @errorToInt(error.err1);
35 const b = @errorToInt(error.err2);
3636 assert(a != b);
3737}
3838
......@@ -124,8 +124,8 @@ const Set2 = error{
124124};
125125
126126fn testExplicitErrorSetCast(set1: Set1) void {
127 var x = Set2(set1);
128 var y = Set1(x);
127 var x = @errSetCast(Set2, set1);
128 var y = @errSetCast(Set1, x);
129129 assert(y == error.A);
130130}
131131
......@@ -147,14 +147,14 @@ test "syntax: optional operator in front of error union operator" {
147147}
148148
149149test "comptime err to int of error set with only 1 possible value" {
150 testErrToIntWithOnePossibleValue(error.A, u32(error.A));
151 comptime testErrToIntWithOnePossibleValue(error.A, u32(error.A));
150 testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
151 comptime testErrToIntWithOnePossibleValue(error.A, @errorToInt(error.A));
152152}
153153fn testErrToIntWithOnePossibleValue(
154154 x: error{A},
155155 comptime value: u32,
156156) void {
157 if (u32(x) != value) {
157 if (@errorToInt(x) != value) {
158158 @compileError("bad");
159159 }
160160}
test/cases/misc.zig+2-2
......@@ -422,14 +422,14 @@ test "cast slice to u8 slice" {
422422 4,
423423 };
424424 const big_thing_slice: []i32 = big_thing_array[0..];
425 const bytes = ([]u8)(big_thing_slice);
425 const bytes = @sliceToBytes(big_thing_slice);
426426 assert(bytes.len == 4 * 4);
427427 bytes[4] = 0;
428428 bytes[5] = 0;
429429 bytes[6] = 0;
430430 bytes[7] = 0;
431431 assert(big_thing_slice[1] == 0);
432 const big_thing_again = ([]align(1) i32)(bytes);
432 const big_thing_again = @bytesToSlice(i32, bytes);
433433 assert(big_thing_again[2] == 3);
434434 big_thing_again[2] = -1;
435435 assert(bytes[8] == @maxValue(u8));
test/cases/struct.zig+2-2
......@@ -302,7 +302,7 @@ test "packed array 24bits" {
302302
303303 var bytes = []u8{0} ** (@sizeOf(FooArray24Bits) + 1);
304304 bytes[bytes.len - 1] = 0xaa;
305 const ptr = &([]FooArray24Bits)(bytes[0 .. bytes.len - 1])[0];
305 const ptr = &@bytesToSlice(FooArray24Bits, bytes[0 .. bytes.len - 1])[0];
306306 assert(ptr.a == 0);
307307 assert(ptr.b[0].field == 0);
308308 assert(ptr.b[1].field == 0);
......@@ -351,7 +351,7 @@ test "aligned array of packed struct" {
351351 }
352352
353353 var bytes = []u8{0xbb} ** @sizeOf(FooArrayOfAligned);
354 const ptr = &([]FooArrayOfAligned)(bytes[0..bytes.len])[0];
354 const ptr = &@bytesToSlice(FooArrayOfAligned, bytes[0..bytes.len])[0];
355355
356356 assert(ptr.a[0].a == 0xbb);
357357 assert(ptr.a[0].b == 0xbb);
test/cases/type_info.zig+1-1
......@@ -130,7 +130,7 @@ fn testErrorSet() void {
130130 assert(TypeId(error_set_info) == TypeId.ErrorSet);
131131 assert(error_set_info.ErrorSet.errors.len == 3);
132132 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
135135 const error_union_info = @typeInfo(TestErrorSet!usize);
136136 assert(TypeId(error_union_info) == TypeId.ErrorUnion);
test/cases/union.zig+2-2
......@@ -126,7 +126,7 @@ const MultipleChoice = union(enum(u32)) {
126126test "simple union(enum(u32))" {
127127 var x = MultipleChoice.C;
128128 assert(x == MultipleChoice.C);
129 assert(u32(@TagType(MultipleChoice)(x)) == 60);
129 assert(@enumToInt(@TagType(MultipleChoice)(x)) == 60);
130130}
131131
132132const MultipleChoice2 = union(enum(u32)) {
......@@ -148,7 +148,7 @@ test "union(enum(u32)) with specified and unspecified tag values" {
148148}
149149
150150fn testEnumWithSpecifiedAndUnspecifiedTagValues(x: *const MultipleChoice2) void {
151 assert(u32(@TagType(MultipleChoice2)(x.*)) == 60);
151 assert(@enumToInt(@TagType(MultipleChoice2)(x.*)) == 60);
152152 assert(1123 == switch (x.*) {
153153 MultipleChoice2.A => 1,
154154 MultipleChoice2.B => 2,
test/compile_errors.zig+27-56
......@@ -404,10 +404,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
404404 \\const Set2 = error {A, C};
405405 \\comptime {
406406 \\ var x = Set1.B;
407 \\ var y = Set2(x);
407 \\ var y = @errSetCast(Set2, x);
408408 \\}
409409 ,
410 ".tmp_source.zig:5:17: error: error.B not a member of error set 'Set2'",
410 ".tmp_source.zig:5:13: error: error.B not a member of error set 'Set2'",
411411 );
412412
413413 cases.add(
......@@ -467,25 +467,34 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
467467
468468 cases.add(
469469 "int to err global invalid number",
470 \\const Set1 = error{A, B};
470 \\const Set1 = error{
471 \\ A,
472 \\ B,
473 \\};
471474 \\comptime {
472 \\ var x: usize = 3;
473 \\ var y = error(x);
475 \\ var x: u16 = 3;
476 \\ var y = @intToError(x);
474477 \\}
475478 ,
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",
477480 );
478481
479482 cases.add(
480483 "int to err non global invalid number",
481 \\const Set1 = error{A, B};
482 \\const Set2 = error{A, C};
484 \\const Set1 = error{
485 \\ A,
486 \\ B,
487 \\};
488 \\const Set2 = error{
489 \\ A,
490 \\ C,
491 \\};
483492 \\comptime {
484 \\ var x = usize(Set1.B);
485 \\ var y = Set2(x);
493 \\ var x = @errorToInt(Set1.B);
494 \\ var y = @errSetCast(Set2, @intToError(x));
486495 \\}
487496 ,
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'",
489498 );
490499
491500 cases.add(
......@@ -2086,10 +2095,11 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
20862095 "convert fixed size array to slice with invalid size",
20872096 \\export fn f() void {
20882097 \\ var array: [5]u8 = undefined;
2089 \\ var foo = ([]const u32)(array)[0];
2098 \\ var foo = @bytesToSlice(u32, array)[0];
20902099 \\}
20912100 ,
2092 ".tmp_source.zig:3:28: error: unable to convert [5]u8 to []const u32: size mismatch",
2101 ".tmp_source.zig:3:15: error: unable to convert [5]u8 to []align(1) const u32: size mismatch",
2102 ".tmp_source.zig:3:29: note: u32 has size 4; remaining bytes: 1",
20932103 );
20942104
20952105 cases.add(
......@@ -2611,17 +2621,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
26112621 ".tmp_source.zig:2:21: error: expected pointer, found 'usize'",
26122622 );
26132623
2614 cases.add(
2615 "too many error values to cast to small integer",
2616 \\const Error = error { A, B, C, D, E, F, G, H };
2617 \\fn foo(e: Error) u2 {
2618 \\ return u2(e);
2619 \\}
2620 \\export fn entry() usize { return @sizeOf(@typeOf(foo)); }
2621 ,
2622 ".tmp_source.zig:3:14: error: too many error values to fit in 'u2'",
2623 );
2624
26252624 cases.add(
26262625 "asm at compile time",
26272626 \\comptime {
......@@ -3239,18 +3238,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
32393238 ".tmp_source.zig:3:26: note: '*u32' has alignment 4",
32403239 );
32413240
3242 cases.add(
3243 "increase pointer alignment in slice resize",
3244 \\export fn entry() u32 {
3245 \\ var bytes = []u8{0x01, 0x02, 0x03, 0x04};
3246 \\ return ([]u32)(bytes[0..])[0];
3247 \\}
3248 ,
3249 ".tmp_source.zig:3:19: error: cast increases pointer alignment",
3250 ".tmp_source.zig:3:19: note: '[]u8' has alignment 1",
3251 ".tmp_source.zig:3:19: note: '[]u32' has alignment 4",
3252 );
3253
32543241 cases.add(
32553242 "@alignCast expects pointer or slice",
32563243 \\export fn entry() void {
......@@ -3722,22 +3709,6 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
37223709 ".tmp_source.zig:9:22: error: expected type 'u2', found 'Small'",
37233710 );
37243711
3725 cases.add(
3726 "explicitly casting enum to non tag type",
3727 \\const Small = enum(u2) {
3728 \\ One,
3729 \\ Two,
3730 \\ Three,
3731 \\ Four,
3732 \\};
3733 \\
3734 \\export fn entry() void {
3735 \\ var x = u3(Small.Two);
3736 \\}
3737 ,
3738 ".tmp_source.zig:9:15: error: enum to integer cast to 'u3' instead of its tag type, 'u2'",
3739 );
3740
37413712 cases.add(
37423713 "explicitly casting non tag type to enum",
37433714 \\const Small = enum(u2) {
......@@ -3749,10 +3720,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
37493720 \\
37503721 \\export fn entry() void {
37513722 \\ var y = u3(3);
3752 \\ var x = Small(y);
3723 \\ var x = @intToEnum(Small, y);
37533724 \\}
37543725 ,
3755 ".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'",
37563727 );
37573728
37583729 cases.add(
......@@ -4033,10 +4004,10 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
40334004 \\ B = 11,
40344005 \\};
40354006 \\export fn entry() void {
4036 \\ var x = Foo(0);
4007 \\ var x = @intToEnum(Foo, 0);
40374008 \\}
40384009 ,
4039 ".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",
40404011 ".tmp_source.zig:1:13: note: 'Foo' declared here",
40414012 );
40424013
test/runtime_safety.zig+7-7
......@@ -175,7 +175,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
175175 \\ if (x.len == 0) return error.Whatever;
176176 \\}
177177 \\fn widenSlice(slice: []align(1) const u8) []align(1) const i32 {
178 \\ return ([]align(1) const i32)(slice);
178 \\ return @bytesToSlice(i32, slice);
179179 \\}
180180 );
181181
......@@ -227,12 +227,12 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
227227 \\pub fn main() void {
228228 \\ _ = bar(9999);
229229 \\}
230 \\fn bar(x: u32) error {
231 \\ return error(x);
230 \\fn bar(x: u16) error {
231 \\ return @intToError(x);
232232 \\}
233233 );
234234
235 cases.addRuntimeSafety("cast integer to non-global error set and no match",
235 cases.addRuntimeSafety("@errSetCast error not present in destination",
236236 \\pub fn panic(message: []const u8, stack_trace: ?*@import("builtin").StackTrace) noreturn {
237237 \\ @import("std").os.exit(126);
238238 \\}
......@@ -242,7 +242,7 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
242242 \\ _ = foo(Set1.B);
243243 \\}
244244 \\fn foo(set1: Set1) Set2 {
245 \\ return Set2(set1);
245 \\ return @errSetCast(Set2, set1);
246246 \\}
247247 );
248248
......@@ -252,12 +252,12 @@ pub fn addCases(cases: *tests.CompareOutputContext) void {
252252 \\}
253253 \\pub fn main() !void {
254254 \\ var array align(4) = []u32{0x11111111, 0x11111111};
255 \\ const bytes = ([]u8)(array[0..]);
255 \\ const bytes = @sliceToBytes(array[0..]);
256256 \\ if (foo(bytes) != 0x11111111) return error.Wrong;
257257 \\}
258258 \\fn foo(bytes: []u8) u32 {
259259 \\ const slice4 = bytes[1..5];
260 \\ const int_slice = ([]u32)(@alignCast(4, slice4));
260 \\ const int_slice = @bytesToSlice(u32, @alignCast(4, slice4));
261261 \\ return int_slice[0];
262262 \\}
263263 );