| author | |
| committer | |
| log | f4f8036ec048daa072c7caa72edd320c85bf426c |
| tree | b0ab4a567d57e1d562c950c98e810b420ea4f723 |
| parent | 3e939e61538706f37abb76a97af0ee77c15b24fc |
| parent | 78e982f7c3e8a441259d26a69690d8934dd32bf0 |
| signature |
Fix some generic{Reader,Writer} related issues6 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 | 22368 | |
| 22369 | 22369 | try sema.requireRuntimeBlock(block, src, operand_src); |
| 22370 | 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 | 22375 | if (dest_tag == .ErrorUnion) { |
| 22373 | 22376 | const err_code = try sema.analyzeErrUnionCode(block, operand_src, operand); |
| 22374 | 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 | 8694 | if (!result_is_ref) { |
| 8695 | 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 | 8699 | const bitcast_ok = elem_ty.bitSize(mod) == elem_ty.abiSize(mod) * 8; |
| 8699 | 8700 | if (bitcast_ok) { |
| 8700 | const alignment = inst_ty.abiAlignment(mod).toLlvm(); | |
| 8701 | 8701 | _ = try self.wip.store(.normal, operand, array_ptr, alignment); |
| 8702 | 8702 | } else { |
| 8703 | 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 | 1550 | }, |
| 1551 | 1551 | .ptr => |ptr| switch (ptr.addr) { |
| 1552 | 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 | 1555 | else => false, |
| 1554 | 1556 | }, |
| 1555 | 1557 | .opt => |opt| switch (opt.val) { |
test/behavior/comptime_memory.zig+74| ... | ... | @@ -459,3 +459,77 @@ test "write empty array to end" { |
| 459 | 459 | array[5..5].* = [_]u8{}; |
| 460 | 460 | try testing.expectEqualStrings("hello", &array); |
| 461 | 461 | } |
| 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+12| ... | ... | @@ -1027,3 +1027,15 @@ test "generic type constructed from inferred error set of unresolved function" { |
| 1027 | 1027 | }; |
| 1028 | 1028 | _ = std.io.multiWriter(.{S.writer()}); |
| 1029 | 1029 | } |
| 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+19| ... | ... | @@ -1566,3 +1566,22 @@ test "@reduce on bool vector" { |
| 1566 | 1566 | try std.testing.expect(@reduce(.And, a)); |
| 1567 | 1567 | try std.testing.expect(@reduce(.And, b)); |
| 1568 | 1568 | } |
| 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 | } |