aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2024-01-29 13:07:37 -0800
committerGitHub <noreply@github.com>2024-01-29 13:07:37 -0800
commitf4f8036ec048daa072c7caa72edd320c85bf426c (patch)
treeb0ab4a567d57e1d562c950c98e810b420ea4f723
parent3e939e61538706f37abb76a97af0ee77c15b24fc (diff)
parent78e982f7c3e8a441259d26a69690d8934dd32bf0 (diff)
downloadzig-f4f8036ec048daa072c7caa72edd320c85bf426c.tar.gz
zig-f4f8036ec048daa072c7caa72edd320c85bf426c.zip
Merge pull request #18729 from Vexu/fixes
Fix some generic{Reader,Writer} related issues
-rw-r--r--src/Sema.zig5
-rw-r--r--src/codegen/llvm.zig4
-rw-r--r--src/value.zig2
-rw-r--r--test/behavior/comptime_memory.zig74
-rw-r--r--test/behavior/error.zig12
-rw-r--r--test/behavior/vector.zig19
6 files changed, 113 insertions, 3 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index af3e3700d7..2c404c476e 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -22368,7 +22368,10 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
try sema.requireRuntimeBlock(block, src, operand_src);
const err_int_ty = try mod.errorIntType();
- if (block.wantSafety() and !dest_ty.isAnyError(mod) and sema.mod.backendSupportsFeature(.error_set_has_value)) {
+ if (block.wantSafety() and !dest_ty.isAnyError(mod) and
+ dest_ty.toIntern() != .adhoc_inferred_error_set_type and
+ sema.mod.backendSupportsFeature(.error_set_has_value))
+ {
if (dest_tag == .ErrorUnion) {
const err_code = try sema.analyzeErrUnionCode(block, operand_src, operand);
const err_int = try block.addBitCast(err_int_ty, err_code);
diff --git a/src/codegen/llvm.zig b/src/codegen/llvm.zig
index f01c27042b..5cbcf6b3d6 100644
--- a/src/codegen/llvm.zig
+++ b/src/codegen/llvm.zig
@@ -8694,10 +8694,10 @@ pub const FuncGen = struct {
if (!result_is_ref) {
return self.dg.todo("implement bitcast vector to non-ref array", .{});
}
- const array_ptr = try self.buildAllocaWorkaround(inst_ty, .default);
+ const alignment = inst_ty.abiAlignment(mod).toLlvm();
+ const array_ptr = try self.buildAllocaWorkaround(inst_ty, alignment);
const bitcast_ok = elem_ty.bitSize(mod) == elem_ty.abiSize(mod) * 8;
if (bitcast_ok) {
- const alignment = inst_ty.abiAlignment(mod).toLlvm();
_ = try self.wip.store(.normal, operand, array_ptr, alignment);
} else {
// If the ABI size of the element type is not evenly divisible by size in bits;
diff --git a/src/value.zig b/src/value.zig
index 1de0f66717..69ddb56b8f 100644
--- a/src/value.zig
+++ b/src/value.zig
@@ -1550,6 +1550,8 @@ pub const Value = struct {
},
.ptr => |ptr| switch (ptr.addr) {
.eu_payload, .opt_payload => |base| Value.fromInterned(base).canMutateComptimeVarState(mod),
+ .anon_decl => |anon_decl| Value.fromInterned(anon_decl.val).canMutateComptimeVarState(mod),
+ .elem, .field => |base_index| Value.fromInterned(base_index.base).canMutateComptimeVarState(mod),
else => false,
},
.opt => |opt| switch (opt.val) {
diff --git a/test/behavior/comptime_memory.zig b/test/behavior/comptime_memory.zig
index bfeaa339b2..e56de79d9d 100644
--- a/test/behavior/comptime_memory.zig
+++ b/test/behavior/comptime_memory.zig
@@ -459,3 +459,77 @@ test "write empty array to end" {
array[5..5].* = [_]u8{};
try testing.expectEqualStrings("hello", &array);
}
+
+fn doublePtrTest() !void {
+ var a: u32 = 0;
+ const ptr = &a;
+ const double_ptr = &ptr;
+ setDoublePtr(double_ptr, 1);
+ setDoublePtr(double_ptr, 2);
+ setDoublePtr(double_ptr, 1);
+ try std.testing.expect(a == 1);
+}
+fn setDoublePtr(ptr: *const *const u32, value: u32) void {
+ setPtr(ptr.*, value);
+}
+fn setPtr(ptr: *const u32, value: u32) void {
+ const mut_ptr: *u32 = @constCast(ptr);
+ mut_ptr.* = value;
+}
+test "double pointer can mutate comptime state" {
+ try comptime doublePtrTest();
+}
+
+fn GenericIntApplier(
+ comptime Context: type,
+ comptime applyFn: fn (context: Context, arg: u32) void,
+) type {
+ return struct {
+ context: Context,
+
+ const Self = @This();
+
+ inline fn any(self: *const Self) IntApplier {
+ return .{
+ .context = @ptrCast(&self.context),
+ .applyFn = typeErasedApplyFn,
+ };
+ }
+
+ fn typeErasedApplyFn(context: *const anyopaque, arg: u32) void {
+ const ptr: *const Context = @alignCast(@ptrCast(context));
+ applyFn(ptr.*, arg);
+ }
+ };
+}
+const IntApplier = struct {
+ context: *const anyopaque,
+ applyFn: *const fn (context: *const anyopaque, arg: u32) void,
+
+ fn apply(ia: IntApplier, arg: u32) void {
+ ia.applyFn(ia.context, arg);
+ }
+};
+const Accumulator = struct {
+ value: u32,
+
+ const Applier = GenericIntApplier(*u32, add);
+
+ fn applier(a: *Accumulator) Applier {
+ return .{ .context = &a.value };
+ }
+
+ fn add(context: *u32, arg: u32) void {
+ context.* += arg;
+ }
+};
+fn fieldPtrTest() u32 {
+ var a: Accumulator = .{ .value = 0 };
+ const applier = a.applier();
+ applier.any().apply(1);
+ applier.any().apply(1);
+ return a.value;
+}
+test "pointer in aggregate field can mutate comptime state" {
+ try comptime std.testing.expect(fieldPtrTest() == 2);
+}
diff --git a/test/behavior/error.zig b/test/behavior/error.zig
index 1d5457fa3a..8e4dd2c091 100644
--- a/test/behavior/error.zig
+++ b/test/behavior/error.zig
@@ -1027,3 +1027,15 @@ test "generic type constructed from inferred error set of unresolved function" {
};
_ = std.io.multiWriter(.{S.writer()});
}
+
+test "errorCast to adhoc inferred error set" {
+ const S = struct {
+ inline fn baz() !i32 {
+ return @errorCast(err());
+ }
+ fn err() anyerror!i32 {
+ return 1234;
+ }
+ };
+ try std.testing.expect((try S.baz()) == 1234);
+}
diff --git a/test/behavior/vector.zig b/test/behavior/vector.zig
index 6a38891494..ab4f89a052 100644
--- a/test/behavior/vector.zig
+++ b/test/behavior/vector.zig
@@ -1566,3 +1566,22 @@ test "@reduce on bool vector" {
try std.testing.expect(@reduce(.And, a));
try std.testing.expect(@reduce(.And, b));
}
+
+test "bitcast vector to array of smaller vectors" {
+ if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
+ if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
+
+ const u8x32 = @Vector(32, u8);
+ const u8x64 = @Vector(64, u8);
+ const S = struct {
+ fn doTheTest(input_vec: u8x64) !void {
+ try compare(@bitCast(input_vec));
+ }
+ fn compare(chunks: [2]u8x32) !void {
+ try expectEqual(@as(u8x32, @splat(1)), chunks[0]);
+ try expectEqual(@as(u8x32, @splat(2)), chunks[1]);
+ }
+ };
+ const input: u8x64 = @bitCast([2]u8x32{ @splat(1), @splat(2) });
+ try S.doTheTest(input);
+}