From 9e49a65e1bd474f0f678465fb4b965ddc5899226 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Thu, 29 Apr 2021 17:13:18 -0700 Subject: [PATCH] AstGen: implement anytype struct fields --- src/AstGen.zig | 13 +++++++++---- src/Module.zig | 1 + src/Sema.zig | 14 ++++++++++---- src/Zir.zig | 10 +++++----- 4 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/AstGen.zig b/src/AstGen.zig index d6456f14e4..8e653d4feb 100644 --- a/src/AstGen.zig +++ b/src/AstGen.zig @@ -483,6 +483,8 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn .asm_output => unreachable, // Handled in `asmExpr`. .asm_input => unreachable, // Handled in `asmExpr`. + .@"anytype" => unreachable, // Handled in `containerDecl`. + .assign => { try assign(gz, scope, node); return rvalue(gz, scope, rl, .void_value, node); @@ -869,8 +871,6 @@ pub fn expr(gz: *GenZir, scope: *Scope, rl: ResultLoc, node: ast.Node.Index) Inn .struct_init_comma, => return structInitExpr(gz, scope, rl, node, tree.structInit(node)), - .@"anytype" => return astgen.failNode(node, "TODO implement astgen.expr for .anytype", .{}), - .fn_proto_simple => { var params: [1]ast.Node.Index = undefined; return fnProtoExpr(gz, scope, rl, tree.fnProtoSimple(¶ms, node)); @@ -3318,7 +3318,10 @@ fn structDeclInner( const field_name = try gz.identAsString(member.ast.name_token); fields_data.appendAssumeCapacity(field_name); - const field_type = try typeExpr(&block_scope, &block_scope.base, member.ast.type_expr); + const field_type: Zir.Inst.Ref = if (node_tags[member.ast.type_expr] == .@"anytype") + .none + else + try typeExpr(&block_scope, &block_scope.base, member.ast.type_expr); fields_data.appendAssumeCapacity(@enumToInt(field_type)); const have_align = member.ast.align_expr != 0; @@ -3336,7 +3339,9 @@ fn structDeclInner( fields_data.appendAssumeCapacity(@enumToInt(align_inst)); } if (have_value) { - const default_inst = try expr(&block_scope, &block_scope.base, .{ .ty = field_type }, member.ast.value_expr); + const rl: ResultLoc = if (field_type == .none) .none else .{ .ty = field_type }; + + const default_inst = try expr(&block_scope, &block_scope.base, rl, member.ast.value_expr); fields_data.appendAssumeCapacity(@enumToInt(default_inst)); } else if (member.comptime_token) |comptime_token| { return astgen.failTok(comptime_token, "comptime field without default initialization value", .{}); diff --git a/src/Module.zig b/src/Module.zig index cfaac07570..4b50c298e3 100644 --- a/src/Module.zig +++ b/src/Module.zig @@ -467,6 +467,7 @@ pub const Struct = struct { node_offset: i32, pub const Field = struct { + /// Uses `noreturn` to indicate `anytype`. ty: Type, abi_align: Value, /// Uses `unreachable_value` to indicate no default. diff --git a/src/Sema.zig b/src/Sema.zig index b99c31debb..224d61ca24 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -750,10 +750,16 @@ pub fn zirStructDecl( // This string needs to outlive the ZIR code. const field_name = try new_decl_arena.allocator.dupe(u8, field_name_zir); - // TODO: if we need to report an error here, use a source location - // that points to this type expression rather than the struct. - // But only resolve the source location if we need to emit a compile error. - const field_ty = try sema.resolveType(block, src, field_type_ref); + if (field_type_ref == .none) { + return sema.mod.fail(&block.base, src, "TODO: implement anytype struct field", .{}); + } + const field_ty: Type = if (field_type_ref == .none) + Type.initTag(.noreturn) + else + // TODO: if we need to report an error here, use a source location + // that points to this type expression rather than the struct. + // But only resolve the source location if we need to emit a compile error. + try sema.resolveType(block, src, field_type_ref); const gop = struct_obj.fields.getOrPutAssumeCapacity(field_name); assert(!gop.found_existing); diff --git a/src/Zir.zig b/src/Zir.zig index 64450fa545..9692415407 100644 --- a/src/Zir.zig +++ b/src/Zir.zig @@ -3367,15 +3367,15 @@ const Writer = struct { var extra_index: usize = undefined; if (decls_len == 0) { - try stream.writeAll("}) "); + try stream.writeAll("{}, "); extra_index = extra.end; } else { - try stream.writeAll("\n"); + try stream.writeAll("{\n"); self.indent += 2; extra_index = try self.writeDecls(stream, decls_len, extra.end); self.indent -= 2; try stream.writeByteNTimes(' ', self.indent); - try stream.writeAll("}) "); + try stream.writeAll("}, "); } const body = self.code.extra[extra_index..][0..extra.data.body_len]; @@ -3383,7 +3383,7 @@ const Writer = struct { if (fields_len == 0) { assert(body.len == 0); - try stream.writeAll("{}, {}, {"); + try stream.writeAll("{}, {}) "); extra_index = extra.end; } else { self.indent += 2; @@ -3451,7 +3451,7 @@ const Writer = struct { self.indent -= 2; try stream.writeByteNTimes(' ', self.indent); - try stream.writeAll("}, {"); + try stream.writeAll("}) "); } try self.writeSrc(stream, inst_data.src()); }