authorgravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2024-01-29 12:43:17+02:00
committergravatar for git@vexu.euVeikka Tuominen <git@vexu.eu> 2024-01-29 13:48:45+02:00
log281b2695c480de1d50e1a0c03c5f5dde36010501
treedad1ed6ecebae4124866ebd98f7c9b2ce1fbdb05
parentf7822029100de9f91c9a7758ffb32d95f7768f70

Value: expand `canMutateComptimeVarState`

Closes #17761

2 files changed, 76 insertions(+), 0 deletions(-)

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}