authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-08 12:27:02-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-08 12:27:02-05:00
logd57370d3ca28db17a183157b0497c0ab25e22c19
tree0dfbe27beb71eabdce5add8e423f5ad5d50f8b09
parent19c1b5a33a21bdddfbbca3c65b1c0e6419c4629f
parent64d700bfa6cea1d9a440a7431ec8d64964cdd6c1
signaturelock-open Commit is signed but in an unrecognized format.

Merge branch 'comptime-fields'

closes #3677

11 files changed, 121 insertions(+), 35 deletions(-)

lib/std/zig/ast.zig+3-2
...@@ -754,8 +754,9 @@ pub const Node = struct {...@@ -754,8 +754,9 @@ pub const Node = struct {
754 };754 };
755755
756 pub const ContainerField = struct {756 pub const ContainerField = struct {
757 base: Node,757 base: Node = Node{ .id = .ContainerField },
758 doc_comments: ?*DocComment,758 doc_comments: ?*DocComment,
759 comptime_token: ?TokenIndex,
759 name_token: TokenIndex,760 name_token: TokenIndex,
760 type_expr: ?*Node,761 type_expr: ?*Node,
761 value_expr: ?*Node,762 value_expr: ?*Node,
...@@ -778,7 +779,7 @@ pub const Node = struct {...@@ -778,7 +779,7 @@ pub const Node = struct {
778 }779 }
779780
780 pub fn firstToken(self: *const ContainerField) TokenIndex {781 pub fn firstToken(self: *const ContainerField) TokenIndex {
781 return self.name_token;782 return self.comptime_token orelse self.name_token;
782 }783 }
783784
784 pub fn lastToken(self: *const ContainerField) TokenIndex {785 pub fn lastToken(self: *const ContainerField) TokenIndex {
lib/std/zig/parse.zig+12-3
...@@ -206,6 +206,11 @@ fn parseTestDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -206,6 +206,11 @@ fn parseTestDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
206/// TopLevelComptime <- KEYWORD_comptime BlockExpr206/// TopLevelComptime <- KEYWORD_comptime BlockExpr
207fn parseTopLevelComptime(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {207fn parseTopLevelComptime(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
208 const tok = eatToken(it, .Keyword_comptime) orelse return null;208 const tok = eatToken(it, .Keyword_comptime) orelse return null;
209 const lbrace = eatToken(it, .LBrace) orelse {
210 putBackToken(it, tok);
211 return null;
212 };
213 putBackToken(it, lbrace);
209 const block_node = try expectNode(arena, it, tree, parseBlockExpr, AstError{214 const block_node = try expectNode(arena, it, tree, parseBlockExpr, AstError{
210 .ExpectedLabelOrLBrace = AstError.ExpectedLabelOrLBrace{ .token = it.index },215 .ExpectedLabelOrLBrace = AstError.ExpectedLabelOrLBrace{ .token = it.index },
211 });216 });
...@@ -403,9 +408,13 @@ fn parseVarDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {...@@ -403,9 +408,13 @@ fn parseVarDecl(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
403 return &node.base;408 return &node.base;
404}409}
405410
406/// ContainerField <- IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)?411/// ContainerField <- KEYWORD_comptime? IDENTIFIER (COLON TypeExpr ByteAlign?)? (EQUAL Expr)?
407fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {412fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*Node {
408 const name_token = eatToken(it, .Identifier) orelse return null;413 const comptime_token = eatToken(it, .Keyword_comptime);
414 const name_token = eatToken(it, .Identifier) orelse {
415 if (comptime_token) |t| putBackToken(it, t);
416 return null;
417 };
409418
410 var align_expr: ?*Node = null;419 var align_expr: ?*Node = null;
411 var type_expr: ?*Node = null;420 var type_expr: ?*Node = null;
...@@ -431,8 +440,8 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No...@@ -431,8 +440,8 @@ fn parseContainerField(arena: *Allocator, it: *TokenIterator, tree: *Tree) !?*No
431440
432 const node = try arena.create(Node.ContainerField);441 const node = try arena.create(Node.ContainerField);
433 node.* = Node.ContainerField{442 node.* = Node.ContainerField{
434 .base = Node{ .id = .ContainerField },
435 .doc_comments = null,443 .doc_comments = null,
444 .comptime_token = comptime_token,
436 .name_token = name_token,445 .name_token = name_token,
437 .type_expr = type_expr,446 .type_expr = type_expr,
438 .value_expr = value_expr,447 .value_expr = value_expr,
lib/std/zig/parser_test.zig+10
...@@ -1,3 +1,13 @@...@@ -1,3 +1,13 @@
1test "zig fmt: comptime struct field" {
2 try testCanonical(
3 \\const Foo = struct {
4 \\ a: i32,
5 \\ comptime b: i32 = 1234,
6 \\};
7 \\
8 );
9}
10
1test "zig fmt: c pointer type" {11test "zig fmt: c pointer type" {
2 try testCanonical(12 try testCanonical(
3 \\pub extern fn repro() [*c]const u8;13 \\pub extern fn repro() [*c]const u8;
lib/std/zig/render.zig+3
...@@ -251,6 +251,9 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i...@@ -251,6 +251,9 @@ fn renderTopLevelDecl(allocator: *mem.Allocator, stream: var, tree: *ast.Tree, i
251 const field = @fieldParentPtr(ast.Node.ContainerField, "base", decl);251 const field = @fieldParentPtr(ast.Node.ContainerField, "base", decl);
252252
253 try renderDocComments(tree, stream, field, indent, start_col);253 try renderDocComments(tree, stream, field, indent, start_col);
254 if (field.comptime_token) |t| {
255 try renderToken(tree, stream, t, indent, start_col, Space.Space); // comptime
256 }
254257
255 if (field.type_expr == null and field.value_expr == null) {258 if (field.type_expr == null and field.value_expr == null) {
256 return renderToken(tree, stream, field.name_token, indent, start_col, Space.Comma); // name,259 return renderToken(tree, stream, field.name_token, indent, start_col, Space.Comma); // name,
src/all_types.hpp+2
...@@ -1006,6 +1006,7 @@ struct AstNodeStructField {...@@ -1006,6 +1006,7 @@ struct AstNodeStructField {
1006 // populated if the "align(A)" is present1006 // populated if the "align(A)" is present
1007 AstNode *align_expr;1007 AstNode *align_expr;
1008 Buf doc_comments;1008 Buf doc_comments;
1009 Token *comptime_token;
1009};1010};
10101011
1011struct AstNodeStringLiteral {1012struct AstNodeStringLiteral {
...@@ -1263,6 +1264,7 @@ struct TypeStructField {...@@ -1263,6 +1264,7 @@ struct TypeStructField {
1263 uint32_t bit_offset_in_host; // offset from the memory at gen_index1264 uint32_t bit_offset_in_host; // offset from the memory at gen_index
1264 uint32_t host_int_bytes; // size of host integer1265 uint32_t host_int_bytes; // size of host integer
1265 uint32_t align;1266 uint32_t align;
1267 bool is_comptime;
1266};1268};
12671269
1268enum ResolveStatus {1270enum ResolveStatus {
src/analyze.cpp+17-3
...@@ -2736,6 +2736,16 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2736,6 +2736,16 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
2736 field_node = decl_node->data.container_decl.fields.at(i);2736 field_node = decl_node->data.container_decl.fields.at(i);
2737 type_struct_field->name = field_node->data.struct_field.name;2737 type_struct_field->name = field_node->data.struct_field.name;
2738 type_struct_field->decl_node = field_node;2738 type_struct_field->decl_node = field_node;
2739 if (field_node->data.struct_field.comptime_token != nullptr) {
2740 if (field_node->data.struct_field.value == nullptr) {
2741 add_token_error(g, field_node->owner,
2742 field_node->data.struct_field.comptime_token,
2743 buf_sprintf("comptime struct field missing initialization value"));
2744 struct_type->data.structure.resolve_status = ResolveStatusInvalid;
2745 return ErrorSemanticAnalyzeFail;
2746 }
2747 type_struct_field->is_comptime = true;
2748 }
27392749
2740 if (field_node->data.struct_field.type == nullptr) {2750 if (field_node->data.struct_field.type == nullptr) {
2741 add_node_error(g, field_node, buf_sprintf("struct field missing type"));2751 add_node_error(g, field_node, buf_sprintf("struct field missing type"));
...@@ -2788,6 +2798,9 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {...@@ -2788,6 +2798,9 @@ static Error resolve_struct_zero_bits(CodeGen *g, ZigType *struct_type) {
2788 type_struct_field->src_index = i;2798 type_struct_field->src_index = i;
2789 type_struct_field->gen_index = SIZE_MAX;2799 type_struct_field->gen_index = SIZE_MAX;
27902800
2801 if (type_struct_field->is_comptime)
2802 continue;
2803
2791 switch (type_val_resolve_requires_comptime(g, field_type_val)) {2804 switch (type_val_resolve_requires_comptime(g, field_type_val)) {
2792 case ReqCompTimeYes:2805 case ReqCompTimeYes:
2793 struct_type->data.structure.requires_comptime = true;2806 struct_type->data.structure.requires_comptime = true;
...@@ -7987,8 +8000,9 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS...@@ -7987,8 +8000,9 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
7987 // inserting padding bytes where LLVM would do it automatically.8000 // inserting padding bytes where LLVM would do it automatically.
7988 size_t llvm_struct_abi_align = 0;8001 size_t llvm_struct_abi_align = 0;
7989 for (size_t i = 0; i < field_count; i += 1) {8002 for (size_t i = 0; i < field_count; i += 1) {
7990 ZigType *field_type = struct_type->data.structure.fields[i]->type_entry;8003 TypeStructField *field = struct_type->data.structure.fields[i];
7991 if (!type_has_bits(field_type))8004 ZigType *field_type = field->type_entry;
8005 if (field->is_comptime || !type_has_bits(field_type))
7992 continue;8006 continue;
7993 LLVMTypeRef field_llvm_type = get_llvm_type(g, field_type);8007 LLVMTypeRef field_llvm_type = get_llvm_type(g, field_type);
7994 size_t llvm_field_abi_align = LLVMABIAlignmentOfType(g->target_data_ref, field_llvm_type);8008 size_t llvm_field_abi_align = LLVMABIAlignmentOfType(g->target_data_ref, field_llvm_type);
...@@ -7999,7 +8013,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS...@@ -7999,7 +8013,7 @@ static void resolve_llvm_types_struct(CodeGen *g, ZigType *struct_type, ResolveS
7999 TypeStructField *field = struct_type->data.structure.fields[i];8013 TypeStructField *field = struct_type->data.structure.fields[i];
8000 ZigType *field_type = field->type_entry;8014 ZigType *field_type = field->type_entry;
80018015
8002 if (!type_has_bits(field_type)) {8016 if (field->is_comptime || !type_has_bits(field_type)) {
8003 field->gen_index = SIZE_MAX;8017 field->gen_index = SIZE_MAX;
8004 continue;8018 continue;
8005 }8019 }
src/ir.cpp+38-18
...@@ -655,6 +655,10 @@ static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) {...@@ -655,6 +655,10 @@ static ZigValue *const_ptr_pointee_unchecked(CodeGen *g, ZigValue *const_val) {
655 if (isf != nullptr) {655 if (isf != nullptr) {
656 TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name);656 TypeStructField *field = find_struct_type_field(isf->inferred_struct_type, isf->field_name);
657 assert(field != nullptr);657 assert(field != nullptr);
658 if (field->is_comptime) {
659 assert(field->init_val != nullptr);
660 return field->init_val;
661 }
658 assert(const_val->data.x_ptr.special == ConstPtrSpecialRef);662 assert(const_val->data.x_ptr.special == ConstPtrSpecialRef);
659 ZigValue *struct_val = const_val->data.x_ptr.data.ref.pointee;663 ZigValue *struct_val = const_val->data.x_ptr.data.ref.pointee;
660 return struct_val->data.x_struct.fields[field->src_index];664 return struct_val->data.x_struct.fields[field->src_index];
...@@ -17373,6 +17377,13 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source...@@ -17373,6 +17377,13 @@ static IrInstruction *ir_analyze_store_ptr(IrAnalyze *ira, IrInstruction *source
17373 field->type_val = create_const_type(ira->codegen, field->type_entry);17377 field->type_val = create_const_type(ira->codegen, field->type_entry);
17374 field->src_index = old_field_count;17378 field->src_index = old_field_count;
17375 field->decl_node = uncasted_value->source_node;17379 field->decl_node = uncasted_value->source_node;
17380 if (instr_is_comptime(uncasted_value)) {
17381 ZigValue *uncasted_val = ir_resolve_const(ira, uncasted_value, UndefOk);
17382 field->is_comptime = true;
17383 field->init_val = create_const_vals(1);
17384 copy_const_val(field->init_val, uncasted_val);
17385 return ir_const_void(ira, source_instr);
17386 }
1737617387
17377 ZigType *struct_ptr_type = get_pointer_to_type(ira->codegen, isf->inferred_struct_type, false);17388 ZigType *struct_ptr_type = get_pointer_to_type(ira->codegen, isf->inferred_struct_type, false);
17378 IrInstruction *casted_ptr;17389 IrInstruction *casted_ptr;
...@@ -19503,6 +19514,18 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,...@@ -19503,6 +19514,18 @@ static IrInstruction *ir_analyze_container_member_access_inner(IrAnalyze *ira,
19503 return ira->codegen->invalid_instruction;19514 return ira->codegen->invalid_instruction;
19504}19515}
1950519516
19517static void memoize_field_init_val(CodeGen *codegen, ZigType *container_type, TypeStructField *field) {
19518 if (field->init_val != nullptr) return;
19519 if (field->decl_node->type != NodeTypeStructField) return;
19520 AstNode *init_node = field->decl_node->data.struct_field.value;
19521 if (init_node == nullptr) return;
19522 // scope is not the scope of the struct init, it's the scope of the struct type decl
19523 Scope *analyze_scope = &get_container_scope(container_type)->base;
19524 // memoize it
19525 field->init_val = analyze_const_value(codegen, analyze_scope, init_node,
19526 field->type_entry, nullptr, UndefOk);
19527}
19528
19506static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction *source_instr,19529static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction *source_instr,
19507 TypeStructField *field, IrInstruction *struct_ptr, ZigType *struct_type, bool initializing)19530 TypeStructField *field, IrInstruction *struct_ptr, ZigType *struct_type, bool initializing)
19508{19531{
...@@ -19510,6 +19533,12 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction...@@ -19510,6 +19533,12 @@ static IrInstruction *ir_analyze_struct_field_ptr(IrAnalyze *ira, IrInstruction
19510 ZigType *field_type = resolve_struct_field_type(ira->codegen, field);19533 ZigType *field_type = resolve_struct_field_type(ira->codegen, field);
19511 if (field_type == nullptr)19534 if (field_type == nullptr)
19512 return ira->codegen->invalid_instruction;19535 return ira->codegen->invalid_instruction;
19536 if (field->is_comptime) {
19537 IrInstruction *elem = ir_const(ira, source_instr, field_type);
19538 memoize_field_init_val(ira->codegen, struct_type, field);
19539 copy_const_val(elem->value, field->init_val);
19540 return ir_get_ref(ira, source_instr, elem, true, false);
19541 }
19513 switch (type_has_one_possible_value(ira->codegen, field_type)) {19542 switch (type_has_one_possible_value(ira->codegen, field_type)) {
19514 case OnePossibleValueInvalid:19543 case OnePossibleValueInvalid:
19515 return ira->codegen->invalid_instruction;19544 return ira->codegen->invalid_instruction;
...@@ -21540,25 +21569,12 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc...@@ -21540,25 +21569,12 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
2154021569
21541 // look for a default field value21570 // look for a default field value
21542 TypeStructField *field = container_type->data.structure.fields[i];21571 TypeStructField *field = container_type->data.structure.fields[i];
21572 memoize_field_init_val(ira->codegen, container_type, field);
21543 if (field->init_val == nullptr) {21573 if (field->init_val == nullptr) {
21544 // it's not memoized. time to go analyze it21574 ir_add_error_node(ira, instruction->source_node,
21545 AstNode *init_node;21575 buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i]->name)));
21546 if (field->decl_node->type == NodeTypeStructField) {21576 any_missing = true;
21547 init_node = field->decl_node->data.struct_field.value;21577 continue;
21548 } else {
21549 init_node = nullptr;
21550 }
21551 if (init_node == nullptr) {
21552 ir_add_error_node(ira, instruction->source_node,
21553 buf_sprintf("missing field: '%s'", buf_ptr(container_type->data.structure.fields[i]->name)));
21554 any_missing = true;
21555 continue;
21556 }
21557 // scope is not the scope of the struct init, it's the scope of the struct type decl
21558 Scope *analyze_scope = &get_container_scope(container_type)->base;
21559 // memoize it
21560 field->init_val = analyze_const_value(ira->codegen, analyze_scope, init_node,
21561 field->type_entry, nullptr, UndefOk);
21562 }21578 }
21563 if (type_is_invalid(field->init_val->type))21579 if (type_is_invalid(field->init_val->type))
21564 return ira->codegen->invalid_instruction;21580 return ira->codegen->invalid_instruction;
...@@ -21716,6 +21732,10 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,...@@ -21716,6 +21732,10 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
21716 for (size_t i = 0; i < const_ptrs.length; i += 1) {21732 for (size_t i = 0; i < const_ptrs.length; i += 1) {
21717 IrInstruction *elem_result_loc = const_ptrs.at(i);21733 IrInstruction *elem_result_loc = const_ptrs.at(i);
21718 assert(elem_result_loc->value->special == ConstValSpecialStatic);21734 assert(elem_result_loc->value->special == ConstValSpecialStatic);
21735 if (elem_result_loc->value->type->data.pointer.inferred_struct_field != nullptr) {
21736 // This field will be generated comptime; no need to do this.
21737 continue;
21738 }
21719 IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr);21739 IrInstruction *deref = ir_get_deref(ira, elem_result_loc, elem_result_loc, nullptr);
21720 elem_result_loc->value->special = ConstValSpecialRuntime;21740 elem_result_loc->value->special = ConstValSpecialRuntime;
21721 ir_analyze_store_ptr(ira, elem_result_loc, elem_result_loc, deref, false);21741 ir_analyze_store_ptr(ira, elem_result_loc, elem_result_loc, deref, false);
src/parser.cpp+12-2
...@@ -536,8 +536,8 @@ static void ast_parse_container_doc_comments(ParseContext *pc, Buf *buf) {...@@ -536,8 +536,8 @@ static void ast_parse_container_doc_comments(ParseContext *pc, Buf *buf) {
536// <- TestDecl ContainerMembers536// <- TestDecl ContainerMembers
537// / TopLevelComptime ContainerMembers537// / TopLevelComptime ContainerMembers
538// / KEYWORD_pub? TopLevelDecl ContainerMembers538// / KEYWORD_pub? TopLevelDecl ContainerMembers
539// / ContainerField COMMA ContainerMembers539// / KEYWORD_comptime? ContainerField COMMA ContainerMembers
540// / ContainerField540// / KEYWORD_comptime? ContainerField
541// /541// /
542static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) {542static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) {
543 AstNodeContainerDecl res = {};543 AstNodeContainerDecl res = {};
...@@ -574,10 +574,13 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) {...@@ -574,10 +574,13 @@ static AstNodeContainerDecl ast_parse_container_members(ParseContext *pc) {
574 ast_error(pc, peek_token(pc), "expected function or variable declaration after pub");574 ast_error(pc, peek_token(pc), "expected function or variable declaration after pub");
575 }575 }
576576
577 Token *comptime_token = eat_token_if(pc, TokenIdKeywordCompTime);
578
577 AstNode *container_field = ast_parse_container_field(pc);579 AstNode *container_field = ast_parse_container_field(pc);
578 if (container_field != nullptr) {580 if (container_field != nullptr) {
579 assert(container_field->type == NodeTypeStructField);581 assert(container_field->type == NodeTypeStructField);
580 container_field->data.struct_field.doc_comments = doc_comment_buf;582 container_field->data.struct_field.doc_comments = doc_comment_buf;
583 container_field->data.struct_field.comptime_token = comptime_token;
581 res.fields.append(container_field);584 res.fields.append(container_field);
582 if (eat_token_if(pc, TokenIdComma) != nullptr) {585 if (eat_token_if(pc, TokenIdComma) != nullptr) {
583 continue;586 continue;
...@@ -612,6 +615,13 @@ static AstNode *ast_parse_top_level_comptime(ParseContext *pc) {...@@ -612,6 +615,13 @@ static AstNode *ast_parse_top_level_comptime(ParseContext *pc) {
612 if (comptime == nullptr)615 if (comptime == nullptr)
613 return nullptr;616 return nullptr;
614617
618 // 1 token lookahead because it could be a comptime struct field
619 Token *lbrace = peek_token(pc);
620 if (lbrace->id != TokenIdLBrace) {
621 put_back_token(pc);
622 return nullptr;
623 }
624
615 AstNode *block = ast_expect(pc, ast_parse_block_expr);625 AstNode *block = ast_expect(pc, ast_parse_block_expr);
616 AstNode *res = ast_create_node(pc, NodeTypeCompTime, comptime);626 AstNode *res = ast_create_node(pc, NodeTypeCompTime, comptime);
617 res->data.comptime_expr.expr = block;627 res->data.comptime_expr.expr = block;
test/compile_errors.zig+10-1
...@@ -2,6 +2,15 @@ const tests = @import("tests.zig");...@@ -2,6 +2,15 @@ const tests = @import("tests.zig");
2const builtin = @import("builtin");2const builtin = @import("builtin");
33
4pub fn addCases(cases: *tests.CompileErrorContext) void {4pub fn addCases(cases: *tests.CompileErrorContext) void {
5 cases.add("comptime struct field, no init value",
6 \\const Foo = struct {
7 \\ comptime b: i32,
8 \\};
9 \\export fn entry() void {
10 \\ var f: Foo = undefined;
11 \\}
12 , "tmp.zig:2:5: error: comptime struct field missing initialization value");
13
5 cases.add(14 cases.add(
6 "bad usage of @call",15 "bad usage of @call",
7 \\export fn entry1() void {16 \\export fn entry1() void {
...@@ -32,7 +41,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {...@@ -32,7 +41,7 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
32 "tmp.zig:15:43: error: unable to evaluate constant expression",41 "tmp.zig:15:43: error: unable to evaluate constant expression",
33 );42 );
3443
35 cases.add(44 cases.add("exported async function",
36 \\export async fn foo() void {}45 \\export async fn foo() void {}
37 , "tmp.zig:1:1: error: exported function cannot be async");46 , "tmp.zig:1:1: error: exported function cannot be async");
3847
test/stage1/behavior/call.zig+4-4
...@@ -37,12 +37,12 @@ test "tuple parameters" {...@@ -37,12 +37,12 @@ test "tuple parameters" {
37 comptime expect(@call(.{}, add, .{ 12, 34 }) == 46);37 comptime expect(@call(.{}, add, .{ 12, 34 }) == 46);
38 {38 {
39 const separate_args0 = .{ a, b };39 const separate_args0 = .{ a, b };
40 //TODO const separate_args1 = .{ a, 34 };40 const separate_args1 = .{ a, 34 };
41 const separate_args2 = .{ 12, 34 };41 const separate_args2 = .{ 12, 34 };
42 //TODO const separate_args3 = .{ 12, b };42 const separate_args3 = .{ 12, b };
43 expect(@call(.{ .modifier = .always_inline }, add, separate_args0) == 46);43 expect(@call(.{ .modifier = .always_inline }, add, separate_args0) == 46);
44 // TODO expect(@call(.{ .modifier = .always_inline }, add, separate_args1) == 46);44 expect(@call(.{ .modifier = .always_inline }, add, separate_args1) == 46);
45 expect(@call(.{ .modifier = .always_inline }, add, separate_args2) == 46);45 expect(@call(.{ .modifier = .always_inline }, add, separate_args2) == 46);
46 // TODO expect(@call(.{ .modifier = .always_inline }, add, separate_args3) == 46);46 expect(@call(.{ .modifier = .always_inline }, add, separate_args3) == 46);
47 }47 }
48}48}
test/stage1/behavior/struct.zig+10-2
...@@ -775,8 +775,6 @@ test "anonymous struct literal assigned to variable" {...@@ -775,8 +775,6 @@ test "anonymous struct literal assigned to variable" {
775 expect(vec.@"0" == 22);775 expect(vec.@"0" == 22);
776 expect(vec.@"1" == 55);776 expect(vec.@"1" == 55);
777 expect(vec.@"2" == 99);777 expect(vec.@"2" == 99);
778 vec.@"1" += 1;
779 expect(vec.@"1" == 56);
780}778}
781779
782test "struct with var field" {780test "struct with var field" {
...@@ -791,3 +789,13 @@ test "struct with var field" {...@@ -791,3 +789,13 @@ test "struct with var field" {
791 expect(pt.x == 1);789 expect(pt.x == 1);
792 expect(pt.y == 2);790 expect(pt.y == 2);
793}791}
792
793test "comptime struct field" {
794 const T = struct {
795 a: i32,
796 comptime b: i32 = 1234,
797 };
798
799 var foo: T = undefined;
800 comptime expect(foo.b == 1234);
801}