diff --git a/src/Sema.zig b/src/Sema.zig index 791430c738..0528b31b91 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -15872,50 +15872,40 @@ fn bitOffsetOf(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!u6 const target = sema.mod.getTarget(); try sema.resolveTypeLayout(block, lhs_src, ty); - if (ty.tag() != .@"struct") { - const msg = msg: { - const msg = try sema.errMsg(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(sema.mod)}); - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); + switch (ty.tag()) { + .@"struct", .tuple, .anon_struct => {}, + else => { + const msg = msg: { + const msg = try sema.errMsg(block, lhs_src, "expected struct type, found '{}'", .{ty.fmt(sema.mod)}); + errdefer msg.destroy(sema.gpa); + try sema.addDeclaredHereNote(msg, ty); + break :msg msg; + }; + return sema.failWithOwnedErrorMsg(block, msg); + }, } - const fields = ty.structFields(); - const index = fields.getIndex(field_name) orelse { - const msg = msg: { - const msg = try sema.errMsg( - block, - rhs_src, - "struct '{}' has no field '{s}'", - .{ ty.fmt(sema.mod), field_name }, - ); - errdefer msg.destroy(sema.gpa); - try sema.addDeclaredHereNote(msg, ty); - break :msg msg; - }; - return sema.failWithOwnedErrorMsg(block, msg); - }; + const field_index = if (ty.isTuple()) b: { + if (std.fmt.parseUnsigned(u32, field_name, 10)) |idx| { + if (idx < ty.structFieldCount()) break :b idx; + } else |_| {} + return sema.fail(block, rhs_src, "tuple '{}' has no such field '{s}'", .{ + ty.fmt(sema.mod), field_name, + }); + } else try sema.structFieldIndex(block, ty, field_name, rhs_src); switch (ty.containerLayout()) { .Packed => { var bit_sum: u64 = 0; + const fields = ty.structFields(); for (fields.values()) |field, i| { - if (i == index) { + if (i == field_index) { return bit_sum; } bit_sum += field.ty.bitSize(target); } else unreachable; }, - else => { - var it = ty.iterateStructOffsets(target); - while (it.next()) |field_offset| { - if (field_offset.field == index) { - return field_offset.offset * 8; - } - } else unreachable; - }, + else => return ty.structFieldOffset(field_index, target) * 8, } } diff --git a/test/behavior/tuple.zig b/test/behavior/tuple.zig index 7cec421588..aa73dbc98b 100644 --- a/test/behavior/tuple.zig +++ b/test/behavior/tuple.zig @@ -221,20 +221,14 @@ test "fieldParentPtr of anon struct" { } test "offsetOf tuple" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; - var x: u32 = 0; const T = @TypeOf(.{ x, x }); - _ = @offsetOf(T, "1"); } test "offsetOf anon struct" { - if (builtin.zig_backend != .stage1) return error.SkipZigTest; - var x: u32 = 0; const T = @TypeOf(.{ .foo = x, .bar = x }); - _ = @offsetOf(T, "bar"); } diff --git a/test/cases/compile_errors/offsetOf-bad_field_name.zig b/test/cases/compile_errors/offsetOf-bad_field_name.zig index 5beee8fe2e..eb04da3c68 100644 --- a/test/cases/compile_errors/offsetOf-bad_field_name.zig +++ b/test/cases/compile_errors/offsetOf-bad_field_name.zig @@ -9,5 +9,5 @@ export fn foo() usize { // backend=stage2 // target=native // -// :5:27: error: struct 'tmp.Foo' has no field 'a' +// :5:27: error: no field named 'a' in struct 'tmp.Foo' // :1:13: note: struct declared here