Commit 5404dcdfd8

Veikka Tuominen <git@vexu.eu>
2022-08-22 10:13:01
Sema: fix fieldCallBind on tuples and anon structs
Closes #12573
1 parent 560baf6
Changed files (2)
src
test
cases
src/Sema.zig
@@ -21394,14 +21394,30 @@ fn fieldCallBind(
         switch (concrete_ty.zigTypeTag()) {
             .Struct => {
                 const struct_ty = try sema.resolveTypeFields(block, src, concrete_ty);
-                const struct_obj = struct_ty.castTag(.@"struct").?.data;
-
-                const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
-                    break :find_field;
-                const field_index = @intCast(u32, field_index_usize);
-                const field = struct_obj.fields.values()[field_index];
+                if (struct_ty.castTag(.@"struct")) |struct_obj| {
+                    const field_index_usize = struct_obj.data.fields.getIndex(field_name) orelse
+                        break :find_field;
+                    const field_index = @intCast(u32, field_index_usize);
+                    const field = struct_obj.data.fields.values()[field_index];
 
-                return finishFieldCallBind(sema, block, src, ptr_ty, field.ty, field_index, object_ptr);
+                    return finishFieldCallBind(sema, block, src, ptr_ty, field.ty, field_index, object_ptr);
+                } else if (struct_ty.isTuple()) {
+                    if (mem.eql(u8, field_name, "len")) {
+                        return sema.addIntUnsigned(Type.usize, struct_ty.structFieldCount());
+                    }
+                    if (std.fmt.parseUnsigned(u32, field_name, 10)) |field_index| {
+                        if (field_index >= struct_ty.structFieldCount()) break :find_field;
+                        return finishFieldCallBind(sema, block, src, ptr_ty, struct_ty.structFieldType(field_index), field_index, object_ptr);
+                    } else |_| {}
+                } else {
+                    const max = struct_ty.structFieldCount();
+                    var i: u32 = 0;
+                    while (i < max) : (i += 1) {
+                        if (mem.eql(u8, struct_ty.structFieldName(i), field_name)) {
+                            return finishFieldCallBind(sema, block, src, ptr_ty, struct_ty.structFieldType(i), i, object_ptr);
+                        }
+                    }
+                }
             },
             .Union => {
                 const union_ty = try sema.resolveTypeFields(block, src, concrete_ty);
test/cases/compile_errors/bogus_method_call_on_slice.zig
@@ -3,9 +3,17 @@ fn f(m: []const u8) void {
     m.copy(u8, self[0..], m);
 }
 export fn entry() usize { return @sizeOf(@TypeOf(&f)); }
+pub export fn entry1() void {
+    .{}.bar();
+}
+pub export fn entry2() void {
+    .{ .foo = 1 }.bar();
+}
 
 // error
 // backend=stage2
 // target=native
 //
+// :7:8: error: no field or member function named 'bar' in '@TypeOf(.{})'
+// :10:18: error: no field or member function named 'bar' in 'struct{comptime foo: comptime_int = 1}'
 // :3:6: error: no field or member function named 'copy' in '[]const u8'