authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-13 17:53:28-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2021-10-13 17:53:28-07:00
logdf7d6d263e4ad6adb302856235641ae9ceb142b6
tree186182733c89cec8fa990a681ab8e6f915d15908
parentda7fcfd1586fa93c3d00815f60030e00ea583701

stage2: implement opaque declarations

* Module: implement opaque type namespace lookup * Add `Type.type` for convenience * Sema: fix `validateVarType` for pointer-to-opaque * x86_64 ABI: implement support for pointers * LLVM backend: fix lowering of opaque types * Type: implement equality checking for opaques

8 files changed, 158 insertions(+), 46 deletions(-)

src/Module.zig+24-1
...@@ -708,7 +708,9 @@ pub const Decl = struct {...@@ -708,7 +708,9 @@ pub const Decl = struct {
708 return ty.castTag(.empty_struct).?.data;708 return ty.castTag(.empty_struct).?.data;
709 },709 },
710 .@"opaque" => {710 .@"opaque" => {
711 @panic("TODO opaque types");711 const opaque_obj = ty.cast(Type.Payload.Opaque).?.data;
712 assert(opaque_obj.owner_decl == decl);
713 return &opaque_obj.namespace;
712 },714 },
713 .@"union", .union_tagged => {715 .@"union", .union_tagged => {
714 const union_obj = ty.cast(Type.Payload.Union).?.data;716 const union_obj = ty.cast(Type.Payload.Union).?.data;
...@@ -1080,6 +1082,27 @@ pub const Union = struct {...@@ -1080,6 +1082,27 @@ pub const Union = struct {
1080 }1082 }
1081};1083};
10821084
1085pub const Opaque = struct {
1086 /// The Decl that corresponds to the opaque itself.
1087 owner_decl: *Decl,
1088 /// Represents the declarations inside this opaque.
1089 namespace: Namespace,
1090 /// Offset from `owner_decl`, points to the opaque decl AST node.
1091 node_offset: i32,
1092
1093 pub fn srcLoc(self: Opaque) SrcLoc {
1094 return .{
1095 .file_scope = self.owner_decl.getFileScope(),
1096 .parent_decl_node = self.owner_decl.src_node,
1097 .lazy = .{ .node_offset = self.node_offset },
1098 };
1099 }
1100
1101 pub fn getFullyQualifiedName(s: *Opaque, gpa: *Allocator) ![:0]u8 {
1102 return s.owner_decl.getFullyQualifiedName(gpa);
1103 }
1104};
1105
1083/// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.1106/// Some Fn struct memory is owned by the Decl's TypedValue.Managed arena allocator.
1084/// Extern functions do not have this data structure; they are represented by1107/// Extern functions do not have this data structure; they are represented by
1085/// the `Decl` only, with a `Value` tag of `extern_fn`.1108/// the `Decl` only, with a `Value` tag of `extern_fn`.
src/Sema.zig+68-13
...@@ -957,7 +957,7 @@ fn zirExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai...@@ -957,7 +957,7 @@ fn zirExtended(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
957 .struct_decl => return sema.zirStructDecl( block, extended, inst),957 .struct_decl => return sema.zirStructDecl( block, extended, inst),
958 .enum_decl => return sema.zirEnumDecl( block, extended),958 .enum_decl => return sema.zirEnumDecl( block, extended),
959 .union_decl => return sema.zirUnionDecl( block, extended, inst),959 .union_decl => return sema.zirUnionDecl( block, extended, inst),
960 .opaque_decl => return sema.zirOpaqueDecl( block, extended, inst),960 .opaque_decl => return sema.zirOpaqueDecl( block, extended),
961 .ret_ptr => return sema.zirRetPtr( block, extended),961 .ret_ptr => return sema.zirRetPtr( block, extended),
962 .ret_type => return sema.zirRetType( block, extended),962 .ret_type => return sema.zirRetType( block, extended),
963 .this => return sema.zirThis( block, extended),963 .this => return sema.zirThis( block, extended),
...@@ -1432,7 +1432,7 @@ fn zirStructDecl(...@@ -1432,7 +1432,7 @@ fn zirStructDecl(
1432 const struct_val = try Value.Tag.ty.create(&new_decl_arena.allocator, struct_ty);1432 const struct_val = try Value.Tag.ty.create(&new_decl_arena.allocator, struct_ty);
1433 const type_name = try sema.createTypeName(block, small.name_strategy);1433 const type_name = try sema.createTypeName(block, small.name_strategy);
1434 const new_decl = try sema.mod.createAnonymousDeclNamed(block, .{1434 const new_decl = try sema.mod.createAnonymousDeclNamed(block, .{
1435 .ty = Type.initTag(.type),1435 .ty = Type.type,
1436 .val = struct_val,1436 .val = struct_val,
1437 }, type_name);1437 }, type_name);
1438 new_decl.owns_tv = true;1438 new_decl.owns_tv = true;
...@@ -1541,7 +1541,7 @@ fn zirEnumDecl(...@@ -1541,7 +1541,7 @@ fn zirEnumDecl(
1541 const enum_val = try Value.Tag.ty.create(&new_decl_arena.allocator, enum_ty);1541 const enum_val = try Value.Tag.ty.create(&new_decl_arena.allocator, enum_ty);
1542 const type_name = try sema.createTypeName(block, small.name_strategy);1542 const type_name = try sema.createTypeName(block, small.name_strategy);
1543 const new_decl = try mod.createAnonymousDeclNamed(block, .{1543 const new_decl = try mod.createAnonymousDeclNamed(block, .{
1544 .ty = Type.initTag(.type),1544 .ty = Type.type,
1545 .val = enum_val,1545 .val = enum_val,
1546 }, type_name);1546 }, type_name);
1547 new_decl.owns_tv = true;1547 new_decl.owns_tv = true;
...@@ -1731,7 +1731,7 @@ fn zirUnionDecl(...@@ -1731,7 +1731,7 @@ fn zirUnionDecl(
1731 const union_val = try Value.Tag.ty.create(&new_decl_arena.allocator, union_ty);1731 const union_val = try Value.Tag.ty.create(&new_decl_arena.allocator, union_ty);
1732 const type_name = try sema.createTypeName(block, small.name_strategy);1732 const type_name = try sema.createTypeName(block, small.name_strategy);
1733 const new_decl = try sema.mod.createAnonymousDeclNamed(block, .{1733 const new_decl = try sema.mod.createAnonymousDeclNamed(block, .{
1734 .ty = Type.initTag(.type),1734 .ty = Type.type,
1735 .val = union_val,1735 .val = union_val,
1736 }, type_name);1736 }, type_name);
1737 new_decl.owns_tv = true;1737 new_decl.owns_tv = true;
...@@ -1764,14 +1764,63 @@ fn zirOpaqueDecl(...@@ -1764,14 +1764,63 @@ fn zirOpaqueDecl(
1764 sema: *Sema,1764 sema: *Sema,
1765 block: *Block,1765 block: *Block,
1766 extended: Zir.Inst.Extended.InstData,1766 extended: Zir.Inst.Extended.InstData,
1767 inst: Zir.Inst.Index,
1768) CompileError!Air.Inst.Ref {1767) CompileError!Air.Inst.Ref {
1769 const tracy = trace(@src());1768 const tracy = trace(@src());
1770 defer tracy.end();1769 defer tracy.end();
17711770
1772 _ = extended;1771 const mod = sema.mod;
1773 _ = inst;1772 const gpa = sema.gpa;
1774 return sema.fail(block, sema.src, "TODO implement zirOpaqueDecl", .{});1773 const small = @bitCast(Zir.Inst.OpaqueDecl.Small, extended.small);
1774 var extra_index: usize = extended.operand;
1775
1776 const src: LazySrcLoc = if (small.has_src_node) blk: {
1777 const node_offset = @bitCast(i32, sema.code.extra[extra_index]);
1778 extra_index += 1;
1779 break :blk .{ .node_offset = node_offset };
1780 } else sema.src;
1781
1782 const decls_len = if (small.has_decls_len) blk: {
1783 const decls_len = sema.code.extra[extra_index];
1784 extra_index += 1;
1785 break :blk decls_len;
1786 } else 0;
1787
1788 var new_decl_arena = std.heap.ArenaAllocator.init(gpa);
1789 errdefer new_decl_arena.deinit();
1790
1791 const opaque_obj = try new_decl_arena.allocator.create(Module.Opaque);
1792 const opaque_ty_payload = try new_decl_arena.allocator.create(Type.Payload.Opaque);
1793 opaque_ty_payload.* = .{
1794 .base = .{ .tag = .@"opaque" },
1795 .data = opaque_obj,
1796 };
1797 const opaque_ty = Type.initPayload(&opaque_ty_payload.base);
1798 const opaque_val = try Value.Tag.ty.create(&new_decl_arena.allocator, opaque_ty);
1799 const type_name = try sema.createTypeName(block, small.name_strategy);
1800 const new_decl = try mod.createAnonymousDeclNamed(block, .{
1801 .ty = Type.type,
1802 .val = opaque_val,
1803 }, type_name);
1804 new_decl.owns_tv = true;
1805 errdefer mod.abortAnonDecl(new_decl);
1806
1807 opaque_obj.* = .{
1808 .owner_decl = new_decl,
1809 .node_offset = src.node_offset,
1810 .namespace = .{
1811 .parent = block.namespace,
1812 .ty = opaque_ty,
1813 .file_scope = block.getFileScope(),
1814 },
1815 };
1816 std.log.scoped(.module).debug("create opaque {*} owned by {*} ({s})", .{
1817 &opaque_obj.namespace, new_decl, new_decl.name,
1818 });
1819
1820 extra_index = try mod.scanNamespace(&opaque_obj.namespace, extra_index, decls_len, new_decl);
1821
1822 try new_decl.finalizeNewArena(&new_decl_arena);
1823 return sema.analyzeDeclVal(block, src, new_decl);
1775}1824}
17761825
1777fn zirErrorSetDecl(1826fn zirErrorSetDecl(
...@@ -1797,7 +1846,7 @@ fn zirErrorSetDecl(...@@ -1797,7 +1846,7 @@ fn zirErrorSetDecl(
1797 const error_set_val = try Value.Tag.ty.create(&new_decl_arena.allocator, error_set_ty);1846 const error_set_val = try Value.Tag.ty.create(&new_decl_arena.allocator, error_set_ty);
1798 const type_name = try sema.createTypeName(block, name_strategy);1847 const type_name = try sema.createTypeName(block, name_strategy);
1799 const new_decl = try sema.mod.createAnonymousDeclNamed(block, .{1848 const new_decl = try sema.mod.createAnonymousDeclNamed(block, .{
1800 .ty = Type.initTag(.type),1849 .ty = Type.type,
1801 .val = error_set_val,1850 .val = error_set_val,
1802 }, type_name);1851 }, type_name);
1803 new_decl.owns_tv = true;1852 new_decl.owns_tv = true;
...@@ -4278,7 +4327,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr...@@ -4278,7 +4327,7 @@ fn zirMergeErrorSets(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileEr
4278 .names_len = @intCast(u32, new_names.len),4327 .names_len = @intCast(u32, new_names.len),
4279 };4328 };
4280 const error_set_ty = try Type.Tag.error_set.create(sema.arena, new_error_set);4329 const error_set_ty = try Type.Tag.error_set.create(sema.arena, new_error_set);
4281 return sema.addConstant(Type.initTag(.type), try Value.Tag.ty.create(sema.arena, error_set_ty));4330 return sema.addConstant(Type.type, try Value.Tag.ty.create(sema.arena, error_set_ty));
4282}4331}
42834332
4284fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {4333fn zirEnumLiteral(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.Inst.Ref {
...@@ -10158,6 +10207,11 @@ fn validateVarType(...@@ -10158,6 +10207,11 @@ fn validateVarType(
10158 .Null,10207 .Null,
10159 => break false,10208 => break false,
1016010209
10210 .Pointer => {
10211 const elem_ty = ty.childType();
10212 if (elem_ty.zigTypeTag() == .Opaque) return;
10213 ty = elem_ty;
10214 },
10161 .Opaque => break is_extern,10215 .Opaque => break is_extern,
1016210216
10163 .Optional => {10217 .Optional => {
...@@ -10165,7 +10219,8 @@ fn validateVarType(...@@ -10165,7 +10219,8 @@ fn validateVarType(
10165 const child_ty = ty.optionalChild(&buf);10219 const child_ty = ty.optionalChild(&buf);
10166 return validateVarType(sema, block, src, child_ty, is_extern);10220 return validateVarType(sema, block, src, child_ty, is_extern);
10167 },10221 },
10168 .Pointer, .Array, .Vector => ty = ty.elemType(),10222 .Array, .Vector => ty = ty.elemType(),
10223
10169 .ErrorUnion => ty = ty.errorUnionPayload(),10224 .ErrorUnion => ty = ty.errorUnionPayload(),
1017010225
10171 .Fn => @panic("TODO fn validateVarType"),10226 .Fn => @panic("TODO fn validateVarType"),
...@@ -12978,7 +13033,7 @@ fn generateUnionTagTypeNumbered(...@@ -12978,7 +13033,7 @@ fn generateUnionTagTypeNumbered(
12978 const enum_val = try Value.Tag.ty.create(&new_decl_arena.allocator, enum_ty);13033 const enum_val = try Value.Tag.ty.create(&new_decl_arena.allocator, enum_ty);
12979 // TODO better type name13034 // TODO better type name
12980 const new_decl = try mod.createAnonymousDecl(block, .{13035 const new_decl = try mod.createAnonymousDecl(block, .{
12981 .ty = Type.initTag(.type),13036 .ty = Type.type,
12982 .val = enum_val,13037 .val = enum_val,
12983 });13038 });
12984 new_decl.owns_tv = true;13039 new_decl.owns_tv = true;
...@@ -13014,7 +13069,7 @@ fn generateUnionTagTypeSimple(sema: *Sema, block: *Block, fields_len: u32) !Type...@@ -13014,7 +13069,7 @@ fn generateUnionTagTypeSimple(sema: *Sema, block: *Block, fields_len: u32) !Type
13014 const enum_val = try Value.Tag.ty.create(&new_decl_arena.allocator, enum_ty);13069 const enum_val = try Value.Tag.ty.create(&new_decl_arena.allocator, enum_ty);
13015 // TODO better type name13070 // TODO better type name
13016 const new_decl = try mod.createAnonymousDecl(block, .{13071 const new_decl = try mod.createAnonymousDecl(block, .{
13017 .ty = Type.initTag(.type),13072 .ty = Type.type,
13018 .val = enum_val,13073 .val = enum_val,
13019 });13074 });
13020 new_decl.owns_tv = true;13075 new_decl.owns_tv = true;
src/arch/x86_64/abi.zig+11
...@@ -34,6 +34,17 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class {...@@ -34,6 +34,17 @@ pub fn classifySystemV(ty: Type, target: Target) [8]Class {
34 };34 };
35 var result = [1]Class{.none} ** 8;35 var result = [1]Class{.none} ** 8;
36 switch (ty.zigTypeTag()) {36 switch (ty.zigTypeTag()) {
37 .Pointer => switch (ty.ptrSize()) {
38 .Slice => {
39 result[0] = .integer;
40 result[1] = .integer;
41 return result;
42 },
43 else => {
44 result[0] = .integer;
45 return result;
46 },
47 },
37 .Int, .Enum, .ErrorSet => {48 .Int, .Enum, .ErrorSet => {
38 const bits = ty.intInfo(target).bits;49 const bits = ty.intInfo(target).bits;
39 if (bits <= 64) {50 if (bits <= 64) {
src/codegen/llvm.zig+18-3
...@@ -758,11 +758,27 @@ pub const DeclGen = struct {...@@ -758,11 +758,27 @@ pub const DeclGen = struct {
758 };758 };
759 return dg.context.structType(&fields, fields.len, .False);759 return dg.context.structType(&fields, fields.len, .False);
760 } else {760 } else {
761 const elem_type = try dg.llvmType(t.elemType());
762 const llvm_addrspace = dg.llvmAddressSpace(t.ptrAddressSpace());761 const llvm_addrspace = dg.llvmAddressSpace(t.ptrAddressSpace());
763 return elem_type.pointerType(llvm_addrspace);762 const llvm_elem_ty = try dg.llvmType(t.childType());
763 return llvm_elem_ty.pointerType(llvm_addrspace);
764 }764 }
765 },765 },
766 .Opaque => {
767 const gop = try dg.object.type_map.getOrPut(gpa, t);
768 if (gop.found_existing) return gop.value_ptr.*;
769
770 // The Type memory is ephemeral; since we want to store a longer-lived
771 // reference, we need to copy it here.
772 gop.key_ptr.* = try t.copy(&dg.object.type_map_arena.allocator);
773
774 const opaque_obj = t.castTag(.@"opaque").?.data;
775 const name = try opaque_obj.getFullyQualifiedName(gpa);
776 defer gpa.free(name);
777
778 const llvm_struct_ty = dg.context.structCreateNamed(name);
779 gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
780 return llvm_struct_ty;
781 },
766 .Array => {782 .Array => {
767 const elem_type = try dg.llvmType(t.elemType());783 const elem_type = try dg.llvmType(t.elemType());
768 const total_len = t.arrayLen() + @boolToInt(t.sentinel() != null);784 const total_len = t.arrayLen() + @boolToInt(t.sentinel() != null);
...@@ -896,7 +912,6 @@ pub const DeclGen = struct {...@@ -896,7 +912,6 @@ pub const DeclGen = struct {
896912
897 .BoundFn => @panic("TODO remove BoundFn from the language"),913 .BoundFn => @panic("TODO remove BoundFn from the language"),
898914
899 .Opaque,
900 .Frame,915 .Frame,
901 .AnyFrame,916 .AnyFrame,
902 .Vector,917 .Vector,
src/type.zig+9-4
...@@ -571,6 +571,11 @@ pub const Type = extern union {...@@ -571,6 +571,11 @@ pub const Type = extern union {
571 }571 }
572 return a.tag() == b.tag();572 return a.tag() == b.tag();
573 },573 },
574 .Opaque => {
575 const opaque_obj_a = a.castTag(.@"opaque").?.data;
576 const opaque_obj_b = b.castTag(.@"opaque").?.data;
577 return opaque_obj_a == opaque_obj_b;
578 },
574 .Union => {579 .Union => {
575 if (a.cast(Payload.Union)) |a_payload| {580 if (a.cast(Payload.Union)) |a_payload| {
576 if (b.cast(Payload.Union)) |b_payload| {581 if (b.cast(Payload.Union)) |b_payload| {
...@@ -611,7 +616,6 @@ pub const Type = extern union {...@@ -611,7 +616,6 @@ pub const Type = extern union {
611 return false;616 return false;
612 },617 },
613 .Float => return a.tag() == b.tag(),618 .Float => return a.tag() == b.tag(),
614 .Opaque,
615 .BoundFn,619 .BoundFn,
616 .Frame,620 .Frame,
617 => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }),621 => std.debug.panic("TODO implement Type equality comparison of {} and {}", .{ a, b }),
...@@ -1408,6 +1412,7 @@ pub const Type = extern union {...@@ -1408,6 +1412,7 @@ pub const Type = extern union {
1408 .extern_options,1412 .extern_options,
1409 .@"anyframe",1413 .@"anyframe",
1410 .anyframe_T,1414 .anyframe_T,
1415 .@"opaque",
1411 => true,1416 => true,
14121417
1413 .function => !self.castTag(.function).?.data.is_generic,1418 .function => !self.castTag(.function).?.data.is_generic,
...@@ -1499,7 +1504,6 @@ pub const Type = extern union {...@@ -1499,7 +1504,6 @@ pub const Type = extern union {
1499 .enum_literal,1504 .enum_literal,
1500 .empty_struct,1505 .empty_struct,
1501 .empty_struct_literal,1506 .empty_struct_literal,
1502 .@"opaque",
1503 .type_info,1507 .type_info,
1504 .bound_fn,1508 .bound_fn,
1505 => false,1509 => false,
...@@ -3097,7 +3101,7 @@ pub const Type = extern union {...@@ -3097,7 +3101,7 @@ pub const Type = extern union {
3097 .enum_full => &self.castTag(.enum_full).?.data.namespace,3101 .enum_full => &self.castTag(.enum_full).?.data.namespace,
3098 .enum_nonexhaustive => &self.castTag(.enum_nonexhaustive).?.data.namespace,3102 .enum_nonexhaustive => &self.castTag(.enum_nonexhaustive).?.data.namespace,
3099 .empty_struct => self.castTag(.empty_struct).?.data,3103 .empty_struct => self.castTag(.empty_struct).?.data,
3100 .@"opaque" => &self.castTag(.@"opaque").?.data,3104 .@"opaque" => &self.castTag(.@"opaque").?.data.namespace,
3101 .@"union" => &self.castTag(.@"union").?.data.namespace,3105 .@"union" => &self.castTag(.@"union").?.data.namespace,
3102 .union_tagged => &self.castTag(.union_tagged).?.data.namespace,3106 .union_tagged => &self.castTag(.union_tagged).?.data.namespace,
31033107
...@@ -3870,7 +3874,7 @@ pub const Type = extern union {...@@ -3870,7 +3874,7 @@ pub const Type = extern union {
38703874
3871 pub const Opaque = struct {3875 pub const Opaque = struct {
3872 base: Payload = .{ .tag = .@"opaque" },3876 base: Payload = .{ .tag = .@"opaque" },
3873 data: Module.Namespace,3877 data: *Module.Opaque,
3874 };3878 };
38753879
3876 pub const Struct = struct {3880 pub const Struct = struct {
...@@ -3904,6 +3908,7 @@ pub const Type = extern union {...@@ -3904,6 +3908,7 @@ pub const Type = extern union {
3904 pub const @"usize" = initTag(.usize);3908 pub const @"usize" = initTag(.usize);
3905 pub const @"comptime_int" = initTag(.comptime_int);3909 pub const @"comptime_int" = initTag(.comptime_int);
3906 pub const @"void" = initTag(.void);3910 pub const @"void" = initTag(.void);
3911 pub const @"type" = initTag(.type);
39073912
3908 pub fn ptr(arena: *Allocator, d: Payload.Pointer.Data) !Type {3913 pub fn ptr(arena: *Allocator, d: Payload.Pointer.Data) !Type {
3909 assert(d.host_size == 0 or d.bit_offset < d.host_size * 8);3914 assert(d.host_size == 0 or d.bit_offset < d.host_size * 8);
test/behavior/basic.zig+12
...@@ -188,3 +188,15 @@ fn testMemcpyMemset() !void {...@@ -188,3 +188,15 @@ fn testMemcpyMemset() !void {
188 try expect(bar[11] == 'A');188 try expect(bar[11] == 'A');
189 try expect(bar[19] == 'A');189 try expect(bar[19] == 'A');
190}190}
191
192const OpaqueA = opaque {};
193const OpaqueB = opaque {};
194
195test "variable is allowed to be a pointer to an opaque type" {
196 var x: i32 = 1234;
197 _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x));
198}
199fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
200 var a = ptr;
201 return a;
202}
test/behavior/misc.zig-25
...@@ -5,22 +5,6 @@ const expectEqualStrings = std.testing.expectEqualStrings;...@@ -5,22 +5,6 @@ const expectEqualStrings = std.testing.expectEqualStrings;
5const mem = std.mem;5const mem = std.mem;
6const builtin = @import("builtin");6const builtin = @import("builtin");
77
8test "slicing" {
9 var array: [20]i32 = undefined;
10
11 array[5] = 1234;
12
13 var slice = array[5..10];
14
15 if (slice.len != 5) unreachable;
16
17 const ptr = &slice[0];
18 if (ptr.* != 1234) unreachable;
19
20 var slice_rest = array[10..];
21 if (slice_rest.len != 10) unreachable;
22}
23
24test "constant equal function pointers" {8test "constant equal function pointers" {
25 const alias = emptyFn;9 const alias = emptyFn;
26 try expect(comptime x: {10 try expect(comptime x: {
...@@ -230,15 +214,6 @@ test "opaque types" {...@@ -230,15 +214,6 @@ test "opaque types" {
230 try expect(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));214 try expect(mem.eql(u8, @typeName(OpaqueB), "OpaqueB"));
231}215}
232216
233test "variable is allowed to be a pointer to an opaque type" {
234 var x: i32 = 1234;
235 _ = hereIsAnOpaqueType(@ptrCast(*OpaqueA, &x));
236}
237fn hereIsAnOpaqueType(ptr: *OpaqueA) *OpaqueA {
238 var a = ptr;
239 return a;
240}
241
242test "comptime if inside runtime while which unconditionally breaks" {217test "comptime if inside runtime while which unconditionally breaks" {
243 testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);218 testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
244 comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);219 comptime testComptimeIfInsideRuntimeWhileWhichUnconditionallyBreaks(true);
test/behavior/slice_stage1.zig+16
...@@ -4,6 +4,22 @@ const expectEqualSlices = std.testing.expectEqualSlices;...@@ -4,6 +4,22 @@ const expectEqualSlices = std.testing.expectEqualSlices;
4const expectEqual = std.testing.expectEqual;4const expectEqual = std.testing.expectEqual;
5const mem = std.mem;5const mem = std.mem;
66
7test "slicing" {
8 var array: [20]i32 = undefined;
9
10 array[5] = 1234;
11
12 var slice = array[5..10];
13
14 if (slice.len != 5) unreachable;
15
16 const ptr = &slice[0];
17 if (ptr.* != 1234) unreachable;
18
19 var slice_rest = array[10..];
20 if (slice_rest.len != 10) unreachable;
21}
22
7const x = @intToPtr([*]i32, 0x1000)[0..0x500];23const x = @intToPtr([*]i32, 0x1000)[0..0x500];
8const y = x[0x100..];24const y = x[0x100..];
9test "compile time slice of pointer to hard coded address" {25test "compile time slice of pointer to hard coded address" {