mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 12:59:04 +00:00
parent
f954950485
commit
6c690a966a
32
src/Sema.zig
32
src/Sema.zig
@ -20290,11 +20290,41 @@ fn zirStructInitEmptyResult(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is
|
||||
const zcu = pt.zcu;
|
||||
const inst_data = sema.code.instructions.items(.data)[@intFromEnum(inst)].un_node;
|
||||
const src = block.nodeOffset(inst_data.src_node);
|
||||
|
||||
// Generic poison means this is an untyped anonymous empty struct/array init
|
||||
const ty_operand = try sema.resolveTypeOrPoison(block, src, inst_data.operand) orelse return .empty_tuple;
|
||||
const ty_operand = try sema.resolveTypeOrPoison(block, src, inst_data.operand) orelse {
|
||||
if (is_byref) {
|
||||
return sema.uavRef(.empty_tuple);
|
||||
} else {
|
||||
return .empty_tuple;
|
||||
}
|
||||
};
|
||||
|
||||
const init_ty = if (is_byref) ty: {
|
||||
const ptr_ty = ty_operand.optEuBaseType(zcu);
|
||||
assert(ptr_ty.zigTypeTag(zcu) == .pointer); // validated by a previous instruction
|
||||
switch (ptr_ty.ptrSize(zcu)) {
|
||||
// Use a zero-length array for a slice or many-ptr result
|
||||
.slice, .many => break :ty try pt.arrayType(.{
|
||||
.len = 0,
|
||||
.child = ptr_ty.childType(zcu).toIntern(),
|
||||
.sentinel = if (ptr_ty.sentinel(zcu)) |s| s.toIntern() else .none,
|
||||
}),
|
||||
// Just use the child type for a single-pointer or C-pointer result
|
||||
.one, .c => {
|
||||
const child = ptr_ty.childType(zcu);
|
||||
if (child.toIntern() == .anyopaque_type) {
|
||||
// ...unless that child is anyopaque, in which case this is equivalent to an untyped init.
|
||||
// `.{}` is an empty tuple.
|
||||
if (is_byref) {
|
||||
return sema.uavRef(.empty_tuple);
|
||||
} else {
|
||||
return .empty_tuple;
|
||||
}
|
||||
}
|
||||
break :ty child;
|
||||
},
|
||||
}
|
||||
if (!ptr_ty.isSlice(zcu)) {
|
||||
break :ty ptr_ty.childType(zcu);
|
||||
}
|
||||
|
||||
@ -1094,3 +1094,44 @@ test "@splat zero-length array" {
|
||||
try S.doTheTest(?*anyopaque, null);
|
||||
try comptime S.doTheTest(?*anyopaque, null);
|
||||
}
|
||||
|
||||
test "initialize slice with reference to empty array initializer" {
|
||||
const a: []const u8 = &.{};
|
||||
comptime assert(a.len == 0);
|
||||
}
|
||||
|
||||
test "initialize many-pointer with reference to empty array initializer" {
|
||||
const a: [*]const u8 = &.{};
|
||||
_ = a; // nothing meaningful to test; points to zero bits
|
||||
}
|
||||
|
||||
test "initialize sentinel-terminated slice with reference to empty array initializer" {
|
||||
const a: [:0]const u8 = &.{};
|
||||
comptime assert(a.len == 0);
|
||||
comptime assert(a[0] == 0);
|
||||
}
|
||||
|
||||
test "initialize sentinel-terminated many-pointer with reference to empty array initializer" {
|
||||
const a: [*:0]const u8 = &.{};
|
||||
comptime assert(a[0] == 0);
|
||||
}
|
||||
|
||||
test "pass pointer to empty array initializer to anytype parameter" {
|
||||
const S = struct {
|
||||
fn TypeOf(x: anytype) type {
|
||||
return @TypeOf(x);
|
||||
}
|
||||
};
|
||||
comptime assert(S.TypeOf(&.{}) == @TypeOf(&.{}));
|
||||
}
|
||||
|
||||
test "initialize pointer to anyopaque with reference to empty array initializer" {
|
||||
const ptr: *const anyopaque = &.{};
|
||||
// The above acts like an untyped initializer, since the `.{}` has no result type.
|
||||
// So, `ptr` points in memory to an empty tuple (`@TypeOf(.{})`).
|
||||
const casted: *const @TypeOf(.{}) = @alignCast(@ptrCast(ptr));
|
||||
const loaded = casted.*;
|
||||
// `val` should be a `@TypeOf(.{})`, as expected.
|
||||
// We can't check the value, but it's zero-bit, so the type matching is good enough.
|
||||
comptime assert(@TypeOf(loaded) == @TypeOf(.{}));
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user