authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-13 14:16:01-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-13 14:16:01-07:00
loge851d89113a57064c38ed85722edc7f686d0c11a
tree959a2858d2fe1e72356b888c9e67b1866b81b41c
parent2a701a92c403dda47a61848a38998b474442d805

Sema: implement comptime `coerce_result_ptr` and `alloc`

This is progress towards being able to use `builtin.cpu.arch` instead of the `stage2_arch` workaround. The next blocker is comptime `elemVal`.

4 files changed, 375 insertions(+), 348 deletions(-)

src/Sema.zig+39-14
...@@ -1340,29 +1340,50 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE...@@ -1340,29 +1340,50 @@ fn zirCoerceResultPtr(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileE
1340 const pointee_ty = try sema.resolveType(block, src, bin_inst.lhs);1340 const pointee_ty = try sema.resolveType(block, src, bin_inst.lhs);
1341 const ptr = sema.resolveInst(bin_inst.rhs);1341 const ptr = sema.resolveInst(bin_inst.rhs);
13421342
1343 // Create a runtime bitcast instruction with exactly the type the pointer wants.
1344 const ptr_ty = try Type.ptr(sema.arena, .{1343 const ptr_ty = try Type.ptr(sema.arena, .{
1345 .pointee_type = pointee_ty,1344 .pointee_type = pointee_ty,
1346 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),1345 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
1347 });1346 });
1348 try sema.requireRuntimeBlock(block, src);
1349 const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);
13501347
1351 if (Air.refToIndex(ptr)) |ptr_inst| {1348 if (Air.refToIndex(ptr)) |ptr_inst| {
1352 if (sema.air_instructions.items(.tag)[ptr_inst] == .constant) {1349 if (sema.air_instructions.items(.tag)[ptr_inst] == .constant) {
1353 const air_datas = sema.air_instructions.items(.data);1350 const air_datas = sema.air_instructions.items(.data);
1354 const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload];1351 const ptr_val = sema.air_values.items[air_datas[ptr_inst].ty_pl.payload];
1355 if (ptr_val.castTag(.inferred_alloc)) |inferred_alloc| {1352 switch (ptr_val.tag()) {
1356 // Add the stored instruction to the set we will use to resolve peer types1353 .inferred_alloc => {
1357 // for the inferred allocation.1354 const inferred_alloc = &ptr_val.castTag(.inferred_alloc).?.data;
1358 // This instruction will not make it to codegen; it is only to participate1355 // Add the stored instruction to the set we will use to resolve peer types
1359 // in the `stored_inst_list` of the `inferred_alloc`.1356 // for the inferred allocation.
1360 const operand = try block.addTyOp(.bitcast, pointee_ty, .void_value);1357 // This instruction will not make it to codegen; it is only to participate
1361 try inferred_alloc.data.stored_inst_list.append(sema.arena, operand);1358 // in the `stored_inst_list` of the `inferred_alloc`.
1359 const operand = try block.addTyOp(.bitcast, pointee_ty, .void_value);
1360 try inferred_alloc.stored_inst_list.append(sema.arena, operand);
1361 },
1362 .inferred_alloc_comptime => {
1363 const iac = ptr_val.castTag(.inferred_alloc_comptime).?;
1364 // There will be only one coerce_result_ptr because we are running at comptime.
1365 // The alloc will turn into a Decl.
1366 var anon_decl = try block.startAnonDecl();
1367 defer anon_decl.deinit();
1368 iac.data = try anon_decl.finish(
1369 try pointee_ty.copy(anon_decl.arena()),
1370 Value.undef,
1371 );
1372 return sema.addConstant(
1373 ptr_ty,
1374 try Value.Tag.decl_ref_mut.create(sema.arena, .{
1375 .decl = iac.data,
1376 .runtime_index = block.runtime_index,
1377 }),
1378 );
1379 },
1380 .decl_ref_mut => return sema.addConstant(ptr_ty, ptr_val),
1381 else => {},
1362 }1382 }
1363 }1383 }
1364 }1384 }
13651385 try sema.requireRuntimeBlock(block, src);
1386 const bitcasted_ptr = try block.addTyOp(.bitcast, ptr_ty, ptr);
1366 return bitcasted_ptr;1387 return bitcasted_ptr;
1367}1388}
13681389
...@@ -1996,6 +2017,9 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I...@@ -1996,6 +2017,9 @@ fn zirAlloc(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
1996 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node };2017 const ty_src: LazySrcLoc = .{ .node_offset_var_decl_ty = inst_data.src_node };
1997 const var_decl_src = inst_data.src();2018 const var_decl_src = inst_data.src();
1998 const var_type = try sema.resolveType(block, ty_src, inst_data.operand);2019 const var_type = try sema.resolveType(block, ty_src, inst_data.operand);
2020 if (block.is_comptime) {
2021 return sema.analyzeComptimeAlloc(block, var_type);
2022 }
1999 const ptr_type = try Type.ptr(sema.arena, .{2023 const ptr_type = try Type.ptr(sema.arena, .{
2000 .pointee_type = var_type,2024 .pointee_type = var_type,
2001 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),2025 .@"addrspace" = target_util.defaultAddressSpace(sema.mod.getTarget(), .local),
...@@ -13418,9 +13442,10 @@ fn analyzeComptimeAlloc(...@@ -13418,9 +13442,10 @@ fn analyzeComptimeAlloc(
13418 defer anon_decl.deinit();13442 defer anon_decl.deinit();
13419 const decl = try anon_decl.finish(13443 const decl = try anon_decl.finish(
13420 try var_type.copy(anon_decl.arena()),13444 try var_type.copy(anon_decl.arena()),
13421 // AstGen guarantees there will be a store before the first load, so we put a value13445 // There will be stores before the first load, but they may be to sub-elements or
13422 // here indicating there is no valid value.13446 // sub-fields. So we need to initialize with undef to allow the mechanism to expand
13423 Value.initTag(.unreachable_value),13447 // into fields/elements and have those overridden with stored values.
13448 Value.undef,
13424 );13449 );
13425 try sema.mod.declareDeclDependency(sema.owner_decl, decl);13450 try sema.mod.declareDeclDependency(sema.owner_decl, decl);
13426 return sema.addConstant(ptr_type, try Value.Tag.decl_ref_mut.create(sema.arena, .{13451 return sema.addConstant(ptr_type, try Value.Tag.decl_ref_mut.create(sema.arena, .{
test/behavior.zig+2-1
...@@ -26,6 +26,7 @@ test {...@@ -26,6 +26,7 @@ test {
26 _ = @import("behavior/math.zig");26 _ = @import("behavior/math.zig");
27 _ = @import("behavior/member_func.zig");27 _ = @import("behavior/member_func.zig");
28 _ = @import("behavior/pointers.zig");28 _ = @import("behavior/pointers.zig");
29 _ = @import("behavior/slice.zig");
29 _ = @import("behavior/sizeof_and_typeof.zig");30 _ = @import("behavior/sizeof_and_typeof.zig");
30 _ = @import("behavior/struct.zig");31 _ = @import("behavior/struct.zig");
31 _ = @import("behavior/switch.zig");32 _ = @import("behavior/switch.zig");
...@@ -150,7 +151,7 @@ test {...@@ -150,7 +151,7 @@ test {
150 _ = @import("behavior/shuffle.zig");151 _ = @import("behavior/shuffle.zig");
151 _ = @import("behavior/select.zig");152 _ = @import("behavior/select.zig");
152 _ = @import("behavior/sizeof_and_typeof_stage1.zig");153 _ = @import("behavior/sizeof_and_typeof_stage1.zig");
153 _ = @import("behavior/slice.zig");154 _ = @import("behavior/slice_stage1.zig");
154 _ = @import("behavior/slice_sentinel_comptime.zig");155 _ = @import("behavior/slice_sentinel_comptime.zig");
155 _ = @import("behavior/struct_stage1.zig");156 _ = @import("behavior/struct_stage1.zig");
156 _ = @import("behavior/struct_contains_null_ptr_itself.zig");157 _ = @import("behavior/struct_contains_null_ptr_itself.zig");
test/behavior/slice.zig-333
...@@ -3,336 +3,3 @@ const expect = std.testing.expect;...@@ -3,336 +3,3 @@ const expect = std.testing.expect;
3const expectEqualSlices = std.testing.expectEqualSlices;3const expectEqualSlices = std.testing.expectEqualSlices;
4const expectEqual = std.testing.expectEqual;4const expectEqual = std.testing.expectEqual;
5const mem = std.mem;5const mem = std.mem;
6
7const x = @intToPtr([*]i32, 0x1000)[0..0x500];
8const y = x[0x100..];
9test "compile time slice of pointer to hard coded address" {
10 try expect(@ptrToInt(x) == 0x1000);
11 try expect(x.len == 0x500);
12
13 try expect(@ptrToInt(y) == 0x1100);
14 try expect(y.len == 0x400);
15}
16
17test "runtime safety lets us slice from len..len" {
18 var an_array = [_]u8{
19 1,
20 2,
21 3,
22 };
23 try expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
24}
25
26fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
27 return a_slice[start..end];
28}
29
30test "implicitly cast array of size 0 to slice" {
31 var msg = [_]u8{};
32 try assertLenIsZero(&msg);
33}
34
35fn assertLenIsZero(msg: []const u8) !void {
36 try expect(msg.len == 0);
37}
38
39test "C pointer" {
40 var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
41 var len: u32 = 10;
42 var slice = buf[0..len];
43 try expectEqualSlices(u8, "kjdhfkjdhf", slice);
44}
45
46test "C pointer slice access" {
47 var buf: [10]u32 = [1]u32{42} ** 10;
48 const c_ptr = @ptrCast([*c]const u32, &buf);
49
50 var runtime_zero: usize = 0;
51 comptime try expectEqual([]const u32, @TypeOf(c_ptr[runtime_zero..1]));
52 comptime try expectEqual(*const [1]u32, @TypeOf(c_ptr[0..1]));
53
54 for (c_ptr[0..5]) |*cl| {
55 try expectEqual(@as(u32, 42), cl.*);
56 }
57}
58
59fn sliceSum(comptime q: []const u8) i32 {
60 comptime var result = 0;
61 inline for (q) |item| {
62 result += item;
63 }
64 return result;
65}
66
67test "comptime slices are disambiguated" {
68 try expect(sliceSum(&[_]u8{ 1, 2 }) == 3);
69 try expect(sliceSum(&[_]u8{ 3, 4 }) == 7);
70}
71
72test "slice type with custom alignment" {
73 const LazilyResolvedType = struct {
74 anything: i32,
75 };
76 var slice: []align(32) LazilyResolvedType = undefined;
77 var array: [10]LazilyResolvedType align(32) = undefined;
78 slice = &array;
79 slice[1].anything = 42;
80 try expect(array[1].anything == 42);
81}
82
83test "access len index of sentinel-terminated slice" {
84 const S = struct {
85 fn doTheTest() !void {
86 var slice: [:0]const u8 = "hello";
87
88 try expect(slice.len == 5);
89 try expect(slice[5] == 0);
90 }
91 };
92 try S.doTheTest();
93 comptime try S.doTheTest();
94}
95
96test "obtaining a null terminated slice" {
97 // here we have a normal array
98 var buf: [50]u8 = undefined;
99
100 buf[0] = 'a';
101 buf[1] = 'b';
102 buf[2] = 'c';
103 buf[3] = 0;
104
105 // now we obtain a null terminated slice:
106 const ptr = buf[0..3 :0];
107 _ = ptr;
108
109 var runtime_len: usize = 3;
110 const ptr2 = buf[0..runtime_len :0];
111 // ptr2 is a null-terminated slice
112 comptime try expect(@TypeOf(ptr2) == [:0]u8);
113 comptime try expect(@TypeOf(ptr2[0..2]) == *[2]u8);
114 var runtime_zero: usize = 0;
115 comptime try expect(@TypeOf(ptr2[runtime_zero..2]) == []u8);
116}
117
118test "empty array to slice" {
119 const S = struct {
120 fn doTheTest() !void {
121 const empty: []align(16) u8 = &[_]u8{};
122 const align_1: []align(1) u8 = empty;
123 const align_4: []align(4) u8 = empty;
124 const align_16: []align(16) u8 = empty;
125 try expectEqual(1, @typeInfo(@TypeOf(align_1)).Pointer.alignment);
126 try expectEqual(4, @typeInfo(@TypeOf(align_4)).Pointer.alignment);
127 try expectEqual(16, @typeInfo(@TypeOf(align_16)).Pointer.alignment);
128 }
129 };
130
131 try S.doTheTest();
132 comptime try S.doTheTest();
133}
134
135test "@ptrCast slice to pointer" {
136 const S = struct {
137 fn doTheTest() !void {
138 var array align(@alignOf(u16)) = [5]u8{ 0xff, 0xff, 0xff, 0xff, 0xff };
139 var slice: []u8 = &array;
140 var ptr = @ptrCast(*u16, slice);
141 try expect(ptr.* == 65535);
142 }
143 };
144
145 try S.doTheTest();
146 comptime try S.doTheTest();
147}
148
149test "slice syntax resulting in pointer-to-array" {
150 const S = struct {
151 fn doTheTest() !void {
152 try testArray();
153 try testArrayZ();
154 try testArray0();
155 try testArrayAlign();
156 try testPointer();
157 try testPointerZ();
158 try testPointer0();
159 try testPointerAlign();
160 try testSlice();
161 try testSliceZ();
162 try testSlice0();
163 try testSliceOpt();
164 try testSliceAlign();
165 }
166
167 fn testArray() !void {
168 var array = [5]u8{ 1, 2, 3, 4, 5 };
169 var slice = array[1..3];
170 comptime try expect(@TypeOf(slice) == *[2]u8);
171 try expect(slice[0] == 2);
172 try expect(slice[1] == 3);
173 }
174
175 fn testArrayZ() !void {
176 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
177 comptime try expect(@TypeOf(array[1..3]) == *[2]u8);
178 comptime try expect(@TypeOf(array[1..5]) == *[4:0]u8);
179 comptime try expect(@TypeOf(array[1..]) == *[4:0]u8);
180 comptime try expect(@TypeOf(array[1..3 :4]) == *[2:4]u8);
181 }
182
183 fn testArray0() !void {
184 {
185 var array = [0]u8{};
186 var slice = array[0..0];
187 comptime try expect(@TypeOf(slice) == *[0]u8);
188 }
189 {
190 var array = [0:0]u8{};
191 var slice = array[0..0];
192 comptime try expect(@TypeOf(slice) == *[0:0]u8);
193 try expect(slice[0] == 0);
194 }
195 }
196
197 fn testArrayAlign() !void {
198 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
199 var slice = array[4..5];
200 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
201 try expect(slice[0] == 5);
202 comptime try expect(@TypeOf(array[0..2]) == *align(4) [2]u8);
203 }
204
205 fn testPointer() !void {
206 var array = [5]u8{ 1, 2, 3, 4, 5 };
207 var pointer: [*]u8 = &array;
208 var slice = pointer[1..3];
209 comptime try expect(@TypeOf(slice) == *[2]u8);
210 try expect(slice[0] == 2);
211 try expect(slice[1] == 3);
212 }
213
214 fn testPointerZ() !void {
215 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
216 var pointer: [*:0]u8 = &array;
217 comptime try expect(@TypeOf(pointer[1..3]) == *[2]u8);
218 comptime try expect(@TypeOf(pointer[1..3 :4]) == *[2:4]u8);
219 }
220
221 fn testPointer0() !void {
222 var pointer: [*]const u0 = &[1]u0{0};
223 var slice = pointer[0..1];
224 comptime try expect(@TypeOf(slice) == *const [1]u0);
225 try expect(slice[0] == 0);
226 }
227
228 fn testPointerAlign() !void {
229 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
230 var pointer: [*]align(4) u8 = &array;
231 var slice = pointer[4..5];
232 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
233 try expect(slice[0] == 5);
234 comptime try expect(@TypeOf(pointer[0..2]) == *align(4) [2]u8);
235 }
236
237 fn testSlice() !void {
238 var array = [5]u8{ 1, 2, 3, 4, 5 };
239 var src_slice: []u8 = &array;
240 var slice = src_slice[1..3];
241 comptime try expect(@TypeOf(slice) == *[2]u8);
242 try expect(slice[0] == 2);
243 try expect(slice[1] == 3);
244 }
245
246 fn testSliceZ() !void {
247 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
248 var slice: [:0]u8 = &array;
249 comptime try expect(@TypeOf(slice[1..3]) == *[2]u8);
250 comptime try expect(@TypeOf(slice[1..]) == [:0]u8);
251 comptime try expect(@TypeOf(slice[1..3 :4]) == *[2:4]u8);
252 }
253
254 fn testSliceOpt() !void {
255 var array: [2]u8 = [2]u8{ 1, 2 };
256 var slice: ?[]u8 = &array;
257 comptime try expect(@TypeOf(&array, slice) == ?[]u8);
258 comptime try expect(@TypeOf(slice.?[0..2]) == *[2]u8);
259 }
260
261 fn testSlice0() !void {
262 {
263 var array = [0]u8{};
264 var src_slice: []u8 = &array;
265 var slice = src_slice[0..0];
266 comptime try expect(@TypeOf(slice) == *[0]u8);
267 }
268 {
269 var array = [0:0]u8{};
270 var src_slice: [:0]u8 = &array;
271 var slice = src_slice[0..0];
272 comptime try expect(@TypeOf(slice) == *[0]u8);
273 }
274 }
275
276 fn testSliceAlign() !void {
277 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
278 var src_slice: []align(4) u8 = &array;
279 var slice = src_slice[4..5];
280 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
281 try expect(slice[0] == 5);
282 comptime try expect(@TypeOf(src_slice[0..2]) == *align(4) [2]u8);
283 }
284
285 fn testConcatStrLiterals() !void {
286 try expectEqualSlices("a"[0..] ++ "b"[0..], "ab");
287 try expectEqualSlices("a"[0.. :0] ++ "b"[0.. :0], "ab");
288 }
289 };
290
291 try S.doTheTest();
292 comptime try S.doTheTest();
293}
294
295test "slice of hardcoded address to pointer" {
296 const S = struct {
297 fn doTheTest() !void {
298 const pointer = @intToPtr([*]u8, 0x04)[0..2];
299 comptime try expect(@TypeOf(pointer) == *[2]u8);
300 const slice: []const u8 = pointer;
301 try expect(@ptrToInt(slice.ptr) == 4);
302 try expect(slice.len == 2);
303 }
304 };
305
306 try S.doTheTest();
307}
308
309test "type coercion of pointer to anon struct literal to pointer to slice" {
310 const S = struct {
311 const U = union {
312 a: u32,
313 b: bool,
314 c: []const u8,
315 };
316
317 fn doTheTest() !void {
318 var x1: u8 = 42;
319 const t1 = &.{ x1, 56, 54 };
320 var slice1: []const u8 = t1;
321 try expect(slice1.len == 3);
322 try expect(slice1[0] == 42);
323 try expect(slice1[1] == 56);
324 try expect(slice1[2] == 54);
325
326 var x2: []const u8 = "hello";
327 const t2 = &.{ x2, ", ", "world!" };
328 // @compileLog(@TypeOf(t2));
329 var slice2: []const []const u8 = t2;
330 try expect(slice2.len == 3);
331 try expect(mem.eql(u8, slice2[0], "hello"));
332 try expect(mem.eql(u8, slice2[1], ", "));
333 try expect(mem.eql(u8, slice2[2], "world!"));
334 }
335 };
336 // try S.doTheTest();
337 comptime try S.doTheTest();
338}
test/behavior/slice_stage1.zig created+334
...@@ -0,0 +1,334 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqualSlices = std.testing.expectEqualSlices;
4const expectEqual = std.testing.expectEqual;
5const mem = std.mem;
6
7const x = @intToPtr([*]i32, 0x1000)[0..0x500];
8const y = x[0x100..];
9test "compile time slice of pointer to hard coded address" {
10 try expect(@ptrToInt(x) == 0x1000);
11 try expect(x.len == 0x500);
12
13 try expect(@ptrToInt(y) == 0x1100);
14 try expect(y.len == 0x400);
15}
16
17test "runtime safety lets us slice from len..len" {
18 var an_array = [_]u8{ 1, 2, 3 };
19 try expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
20}
21
22fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
23 return a_slice[start..end];
24}
25
26test "implicitly cast array of size 0 to slice" {
27 var msg = [_]u8{};
28 try assertLenIsZero(&msg);
29}
30
31fn assertLenIsZero(msg: []const u8) !void {
32 try expect(msg.len == 0);
33}
34
35test "C pointer" {
36 var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
37 var len: u32 = 10;
38 var slice = buf[0..len];
39 try expectEqualSlices(u8, "kjdhfkjdhf", slice);
40}
41
42test "C pointer slice access" {
43 var buf: [10]u32 = [1]u32{42} ** 10;
44 const c_ptr = @ptrCast([*c]const u32, &buf);
45
46 var runtime_zero: usize = 0;
47 comptime try expectEqual([]const u32, @TypeOf(c_ptr[runtime_zero..1]));
48 comptime try expectEqual(*const [1]u32, @TypeOf(c_ptr[0..1]));
49
50 for (c_ptr[0..5]) |*cl| {
51 try expectEqual(@as(u32, 42), cl.*);
52 }
53}
54
55fn sliceSum(comptime q: []const u8) i32 {
56 comptime var result = 0;
57 inline for (q) |item| {
58 result += item;
59 }
60 return result;
61}
62
63test "comptime slices are disambiguated" {
64 try expect(sliceSum(&[_]u8{ 1, 2 }) == 3);
65 try expect(sliceSum(&[_]u8{ 3, 4 }) == 7);
66}
67
68test "slice type with custom alignment" {
69 const LazilyResolvedType = struct {
70 anything: i32,
71 };
72 var slice: []align(32) LazilyResolvedType = undefined;
73 var array: [10]LazilyResolvedType align(32) = undefined;
74 slice = &array;
75 slice[1].anything = 42;
76 try expect(array[1].anything == 42);
77}
78
79test "access len index of sentinel-terminated slice" {
80 const S = struct {
81 fn doTheTest() !void {
82 var slice: [:0]const u8 = "hello";
83
84 try expect(slice.len == 5);
85 try expect(slice[5] == 0);
86 }
87 };
88 try S.doTheTest();
89 comptime try S.doTheTest();
90}
91
92test "obtaining a null terminated slice" {
93 // here we have a normal array
94 var buf: [50]u8 = undefined;
95
96 buf[0] = 'a';
97 buf[1] = 'b';
98 buf[2] = 'c';
99 buf[3] = 0;
100
101 // now we obtain a null terminated slice:
102 const ptr = buf[0..3 :0];
103 _ = ptr;
104
105 var runtime_len: usize = 3;
106 const ptr2 = buf[0..runtime_len :0];
107 // ptr2 is a null-terminated slice
108 comptime try expect(@TypeOf(ptr2) == [:0]u8);
109 comptime try expect(@TypeOf(ptr2[0..2]) == *[2]u8);
110 var runtime_zero: usize = 0;
111 comptime try expect(@TypeOf(ptr2[runtime_zero..2]) == []u8);
112}
113
114test "empty array to slice" {
115 const S = struct {
116 fn doTheTest() !void {
117 const empty: []align(16) u8 = &[_]u8{};
118 const align_1: []align(1) u8 = empty;
119 const align_4: []align(4) u8 = empty;
120 const align_16: []align(16) u8 = empty;
121 try expectEqual(1, @typeInfo(@TypeOf(align_1)).Pointer.alignment);
122 try expectEqual(4, @typeInfo(@TypeOf(align_4)).Pointer.alignment);
123 try expectEqual(16, @typeInfo(@TypeOf(align_16)).Pointer.alignment);
124 }
125 };
126
127 try S.doTheTest();
128 comptime try S.doTheTest();
129}
130
131test "@ptrCast slice to pointer" {
132 const S = struct {
133 fn doTheTest() !void {
134 var array align(@alignOf(u16)) = [5]u8{ 0xff, 0xff, 0xff, 0xff, 0xff };
135 var slice: []u8 = &array;
136 var ptr = @ptrCast(*u16, slice);
137 try expect(ptr.* == 65535);
138 }
139 };
140
141 try S.doTheTest();
142 comptime try S.doTheTest();
143}
144
145test "slice syntax resulting in pointer-to-array" {
146 const S = struct {
147 fn doTheTest() !void {
148 try testArray();
149 try testArrayZ();
150 try testArray0();
151 try testArrayAlign();
152 try testPointer();
153 try testPointerZ();
154 try testPointer0();
155 try testPointerAlign();
156 try testSlice();
157 try testSliceZ();
158 try testSlice0();
159 try testSliceOpt();
160 try testSliceAlign();
161 }
162
163 fn testArray() !void {
164 var array = [5]u8{ 1, 2, 3, 4, 5 };
165 var slice = array[1..3];
166 comptime try expect(@TypeOf(slice) == *[2]u8);
167 try expect(slice[0] == 2);
168 try expect(slice[1] == 3);
169 }
170
171 fn testArrayZ() !void {
172 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
173 comptime try expect(@TypeOf(array[1..3]) == *[2]u8);
174 comptime try expect(@TypeOf(array[1..5]) == *[4:0]u8);
175 comptime try expect(@TypeOf(array[1..]) == *[4:0]u8);
176 comptime try expect(@TypeOf(array[1..3 :4]) == *[2:4]u8);
177 }
178
179 fn testArray0() !void {
180 {
181 var array = [0]u8{};
182 var slice = array[0..0];
183 comptime try expect(@TypeOf(slice) == *[0]u8);
184 }
185 {
186 var array = [0:0]u8{};
187 var slice = array[0..0];
188 comptime try expect(@TypeOf(slice) == *[0:0]u8);
189 try expect(slice[0] == 0);
190 }
191 }
192
193 fn testArrayAlign() !void {
194 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
195 var slice = array[4..5];
196 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
197 try expect(slice[0] == 5);
198 comptime try expect(@TypeOf(array[0..2]) == *align(4) [2]u8);
199 }
200
201 fn testPointer() !void {
202 var array = [5]u8{ 1, 2, 3, 4, 5 };
203 var pointer: [*]u8 = &array;
204 var slice = pointer[1..3];
205 comptime try expect(@TypeOf(slice) == *[2]u8);
206 try expect(slice[0] == 2);
207 try expect(slice[1] == 3);
208 }
209
210 fn testPointerZ() !void {
211 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
212 var pointer: [*:0]u8 = &array;
213 comptime try expect(@TypeOf(pointer[1..3]) == *[2]u8);
214 comptime try expect(@TypeOf(pointer[1..3 :4]) == *[2:4]u8);
215 }
216
217 fn testPointer0() !void {
218 var pointer: [*]const u0 = &[1]u0{0};
219 var slice = pointer[0..1];
220 comptime try expect(@TypeOf(slice) == *const [1]u0);
221 try expect(slice[0] == 0);
222 }
223
224 fn testPointerAlign() !void {
225 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
226 var pointer: [*]align(4) u8 = &array;
227 var slice = pointer[4..5];
228 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
229 try expect(slice[0] == 5);
230 comptime try expect(@TypeOf(pointer[0..2]) == *align(4) [2]u8);
231 }
232
233 fn testSlice() !void {
234 var array = [5]u8{ 1, 2, 3, 4, 5 };
235 var src_slice: []u8 = &array;
236 var slice = src_slice[1..3];
237 comptime try expect(@TypeOf(slice) == *[2]u8);
238 try expect(slice[0] == 2);
239 try expect(slice[1] == 3);
240 }
241
242 fn testSliceZ() !void {
243 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
244 var slice: [:0]u8 = &array;
245 comptime try expect(@TypeOf(slice[1..3]) == *[2]u8);
246 comptime try expect(@TypeOf(slice[1..]) == [:0]u8);
247 comptime try expect(@TypeOf(slice[1..3 :4]) == *[2:4]u8);
248 }
249
250 fn testSliceOpt() !void {
251 var array: [2]u8 = [2]u8{ 1, 2 };
252 var slice: ?[]u8 = &array;
253 comptime try expect(@TypeOf(&array, slice) == ?[]u8);
254 comptime try expect(@TypeOf(slice.?[0..2]) == *[2]u8);
255 }
256
257 fn testSlice0() !void {
258 {
259 var array = [0]u8{};
260 var src_slice: []u8 = &array;
261 var slice = src_slice[0..0];
262 comptime try expect(@TypeOf(slice) == *[0]u8);
263 }
264 {
265 var array = [0:0]u8{};
266 var src_slice: [:0]u8 = &array;
267 var slice = src_slice[0..0];
268 comptime try expect(@TypeOf(slice) == *[0]u8);
269 }
270 }
271
272 fn testSliceAlign() !void {
273 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
274 var src_slice: []align(4) u8 = &array;
275 var slice = src_slice[4..5];
276 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
277 try expect(slice[0] == 5);
278 comptime try expect(@TypeOf(src_slice[0..2]) == *align(4) [2]u8);
279 }
280
281 fn testConcatStrLiterals() !void {
282 try expectEqualSlices("a"[0..] ++ "b"[0..], "ab");
283 try expectEqualSlices("a"[0.. :0] ++ "b"[0.. :0], "ab");
284 }
285 };
286
287 try S.doTheTest();
288 comptime try S.doTheTest();
289}
290
291test "slice of hardcoded address to pointer" {
292 const S = struct {
293 fn doTheTest() !void {
294 const pointer = @intToPtr([*]u8, 0x04)[0..2];
295 comptime try expect(@TypeOf(pointer) == *[2]u8);
296 const slice: []const u8 = pointer;
297 try expect(@ptrToInt(slice.ptr) == 4);
298 try expect(slice.len == 2);
299 }
300 };
301
302 try S.doTheTest();
303}
304
305test "type coercion of pointer to anon struct literal to pointer to slice" {
306 const S = struct {
307 const U = union {
308 a: u32,
309 b: bool,
310 c: []const u8,
311 };
312
313 fn doTheTest() !void {
314 var x1: u8 = 42;
315 const t1 = &.{ x1, 56, 54 };
316 var slice1: []const u8 = t1;
317 try expect(slice1.len == 3);
318 try expect(slice1[0] == 42);
319 try expect(slice1[1] == 56);
320 try expect(slice1[2] == 54);
321
322 var x2: []const u8 = "hello";
323 const t2 = &.{ x2, ", ", "world!" };
324 // @compileLog(@TypeOf(t2));
325 var slice2: []const []const u8 = t2;
326 try expect(slice2.len == 3);
327 try expect(mem.eql(u8, slice2[0], "hello"));
328 try expect(mem.eql(u8, slice2[1], ", "));
329 try expect(mem.eql(u8, slice2[2], "world!"));
330 }
331 };
332 // try S.doTheTest();
333 comptime try S.doTheTest();
334}