commit 05cb944709d2a05a944e60f032638cae5ee01fb0 (tree)
parent b636906fb640a12107cd21637c2af67b8e9d6ebd
Author: Andrew Kelley <andrew@ziglang.org>
Date: Fri, 26 Jun 2026 23:35:11 +0200
Merge pull request 'Sema: more fixes' (#35707) from sinon/zig:more-fixes into master
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/35707
Reviewed-by: Andrew Kelley <andrew@ziglang.org>
Diffstat:
5 files changed, 68 insertions(+), 32 deletions(-)
diff --git a/src/Sema.zig b/src/Sema.zig
@@ -9314,7 +9314,7 @@ fn intCast(
break :ok all_in_range;
} else ok: {
const zero_inst = Air.internedToRef((try pt.intValue(operand_ty, 0)).toIntern());
- const is_in_range = try block.addBinOp(.cmp_lte, operand, zero_inst);
+ const is_in_range = try block.addBinOp(.cmp_eq, operand, zero_inst);
break :ok is_in_range;
};
try sema.addSafetyCheck(block, src, ok, .integer_out_of_bounds);
@@ -12012,15 +12012,12 @@ fn resolveSwitchPayloadCaptureTaggedUnion(
const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);
const payload_ref: Air.Inst.Ref = payload_ref: {
if (capture_by_ref) {
- const operand_ptr_info = sema.typeOf(loaded_operand).ptrInfo(zcu);
- const ptr_field_ty = try pt.ptrType(.{
- .child = field_ty.toIntern(),
- .flags = .{
- .is_const = operand_ptr_info.flags.is_const,
- .is_volatile = operand_ptr_info.flags.is_volatile,
- .address_space = operand_ptr_info.flags.address_space,
- },
- });
+ const ptr_field_ty = try sema.typeOf(loaded_operand).fieldPtrType(field_index, pt);
+ if (try sema.resolveDefinedValue(case_block, operand_src, loaded_operand)) |op_ptr_val| {
+ if (op_ptr_val.isUndef(zcu)) break :payload_ref try pt.undefRef(ptr_field_ty);
+ const field_ptr_val = try op_ptr_val.ptrField(field_index, pt);
+ break :payload_ref .fromValue(try pt.getCoerced(field_ptr_val, ptr_field_ty));
+ }
break :payload_ref try case_block.addStructFieldPtr(loaded_operand, field_index, ptr_field_ty);
}
if (try sema.resolveDefinedValue(case_block, operand_src, loaded_operand)) |union_val| {
@@ -17548,15 +17545,10 @@ fn zirTryPtr(sema: *Sema, parent_block: *Block, inst: Zir.Inst.Index) CompileErr
const is_cold = sema.branch_hint == .cold;
const operand_ty = sema.typeOf(operand);
- const ptr_info = operand_ty.ptrInfo(zcu);
- const res_ty = try pt.ptrType(.{
- .child = err_union_ty.errorUnionPayload(zcu).toIntern(),
- .flags = .{
- .is_const = ptr_info.flags.is_const,
- .is_volatile = ptr_info.flags.is_volatile,
- .is_allowzero = ptr_info.flags.is_allowzero,
- .address_space = ptr_info.flags.address_space,
- },
+ const res_ty = try pt.ptrType(info: {
+ var new = operand_ty.ptrInfo(zcu);
+ new.child = err_union_ty.errorUnionPayload(zcu).toIntern();
+ break :info new;
});
const res_ty_ref = Air.internedToRef(res_ty.toIntern());
try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.TryPtr).@"struct".field_names.len +
@@ -26404,23 +26396,21 @@ fn fieldCallBind(
.@"struct" => {
if (zcu.typeToStruct(concrete_ty)) |struct_type| {
const field_index = struct_type.nameIndex(ip, field_name) orelse break :find_field;
- const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);
-
- return sema.finishFieldCallBind(block, src, ptr_ty, field_ty, field_index, object_ptr);
+ return sema.finishFieldCallBind(block, src, ptr_ty, field_index, object_ptr);
} else if (concrete_ty.isTuple(zcu)) {
if (field_name.eqlSlice("len", ip)) {
return .{ .direct = try pt.intRef(.usize, concrete_ty.structFieldCount(zcu)) };
}
if (field_name.toUnsigned(ip)) |field_index| {
if (field_index >= concrete_ty.structFieldCount(zcu)) break :find_field;
- return sema.finishFieldCallBind(block, src, ptr_ty, concrete_ty.fieldType(field_index, zcu), field_index, object_ptr);
+ return sema.finishFieldCallBind(block, src, ptr_ty, field_index, object_ptr);
}
} else {
const max = concrete_ty.structFieldCount(zcu);
for (0..max) |i_usize| {
const i: u32 = @intCast(i_usize);
if (field_name == concrete_ty.structFieldName(i, zcu).unwrap().?) {
- return sema.finishFieldCallBind(block, src, ptr_ty, concrete_ty.fieldType(i, zcu), i, object_ptr);
+ return sema.finishFieldCallBind(block, src, ptr_ty, i, object_ptr);
}
}
}
@@ -26536,19 +26526,12 @@ fn finishFieldCallBind(
block: *Block,
src: LazySrcLoc,
ptr_ty: Type,
- field_ty: Type,
field_index: u32,
object_ptr: Air.Inst.Ref,
) CompileError!ResolvedFieldCallee {
const pt = sema.pt;
const zcu = pt.zcu;
- const ptr_field_ty = try pt.ptrType(.{
- .child = field_ty.toIntern(),
- .flags = .{
- .is_const = !ptr_ty.ptrIsMutable(zcu),
- .address_space = ptr_ty.ptrAddressSpace(zcu),
- },
- });
+ const ptr_field_ty = try ptr_ty.fieldPtrType(field_index, pt);
const container_ty = ptr_ty.childType(zcu);
if (container_ty.zigTypeTag(zcu) == .@"struct") {
diff --git a/test/behavior/switch.zig b/test/behavior/switch.zig
@@ -1574,3 +1574,22 @@ test "repeated switch analysis overrides previous analysis results" {
};
}
}
+
+test "union field pointer capture preserves alignment in inline prong" {
+ const U = union(enum) {
+ a: u32,
+ b: u32,
+ fn doTheTest(u: *align(1) const @This()) !void {
+ switch (u.*) {
+ inline .a, .b => |*a_ptr| {
+ comptime assert(@TypeOf(a_ptr) == *align(1) const u32);
+ try expect(a_ptr.* == 123);
+ },
+ }
+ }
+ };
+ try U.doTheTest(&.{ .a = 123 });
+ try U.doTheTest(&.{ .b = 123 });
+ try comptime U.doTheTest(&.{ .a = 123 });
+ try comptime U.doTheTest(&.{ .b = 123 });
+}
diff --git a/test/behavior/try.zig b/test/behavior/try.zig
@@ -1,5 +1,6 @@
const std = @import("std");
const builtin = @import("builtin");
+const assert = std.debug.assert;
const expect = std.testing.expect;
test "try on error union" {
@@ -197,3 +198,14 @@ test "try ptr propagation mutate" {
try S.doTheTest();
try comptime S.doTheTest();
}
+
+test "try pointer expression alignment" {
+ const S = struct {
+ fn doTheTest(p: *align(1) (anyerror!u32)) !void {
+ comptime assert(@TypeOf(&(try p.*)) == *align(1) u32);
+ try expect((try p.*) == 10);
+ }
+ };
+ var x: anyerror!u32 = 10;
+ try S.doTheTest(&x);
+}
diff --git a/test/cases/safety/@intCast negative to u0.zig b/test/cases/safety/@intCast negative to u0.zig
@@ -0,0 +1,22 @@
+const std = @import("std");
+
+pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
+ _ = stack_trace;
+ if (std.mem.eql(u8, message, "integer does not fit in destination type")) {
+ std.process.exit(0);
+ }
+ std.process.exit(1);
+}
+
+pub fn main() !void {
+ bar(1, -1);
+ return error.TestFailed;
+}
+
+fn bar(one: u1, not_zero: i32) void {
+ const x = one << @intCast(not_zero);
+ _ = x;
+}
+// run
+// backend=selfhosted,llvm
+// target=x86_64-linux,aarch64-linux
diff --git a/test/cases/safety/@intCast to u0.zig b/test/cases/safety/@intCast positive to u0.zig