authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-06-26 23:35:11+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-06-26 23:35:11+02:00
log05cb944709d2a05a944e60f032638cae5ee01fb0
tree6951331c63eec3a29f0961ee8d5e528a43b2328c
parentb636906fb640a12107cd21637c2af67b8e9d6ebd
parentf2d13f6d074139c01184e170fe24127a2d9db944

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>

6 files changed, 90 insertions(+), 54 deletions(-)

src/Sema.zig+15-32
......@@ -9314,7 +9314,7 @@ fn intCast(
93149314 break :ok all_in_range;
93159315 } else ok: {
93169316 const zero_inst = Air.internedToRef((try pt.intValue(operand_ty, 0)).toIntern());
9317 const is_in_range = try block.addBinOp(.cmp_lte, operand, zero_inst);
9317 const is_in_range = try block.addBinOp(.cmp_eq, operand, zero_inst);
93189318 break :ok is_in_range;
93199319 };
93209320 try sema.addSafetyCheck(block, src, ok, .integer_out_of_bounds);
......@@ -12012,15 +12012,12 @@ fn resolveSwitchPayloadCaptureTaggedUnion(
1201212012 const field_ty: Type = .fromInterned(union_obj.field_types.get(ip)[field_index]);
1201312013 const payload_ref: Air.Inst.Ref = payload_ref: {
1201412014 if (capture_by_ref) {
12015 const operand_ptr_info = sema.typeOf(loaded_operand).ptrInfo(zcu);
12016 const ptr_field_ty = try pt.ptrType(.{
12017 .child = field_ty.toIntern(),
12018 .flags = .{
12019 .is_const = operand_ptr_info.flags.is_const,
12020 .is_volatile = operand_ptr_info.flags.is_volatile,
12021 .address_space = operand_ptr_info.flags.address_space,
12022 },
12023 });
12015 const ptr_field_ty = try sema.typeOf(loaded_operand).fieldPtrType(field_index, pt);
12016 if (try sema.resolveDefinedValue(case_block, operand_src, loaded_operand)) |op_ptr_val| {
12017 if (op_ptr_val.isUndef(zcu)) break :payload_ref try pt.undefRef(ptr_field_ty);
12018 const field_ptr_val = try op_ptr_val.ptrField(field_index, pt);
12019 break :payload_ref .fromValue(try pt.getCoerced(field_ptr_val, ptr_field_ty));
12020 }
1202412021 break :payload_ref try case_block.addStructFieldPtr(loaded_operand, field_index, ptr_field_ty);
1202512022 }
1202612023 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
1754817545 const is_cold = sema.branch_hint == .cold;
1754917546
1755017547 const operand_ty = sema.typeOf(operand);
17551 const ptr_info = operand_ty.ptrInfo(zcu);
17552 const res_ty = try pt.ptrType(.{
17553 .child = err_union_ty.errorUnionPayload(zcu).toIntern(),
17554 .flags = .{
17555 .is_const = ptr_info.flags.is_const,
17556 .is_volatile = ptr_info.flags.is_volatile,
17557 .is_allowzero = ptr_info.flags.is_allowzero,
17558 .address_space = ptr_info.flags.address_space,
17559 },
17548 const res_ty = try pt.ptrType(info: {
17549 var new = operand_ty.ptrInfo(zcu);
17550 new.child = err_union_ty.errorUnionPayload(zcu).toIntern();
17551 break :info new;
1756017552 });
1756117553 const res_ty_ref = Air.internedToRef(res_ty.toIntern());
1756217554 try sema.air_extra.ensureUnusedCapacity(sema.gpa, @typeInfo(Air.TryPtr).@"struct".field_names.len +
......@@ -26404,23 +26396,21 @@ fn fieldCallBind(
2640426396 .@"struct" => {
2640526397 if (zcu.typeToStruct(concrete_ty)) |struct_type| {
2640626398 const field_index = struct_type.nameIndex(ip, field_name) orelse break :find_field;
26407 const field_ty: Type = .fromInterned(struct_type.field_types.get(ip)[field_index]);
26408
26409 return sema.finishFieldCallBind(block, src, ptr_ty, field_ty, field_index, object_ptr);
26399 return sema.finishFieldCallBind(block, src, ptr_ty, field_index, object_ptr);
2641026400 } else if (concrete_ty.isTuple(zcu)) {
2641126401 if (field_name.eqlSlice("len", ip)) {
2641226402 return .{ .direct = try pt.intRef(.usize, concrete_ty.structFieldCount(zcu)) };
2641326403 }
2641426404 if (field_name.toUnsigned(ip)) |field_index| {
2641526405 if (field_index >= concrete_ty.structFieldCount(zcu)) break :find_field;
26416 return sema.finishFieldCallBind(block, src, ptr_ty, concrete_ty.fieldType(field_index, zcu), field_index, object_ptr);
26406 return sema.finishFieldCallBind(block, src, ptr_ty, field_index, object_ptr);
2641726407 }
2641826408 } else {
2641926409 const max = concrete_ty.structFieldCount(zcu);
2642026410 for (0..max) |i_usize| {
2642126411 const i: u32 = @intCast(i_usize);
2642226412 if (field_name == concrete_ty.structFieldName(i, zcu).unwrap().?) {
26423 return sema.finishFieldCallBind(block, src, ptr_ty, concrete_ty.fieldType(i, zcu), i, object_ptr);
26413 return sema.finishFieldCallBind(block, src, ptr_ty, i, object_ptr);
2642426414 }
2642526415 }
2642626416 }
......@@ -26536,19 +26526,12 @@ fn finishFieldCallBind(
2653626526 block: *Block,
2653726527 src: LazySrcLoc,
2653826528 ptr_ty: Type,
26539 field_ty: Type,
2654026529 field_index: u32,
2654126530 object_ptr: Air.Inst.Ref,
2654226531) CompileError!ResolvedFieldCallee {
2654326532 const pt = sema.pt;
2654426533 const zcu = pt.zcu;
26545 const ptr_field_ty = try pt.ptrType(.{
26546 .child = field_ty.toIntern(),
26547 .flags = .{
26548 .is_const = !ptr_ty.ptrIsMutable(zcu),
26549 .address_space = ptr_ty.ptrAddressSpace(zcu),
26550 },
26551 });
26534 const ptr_field_ty = try ptr_ty.fieldPtrType(field_index, pt);
2655226535
2655326536 const container_ty = ptr_ty.childType(zcu);
2655426537 if (container_ty.zigTypeTag(zcu) == .@"struct") {
test/behavior/switch.zig+19
......@@ -1574,3 +1574,22 @@ test "repeated switch analysis overrides previous analysis results" {
15741574 };
15751575 }
15761576}
1577
1578test "union field pointer capture preserves alignment in inline prong" {
1579 const U = union(enum) {
1580 a: u32,
1581 b: u32,
1582 fn doTheTest(u: *align(1) const @This()) !void {
1583 switch (u.*) {
1584 inline .a, .b => |*a_ptr| {
1585 comptime assert(@TypeOf(a_ptr) == *align(1) const u32);
1586 try expect(a_ptr.* == 123);
1587 },
1588 }
1589 }
1590 };
1591 try U.doTheTest(&.{ .a = 123 });
1592 try U.doTheTest(&.{ .b = 123 });
1593 try comptime U.doTheTest(&.{ .a = 123 });
1594 try comptime U.doTheTest(&.{ .b = 123 });
1595}
test/behavior/try.zig+12
......@@ -1,5 +1,6 @@
11const std = @import("std");
22const builtin = @import("builtin");
3const assert = std.debug.assert;
34const expect = std.testing.expect;
45
56test "try on error union" {
......@@ -197,3 +198,14 @@ test "try ptr propagation mutate" {
197198 try S.doTheTest();
198199 try comptime S.doTheTest();
199200}
201
202test "try pointer expression alignment" {
203 const S = struct {
204 fn doTheTest(p: *align(1) (anyerror!u32)) !void {
205 comptime assert(@TypeOf(&(try p.*)) == *align(1) u32);
206 try expect((try p.*) == 10);
207 }
208 };
209 var x: anyerror!u32 = 10;
210 try S.doTheTest(&x);
211}
test/cases/safety/@intCast negative to u0.zig created+22
......@@ -0,0 +1,22 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "integer does not fit in destination type")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10
11pub fn main() !void {
12 bar(1, -1);
13 return error.TestFailed;
14}
15
16fn bar(one: u1, not_zero: i32) void {
17 const x = one << @intCast(not_zero);
18 _ = x;
19}
20// run
21// backend=selfhosted,llvm
22// target=x86_64-linux,aarch64-linux
test/cases/safety/@intCast positive to u0.zig created+22
......@@ -0,0 +1,22 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "integer does not fit in destination type")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10
11pub fn main() !void {
12 bar(1, 1);
13 return error.TestFailed;
14}
15
16fn bar(one: u1, not_zero: i32) void {
17 const x = one << @intCast(not_zero);
18 _ = x;
19}
20// run
21// backend=selfhosted,llvm
22// target=x86_64-linux,aarch64-linux
test/cases/safety/@intCast to u0.zig deleted-22
......@@ -1,22 +0,0 @@
1const std = @import("std");
2
3pub fn panic(message: []const u8, stack_trace: ?*std.builtin.StackTrace, _: ?usize) noreturn {
4 _ = stack_trace;
5 if (std.mem.eql(u8, message, "integer does not fit in destination type")) {
6 std.process.exit(0);
7 }
8 std.process.exit(1);
9}
10
11pub fn main() !void {
12 bar(1, 1);
13 return error.TestFailed;
14}
15
16fn bar(one: u1, not_zero: i32) void {
17 const x = one << @intCast(not_zero);
18 _ = x;
19}
20// run
21// backend=selfhosted,llvm
22// target=x86_64-linux,aarch64-linux