authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-03 23:57:05-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2022-02-03 23:59:32-07:00
log95fbce2b958395a367a82ce33170edd93e686173
treedae1e68036754591c53b71571d5b12b3b2f33539
parent64f7231f86d4b8a155f48087b3f173d8e41b620c

Sema: fixes to fieldVal, resolveStructFully, Type.eql

fieldVal handles pointer to pointer to array. This can happen for example, if a pointer to an array is used as the condition expression of a for loop. resolveStructFully handles tuples (by doing nothing). fixed Type comparison for tuples to handle comptime fields properly.

5 files changed, 405 insertions(+), 371 deletions(-)

src/Sema.zig+40-22
......@@ -12998,7 +12998,7 @@ fn fieldVal(
1299812998 .Array => {
1299912999 if (mem.eql(u8, field_name, "len")) {
1300013000 return sema.addConstant(
13001 Type.initTag(.comptime_int),
13001 Type.comptime_int,
1300213002 try Value.Tag.int_u64.create(arena, inner_ty.arrayLen()),
1300313003 );
1300413004 } else {
......@@ -13010,26 +13010,43 @@ fn fieldVal(
1301013010 );
1301113011 }
1301213012 },
13013 .Pointer => if (inner_ty.isSlice()) {
13014 if (mem.eql(u8, field_name, "ptr")) {
13015 const slice = if (is_pointer_to)
13016 try sema.analyzeLoad(block, src, object, object_src)
13017 else
13018 object;
13019 return sema.analyzeSlicePtr(block, src, slice, inner_ty, object_src);
13020 } else if (mem.eql(u8, field_name, "len")) {
13021 const slice = if (is_pointer_to)
13022 try sema.analyzeLoad(block, src, object, object_src)
13023 else
13024 object;
13025 return sema.analyzeSliceLen(block, src, slice);
13026 } else {
13027 return sema.fail(
13028 block,
13029 field_name_src,
13030 "no member named '{s}' in '{}'",
13031 .{ field_name, object_ty },
13032 );
13013 .Pointer => {
13014 const ptr_info = inner_ty.ptrInfo().data;
13015 if (ptr_info.size == .Slice) {
13016 if (mem.eql(u8, field_name, "ptr")) {
13017 const slice = if (is_pointer_to)
13018 try sema.analyzeLoad(block, src, object, object_src)
13019 else
13020 object;
13021 return sema.analyzeSlicePtr(block, src, slice, inner_ty, object_src);
13022 } else if (mem.eql(u8, field_name, "len")) {
13023 const slice = if (is_pointer_to)
13024 try sema.analyzeLoad(block, src, object, object_src)
13025 else
13026 object;
13027 return sema.analyzeSliceLen(block, src, slice);
13028 } else {
13029 return sema.fail(
13030 block,
13031 field_name_src,
13032 "no member named '{s}' in '{}'",
13033 .{ field_name, object_ty },
13034 );
13035 }
13036 } else if (ptr_info.pointee_type.zigTypeTag() == .Array) {
13037 if (mem.eql(u8, field_name, "len")) {
13038 return sema.addConstant(
13039 Type.comptime_int,
13040 try Value.Tag.int_u64.create(arena, ptr_info.pointee_type.arrayLen()),
13041 );
13042 } else {
13043 return sema.fail(
13044 block,
13045 field_name_src,
13046 "no member named '{s}' in '{}'",
13047 .{ field_name, ptr_info.pointee_type },
13048 );
13049 }
1303313050 }
1303413051 },
1303513052 .Type => {
......@@ -16371,7 +16388,8 @@ fn resolveStructFully(
1637116388 try resolveStructLayout(sema, block, src, ty);
1637216389
1637316390 const resolved_ty = try sema.resolveTypeFields(block, src, ty);
16374 const struct_obj = resolved_ty.castTag(.@"struct").?.data;
16391 const payload = resolved_ty.castTag(.@"struct") orelse return;
16392 const struct_obj = payload.data;
1637516393 switch (struct_obj.status) {
1637616394 .none, .have_field_types, .field_types_wip, .layout_wip, .have_layout => {},
1637716395 .fully_resolved_wip, .fully_resolved => return,
src/type.zig+13-1
......@@ -634,7 +634,19 @@ pub const Type = extern union {
634634 for (a_payload.data.values) |a_val, i| {
635635 const ty = a_payload.data.types[i];
636636 const b_val = b_payload.data.values[i];
637 if (!Value.eql(a_val, b_val, ty)) return false;
637 if (a_val.tag() == .unreachable_value) {
638 if (b_val.tag() == .unreachable_value) {
639 continue;
640 } else {
641 return false;
642 }
643 } else {
644 if (b_val.tag() == .unreachable_value) {
645 return false;
646 } else {
647 if (!Value.eql(a_val, b_val, ty)) return false;
648 }
649 }
638650 }
639651
640652 return true;
test/behavior.zig-1
......@@ -163,7 +163,6 @@ test {
163163 _ = @import("behavior/select.zig");
164164 _ = @import("behavior/shuffle.zig");
165165 _ = @import("behavior/sizeof_and_typeof_stage1.zig");
166 _ = @import("behavior/slice_stage1.zig");
167166 _ = @import("behavior/struct_contains_null_ptr_itself.zig");
168167 _ = @import("behavior/struct_contains_slice_of_itself.zig");
169168 _ = @import("behavior/switch_prong_err_enum.zig");
test/behavior/slice.zig+352
......@@ -204,3 +204,355 @@ test "slice string literal has correct type" {
204204 const array = [_]i32{ 1, 2, 3, 4 };
205205 comptime try expect(@TypeOf(array[runtime_zero..]) == []const i32);
206206}
207
208test "result location zero sized array inside struct field implicit cast to slice" {
209 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
210
211 const E = struct {
212 entries: []u32,
213 };
214 var foo = E{ .entries = &[_]u32{} };
215 try expect(foo.entries.len == 0);
216}
217
218test "runtime safety lets us slice from len..len" {
219 var an_array = [_]u8{ 1, 2, 3 };
220 try expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
221}
222
223fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
224 return a_slice[start..end];
225}
226
227test "C pointer" {
228 var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
229 var len: u32 = 10;
230 var slice = buf[0..len];
231 try expect(mem.eql(u8, "kjdhfkjdhf", slice));
232}
233
234test "C pointer slice access" {
235 var buf: [10]u32 = [1]u32{42} ** 10;
236 const c_ptr = @ptrCast([*c]const u32, &buf);
237
238 var runtime_zero: usize = 0;
239 comptime try expectEqual([]const u32, @TypeOf(c_ptr[runtime_zero..1]));
240 comptime try expectEqual(*const [1]u32, @TypeOf(c_ptr[0..1]));
241
242 for (c_ptr[0..5]) |*cl| {
243 try expect(@as(u32, 42) == cl.*);
244 }
245}
246
247test "comptime slices are disambiguated" {
248 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
249
250 try expect(sliceSum(&[_]u8{ 1, 2 }) == 3);
251 try expect(sliceSum(&[_]u8{ 3, 4 }) == 7);
252}
253
254fn sliceSum(comptime q: []const u8) i32 {
255 comptime var result = 0;
256 inline for (q) |item| {
257 result += item;
258 }
259 return result;
260}
261
262test "slice type with custom alignment" {
263 const LazilyResolvedType = struct {
264 anything: i32,
265 };
266 var slice: []align(32) LazilyResolvedType = undefined;
267 var array: [10]LazilyResolvedType align(32) = undefined;
268 slice = &array;
269 slice[1].anything = 42;
270 try expect(array[1].anything == 42);
271}
272
273test "obtaining a null terminated slice" {
274 if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
275
276 // here we have a normal array
277 var buf: [50]u8 = undefined;
278
279 buf[0] = 'a';
280 buf[1] = 'b';
281 buf[2] = 'c';
282 buf[3] = 0;
283
284 // now we obtain a null terminated slice:
285 const ptr = buf[0..3 :0];
286 _ = ptr;
287
288 var runtime_len: usize = 3;
289 const ptr2 = buf[0..runtime_len :0];
290 // ptr2 is a null-terminated slice
291 comptime try expect(@TypeOf(ptr2) == [:0]u8);
292 comptime try expect(@TypeOf(ptr2[0..2]) == *[2]u8);
293 var runtime_zero: usize = 0;
294 comptime try expect(@TypeOf(ptr2[runtime_zero..2]) == []u8);
295}
296
297test "empty array to slice" {
298 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
299
300 const S = struct {
301 fn doTheTest() !void {
302 const empty: []align(16) u8 = &[_]u8{};
303 const align_1: []align(1) u8 = empty;
304 const align_4: []align(4) u8 = empty;
305 const align_16: []align(16) u8 = empty;
306 try expectEqual(1, @typeInfo(@TypeOf(align_1)).Pointer.alignment);
307 try expectEqual(4, @typeInfo(@TypeOf(align_4)).Pointer.alignment);
308 try expectEqual(16, @typeInfo(@TypeOf(align_16)).Pointer.alignment);
309 }
310 };
311
312 try S.doTheTest();
313 comptime try S.doTheTest();
314}
315
316test "@ptrCast slice to pointer" {
317 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
318
319 const S = struct {
320 fn doTheTest() !void {
321 var array align(@alignOf(u16)) = [5]u8{ 0xff, 0xff, 0xff, 0xff, 0xff };
322 var slice: []u8 = &array;
323 var ptr = @ptrCast(*u16, slice);
324 try expect(ptr.* == 65535);
325 }
326 };
327
328 try S.doTheTest();
329 comptime try S.doTheTest();
330}
331
332test "slice syntax resulting in pointer-to-array" {
333 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
334
335 const S = struct {
336 fn doTheTest() !void {
337 try testArray();
338 try testArrayZ();
339 try testArray0();
340 try testArrayAlign();
341 try testPointer();
342 try testPointerZ();
343 try testPointer0();
344 try testPointerAlign();
345 try testSlice();
346 try testSliceZ();
347 try testSlice0();
348 try testSliceOpt();
349 try testSliceAlign();
350 }
351
352 fn testArray() !void {
353 var array = [5]u8{ 1, 2, 3, 4, 5 };
354 var slice = array[1..3];
355 comptime try expect(@TypeOf(slice) == *[2]u8);
356 try expect(slice[0] == 2);
357 try expect(slice[1] == 3);
358 }
359
360 fn testArrayZ() !void {
361 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
362 comptime try expect(@TypeOf(array[1..3]) == *[2]u8);
363 comptime try expect(@TypeOf(array[1..5]) == *[4:0]u8);
364 comptime try expect(@TypeOf(array[1..]) == *[4:0]u8);
365 comptime try expect(@TypeOf(array[1..3 :4]) == *[2:4]u8);
366 }
367
368 fn testArray0() !void {
369 {
370 var array = [0]u8{};
371 var slice = array[0..0];
372 comptime try expect(@TypeOf(slice) == *[0]u8);
373 }
374 {
375 var array = [0:0]u8{};
376 var slice = array[0..0];
377 comptime try expect(@TypeOf(slice) == *[0:0]u8);
378 try expect(slice[0] == 0);
379 }
380 }
381
382 fn testArrayAlign() !void {
383 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
384 var slice = array[4..5];
385 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
386 try expect(slice[0] == 5);
387 comptime try expect(@TypeOf(array[0..2]) == *align(4) [2]u8);
388 }
389
390 fn testPointer() !void {
391 var array = [5]u8{ 1, 2, 3, 4, 5 };
392 var pointer: [*]u8 = &array;
393 var slice = pointer[1..3];
394 comptime try expect(@TypeOf(slice) == *[2]u8);
395 try expect(slice[0] == 2);
396 try expect(slice[1] == 3);
397 }
398
399 fn testPointerZ() !void {
400 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
401 var pointer: [*:0]u8 = &array;
402 comptime try expect(@TypeOf(pointer[1..3]) == *[2]u8);
403 comptime try expect(@TypeOf(pointer[1..3 :4]) == *[2:4]u8);
404 }
405
406 fn testPointer0() !void {
407 var pointer: [*]const u0 = &[1]u0{0};
408 var slice = pointer[0..1];
409 comptime try expect(@TypeOf(slice) == *const [1]u0);
410 try expect(slice[0] == 0);
411 }
412
413 fn testPointerAlign() !void {
414 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
415 var pointer: [*]align(4) u8 = &array;
416 var slice = pointer[4..5];
417 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
418 try expect(slice[0] == 5);
419 comptime try expect(@TypeOf(pointer[0..2]) == *align(4) [2]u8);
420 }
421
422 fn testSlice() !void {
423 var array = [5]u8{ 1, 2, 3, 4, 5 };
424 var src_slice: []u8 = &array;
425 var slice = src_slice[1..3];
426 comptime try expect(@TypeOf(slice) == *[2]u8);
427 try expect(slice[0] == 2);
428 try expect(slice[1] == 3);
429 }
430
431 fn testSliceZ() !void {
432 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
433 var slice: [:0]u8 = &array;
434 comptime try expect(@TypeOf(slice[1..3]) == *[2]u8);
435 comptime try expect(@TypeOf(slice[1..]) == [:0]u8);
436 comptime try expect(@TypeOf(slice[1..3 :4]) == *[2:4]u8);
437 }
438
439 fn testSliceOpt() !void {
440 var array: [2]u8 = [2]u8{ 1, 2 };
441 var slice: ?[]u8 = &array;
442 comptime try expect(@TypeOf(&array, slice) == ?[]u8);
443 comptime try expect(@TypeOf(slice.?[0..2]) == *[2]u8);
444 }
445
446 fn testSlice0() !void {
447 {
448 var array = [0]u8{};
449 var src_slice: []u8 = &array;
450 var slice = src_slice[0..0];
451 comptime try expect(@TypeOf(slice) == *[0]u8);
452 }
453 {
454 var array = [0:0]u8{};
455 var src_slice: [:0]u8 = &array;
456 var slice = src_slice[0..0];
457 comptime try expect(@TypeOf(slice) == *[0]u8);
458 }
459 }
460
461 fn testSliceAlign() !void {
462 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
463 var src_slice: []align(4) u8 = &array;
464 var slice = src_slice[4..5];
465 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
466 try expect(slice[0] == 5);
467 comptime try expect(@TypeOf(src_slice[0..2]) == *align(4) [2]u8);
468 }
469
470 fn testConcatStrLiterals() !void {
471 try expectEqualSlices("a"[0..] ++ "b"[0..], "ab");
472 try expectEqualSlices("a"[0.. :0] ++ "b"[0.. :0], "ab");
473 }
474 };
475
476 try S.doTheTest();
477 comptime try S.doTheTest();
478}
479
480test "type coercion of pointer to anon struct literal to pointer to slice" {
481 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
482
483 const S = struct {
484 const U = union {
485 a: u32,
486 b: bool,
487 c: []const u8,
488 };
489
490 fn doTheTest() !void {
491 var x1: u8 = 42;
492 const t1 = &.{ x1, 56, 54 };
493 var slice1: []const u8 = t1;
494 try expect(slice1.len == 3);
495 try expect(slice1[0] == 42);
496 try expect(slice1[1] == 56);
497 try expect(slice1[2] == 54);
498
499 var x2: []const u8 = "hello";
500 const t2 = &.{ x2, ", ", "world!" };
501 // @compileLog(@TypeOf(t2));
502 var slice2: []const []const u8 = t2;
503 try expect(slice2.len == 3);
504 try expect(mem.eql(u8, slice2[0], "hello"));
505 try expect(mem.eql(u8, slice2[1], ", "));
506 try expect(mem.eql(u8, slice2[2], "world!"));
507 }
508 };
509 // try S.doTheTest();
510 comptime try S.doTheTest();
511}
512
513test "array concat of slices gives slice" {
514 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
515
516 comptime {
517 var a: []const u8 = "aoeu";
518 var b: []const u8 = "asdf";
519 const c = a ++ b;
520 try expect(std.mem.eql(u8, c, "aoeuasdf"));
521 }
522}
523
524test "slice bounds in comptime concatenation" {
525 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
526
527 const bs = comptime blk: {
528 const b = "........1........";
529 break :blk b[8..9];
530 };
531 const str = "" ++ bs;
532 try expect(str.len == 1);
533 try expect(std.mem.eql(u8, str, "1"));
534
535 const str2 = bs ++ "";
536 try expect(str2.len == 1);
537 try expect(std.mem.eql(u8, str2, "1"));
538}
539
540test "slice sentinel access at comptime" {
541 if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
542
543 {
544 const str0 = &[_:0]u8{ '1', '2', '3' };
545 const slice0: [:0]const u8 = str0;
546
547 try expect(slice0.len == 3);
548 try expect(slice0[slice0.len] == 0);
549 }
550 {
551 const str0 = "123";
552 _ = &str0[0];
553 const slice0: [:0]const u8 = str0;
554
555 try expect(slice0.len == 3);
556 try expect(slice0[slice0.len] == 0);
557 }
558}
test/behavior/slice_stage1.zig deleted-347
......@@ -1,347 +0,0 @@
1const std = @import("std");
2const expect = std.testing.expect;
3const expectEqualSlices = std.testing.expectEqualSlices;
4const expectEqual = std.testing.expectEqual;
5const mem = std.mem;
6
7test "result location zero sized array inside struct field implicit cast to slice" {
8 const E = struct {
9 entries: []u32,
10 };
11 var foo = E{ .entries = &[_]u32{} };
12 try expect(foo.entries.len == 0);
13}
14
15const x = @intToPtr([*]i32, 0x1000)[0..0x500];
16const y = x[0x100..];
17test "compile time slice of pointer to hard coded address" {
18 try expect(@ptrToInt(x) == 0x1000);
19 try expect(x.len == 0x500);
20
21 try expect(@ptrToInt(y) == 0x1100);
22 try expect(y.len == 0x400);
23}
24
25test "runtime safety lets us slice from len..len" {
26 var an_array = [_]u8{ 1, 2, 3 };
27 try expect(mem.eql(u8, sliceFromLenToLen(an_array[0..], 3, 3), ""));
28}
29
30fn sliceFromLenToLen(a_slice: []u8, start: usize, end: usize) []u8 {
31 return a_slice[start..end];
32}
33
34test "C pointer" {
35 var buf: [*c]const u8 = "kjdhfkjdhfdkjhfkfjhdfkjdhfkdjhfdkjhf";
36 var len: u32 = 10;
37 var slice = buf[0..len];
38 try expectEqualSlices(u8, "kjdhfkjdhf", slice);
39}
40
41test "C pointer slice access" {
42 var buf: [10]u32 = [1]u32{42} ** 10;
43 const c_ptr = @ptrCast([*c]const u32, &buf);
44
45 var runtime_zero: usize = 0;
46 comptime try expectEqual([]const u32, @TypeOf(c_ptr[runtime_zero..1]));
47 comptime try expectEqual(*const [1]u32, @TypeOf(c_ptr[0..1]));
48
49 for (c_ptr[0..5]) |*cl| {
50 try expectEqual(@as(u32, 42), cl.*);
51 }
52}
53
54fn sliceSum(comptime q: []const u8) i32 {
55 comptime var result = 0;
56 inline for (q) |item| {
57 result += item;
58 }
59 return result;
60}
61
62test "comptime slices are disambiguated" {
63 try expect(sliceSum(&[_]u8{ 1, 2 }) == 3);
64 try expect(sliceSum(&[_]u8{ 3, 4 }) == 7);
65}
66
67test "slice type with custom alignment" {
68 const LazilyResolvedType = struct {
69 anything: i32,
70 };
71 var slice: []align(32) LazilyResolvedType = undefined;
72 var array: [10]LazilyResolvedType align(32) = undefined;
73 slice = &array;
74 slice[1].anything = 42;
75 try expect(array[1].anything == 42);
76}
77
78test "obtaining a null terminated slice" {
79 // here we have a normal array
80 var buf: [50]u8 = undefined;
81
82 buf[0] = 'a';
83 buf[1] = 'b';
84 buf[2] = 'c';
85 buf[3] = 0;
86
87 // now we obtain a null terminated slice:
88 const ptr = buf[0..3 :0];
89 _ = ptr;
90
91 var runtime_len: usize = 3;
92 const ptr2 = buf[0..runtime_len :0];
93 // ptr2 is a null-terminated slice
94 comptime try expect(@TypeOf(ptr2) == [:0]u8);
95 comptime try expect(@TypeOf(ptr2[0..2]) == *[2]u8);
96 var runtime_zero: usize = 0;
97 comptime try expect(@TypeOf(ptr2[runtime_zero..2]) == []u8);
98}
99
100test "empty array to slice" {
101 const S = struct {
102 fn doTheTest() !void {
103 const empty: []align(16) u8 = &[_]u8{};
104 const align_1: []align(1) u8 = empty;
105 const align_4: []align(4) u8 = empty;
106 const align_16: []align(16) u8 = empty;
107 try expectEqual(1, @typeInfo(@TypeOf(align_1)).Pointer.alignment);
108 try expectEqual(4, @typeInfo(@TypeOf(align_4)).Pointer.alignment);
109 try expectEqual(16, @typeInfo(@TypeOf(align_16)).Pointer.alignment);
110 }
111 };
112
113 try S.doTheTest();
114 comptime try S.doTheTest();
115}
116
117test "@ptrCast slice to pointer" {
118 const S = struct {
119 fn doTheTest() !void {
120 var array align(@alignOf(u16)) = [5]u8{ 0xff, 0xff, 0xff, 0xff, 0xff };
121 var slice: []u8 = &array;
122 var ptr = @ptrCast(*u16, slice);
123 try expect(ptr.* == 65535);
124 }
125 };
126
127 try S.doTheTest();
128 comptime try S.doTheTest();
129}
130
131test "slice syntax resulting in pointer-to-array" {
132 const S = struct {
133 fn doTheTest() !void {
134 try testArray();
135 try testArrayZ();
136 try testArray0();
137 try testArrayAlign();
138 try testPointer();
139 try testPointerZ();
140 try testPointer0();
141 try testPointerAlign();
142 try testSlice();
143 try testSliceZ();
144 try testSlice0();
145 try testSliceOpt();
146 try testSliceAlign();
147 }
148
149 fn testArray() !void {
150 var array = [5]u8{ 1, 2, 3, 4, 5 };
151 var slice = array[1..3];
152 comptime try expect(@TypeOf(slice) == *[2]u8);
153 try expect(slice[0] == 2);
154 try expect(slice[1] == 3);
155 }
156
157 fn testArrayZ() !void {
158 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
159 comptime try expect(@TypeOf(array[1..3]) == *[2]u8);
160 comptime try expect(@TypeOf(array[1..5]) == *[4:0]u8);
161 comptime try expect(@TypeOf(array[1..]) == *[4:0]u8);
162 comptime try expect(@TypeOf(array[1..3 :4]) == *[2:4]u8);
163 }
164
165 fn testArray0() !void {
166 {
167 var array = [0]u8{};
168 var slice = array[0..0];
169 comptime try expect(@TypeOf(slice) == *[0]u8);
170 }
171 {
172 var array = [0:0]u8{};
173 var slice = array[0..0];
174 comptime try expect(@TypeOf(slice) == *[0:0]u8);
175 try expect(slice[0] == 0);
176 }
177 }
178
179 fn testArrayAlign() !void {
180 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
181 var slice = array[4..5];
182 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
183 try expect(slice[0] == 5);
184 comptime try expect(@TypeOf(array[0..2]) == *align(4) [2]u8);
185 }
186
187 fn testPointer() !void {
188 var array = [5]u8{ 1, 2, 3, 4, 5 };
189 var pointer: [*]u8 = &array;
190 var slice = pointer[1..3];
191 comptime try expect(@TypeOf(slice) == *[2]u8);
192 try expect(slice[0] == 2);
193 try expect(slice[1] == 3);
194 }
195
196 fn testPointerZ() !void {
197 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
198 var pointer: [*:0]u8 = &array;
199 comptime try expect(@TypeOf(pointer[1..3]) == *[2]u8);
200 comptime try expect(@TypeOf(pointer[1..3 :4]) == *[2:4]u8);
201 }
202
203 fn testPointer0() !void {
204 var pointer: [*]const u0 = &[1]u0{0};
205 var slice = pointer[0..1];
206 comptime try expect(@TypeOf(slice) == *const [1]u0);
207 try expect(slice[0] == 0);
208 }
209
210 fn testPointerAlign() !void {
211 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
212 var pointer: [*]align(4) u8 = &array;
213 var slice = pointer[4..5];
214 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
215 try expect(slice[0] == 5);
216 comptime try expect(@TypeOf(pointer[0..2]) == *align(4) [2]u8);
217 }
218
219 fn testSlice() !void {
220 var array = [5]u8{ 1, 2, 3, 4, 5 };
221 var src_slice: []u8 = &array;
222 var slice = src_slice[1..3];
223 comptime try expect(@TypeOf(slice) == *[2]u8);
224 try expect(slice[0] == 2);
225 try expect(slice[1] == 3);
226 }
227
228 fn testSliceZ() !void {
229 var array = [5:0]u8{ 1, 2, 3, 4, 5 };
230 var slice: [:0]u8 = &array;
231 comptime try expect(@TypeOf(slice[1..3]) == *[2]u8);
232 comptime try expect(@TypeOf(slice[1..]) == [:0]u8);
233 comptime try expect(@TypeOf(slice[1..3 :4]) == *[2:4]u8);
234 }
235
236 fn testSliceOpt() !void {
237 var array: [2]u8 = [2]u8{ 1, 2 };
238 var slice: ?[]u8 = &array;
239 comptime try expect(@TypeOf(&array, slice) == ?[]u8);
240 comptime try expect(@TypeOf(slice.?[0..2]) == *[2]u8);
241 }
242
243 fn testSlice0() !void {
244 {
245 var array = [0]u8{};
246 var src_slice: []u8 = &array;
247 var slice = src_slice[0..0];
248 comptime try expect(@TypeOf(slice) == *[0]u8);
249 }
250 {
251 var array = [0:0]u8{};
252 var src_slice: [:0]u8 = &array;
253 var slice = src_slice[0..0];
254 comptime try expect(@TypeOf(slice) == *[0]u8);
255 }
256 }
257
258 fn testSliceAlign() !void {
259 var array align(4) = [5]u8{ 1, 2, 3, 4, 5 };
260 var src_slice: []align(4) u8 = &array;
261 var slice = src_slice[4..5];
262 comptime try expect(@TypeOf(slice) == *align(4) [1]u8);
263 try expect(slice[0] == 5);
264 comptime try expect(@TypeOf(src_slice[0..2]) == *align(4) [2]u8);
265 }
266
267 fn testConcatStrLiterals() !void {
268 try expectEqualSlices("a"[0..] ++ "b"[0..], "ab");
269 try expectEqualSlices("a"[0.. :0] ++ "b"[0.. :0], "ab");
270 }
271 };
272
273 try S.doTheTest();
274 comptime try S.doTheTest();
275}
276
277test "type coercion of pointer to anon struct literal to pointer to slice" {
278 const S = struct {
279 const U = union {
280 a: u32,
281 b: bool,
282 c: []const u8,
283 };
284
285 fn doTheTest() !void {
286 var x1: u8 = 42;
287 const t1 = &.{ x1, 56, 54 };
288 var slice1: []const u8 = t1;
289 try expect(slice1.len == 3);
290 try expect(slice1[0] == 42);
291 try expect(slice1[1] == 56);
292 try expect(slice1[2] == 54);
293
294 var x2: []const u8 = "hello";
295 const t2 = &.{ x2, ", ", "world!" };
296 // @compileLog(@TypeOf(t2));
297 var slice2: []const []const u8 = t2;
298 try expect(slice2.len == 3);
299 try expect(mem.eql(u8, slice2[0], "hello"));
300 try expect(mem.eql(u8, slice2[1], ", "));
301 try expect(mem.eql(u8, slice2[2], "world!"));
302 }
303 };
304 // try S.doTheTest();
305 comptime try S.doTheTest();
306}
307
308test "array concat of slices gives slice" {
309 comptime {
310 var a: []const u8 = "aoeu";
311 var b: []const u8 = "asdf";
312 const c = a ++ b;
313 try expect(std.mem.eql(u8, c, "aoeuasdf"));
314 }
315}
316
317test "slice bounds in comptime concatenation" {
318 const bs = comptime blk: {
319 const b = "........1........";
320 break :blk b[8..9];
321 };
322 const str = "" ++ bs;
323 try expect(str.len == 1);
324 try expect(std.mem.eql(u8, str, "1"));
325
326 const str2 = bs ++ "";
327 try expect(str2.len == 1);
328 try expect(std.mem.eql(u8, str2, "1"));
329}
330
331test "slice sentinel access at comptime" {
332 {
333 const str0 = &[_:0]u8{ '1', '2', '3' };
334 const slice0: [:0]const u8 = str0;
335
336 try expect(slice0.len == 3);
337 try expect(slice0[slice0.len] == 0);
338 }
339 {
340 const str0 = "123";
341 _ = &str0[0];
342 const slice0: [:0]const u8 = str0;
343
344 try expect(slice0.len == 3);
345 try expect(slice0[slice0.len] == 0);
346 }
347}