authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-01-29 13:07:37-08:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-01-29 13:07:37-08:00
logf4f8036ec048daa072c7caa72edd320c85bf426c
treeb0ab4a567d57e1d562c950c98e810b420ea4f723
parent3e939e61538706f37abb76a97af0ee77c15b24fc
parent78e982f7c3e8a441259d26a69690d8934dd32bf0
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #18729 from Vexu/fixes

Fix some generic{Reader,Writer} related issues

6 files changed, 113 insertions(+), 3 deletions(-)

src/Sema.zig+4-1
...@@ -22368,7 +22368,10 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData...@@ -22368,7 +22368,10 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
2236822368
22369 try sema.requireRuntimeBlock(block, src, operand_src);22369 try sema.requireRuntimeBlock(block, src, operand_src);
22370 const err_int_ty = try mod.errorIntType();22370 const err_int_ty = try mod.errorIntType();
22371 if (block.wantSafety() and !dest_ty.isAnyError(mod) and sema.mod.backendSupportsFeature(.error_set_has_value)) {22371 if (block.wantSafety() and !dest_ty.isAnyError(mod) and
22372 dest_ty.toIntern() != .adhoc_inferred_error_set_type and
22373 sema.mod.backendSupportsFeature(.error_set_has_value))
22374 {
22372 if (dest_tag == .ErrorUnion) {22375 if (dest_tag == .ErrorUnion) {
22373 const err_code = try sema.analyzeErrUnionCode(block, operand_src, operand);22376 const err_code = try sema.analyzeErrUnionCode(block, operand_src, operand);
22374 const err_int = try block.addBitCast(err_int_ty, err_code);22377 const err_int = try block.addBitCast(err_int_ty, err_code);
src/codegen/llvm.zig+2-2
...@@ -8694,10 +8694,10 @@ pub const FuncGen = struct {...@@ -8694,10 +8694,10 @@ pub const FuncGen = struct {
8694 if (!result_is_ref) {8694 if (!result_is_ref) {
8695 return self.dg.todo("implement bitcast vector to non-ref array", .{});8695 return self.dg.todo("implement bitcast vector to non-ref array", .{});
8696 }8696 }
8697 const array_ptr = try self.buildAllocaWorkaround(inst_ty, .default);8697 const alignment = inst_ty.abiAlignment(mod).toLlvm();
8698 const array_ptr = try self.buildAllocaWorkaround(inst_ty, alignment);
8698 const bitcast_ok = elem_ty.bitSize(mod) == elem_ty.abiSize(mod) * 8;8699 const bitcast_ok = elem_ty.bitSize(mod) == elem_ty.abiSize(mod) * 8;
8699 if (bitcast_ok) {8700 if (bitcast_ok) {
8700 const alignment = inst_ty.abiAlignment(mod).toLlvm();
8701 _ = try self.wip.store(.normal, operand, array_ptr, alignment);8701 _ = try self.wip.store(.normal, operand, array_ptr, alignment);
8702 } else {8702 } else {
8703 // If the ABI size of the element type is not evenly divisible by size in bits;8703 // If the ABI size of the element type is not evenly divisible by size in bits;
src/value.zig+2
...@@ -1550,6 +1550,8 @@ pub const Value = struct {...@@ -1550,6 +1550,8 @@ pub const Value = struct {
1550 },1550 },
1551 .ptr => |ptr| switch (ptr.addr) {1551 .ptr => |ptr| switch (ptr.addr) {
1552 .eu_payload, .opt_payload => |base| Value.fromInterned(base).canMutateComptimeVarState(mod),1552 .eu_payload, .opt_payload => |base| Value.fromInterned(base).canMutateComptimeVarState(mod),
1553 .anon_decl => |anon_decl| Value.fromInterned(anon_decl.val).canMutateComptimeVarState(mod),
1554 .elem, .field => |base_index| Value.fromInterned(base_index.base).canMutateComptimeVarState(mod),
1553 else => false,1555 else => false,
1554 },1556 },
1555 .opt => |opt| switch (opt.val) {1557 .opt => |opt| switch (opt.val) {
test/behavior/comptime_memory.zig+74
...@@ -459,3 +459,77 @@ test "write empty array to end" {...@@ -459,3 +459,77 @@ test "write empty array to end" {
459 array[5..5].* = [_]u8{};459 array[5..5].* = [_]u8{};
460 try testing.expectEqualStrings("hello", &array);460 try testing.expectEqualStrings("hello", &array);
461}461}
462
463fn doublePtrTest() !void {
464 var a: u32 = 0;
465 const ptr = &a;
466 const double_ptr = &ptr;
467 setDoublePtr(double_ptr, 1);
468 setDoublePtr(double_ptr, 2);
469 setDoublePtr(double_ptr, 1);
470 try std.testing.expect(a == 1);
471}
472fn setDoublePtr(ptr: *const *const u32, value: u32) void {
473 setPtr(ptr.*, value);
474}
475fn setPtr(ptr: *const u32, value: u32) void {
476 const mut_ptr: *u32 = @constCast(ptr);
477 mut_ptr.* = value;
478}
479test "double pointer can mutate comptime state" {
480 try comptime doublePtrTest();
481}
482
483fn GenericIntApplier(
484 comptime Context: type,
485 comptime applyFn: fn (context: Context, arg: u32) void,
486) type {
487 return struct {
488 context: Context,
489
490 const Self = @This();
491
492 inline fn any(self: *const Self) IntApplier {
493 return .{
494 .context = @ptrCast(&self.context),
495 .applyFn = typeErasedApplyFn,
496 };
497 }
498
499 fn typeErasedApplyFn(context: *const anyopaque, arg: u32) void {
500 const ptr: *const Context = @alignCast(@ptrCast(context));
501 applyFn(ptr.*, arg);
502 }
503 };
504}
505const IntApplier = struct {
506 context: *const anyopaque,
507 applyFn: *const fn (context: *const anyopaque, arg: u32) void,
508
509 fn apply(ia: IntApplier, arg: u32) void {
510 ia.applyFn(ia.context, arg);
511 }
512};
513const Accumulator = struct {
514 value: u32,
515
516 const Applier = GenericIntApplier(*u32, add);
517
518 fn applier(a: *Accumulator) Applier {
519 return .{ .context = &a.value };
520 }
521
522 fn add(context: *u32, arg: u32) void {
523 context.* += arg;
524 }
525};
526fn fieldPtrTest() u32 {
527 var a: Accumulator = .{ .value = 0 };
528 const applier = a.applier();
529 applier.any().apply(1);
530 applier.any().apply(1);
531 return a.value;
532}
533test "pointer in aggregate field can mutate comptime state" {
534 try comptime std.testing.expect(fieldPtrTest() == 2);
535}
test/behavior/error.zig+12
...@@ -1027,3 +1027,15 @@ test "generic type constructed from inferred error set of unresolved function" {...@@ -1027,3 +1027,15 @@ test "generic type constructed from inferred error set of unresolved function" {
1027 };1027 };
1028 _ = std.io.multiWriter(.{S.writer()});1028 _ = std.io.multiWriter(.{S.writer()});
1029}1029}
1030
1031test "errorCast to adhoc inferred error set" {
1032 const S = struct {
1033 inline fn baz() !i32 {
1034 return @errorCast(err());
1035 }
1036 fn err() anyerror!i32 {
1037 return 1234;
1038 }
1039 };
1040 try std.testing.expect((try S.baz()) == 1234);
1041}
test/behavior/vector.zig+19
...@@ -1566,3 +1566,22 @@ test "@reduce on bool vector" {...@@ -1566,3 +1566,22 @@ test "@reduce on bool vector" {
1566 try std.testing.expect(@reduce(.And, a));1566 try std.testing.expect(@reduce(.And, a));
1567 try std.testing.expect(@reduce(.And, b));1567 try std.testing.expect(@reduce(.And, b));
1568}1568}
1569
1570test "bitcast vector to array of smaller vectors" {
1571 if (builtin.zig_backend == .stage2_aarch64) return error.SkipZigTest; // TODO
1572 if (builtin.zig_backend == .stage2_arm) return error.SkipZigTest; // TODO
1573
1574 const u8x32 = @Vector(32, u8);
1575 const u8x64 = @Vector(64, u8);
1576 const S = struct {
1577 fn doTheTest(input_vec: u8x64) !void {
1578 try compare(@bitCast(input_vec));
1579 }
1580 fn compare(chunks: [2]u8x32) !void {
1581 try expectEqual(@as(u8x32, @splat(1)), chunks[0]);
1582 try expectEqual(@as(u8x32, @splat(2)), chunks[1]);
1583 }
1584 };
1585 const input: u8x64 = @bitCast([2]u8x32{ @splat(1), @splat(2) });
1586 try S.doTheTest(input);
1587}