Skip to content

Commit f4f8036

Browse files
authored
Merge pull request #18729 from Vexu/fixes
Fix some generic{Reader,Writer} related issues
2 parents 3e939e6 + 78e982f commit f4f8036

File tree

6 files changed

+113
-3
lines changed

6 files changed

+113
-3
lines changed

src/Sema.zig

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22368,7 +22368,10 @@ fn zirErrorCast(sema: *Sema, block: *Block, extended: Zir.Inst.Extended.InstData
2236822368

2236922369
try sema.requireRuntimeBlock(block, src, operand_src);
2237022370
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+
{
2237222375
if (dest_tag == .ErrorUnion) {
2237322376
const err_code = try sema.analyzeErrUnionCode(block, operand_src, operand);
2237422377
const err_int = try block.addBitCast(err_int_ty, err_code);

src/codegen/llvm.zig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8694,10 +8694,10 @@ pub const FuncGen = struct {
86948694
if (!result_is_ref) {
86958695
return self.dg.todo("implement bitcast vector to non-ref array", .{});
86968696
}
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);
86988699
const bitcast_ok = elem_ty.bitSize(mod) == elem_ty.abiSize(mod) * 8;
86998700
if (bitcast_ok) {
8700-
const alignment = inst_ty.abiAlignment(mod).toLlvm();
87018701
_ = try self.wip.store(.normal, operand, array_ptr, alignment);
87028702
} else {
87038703
// If the ABI size of the element type is not evenly divisible by size in bits;

src/value.zig

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1550,6 +1550,8 @@ pub const Value = struct {
15501550
},
15511551
.ptr => |ptr| switch (ptr.addr) {
15521552
.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),
15531555
else => false,
15541556
},
15551557
.opt => |opt| switch (opt.val) {

test/behavior/comptime_memory.zig

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -459,3 +459,77 @@ test "write empty array to end" {
459459
array[5..5].* = [_]u8{};
460460
try testing.expectEqualStrings("hello", &array);
461461
}
462+
463+
fn 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+
}
472+
fn setDoublePtr(ptr: *const *const u32, value: u32) void {
473+
setPtr(ptr.*, value);
474+
}
475+
fn setPtr(ptr: *const u32, value: u32) void {
476+
const mut_ptr: *u32 = @constCast(ptr);
477+
mut_ptr.* = value;
478+
}
479+
test "double pointer can mutate comptime state" {
480+
try comptime doublePtrTest();
481+
}
482+
483+
fn 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+
}
505+
const 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+
};
513+
const 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+
};
526+
fn 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+
}
533+
test "pointer in aggregate field can mutate comptime state" {
534+
try comptime std.testing.expect(fieldPtrTest() == 2);
535+
}

test/behavior/error.zig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1027,3 +1027,15 @@ test "generic type constructed from inferred error set of unresolved function" {
10271027
};
10281028
_ = std.io.multiWriter(.{S.writer()});
10291029
}
1030+
1031+
test "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

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1566,3 +1566,22 @@ test "@reduce on bool vector" {
15661566
try std.testing.expect(@reduce(.And, a));
15671567
try std.testing.expect(@reduce(.And, b));
15681568
}
1569+
1570+
test "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+
}

0 commit comments

Comments
 (0)