aboutsummaryrefslogtreecommitdiff
path: root/src/Sema.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-10-18 17:16:43 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-10-19 19:03:20 -0700
commite4c437f23baecf9d170f3f058cde78f34dedd5d0 (patch)
treeb6d6b6fd132fe0b94467445f4bd6816d2126738b /src/Sema.zig
parent6329f4e47a78dc75b234e6d89c82fb3cff058fe1 (diff)
downloadzig-e4c437f23baecf9d170f3f058cde78f34dedd5d0.tar.gz
zig-e4c437f23baecf9d170f3f058cde78f34dedd5d0.zip
stage2: implement union member access as enum tag
Diffstat (limited to 'src/Sema.zig')
-rw-r--r--src/Sema.zig100
1 files changed, 61 insertions, 39 deletions
diff --git a/src/Sema.zig b/src/Sema.zig
index c08cc09c68..aa00ad3fb6 100644
--- a/src/Sema.zig
+++ b/src/Sema.zig
@@ -2316,7 +2316,7 @@ fn validateStructInit(
const field_ptr_extra = sema.code.extraData(Zir.Inst.Field, field_ptr_data.payload_index).data;
const field_name = sema.code.nullTerminatedString(field_ptr_extra.field_name_start);
const field_index = struct_obj.fields.getIndex(field_name) orelse
- return sema.failWithBadFieldAccess(block, struct_obj, field_src, field_name);
+ return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
if (found_fields[field_index] != 0) {
const other_field_ptr = found_fields[field_index];
const other_field_ptr_data = sema.code.instructions.items(.data)[other_field_ptr].pl_node;
@@ -2378,7 +2378,32 @@ fn zirValidateArrayInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index) Compil
}
}
-fn failWithBadFieldAccess(
+fn failWithBadMemberAccess(
+ sema: *Sema,
+ block: *Block,
+ agg_ty: Type,
+ field_src: LazySrcLoc,
+ field_name: []const u8,
+) CompileError {
+ const kw_name = switch (agg_ty.zigTypeTag()) {
+ .Union => "union",
+ .Struct => "struct",
+ .Opaque => "opaque",
+ .Enum => "enum",
+ else => unreachable,
+ };
+ const msg = msg: {
+ const msg = try sema.errMsg(block, field_src, "{s} '{}' has no member named '{s}'", .{
+ kw_name, agg_ty, field_name,
+ });
+ errdefer msg.destroy(sema.gpa);
+ try sema.addDeclaredHereNote(msg, agg_ty);
+ break :msg msg;
+ };
+ return sema.failWithOwnedErrorMsg(msg);
+}
+
+fn failWithBadStructFieldAccess(
sema: *Sema,
block: *Block,
struct_obj: *Module.Struct,
@@ -8828,7 +8853,7 @@ fn zirStructInit(sema: *Sema, block: *Block, inst: Zir.Inst.Index, is_ref: bool)
const field_type_extra = sema.code.extraData(Zir.Inst.FieldType, field_type_data.payload_index).data;
const field_name = sema.code.nullTerminatedString(field_type_extra.name_start);
const field_index = struct_obj.fields.getIndex(field_name) orelse
- return sema.failWithBadFieldAccess(block, struct_obj, field_src, field_name);
+ return sema.failWithBadStructFieldAccess(block, struct_obj, field_src, field_name);
if (found_fields[field_index] != 0) {
const other_field_type = found_fields[field_index];
const other_field_type_data = zir_datas[other_field_type].pl_node;
@@ -9037,7 +9062,7 @@ fn zirFieldType(sema: *Sema, block: *Block, inst: Zir.Inst.Index) CompileError!A
.Struct => {
const struct_obj = resolved_ty.castTag(.@"struct").?.data;
const field = struct_obj.fields.get(field_name) orelse
- return sema.failWithBadFieldAccess(block, struct_obj, src, field_name);
+ return sema.failWithBadStructFieldAccess(block, struct_obj, src, field_name);
return sema.addType(field.ty);
},
.Union => {
@@ -10859,7 +10884,7 @@ fn fieldVal(
},
else => {},
}
- return sema.fail(block, src, "type '{}' does not support field access (fieldVal, {}.{s})", .{object_ty, object_ty, field_name});
+ return sema.fail(block, src, "type '{}' does not support field access (fieldVal, {}.{s})", .{ object_ty, object_ty, field_name });
}
fn fieldPtr(
@@ -11001,22 +11026,24 @@ fn fieldPtr(
try Value.Tag.@"error".create(anon_decl.arena(), .{ .name = name }),
));
},
- .Struct, .Opaque, .Union => {
+ .Union => {
if (child_type.getNamespace()) |namespace| {
if (try sema.namespaceLookupRef(block, src, namespace, field_name)) |inst| {
return inst;
}
}
- // TODO add note: declared here
- const kw_name = switch (child_type.zigTypeTag()) {
- .Struct => "struct",
- .Opaque => "opaque",
- .Union => "union",
- else => unreachable,
- };
- return sema.fail(block, src, "{s} '{}' has no member named '{s}'", .{
- kw_name, child_type, field_name,
- });
+ if (child_type.unionTagType()) |enum_ty| {
+ if (enum_ty.enumFieldIndex(field_name)) |field_index| {
+ const field_index_u32 = @intCast(u32, field_index);
+ var anon_decl = try block.startAnonDecl();
+ defer anon_decl.deinit();
+ return sema.analyzeDeclRef(try anon_decl.finish(
+ try enum_ty.copy(anon_decl.arena()),
+ try Value.Tag.enum_field_index.create(anon_decl.arena(), field_index_u32),
+ ));
+ }
+ }
+ return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);
},
.Enum => {
if (child_type.getNamespace()) |namespace| {
@@ -11025,23 +11052,7 @@ fn fieldPtr(
}
}
const field_index = child_type.enumFieldIndex(field_name) orelse {
- const msg = msg: {
- const msg = try sema.errMsg(
- block,
- src,
- "enum '{}' has no member named '{s}'",
- .{ child_type, field_name },
- );
- errdefer msg.destroy(sema.gpa);
- try sema.mod.errNoteNonLazy(
- child_type.declSrcLoc(),
- msg,
- "enum declared here",
- .{},
- );
- break :msg msg;
- };
- return sema.failWithOwnedErrorMsg(msg);
+ return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);
};
const field_index_u32 = @intCast(u32, field_index);
var anon_decl = try block.startAnonDecl();
@@ -11051,6 +11062,14 @@ fn fieldPtr(
try Value.Tag.enum_field_index.create(anon_decl.arena(), field_index_u32),
));
},
+ .Struct, .Opaque => {
+ if (child_type.getNamespace()) |namespace| {
+ if (try sema.namespaceLookupRef(block, src, namespace, field_name)) |inst| {
+ return inst;
+ }
+ }
+ return sema.failWithBadMemberAccess(block, child_type, field_name_src, field_name);
+ },
else => return sema.fail(block, src, "type '{}' has no members", .{child_type}),
}
},
@@ -11070,7 +11089,7 @@ fn fieldPtr(
},
else => {},
}
- return sema.fail(block, src, "type '{}' does not support field access (fieldPtr, {}.{s})", .{object_ty, object_ptr_ty, field_name});
+ return sema.fail(block, src, "type '{}' does not support field access (fieldPtr, {}.{s})", .{ object_ty, object_ptr_ty, field_name });
}
fn fieldCallBind(
@@ -11242,7 +11261,7 @@ fn structFieldPtr(
const struct_obj = struct_ty.castTag(.@"struct").?.data;
const field_index_big = struct_obj.fields.getIndex(field_name) orelse
- return sema.failWithBadFieldAccess(block, struct_obj, field_name_src, field_name);
+ return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);
const field_index = @intCast(u32, field_index_big);
const field = struct_obj.fields.values()[field_index];
const ptr_field_ty = try Type.ptr(arena, .{
@@ -11279,10 +11298,9 @@ fn structFieldVal(
const struct_ty = try sema.resolveTypeFields(block, src, unresolved_struct_ty);
const struct_obj = struct_ty.castTag(.@"struct").?.data;
- const field_index_big = struct_obj.fields.getIndex(field_name) orelse
- return sema.failWithBadFieldAccess(block, struct_obj, field_name_src, field_name);
- const field_index = @intCast(u32, field_index_big);
-
+ const field_index_usize = struct_obj.fields.getIndex(field_name) orelse
+ return sema.failWithBadStructFieldAccess(block, struct_obj, field_name_src, field_name);
+ const field_index = @intCast(u32, field_index_usize);
const field = struct_obj.fields.values()[field_index];
if (try sema.resolveMaybeUndefVal(block, src, struct_byval)) |struct_val| {
@@ -13168,6 +13186,10 @@ pub fn resolveTypeLayout(
}
union_obj.status = .have_layout;
},
+ .Array => {
+ const elem_ty = ty.childType();
+ return sema.resolveTypeLayout(block, src, elem_ty);
+ },
else => {},
}
}