mirror of
https://github.com/ziglang/zig.git
synced 2025-12-06 14:23:09 +00:00
stage2: introduce anonymous struct literals
This commit is contained in:
parent
6f303c01f3
commit
ed2364a148
170
src/Sema.zig
170
src/Sema.zig
@ -7704,7 +7704,7 @@ fn zirHasDecl(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air
|
|||||||
const decl_name = try sema.resolveConstString(block, rhs_src, extra.rhs);
|
const decl_name = try sema.resolveConstString(block, rhs_src, extra.rhs);
|
||||||
|
|
||||||
// tuples are structs but they don't have a namespace
|
// tuples are structs but they don't have a namespace
|
||||||
if (container_type.isTuple()) return Air.Inst.Ref.bool_false;
|
if (container_type.isTupleOrAnonStruct()) return Air.Inst.Ref.bool_false;
|
||||||
const namespace = container_type.getNamespace() orelse return sema.fail(
|
const namespace = container_type.getNamespace() orelse return sema.fail(
|
||||||
block,
|
block,
|
||||||
lhs_src,
|
lhs_src,
|
||||||
@ -10615,15 +10615,19 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
|||||||
const layout = struct_ty.containerLayout();
|
const layout = struct_ty.containerLayout();
|
||||||
|
|
||||||
const struct_field_vals = fv: {
|
const struct_field_vals = fv: {
|
||||||
if (struct_ty.castTag(.tuple)) |payload| {
|
if (struct_ty.isTupleOrAnonStruct()) {
|
||||||
const field_types = payload.data.types;
|
const tuple = struct_ty.tupleFields();
|
||||||
|
const field_types = tuple.types;
|
||||||
const struct_field_vals = try fields_anon_decl.arena().alloc(Value, field_types.len);
|
const struct_field_vals = try fields_anon_decl.arena().alloc(Value, field_types.len);
|
||||||
for (struct_field_vals) |*struct_field_val, i| {
|
for (struct_field_vals) |*struct_field_val, i| {
|
||||||
const field_ty = field_types[i];
|
const field_ty = field_types[i];
|
||||||
const name_val = v: {
|
const name_val = v: {
|
||||||
var anon_decl = try block.startAnonDecl(src);
|
var anon_decl = try block.startAnonDecl(src);
|
||||||
defer anon_decl.deinit();
|
defer anon_decl.deinit();
|
||||||
const bytes = try std.fmt.allocPrintZ(anon_decl.arena(), "{d}", .{i});
|
const bytes = if (struct_ty.castTag(.anon_struct)) |payload|
|
||||||
|
try anon_decl.arena().dupeZ(u8, payload.data.names[i])
|
||||||
|
else
|
||||||
|
try std.fmt.allocPrintZ(anon_decl.arena(), "{d}", .{i});
|
||||||
const new_decl = try anon_decl.finish(
|
const new_decl = try anon_decl.finish(
|
||||||
try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
|
try Type.Tag.array_u8_sentinel_0.create(anon_decl.arena(), bytes.len),
|
||||||
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
|
try Value.Tag.bytes.create(anon_decl.arena(), bytes[0 .. bytes.len + 1]),
|
||||||
@ -10632,7 +10636,7 @@ fn zirTypeInfo(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Ai
|
|||||||
};
|
};
|
||||||
|
|
||||||
const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
|
const struct_field_fields = try fields_anon_decl.arena().create([5]Value);
|
||||||
const field_val = payload.data.values[i];
|
const field_val = tuple.values[i];
|
||||||
const is_comptime = field_val.tag() != .unreachable_value;
|
const is_comptime = field_val.tag() != .unreachable_value;
|
||||||
const opt_default_val = if (is_comptime) field_val else null;
|
const opt_default_val = if (is_comptime) field_val else null;
|
||||||
const default_val_ptr = try sema.optRefValue(block, src, field_ty, opt_default_val);
|
const default_val_ptr = try sema.optRefValue(block, src, field_ty, opt_default_val);
|
||||||
@ -11631,12 +11635,86 @@ fn finishStructInit(
|
|||||||
return block.addAggregateInit(struct_ty, field_inits);
|
return block.addAggregateInit(struct_ty, field_inits);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zirStructInitAnon(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: bool) CompileError!Air.Inst.Ref {
|
fn zirStructInitAnon(
|
||||||
|
sema: *Sema,
|
||||||
|
block: *Block,
|
||||||
|
inst: Zir.Inst.Index,
|
||||||
|
is_ref: bool,
|
||||||
|
) CompileError!Air.Inst.Ref {
|
||||||
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
const inst_data = sema.code.instructions.items(.data)[inst].pl_node;
|
||||||
const src = inst_data.src();
|
const src = inst_data.src();
|
||||||
|
const extra = sema.code.extraData(Zir.Inst.StructInitAnon, inst_data.payload_index);
|
||||||
|
const types = try sema.arena.alloc(Type, extra.data.fields_len);
|
||||||
|
const values = try sema.arena.alloc(Value, types.len);
|
||||||
|
const names = try sema.arena.alloc([]const u8, types.len);
|
||||||
|
|
||||||
_ = is_ref;
|
const opt_runtime_src = rs: {
|
||||||
return sema.fail(block, src, "TODO: Sema.zirStructInitAnon", .{});
|
var runtime_src: ?LazySrcLoc = null;
|
||||||
|
var extra_index = extra.end;
|
||||||
|
for (types) |*field_ty, i| {
|
||||||
|
const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);
|
||||||
|
extra_index = item.end;
|
||||||
|
|
||||||
|
names[i] = sema.code.nullTerminatedString(item.data.field_name);
|
||||||
|
const init = sema.resolveInst(item.data.init);
|
||||||
|
field_ty.* = sema.typeOf(init);
|
||||||
|
const init_src = src; // TODO better source location
|
||||||
|
if (try sema.resolveMaybeUndefVal(block, init_src, init)) |init_val| {
|
||||||
|
values[i] = init_val;
|
||||||
|
} else {
|
||||||
|
values[i] = Value.initTag(.unreachable_value);
|
||||||
|
runtime_src = init_src;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break :rs runtime_src;
|
||||||
|
};
|
||||||
|
|
||||||
|
const tuple_ty = try Type.Tag.anon_struct.create(sema.arena, .{
|
||||||
|
.names = names,
|
||||||
|
.types = types,
|
||||||
|
.values = values,
|
||||||
|
});
|
||||||
|
|
||||||
|
const runtime_src = opt_runtime_src orelse {
|
||||||
|
const tuple_val = try Value.Tag.@"struct".create(sema.arena, values);
|
||||||
|
return sema.addConstantMaybeRef(block, src, tuple_ty, tuple_val, is_ref);
|
||||||
|
};
|
||||||
|
|
||||||
|
try sema.requireRuntimeBlock(block, runtime_src);
|
||||||
|
|
||||||
|
if (is_ref) {
|
||||||
|
const target = sema.mod.getTarget();
|
||||||
|
const alloc = try block.addTy(.alloc, tuple_ty);
|
||||||
|
var extra_index = extra.end;
|
||||||
|
for (types) |field_ty, i_usize| {
|
||||||
|
const i = @intCast(u32, i_usize);
|
||||||
|
const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);
|
||||||
|
extra_index = item.end;
|
||||||
|
|
||||||
|
const field_ptr_ty = try Type.ptr(sema.arena, target, .{
|
||||||
|
.mutable = true,
|
||||||
|
.@"addrspace" = target_util.defaultAddressSpace(target, .local),
|
||||||
|
.pointee_type = field_ty,
|
||||||
|
});
|
||||||
|
if (values[i].tag() == .unreachable_value) {
|
||||||
|
const init = sema.resolveInst(item.data.init);
|
||||||
|
const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);
|
||||||
|
_ = try block.addBinOp(.store, field_ptr, init);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return alloc;
|
||||||
|
}
|
||||||
|
|
||||||
|
const element_refs = try sema.arena.alloc(Air.Inst.Ref, types.len);
|
||||||
|
var extra_index = extra.end;
|
||||||
|
for (types) |_, i| {
|
||||||
|
const item = sema.code.extraData(Zir.Inst.StructInitAnon.Item, extra_index);
|
||||||
|
extra_index = item.end;
|
||||||
|
element_refs[i] = sema.resolveInst(item.data.init);
|
||||||
|
}
|
||||||
|
|
||||||
|
return block.addAggregateInit(tuple_ty, element_refs);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn zirArrayInit(
|
fn zirArrayInit(
|
||||||
@ -11764,8 +11842,10 @@ fn zirArrayInitAnon(
|
|||||||
.@"addrspace" = target_util.defaultAddressSpace(target, .local),
|
.@"addrspace" = target_util.defaultAddressSpace(target, .local),
|
||||||
.pointee_type = types[i],
|
.pointee_type = types[i],
|
||||||
});
|
});
|
||||||
const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);
|
if (values[i].tag() == .unreachable_value) {
|
||||||
_ = try block.addBinOp(.store, field_ptr, sema.resolveInst(operand));
|
const field_ptr = try block.addStructFieldPtr(alloc, i, field_ptr_ty);
|
||||||
|
_ = try block.addBinOp(.store, field_ptr, sema.resolveInst(operand));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return alloc;
|
return alloc;
|
||||||
@ -12126,7 +12206,7 @@ fn zirReify(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!Air.I
|
|||||||
.size = ptr_size,
|
.size = ptr_size,
|
||||||
.mutable = !is_const_val.toBool(),
|
.mutable = !is_const_val.toBool(),
|
||||||
.@"volatile" = is_volatile_val.toBool(),
|
.@"volatile" = is_volatile_val.toBool(),
|
||||||
.@"align" = @intCast(u8, alignment_val.toUnsignedInt()), // TODO: Validate this value.
|
.@"align" = @intCast(u16, alignment_val.toUnsignedInt()), // TODO: Validate this value.
|
||||||
.@"addrspace" = address_space_val.toEnum(std.builtin.AddressSpace),
|
.@"addrspace" = address_space_val.toEnum(std.builtin.AddressSpace),
|
||||||
.pointee_type = try child_ty.copy(sema.arena),
|
.pointee_type = try child_ty.copy(sema.arena),
|
||||||
.@"allowzero" = is_allowzero_val.toBool(),
|
.@"allowzero" = is_allowzero_val.toBool(),
|
||||||
@ -14842,29 +14922,43 @@ fn structFieldVal(
|
|||||||
assert(unresolved_struct_ty.zigTypeTag() == .Struct);
|
assert(unresolved_struct_ty.zigTypeTag() == .Struct);
|
||||||
|
|
||||||
const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty);
|
const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty);
|
||||||
if (struct_ty.isTuple()) {
|
switch (struct_ty.tag()) {
|
||||||
return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty);
|
.tuple, .empty_struct_literal => return sema.tupleFieldVal(block, src, struct_byval, field_name, field_name_src, struct_ty),
|
||||||
|
.anon_struct => {
|
||||||
|
const anon_struct = struct_ty.castTag(.anon_struct).?.data;
|
||||||
|
|
||||||
|
const field_index = for (anon_struct.names) |name, i| {
|
||||||
|
if (mem.eql(u8, name, field_name)) break @intCast(u32, i);
|
||||||
|
} else {
|
||||||
|
return sema.fail(block, field_name_src, "anonymous struct {} has no such field '{s}'", .{
|
||||||
|
struct_ty, field_name,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
return tupleFieldValByIndex(sema, block, src, struct_byval, field_index, struct_ty);
|
||||||
|
},
|
||||||
|
.@"struct" => {
|
||||||
|
const struct_obj = struct_ty.castTag(.@"struct").?.data;
|
||||||
|
|
||||||
|
const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
|
||||||
|
return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);
|
||||||
|
const field_index = @intCast(u32, field_index_usize);
|
||||||
|
const field = struct_obj.fields.values()[field_index];
|
||||||
|
|
||||||
|
if (try sema.resolveMaybeUndefVal(block, src, struct_byval)) |struct_val| {
|
||||||
|
if (struct_val.isUndef()) return sema.addConstUndef(field.ty);
|
||||||
|
if ((try sema.typeHasOnePossibleValue(block, src, field.ty))) |opv| {
|
||||||
|
return sema.addConstant(field.ty, opv);
|
||||||
|
}
|
||||||
|
|
||||||
|
const field_values = struct_val.castTag(.@"struct").?.data;
|
||||||
|
return sema.addConstant(field.ty, field_values[field_index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
try sema.requireRuntimeBlock(block, src);
|
||||||
|
return block.addStructFieldVal(struct_byval, field_index, field.ty);
|
||||||
|
},
|
||||||
|
else => unreachable,
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct_obj = struct_ty.castTag(.@"struct").?.data;
|
|
||||||
|
|
||||||
const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
|
|
||||||
return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);
|
|
||||||
const field_index = @intCast(u32, field_index_usize);
|
|
||||||
const field = struct_obj.fields.values()[field_index];
|
|
||||||
|
|
||||||
if (try sema.resolveMaybeUndefVal(block, src, struct_byval)) |struct_val| {
|
|
||||||
if (struct_val.isUndef()) return sema.addConstUndef(field.ty);
|
|
||||||
if ((try sema.typeHasOnePossibleValue(block, src, field.ty))) |opv| {
|
|
||||||
return sema.addConstant(field.ty, opv);
|
|
||||||
}
|
|
||||||
|
|
||||||
const field_values = struct_val.castTag(.@"struct").?.data;
|
|
||||||
return sema.addConstant(field.ty, field_values[field_index]);
|
|
||||||
}
|
|
||||||
|
|
||||||
try sema.requireRuntimeBlock(block, src);
|
|
||||||
return block.addStructFieldVal(struct_byval, field_index, field.ty);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tupleFieldVal(
|
fn tupleFieldVal(
|
||||||
@ -14901,7 +14995,7 @@ fn tupleFieldValByIndex(
|
|||||||
field_index: u32,
|
field_index: u32,
|
||||||
tuple_ty: Type,
|
tuple_ty: Type,
|
||||||
) CompileError!Air.Inst.Ref {
|
) CompileError!Air.Inst.Ref {
|
||||||
const tuple = tuple_ty.castTag(.tuple).?.data;
|
const tuple = tuple_ty.tupleFields();
|
||||||
const field_ty = tuple.types[field_index];
|
const field_ty = tuple.types[field_index];
|
||||||
|
|
||||||
if (tuple.values[field_index].tag() != .unreachable_value) {
|
if (tuple.values[field_index].tag() != .unreachable_value) {
|
||||||
@ -18954,8 +19048,8 @@ pub fn typeHasOnePossibleValue(
|
|||||||
return Value.initTag(.empty_struct_value);
|
return Value.initTag(.empty_struct_value);
|
||||||
},
|
},
|
||||||
|
|
||||||
.tuple => {
|
.tuple, .anon_struct => {
|
||||||
const tuple = ty.castTag(.tuple).?.data;
|
const tuple = ty.tupleFields();
|
||||||
for (tuple.values) |val| {
|
for (tuple.values) |val| {
|
||||||
if (val.tag() == .unreachable_value) {
|
if (val.tag() == .unreachable_value) {
|
||||||
return null; // non-comptime field
|
return null; // non-comptime field
|
||||||
@ -19583,8 +19677,8 @@ fn typeRequiresComptime(sema: *Sema, block: *Block, src: LazySrcLoc, ty: Type) C
|
|||||||
return sema.typeRequiresComptime(block, src, ty.optionalChild(&buf));
|
return sema.typeRequiresComptime(block, src, ty.optionalChild(&buf));
|
||||||
},
|
},
|
||||||
|
|
||||||
.tuple => {
|
.tuple, .anon_struct => {
|
||||||
const tuple = ty.castTag(.tuple).?.data;
|
const tuple = ty.tupleFields();
|
||||||
for (tuple.types) |field_ty, i| {
|
for (tuple.types) |field_ty, i| {
|
||||||
const have_comptime_val = tuple.values[i].tag() != .unreachable_value;
|
const have_comptime_val = tuple.values[i].tag() != .unreachable_value;
|
||||||
if (!have_comptime_val and try sema.typeRequiresComptime(block, src, field_ty)) {
|
if (!have_comptime_val and try sema.typeRequiresComptime(block, src, field_ty)) {
|
||||||
|
|||||||
@ -2850,7 +2850,9 @@ pub const Inst = struct {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Trailing is an item per field.
|
/// Trailing is an Item per field.
|
||||||
|
/// TODO make this instead array of inits followed by array of names because
|
||||||
|
/// it will be simpler Sema code and better for CPU cache.
|
||||||
pub const StructInitAnon = struct {
|
pub const StructInitAnon = struct {
|
||||||
fields_len: u32,
|
fields_len: u32,
|
||||||
|
|
||||||
|
|||||||
@ -958,7 +958,7 @@ pub const DeclGen = struct {
|
|||||||
// reference, we need to copy it here.
|
// reference, we need to copy it here.
|
||||||
gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
|
gop.key_ptr.* = try t.copy(dg.object.type_map_arena.allocator());
|
||||||
|
|
||||||
if (t.isTuple()) {
|
if (t.isTupleOrAnonStruct()) {
|
||||||
const tuple = t.tupleFields();
|
const tuple = t.tupleFields();
|
||||||
const llvm_struct_ty = dg.context.structCreateNamed("");
|
const llvm_struct_ty = dg.context.structCreateNamed("");
|
||||||
gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
|
gop.value_ptr.* = llvm_struct_ty; // must be done before any recursive calls
|
||||||
@ -2104,7 +2104,7 @@ pub const DeclGen = struct {
|
|||||||
var zig_big_align: u32 = 0;
|
var zig_big_align: u32 = 0;
|
||||||
var llvm_big_align: u32 = 0;
|
var llvm_big_align: u32 = 0;
|
||||||
|
|
||||||
if (ty.isTuple()) {
|
if (ty.isTupleOrAnonStruct()) {
|
||||||
const tuple = ty.tupleFields();
|
const tuple = ty.tupleFields();
|
||||||
var llvm_field_index: c_uint = 0;
|
var llvm_field_index: c_uint = 0;
|
||||||
for (tuple.types) |field_ty, i| {
|
for (tuple.types) |field_ty, i| {
|
||||||
@ -5704,7 +5704,7 @@ fn isByRef(ty: Type) bool {
|
|||||||
.Struct => {
|
.Struct => {
|
||||||
// Packed structs are represented to LLVM as integers.
|
// Packed structs are represented to LLVM as integers.
|
||||||
if (ty.containerLayout() == .Packed) return false;
|
if (ty.containerLayout() == .Packed) return false;
|
||||||
if (ty.isTuple()) {
|
if (ty.isTupleOrAnonStruct()) {
|
||||||
const tuple = ty.tupleFields();
|
const tuple = ty.tupleFields();
|
||||||
var count: usize = 0;
|
var count: usize = 0;
|
||||||
for (tuple.values) |field_val, i| {
|
for (tuple.values) |field_val, i| {
|
||||||
|
|||||||
175
src/type.zig
175
src/type.zig
@ -131,6 +131,7 @@ pub const Type = extern union {
|
|||||||
.export_options,
|
.export_options,
|
||||||
.extern_options,
|
.extern_options,
|
||||||
.tuple,
|
.tuple,
|
||||||
|
.anon_struct,
|
||||||
=> return .Struct,
|
=> return .Struct,
|
||||||
|
|
||||||
.enum_full,
|
.enum_full,
|
||||||
@ -792,6 +793,42 @@ pub const Type = extern union {
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
|
.anon_struct => {
|
||||||
|
const a_struct_obj = a.castTag(.anon_struct).?.data;
|
||||||
|
const b_struct_obj = (b.castTag(.anon_struct) orelse return false).data;
|
||||||
|
|
||||||
|
if (a_struct_obj.types.len != b_struct_obj.types.len) return false;
|
||||||
|
|
||||||
|
for (a_struct_obj.names) |a_name, i| {
|
||||||
|
const b_name = b_struct_obj.names[i];
|
||||||
|
if (!std.mem.eql(u8, a_name, b_name)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (a_struct_obj.types) |a_ty, i| {
|
||||||
|
const b_ty = b_struct_obj.types[i];
|
||||||
|
if (!eql(a_ty, b_ty)) return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (a_struct_obj.values) |a_val, i| {
|
||||||
|
const ty = a_struct_obj.types[i];
|
||||||
|
const b_val = b_struct_obj.values[i];
|
||||||
|
if (a_val.tag() == .unreachable_value) {
|
||||||
|
if (b_val.tag() == .unreachable_value) {
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (b_val.tag() == .unreachable_value) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (!Value.eql(a_val, b_val, ty)) return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
|
||||||
// we can't compare these based on tags because it wouldn't detect if,
|
// we can't compare these based on tags because it wouldn't detect if,
|
||||||
// for example, a was resolved into .@"struct" but b was one of these tags.
|
// for example, a was resolved into .@"struct" but b was one of these tags.
|
||||||
@ -1062,6 +1099,20 @@ pub const Type = extern union {
|
|||||||
field_val.hash(field_ty, hasher);
|
field_val.hash(field_ty, hasher);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
.anon_struct => {
|
||||||
|
const struct_obj = ty.castTag(.anon_struct).?.data;
|
||||||
|
std.hash.autoHash(hasher, std.builtin.TypeId.Struct);
|
||||||
|
std.hash.autoHash(hasher, struct_obj.types.len);
|
||||||
|
|
||||||
|
for (struct_obj.types) |field_ty, i| {
|
||||||
|
const field_name = struct_obj.names[i];
|
||||||
|
const field_val = struct_obj.values[i];
|
||||||
|
hasher.update(field_name);
|
||||||
|
hashWithHasher(field_ty, hasher);
|
||||||
|
if (field_val.tag() == .unreachable_value) continue;
|
||||||
|
field_val.hash(field_ty, hasher);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
// we can't hash these based on tags because they wouldn't match the expanded version.
|
// we can't hash these based on tags because they wouldn't match the expanded version.
|
||||||
.call_options,
|
.call_options,
|
||||||
@ -1279,6 +1330,26 @@ pub const Type = extern union {
|
|||||||
.values = values,
|
.values = values,
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
.anon_struct => {
|
||||||
|
const payload = self.castTag(.anon_struct).?.data;
|
||||||
|
const names = try allocator.alloc([]const u8, payload.names.len);
|
||||||
|
const types = try allocator.alloc(Type, payload.types.len);
|
||||||
|
const values = try allocator.alloc(Value, payload.values.len);
|
||||||
|
for (payload.names) |name, i| {
|
||||||
|
names[i] = try allocator.dupe(u8, name);
|
||||||
|
}
|
||||||
|
for (payload.types) |ty, i| {
|
||||||
|
types[i] = try ty.copy(allocator);
|
||||||
|
}
|
||||||
|
for (payload.values) |val, i| {
|
||||||
|
values[i] = try val.copy(allocator);
|
||||||
|
}
|
||||||
|
return Tag.anon_struct.create(allocator, .{
|
||||||
|
.names = names,
|
||||||
|
.types = types,
|
||||||
|
.values = values,
|
||||||
|
});
|
||||||
|
},
|
||||||
.function => {
|
.function => {
|
||||||
const payload = self.castTag(.function).?.data;
|
const payload = self.castTag(.function).?.data;
|
||||||
const param_types = try allocator.alloc(Type, payload.param_types.len);
|
const param_types = try allocator.alloc(Type, payload.param_types.len);
|
||||||
@ -1533,6 +1604,26 @@ pub const Type = extern union {
|
|||||||
try writer.writeAll("}");
|
try writer.writeAll("}");
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
|
.anon_struct => {
|
||||||
|
const anon_struct = ty.castTag(.anon_struct).?.data;
|
||||||
|
try writer.writeAll("struct{");
|
||||||
|
for (anon_struct.types) |field_ty, i| {
|
||||||
|
if (i != 0) try writer.writeAll(", ");
|
||||||
|
const val = anon_struct.values[i];
|
||||||
|
if (val.tag() != .unreachable_value) {
|
||||||
|
try writer.writeAll("comptime ");
|
||||||
|
}
|
||||||
|
try writer.writeAll(anon_struct.names[i]);
|
||||||
|
try writer.writeAll(": ");
|
||||||
|
try field_ty.format("", .{}, writer);
|
||||||
|
if (val.tag() != .unreachable_value) {
|
||||||
|
try writer.writeAll(" = ");
|
||||||
|
try val.format("", .{}, writer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
try writer.writeAll("}");
|
||||||
|
return;
|
||||||
|
},
|
||||||
.single_const_pointer => {
|
.single_const_pointer => {
|
||||||
const pointee_type = ty.castTag(.single_const_pointer).?.data;
|
const pointee_type = ty.castTag(.single_const_pointer).?.data;
|
||||||
try writer.writeAll("*const ");
|
try writer.writeAll("*const ");
|
||||||
@ -2020,8 +2111,8 @@ pub const Type = extern union {
|
|||||||
return payload.error_set.hasRuntimeBits() or payload.payload.hasRuntimeBits();
|
return payload.error_set.hasRuntimeBits() or payload.payload.hasRuntimeBits();
|
||||||
},
|
},
|
||||||
|
|
||||||
.tuple => {
|
.tuple, .anon_struct => {
|
||||||
const tuple = ty.castTag(.tuple).?.data;
|
const tuple = ty.tupleFields();
|
||||||
for (tuple.types) |field_ty, i| {
|
for (tuple.types) |field_ty, i| {
|
||||||
const val = tuple.values[i];
|
const val = tuple.values[i];
|
||||||
if (val.tag() != .unreachable_value) continue; // comptime field
|
if (val.tag() != .unreachable_value) continue; // comptime field
|
||||||
@ -2292,8 +2383,8 @@ pub const Type = extern union {
|
|||||||
return big_align;
|
return big_align;
|
||||||
},
|
},
|
||||||
|
|
||||||
.tuple => {
|
.tuple, .anon_struct => {
|
||||||
const tuple = self.castTag(.tuple).?.data;
|
const tuple = self.tupleFields();
|
||||||
var big_align: u32 = 0;
|
var big_align: u32 = 0;
|
||||||
for (tuple.types) |field_ty, i| {
|
for (tuple.types) |field_ty, i| {
|
||||||
const val = tuple.values[i];
|
const val = tuple.values[i];
|
||||||
@ -2375,7 +2466,7 @@ pub const Type = extern union {
|
|||||||
.void,
|
.void,
|
||||||
=> 0,
|
=> 0,
|
||||||
|
|
||||||
.@"struct", .tuple => switch (self.containerLayout()) {
|
.@"struct", .tuple, .anon_struct => switch (self.containerLayout()) {
|
||||||
.Packed => {
|
.Packed => {
|
||||||
const struct_obj = self.castTag(.@"struct").?.data;
|
const struct_obj = self.castTag(.@"struct").?.data;
|
||||||
var buf: Type.Payload.Bits = undefined;
|
var buf: Type.Payload.Bits = undefined;
|
||||||
@ -2575,6 +2666,13 @@ pub const Type = extern union {
|
|||||||
.bound_fn => unreachable,
|
.bound_fn => unreachable,
|
||||||
|
|
||||||
.void => 0,
|
.void => 0,
|
||||||
|
.bool, .u1 => 1,
|
||||||
|
.u8, .i8 => 8,
|
||||||
|
.i16, .u16, .f16 => 16,
|
||||||
|
.i32, .u32, .f32 => 32,
|
||||||
|
.i64, .u64, .f64 => 64,
|
||||||
|
.f80 => 80,
|
||||||
|
.u128, .i128, .f128 => 128,
|
||||||
|
|
||||||
.@"struct" => {
|
.@"struct" => {
|
||||||
const field_count = ty.structFieldCount();
|
const field_count = ty.structFieldCount();
|
||||||
@ -2595,8 +2693,13 @@ pub const Type = extern union {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
.tuple => {
|
.tuple, .anon_struct => {
|
||||||
@panic("TODO bitSize tuples");
|
const tuple = ty.tupleFields();
|
||||||
|
var total: u64 = 0;
|
||||||
|
for (tuple.types) |field_ty| {
|
||||||
|
total += field_ty.bitSize(target);
|
||||||
|
}
|
||||||
|
return total;
|
||||||
},
|
},
|
||||||
|
|
||||||
.enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {
|
.enum_simple, .enum_full, .enum_nonexhaustive, .enum_numbered => {
|
||||||
@ -2608,10 +2711,6 @@ pub const Type = extern union {
|
|||||||
@panic("TODO bitSize unions");
|
@panic("TODO bitSize unions");
|
||||||
},
|
},
|
||||||
|
|
||||||
.u8, .i8 => 8,
|
|
||||||
|
|
||||||
.bool, .u1 => 1,
|
|
||||||
|
|
||||||
.vector => {
|
.vector => {
|
||||||
const payload = ty.castTag(.vector).?.data;
|
const payload = ty.castTag(.vector).?.data;
|
||||||
const elem_bit_size = payload.elem_type.bitSize(target);
|
const elem_bit_size = payload.elem_type.bitSize(target);
|
||||||
@ -2634,11 +2733,6 @@ pub const Type = extern union {
|
|||||||
);
|
);
|
||||||
return payload.len * 8 * elem_size + payload.elem_type.bitSize(target);
|
return payload.len * 8 * elem_size + payload.elem_type.bitSize(target);
|
||||||
},
|
},
|
||||||
.i16, .u16, .f16 => 16,
|
|
||||||
.i32, .u32, .f32 => 32,
|
|
||||||
.i64, .u64, .f64 => 64,
|
|
||||||
.f80 => 80,
|
|
||||||
.u128, .i128, .f128 => 128,
|
|
||||||
|
|
||||||
.isize,
|
.isize,
|
||||||
.usize,
|
.usize,
|
||||||
@ -3295,7 +3389,7 @@ pub const Type = extern union {
|
|||||||
|
|
||||||
pub fn containerLayout(ty: Type) std.builtin.TypeInfo.ContainerLayout {
|
pub fn containerLayout(ty: Type) std.builtin.TypeInfo.ContainerLayout {
|
||||||
return switch (ty.tag()) {
|
return switch (ty.tag()) {
|
||||||
.tuple, .empty_struct_literal => .Auto,
|
.tuple, .empty_struct_literal, .anon_struct => .Auto,
|
||||||
.@"struct" => ty.castTag(.@"struct").?.data.layout,
|
.@"struct" => ty.castTag(.@"struct").?.data.layout,
|
||||||
.@"union" => ty.castTag(.@"union").?.data.layout,
|
.@"union" => ty.castTag(.@"union").?.data.layout,
|
||||||
.union_tagged => ty.castTag(.union_tagged).?.data.layout,
|
.union_tagged => ty.castTag(.union_tagged).?.data.layout,
|
||||||
@ -3369,6 +3463,7 @@ pub const Type = extern union {
|
|||||||
.array_u8 => ty.castTag(.array_u8).?.data,
|
.array_u8 => ty.castTag(.array_u8).?.data,
|
||||||
.array_u8_sentinel_0 => ty.castTag(.array_u8_sentinel_0).?.data,
|
.array_u8_sentinel_0 => ty.castTag(.array_u8_sentinel_0).?.data,
|
||||||
.tuple => ty.castTag(.tuple).?.data.types.len,
|
.tuple => ty.castTag(.tuple).?.data.types.len,
|
||||||
|
.anon_struct => ty.castTag(.anon_struct).?.data.types.len,
|
||||||
.@"struct" => ty.castTag(.@"struct").?.data.fields.count(),
|
.@"struct" => ty.castTag(.@"struct").?.data.fields.count(),
|
||||||
|
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
@ -3383,6 +3478,7 @@ pub const Type = extern union {
|
|||||||
return switch (ty.tag()) {
|
return switch (ty.tag()) {
|
||||||
.vector => @intCast(u32, ty.castTag(.vector).?.data.len),
|
.vector => @intCast(u32, ty.castTag(.vector).?.data.len),
|
||||||
.tuple => @intCast(u32, ty.castTag(.tuple).?.data.types.len),
|
.tuple => @intCast(u32, ty.castTag(.tuple).?.data.types.len),
|
||||||
|
.anon_struct => @intCast(u32, ty.castTag(.anon_struct).?.data.types.len),
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -3849,8 +3945,8 @@ pub const Type = extern union {
|
|||||||
return Value.initTag(.empty_struct_value);
|
return Value.initTag(.empty_struct_value);
|
||||||
},
|
},
|
||||||
|
|
||||||
.tuple => {
|
.tuple, .anon_struct => {
|
||||||
const tuple = ty.castTag(.tuple).?.data;
|
const tuple = ty.tupleFields();
|
||||||
for (tuple.values) |val| {
|
for (tuple.values) |val| {
|
||||||
if (val.tag() == .unreachable_value) {
|
if (val.tag() == .unreachable_value) {
|
||||||
return null; // non-comptime field
|
return null; // non-comptime field
|
||||||
@ -4048,8 +4144,8 @@ pub const Type = extern union {
|
|||||||
return ty.optionalChild(&buf).comptimeOnly();
|
return ty.optionalChild(&buf).comptimeOnly();
|
||||||
},
|
},
|
||||||
|
|
||||||
.tuple => {
|
.tuple, .anon_struct => {
|
||||||
const tuple = ty.castTag(.tuple).?.data;
|
const tuple = ty.tupleFields();
|
||||||
for (tuple.types) |field_ty, i| {
|
for (tuple.types) |field_ty, i| {
|
||||||
const have_comptime_val = tuple.values[i].tag() != .unreachable_value;
|
const have_comptime_val = tuple.values[i].tag() != .unreachable_value;
|
||||||
if (!have_comptime_val and field_ty.comptimeOnly()) return true;
|
if (!have_comptime_val and field_ty.comptimeOnly()) return true;
|
||||||
@ -4350,6 +4446,7 @@ pub const Type = extern union {
|
|||||||
},
|
},
|
||||||
.empty_struct, .empty_struct_literal => return 0,
|
.empty_struct, .empty_struct_literal => return 0,
|
||||||
.tuple => return ty.castTag(.tuple).?.data.types.len,
|
.tuple => return ty.castTag(.tuple).?.data.types.len,
|
||||||
|
.anon_struct => return ty.castTag(.anon_struct).?.data.types.len,
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4366,6 +4463,7 @@ pub const Type = extern union {
|
|||||||
return union_obj.fields.values()[index].ty;
|
return union_obj.fields.values()[index].ty;
|
||||||
},
|
},
|
||||||
.tuple => return ty.castTag(.tuple).?.data.types[index],
|
.tuple => return ty.castTag(.tuple).?.data.types[index],
|
||||||
|
.anon_struct => return ty.castTag(.anon_struct).?.data.types[index],
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4424,8 +4522,8 @@ pub const Type = extern union {
|
|||||||
return std.mem.alignForwardGeneric(u64, it.offset, it.big_align);
|
return std.mem.alignForwardGeneric(u64, it.offset, it.big_align);
|
||||||
},
|
},
|
||||||
|
|
||||||
.tuple => {
|
.tuple, .anon_struct => {
|
||||||
const tuple = ty.castTag(.tuple).?.data;
|
const tuple = ty.tupleFields();
|
||||||
|
|
||||||
var offset: u64 = 0;
|
var offset: u64 = 0;
|
||||||
var big_align: u32 = 0;
|
var big_align: u32 = 0;
|
||||||
@ -4700,6 +4798,8 @@ pub const Type = extern union {
|
|||||||
vector,
|
vector,
|
||||||
/// Possible Value tags for this: @"struct"
|
/// Possible Value tags for this: @"struct"
|
||||||
tuple,
|
tuple,
|
||||||
|
/// Possible Value tags for this: @"struct"
|
||||||
|
anon_struct,
|
||||||
pointer,
|
pointer,
|
||||||
single_const_pointer,
|
single_const_pointer,
|
||||||
single_mut_pointer,
|
single_mut_pointer,
|
||||||
@ -4846,6 +4946,7 @@ pub const Type = extern union {
|
|||||||
.enum_numbered => Payload.EnumNumbered,
|
.enum_numbered => Payload.EnumNumbered,
|
||||||
.empty_struct => Payload.ContainerScope,
|
.empty_struct => Payload.ContainerScope,
|
||||||
.tuple => Payload.Tuple,
|
.tuple => Payload.Tuple,
|
||||||
|
.anon_struct => Payload.AnonStruct,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4869,12 +4970,26 @@ pub const Type = extern union {
|
|||||||
};
|
};
|
||||||
|
|
||||||
pub fn isTuple(ty: Type) bool {
|
pub fn isTuple(ty: Type) bool {
|
||||||
return ty.tag() == .tuple or ty.tag() == .empty_struct_literal;
|
return switch (ty.tag()) {
|
||||||
|
.tuple, .empty_struct_literal => true,
|
||||||
|
else => false,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn isTupleOrAnonStruct(ty: Type) bool {
|
||||||
|
return switch (ty.tag()) {
|
||||||
|
.tuple, .empty_struct_literal, .anon_struct => true,
|
||||||
|
else => false,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tupleFields(ty: Type) Payload.Tuple.Data {
|
pub fn tupleFields(ty: Type) Payload.Tuple.Data {
|
||||||
return switch (ty.tag()) {
|
return switch (ty.tag()) {
|
||||||
.tuple => ty.castTag(.tuple).?.data,
|
.tuple => ty.castTag(.tuple).?.data,
|
||||||
|
.anon_struct => .{
|
||||||
|
.types = ty.castTag(.anon_struct).?.data.types,
|
||||||
|
.values = ty.castTag(.anon_struct).?.data.values,
|
||||||
|
},
|
||||||
.empty_struct_literal => .{ .types = &.{}, .values = &.{} },
|
.empty_struct_literal => .{ .types = &.{}, .values = &.{} },
|
||||||
else => unreachable,
|
else => unreachable,
|
||||||
};
|
};
|
||||||
@ -5042,6 +5157,18 @@ pub const Type = extern union {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const AnonStruct = struct {
|
||||||
|
base: Payload = .{ .tag = .anon_struct },
|
||||||
|
data: Data,
|
||||||
|
|
||||||
|
pub const Data = struct {
|
||||||
|
names: []const []const u8,
|
||||||
|
types: []Type,
|
||||||
|
/// unreachable_value elements are used to indicate runtime-known.
|
||||||
|
values: []Value,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
pub const Union = struct {
|
pub const Union = struct {
|
||||||
base: Payload,
|
base: Payload,
|
||||||
data: *Module.Union,
|
data: *Module.Union,
|
||||||
|
|||||||
@ -1895,7 +1895,7 @@ pub const Value = extern union {
|
|||||||
const a_field_vals = a.castTag(.@"struct").?.data;
|
const a_field_vals = a.castTag(.@"struct").?.data;
|
||||||
const b_field_vals = b.castTag(.@"struct").?.data;
|
const b_field_vals = b.castTag(.@"struct").?.data;
|
||||||
assert(a_field_vals.len == b_field_vals.len);
|
assert(a_field_vals.len == b_field_vals.len);
|
||||||
if (ty.isTuple()) {
|
if (ty.isTupleOrAnonStruct()) {
|
||||||
const types = ty.tupleFields().types;
|
const types = ty.tupleFields().types;
|
||||||
assert(types.len == a_field_vals.len);
|
assert(types.len == a_field_vals.len);
|
||||||
for (types) |field_ty, i| {
|
for (types) |field_ty, i| {
|
||||||
@ -2031,7 +2031,7 @@ pub const Value = extern union {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
.Struct => {
|
.Struct => {
|
||||||
if (ty.isTuple()) {
|
if (ty.isTupleOrAnonStruct()) {
|
||||||
const fields = ty.tupleFields();
|
const fields = ty.tupleFields();
|
||||||
for (fields.values) |field_val, i| {
|
for (fields.values) |field_val, i| {
|
||||||
field_val.hash(fields.types[i], hasher);
|
field_val.hash(fields.types[i], hasher);
|
||||||
|
|||||||
@ -65,19 +65,20 @@ test {
|
|||||||
_ = @import("behavior/inttoptr.zig");
|
_ = @import("behavior/inttoptr.zig");
|
||||||
_ = @import("behavior/ir_block_deps.zig");
|
_ = @import("behavior/ir_block_deps.zig");
|
||||||
_ = @import("behavior/member_func.zig");
|
_ = @import("behavior/member_func.zig");
|
||||||
|
_ = @import("behavior/muladd.zig");
|
||||||
_ = @import("behavior/namespace_depends_on_compile_var.zig");
|
_ = @import("behavior/namespace_depends_on_compile_var.zig");
|
||||||
_ = @import("behavior/null.zig");
|
_ = @import("behavior/null.zig");
|
||||||
_ = @import("behavior/optional.zig");
|
_ = @import("behavior/optional.zig");
|
||||||
_ = @import("behavior/prefetch.zig");
|
|
||||||
_ = @import("behavior/pointers.zig");
|
_ = @import("behavior/pointers.zig");
|
||||||
_ = @import("behavior/pub_enum.zig");
|
_ = @import("behavior/prefetch.zig");
|
||||||
_ = @import("behavior/ptrcast.zig");
|
_ = @import("behavior/ptrcast.zig");
|
||||||
_ = @import("behavior/reflection.zig");
|
_ = @import("behavior/pub_enum.zig");
|
||||||
_ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
|
_ = @import("behavior/ref_var_in_if_after_if_2nd_switch_prong.zig");
|
||||||
|
_ = @import("behavior/reflection.zig");
|
||||||
_ = @import("behavior/slice.zig");
|
_ = @import("behavior/slice.zig");
|
||||||
_ = @import("behavior/slice_sentinel_comptime.zig");
|
_ = @import("behavior/slice_sentinel_comptime.zig");
|
||||||
_ = @import("behavior/struct.zig");
|
|
||||||
_ = @import("behavior/src.zig");
|
_ = @import("behavior/src.zig");
|
||||||
|
_ = @import("behavior/struct.zig");
|
||||||
_ = @import("behavior/this.zig");
|
_ = @import("behavior/this.zig");
|
||||||
_ = @import("behavior/truncate.zig");
|
_ = @import("behavior/truncate.zig");
|
||||||
_ = @import("behavior/try.zig");
|
_ = @import("behavior/try.zig");
|
||||||
@ -135,6 +136,7 @@ test {
|
|||||||
_ = @import("behavior/bugs/5398.zig");
|
_ = @import("behavior/bugs/5398.zig");
|
||||||
_ = @import("behavior/bugs/5413.zig");
|
_ = @import("behavior/bugs/5413.zig");
|
||||||
_ = @import("behavior/bugs/5487.zig");
|
_ = @import("behavior/bugs/5487.zig");
|
||||||
|
_ = @import("behavior/bugs/7003.zig");
|
||||||
_ = @import("behavior/struct_contains_null_ptr_itself.zig");
|
_ = @import("behavior/struct_contains_null_ptr_itself.zig");
|
||||||
_ = @import("behavior/switch_prong_err_enum.zig");
|
_ = @import("behavior/switch_prong_err_enum.zig");
|
||||||
_ = @import("behavior/switch_prong_implicit_cast.zig");
|
_ = @import("behavior/switch_prong_implicit_cast.zig");
|
||||||
@ -156,14 +158,12 @@ test {
|
|||||||
_ = @import("behavior/bugs/3779.zig");
|
_ = @import("behavior/bugs/3779.zig");
|
||||||
_ = @import("behavior/bugs/6456.zig");
|
_ = @import("behavior/bugs/6456.zig");
|
||||||
_ = @import("behavior/bugs/6781.zig");
|
_ = @import("behavior/bugs/6781.zig");
|
||||||
_ = @import("behavior/bugs/7003.zig");
|
|
||||||
_ = @import("behavior/bugs/7027.zig");
|
_ = @import("behavior/bugs/7027.zig");
|
||||||
_ = @import("behavior/bugs/7047.zig");
|
_ = @import("behavior/bugs/7047.zig");
|
||||||
_ = @import("behavior/bugs/10147.zig");
|
_ = @import("behavior/bugs/10147.zig");
|
||||||
_ = @import("behavior/const_slice_child.zig");
|
_ = @import("behavior/const_slice_child.zig");
|
||||||
|
_ = @import("behavior/export.zig");
|
||||||
_ = @import("behavior/export_self_referential_type_info.zig");
|
_ = @import("behavior/export_self_referential_type_info.zig");
|
||||||
_ = @import("behavior/misc.zig");
|
|
||||||
_ = @import("behavior/muladd.zig");
|
|
||||||
_ = @import("behavior/select.zig");
|
_ = @import("behavior/select.zig");
|
||||||
_ = @import("behavior/shuffle.zig");
|
_ = @import("behavior/shuffle.zig");
|
||||||
_ = @import("behavior/struct_contains_slice_of_itself.zig");
|
_ = @import("behavior/struct_contains_slice_of_itself.zig");
|
||||||
|
|||||||
@ -972,22 +972,6 @@ test "enum literal casting to error union with payload enum" {
|
|||||||
try expect((try bar) == Bar.B);
|
try expect((try bar) == Bar.B);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "exporting enum type and value" {
|
|
||||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
|
||||||
|
|
||||||
const S = struct {
|
|
||||||
const E = enum(c_int) { one, two };
|
|
||||||
comptime {
|
|
||||||
@export(E, .{ .name = "E" });
|
|
||||||
}
|
|
||||||
const e: E = .two;
|
|
||||||
comptime {
|
|
||||||
@export(e, .{ .name = "e" });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
try expect(S.e == .two);
|
|
||||||
}
|
|
||||||
|
|
||||||
test "constant enum initialization with differing sizes" {
|
test "constant enum initialization with differing sizes" {
|
||||||
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest;
|
||||||
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest;
|
||||||
|
|||||||
@ -34,3 +34,17 @@ export fn testPackedStuff(a: *const PackedStruct, b: *const PackedUnion) void {
|
|||||||
b;
|
b;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test "exporting enum type and value" {
|
||||||
|
const S = struct {
|
||||||
|
const E = enum(c_int) { one, two };
|
||||||
|
comptime {
|
||||||
|
@export(E, .{ .name = "E" });
|
||||||
|
}
|
||||||
|
const e: E = .two;
|
||||||
|
comptime {
|
||||||
|
@export(e, .{ .name = "e" });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
try expect(S.e == .two);
|
||||||
|
}
|
||||||
@ -2,6 +2,8 @@ const builtin = @import("builtin");
|
|||||||
const expect = @import("std").testing.expect;
|
const expect = @import("std").testing.expect;
|
||||||
|
|
||||||
test "@mulAdd" {
|
test "@mulAdd" {
|
||||||
|
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||||
|
|
||||||
comptime try testMulAdd();
|
comptime try testMulAdd();
|
||||||
try testMulAdd();
|
try testMulAdd();
|
||||||
}
|
}
|
||||||
@ -25,20 +27,40 @@ fn testMulAdd() !void {
|
|||||||
var c: f64 = 6.25;
|
var c: f64 = 6.25;
|
||||||
try expect(@mulAdd(f64, a, b, c) == 20);
|
try expect(@mulAdd(f64, a, b, c) == 20);
|
||||||
}
|
}
|
||||||
// {
|
}
|
||||||
// var a: f16 = 5.5;
|
|
||||||
// var b: f80 = 2.5;
|
test "@mulAdd f80" {
|
||||||
// var c: f80 = 6.25;
|
if (true) {
|
||||||
// try expect(@mulAdd(f80, a, b, c) == 20);
|
// https://github.com/ziglang/zig/issues/11030
|
||||||
// }
|
return error.SkipZigTest;
|
||||||
|
}
|
||||||
|
|
||||||
|
comptime try testMulAdd80();
|
||||||
|
try testMulAdd80();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn testMulAdd80() !void {
|
||||||
|
var a: f16 = 5.5;
|
||||||
|
var b: f80 = 2.5;
|
||||||
|
var c: f80 = 6.25;
|
||||||
|
try expect(@mulAdd(f80, a, b, c) == 20);
|
||||||
|
}
|
||||||
|
|
||||||
|
test "@mulAdd f128" {
|
||||||
|
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||||
|
|
||||||
if (builtin.os.tag == .macos and builtin.cpu.arch == .aarch64) {
|
if (builtin.os.tag == .macos and builtin.cpu.arch == .aarch64) {
|
||||||
// https://github.com/ziglang/zig/issues/9900
|
// https://github.com/ziglang/zig/issues/9900
|
||||||
return error.SkipZigTest;
|
return error.SkipZigTest;
|
||||||
}
|
}
|
||||||
{
|
|
||||||
var a: f16 = 5.5;
|
comptime try testMullAdd128();
|
||||||
var b: f128 = 2.5;
|
try testMullAdd128();
|
||||||
var c: f128 = 6.25;
|
}
|
||||||
try expect(@mulAdd(f128, a, b, c) == 20);
|
|
||||||
}
|
fn testMullAdd128() !void {
|
||||||
|
var a: f16 = 5.5;
|
||||||
|
var b: f128 = 2.5;
|
||||||
|
var c: f128 = 6.25;
|
||||||
|
try expect(@mulAdd(f128, a, b, c) == 20);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -14,7 +14,9 @@ const builtin = @import("builtin");
|
|||||||
const expect = std.testing.expect;
|
const expect = std.testing.expect;
|
||||||
|
|
||||||
test "@src" {
|
test "@src" {
|
||||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest;
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
|
|
||||||
try doTheTest();
|
try doTheTest();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -930,7 +930,9 @@ test "anonymous struct literal syntax" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test "fully anonymous struct" {
|
test "fully anonymous struct" {
|
||||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_c) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||||
|
|
||||||
const S = struct {
|
const S = struct {
|
||||||
fn doTheTest() !void {
|
fn doTheTest() !void {
|
||||||
@ -974,7 +976,7 @@ test "fully anonymous list literal" {
|
|||||||
comptime try S.doTheTest();
|
comptime try S.doTheTest();
|
||||||
}
|
}
|
||||||
|
|
||||||
test "anonymous struct literal assigned to variable" {
|
test "tuple assigned to variable" {
|
||||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||||
|
|
||||||
var vec = .{ @as(i32, 22), @as(i32, 55), @as(i32, 99) };
|
var vec = .{ @as(i32, 22), @as(i32, 55), @as(i32, 99) };
|
||||||
@ -995,7 +997,7 @@ test "comptime struct field" {
|
|||||||
comptime try expect(foo.b == 1234);
|
comptime try expect(foo.b == 1234);
|
||||||
}
|
}
|
||||||
|
|
||||||
test "anon struct literal field value initialized with fn call" {
|
test "tuple element initialized with fn call" {
|
||||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
||||||
|
|
||||||
const S = struct {
|
const S = struct {
|
||||||
|
|||||||
@ -503,9 +503,13 @@ test "Struct.is_tuple for anon list literal" {
|
|||||||
}
|
}
|
||||||
|
|
||||||
test "Struct.is_tuple for anon struct literal" {
|
test "Struct.is_tuple for anon struct literal" {
|
||||||
if (builtin.zig_backend != .stage1) return error.SkipZigTest; // TODO
|
if (builtin.zig_backend == .stage2_x86_64) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
|
||||||
|
if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
|
||||||
|
|
||||||
try expect(!@typeInfo(@TypeOf(.{ .a = 0 })).Struct.is_tuple);
|
const info = @typeInfo(@TypeOf(.{ .a = 0 }));
|
||||||
|
try expect(!info.Struct.is_tuple);
|
||||||
|
try expect(std.mem.eql(u8, info.Struct.fields[0].name, "a"));
|
||||||
}
|
}
|
||||||
|
|
||||||
test "StructField.is_comptime" {
|
test "StructField.is_comptime" {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user