@@ -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+ }
0 commit comments