authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-23 17:51:37-05:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-11-23 17:51:37-05:00
logf25182f46dd672eb5b10533c67ed462a3e5df999
tree142c56629394684cb2d7e15418dbda98ae2fd1a3
parent7597735badd1f6aa6750f354a7e9c85fec705c55
signaturelock-open Commit is signed but in an unrecognized format.

structs can have fields with type `var`

behavior tests passing now

8 files changed, 97 insertions(+), 61 deletions(-)

lib/std/builtin.zig+4-8
......@@ -146,10 +146,8 @@ pub const TypeInfo = union(enum) {
146146 is_allowzero: bool,
147147 /// The type of the sentinel is the element type of the pointer, which is
148148 /// the value of the `child` field in this struct. However there is no way
149 /// to refer to that type here, so this is a pointer to an opaque value.
150 /// It will be known at compile-time to be the correct type. Dereferencing
151 /// this pointer will work at compile-time.
152 sentinel: ?*const c_void,
149 /// to refer to that type here, so we use `var`.
150 sentinel: var,
153151
154152 /// This data structure is used by the Zig language code generation and
155153 /// therefore must be kept in sync with the compiler implementation.
......@@ -168,10 +166,8 @@ pub const TypeInfo = union(enum) {
168166 child: type,
169167 /// The type of the sentinel is the element type of the array, which is
170168 /// the value of the `child` field in this struct. However there is no way
171 /// to refer to that type here, so this is a pointer to an opaque value.
172 /// It will be known at compile-time to be the correct type. Dereferencing
173 /// this pointer will work at compile-time.
174 sentinel: ?*const c_void,
169 /// to refer to that type here, so we use `var`.
170 sentinel: var,
175171 };
176172
177173 /// This data structure is used by the Zig language code generation and
src/all_types.hpp+1
......@@ -601,6 +601,7 @@ enum NodeType {
601601 NodeTypeSuspend,
602602 NodeTypeAnyFrameType,
603603 NodeTypeEnumLiteral,
604 NodeTypeVarFieldType,
604605};
605606
606607enum CallingConvention {
src/analyze.cpp+8
......@@ -1179,6 +1179,10 @@ Error type_val_resolve_zero_bits(CodeGen *g, ConstExprValue *type_val, ZigType *
11791179Error type_val_resolve_is_opaque_type(CodeGen *g, ConstExprValue *type_val, bool *is_opaque_type) {
11801180 if (type_val->special != ConstValSpecialLazy) {
11811181 assert(type_val->special == ConstValSpecialStatic);
1182 if (type_val->data.x_type == g->builtin_types.entry_var) {
1183 *is_opaque_type = false;
1184 return ErrorNone;
1185 }
11821186 *is_opaque_type = (type_val->data.x_type->id == ZigTypeIdOpaque);
11831187 return ErrorNone;
11841188 }
......@@ -3667,6 +3671,7 @@ void scan_decls(CodeGen *g, ScopeDecls *decls_scope, AstNode *node) {
36673671 case NodeTypeEnumLiteral:
36683672 case NodeTypeAnyFrameType:
36693673 case NodeTypeErrorSetField:
3674 case NodeTypeVarFieldType:
36703675 zig_unreachable();
36713676 }
36723677}
......@@ -5587,6 +5592,9 @@ ConstExprValue *get_the_one_possible_value(CodeGen *g, ZigType *type_entry) {
55875592
55885593ReqCompTime type_requires_comptime(CodeGen *g, ZigType *ty) {
55895594 Error err;
5595 if (ty == g->builtin_types.entry_var) {
5596 return ReqCompTimeYes;
5597 }
55905598 switch (ty->id) {
55915599 case ZigTypeIdInvalid:
55925600 zig_unreachable();
src/ast_render.cpp+6
......@@ -268,6 +268,8 @@ static const char *node_type_str(NodeType node_type) {
268268 return "EnumLiteral";
269269 case NodeTypeErrorSetField:
270270 return "ErrorSetField";
271 case NodeTypeVarFieldType:
272 return "VarFieldType";
271273 }
272274 zig_unreachable();
273275}
......@@ -1184,6 +1186,10 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
11841186 fprintf(ar->f, ".%s", buf_ptr(&node->data.enum_literal.identifier->data.str_lit.str));
11851187 break;
11861188 }
1189 case NodeTypeVarFieldType: {
1190 fprintf(ar->f, "var");
1191 break;
1192 }
11871193 case NodeTypeParamDecl:
11881194 case NodeTypeTestDecl:
11891195 case NodeTypeStructField:
src/ir.cpp+67-48
......@@ -8556,6 +8556,9 @@ static IrInstruction *ir_gen_node_raw(IrBuilder *irb, AstNode *node, Scope *scop
85568556 add_node_error(irb->codegen, node,
85578557 buf_sprintf("inferred array size invalid here"));
85588558 return irb->codegen->invalid_instruction;
8559 case NodeTypeVarFieldType:
8560 return ir_lval_wrap(irb, scope,
8561 ir_build_const_type(irb, scope, node, irb->codegen->builtin_types.entry_var), lval, result_loc);
85598562 }
85608563 zig_unreachable();
85618564}
......@@ -8715,6 +8718,9 @@ ConstExprValue *const_ptr_pointee(IrAnalyze *ira, CodeGen *codegen, ConstExprVal
87158718 assert(val != nullptr);
87168719 assert(const_val->type->id == ZigTypeIdPointer);
87178720 ZigType *expected_type = const_val->type->data.pointer.child_type;
8721 if (expected_type == codegen->builtin_types.entry_var) {
8722 return val;
8723 }
87188724 switch (type_has_one_possible_value(codegen, expected_type)) {
87198725 case OnePossibleValueInvalid:
87208726 return nullptr;
......@@ -13502,6 +13508,9 @@ static IrInstruction *ir_get_deref(IrAnalyze *ira, IrInstruction *source_instruc
1350213508 }
1350313509 if (ptr->value.data.x_ptr.mut != ConstPtrMutRuntimeVar) {
1350413510 ConstExprValue *pointee = const_ptr_pointee_unchecked(ira->codegen, &ptr->value);
13511 if (child_type == ira->codegen->builtin_types.entry_var) {
13512 child_type = pointee->type;
13513 }
1350513514 if (pointee->special != ConstValSpecialRuntime) {
1350613515 IrInstruction *result = ir_const(ira, source_instruction, child_type);
1350713516
......@@ -19857,13 +19866,24 @@ static IrInstruction *ir_analyze_instruction_test_non_null(IrAnalyze *ira, IrIns
1985719866 return ir_analyze_test_non_null(ira, &instruction->base, value);
1985819867}
1985919868
19869static ZigType *get_ptr_elem_type(CodeGen *g, IrInstruction *ptr) {
19870 ir_assert(ptr->value.type->id == ZigTypeIdPointer, ptr);
19871 ZigType *elem_type = ptr->value.type->data.pointer.child_type;
19872 if (elem_type != g->builtin_types.entry_var)
19873 return elem_type;
19874
19875 if (ir_resolve_lazy(g, ptr->source_node, &ptr->value))
19876 return g->builtin_types.entry_invalid;
19877
19878 assert(value_is_comptime(&ptr->value));
19879 ConstExprValue *pointee = const_ptr_pointee_unchecked(g, &ptr->value);
19880 return pointee->type;
19881}
19882
1986019883static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstruction *source_instr,
1986119884 IrInstruction *base_ptr, bool safety_check_on, bool initializing)
1986219885{
19863 ZigType *ptr_type = base_ptr->value.type;
19864 assert(ptr_type->id == ZigTypeIdPointer);
19865
19866 ZigType *type_entry = ptr_type->data.pointer.child_type;
19886 ZigType *type_entry = get_ptr_elem_type(ira->codegen, base_ptr);
1986719887 if (type_is_invalid(type_entry))
1986819888 return ira->codegen->invalid_instruction;
1986919889
......@@ -19901,7 +19921,8 @@ static IrInstruction *ir_analyze_unwrap_optional_payload(IrAnalyze *ira, IrInstr
1990119921
1990219922 ZigType *child_type = type_entry->data.maybe.child_type;
1990319923 ZigType *result_type = get_pointer_to_type_extra(ira->codegen, child_type,
19904 ptr_type->data.pointer.is_const, ptr_type->data.pointer.is_volatile, PtrLenSingle, 0, 0, 0, false);
19924 base_ptr->value.type->data.pointer.is_const, base_ptr->value.type->data.pointer.is_volatile,
19925 PtrLenSingle, 0, 0, 0, false);
1990519926
1990619927 bool same_comptime_repr = types_have_same_zig_comptime_repr(ira->codegen, child_type, type_entry);
1990719928
......@@ -21627,20 +21648,15 @@ static ConstExprValue *create_ptr_like_type_info(IrAnalyze *ira, ZigType *ptr_ty
2162721648 fields[5]->special = ConstValSpecialStatic;
2162821649 fields[5]->type = ira->codegen->builtin_types.entry_bool;
2162921650 fields[5]->data.x_bool = attrs_type->data.pointer.allow_zero;
21630 // sentinel: ?*const c_void
21631 ZigType *ptr_type = get_pointer_to_type(ira->codegen, ira->codegen->builtin_types.entry_c_void, true);
21651 // sentinel: var
2163221652 ensure_field_index(result->type, "sentinel", 6);
2163321653 fields[6]->special = ConstValSpecialStatic;
21634 fields[6]->type = get_optional_type(ira->codegen, ptr_type);
21635 if (attrs_type->data.pointer.sentinel == nullptr) {
21636 fields[6]->data.x_optional = nullptr;
21654 if (attrs_type->data.pointer.sentinel != nullptr) {
21655 fields[6]->type = get_optional_type(ira->codegen, attrs_type->data.pointer.child_type);
21656 fields[6]->data.x_optional = attrs_type->data.pointer.sentinel;
2163721657 } else {
21638 ConstExprValue *ptr_val = create_const_vals(1);
21639 fields[6]->data.x_optional = ptr_val;
21640 ptr_val->data.x_ptr.special = ConstPtrSpecialRef;
21641 ptr_val->data.x_ptr.mut = ConstPtrMutComptimeConst;
21642 ptr_val->data.x_ptr.data.ref.pointee = create_const_vals(1);
21643 copy_const_val(ptr_val->data.x_ptr.data.ref.pointee, attrs_type->data.pointer.sentinel, false);
21658 fields[6]->type = ira->codegen->builtin_types.entry_null;
21659 fields[6]->data.x_optional = nullptr;
2164421660 }
2164521661
2164621662 return result;
......@@ -21762,23 +21778,10 @@ static Error ir_make_type_info_value(IrAnalyze *ira, IrInstruction *source_instr
2176221778 fields[1]->special = ConstValSpecialStatic;
2176321779 fields[1]->type = ira->codegen->builtin_types.entry_type;
2176421780 fields[1]->data.x_type = type_entry->data.array.child_type;
21765 // sentinel: ?*const c_void
21781 // sentinel: var
2176621782 fields[2]->special = ConstValSpecialStatic;
21767 ZigType *ptr_type = get_pointer_to_type(ira->codegen,
21768 ira->codegen->builtin_types.entry_c_void, true);
21769 fields[2]->type = get_optional_type(ira->codegen, ptr_type);
21770 if (type_entry->data.array.sentinel == nullptr) {
21771 fields[2]->data.x_optional = nullptr;
21772 } else {
21773 ConstExprValue *ptr_val = create_const_vals(1);
21774 fields[2]->data.x_optional = ptr_val;
21775 ptr_val->type = ptr_type;
21776 ptr_val->data.x_ptr.special = ConstPtrSpecialRef;
21777 ptr_val->data.x_ptr.mut = ConstPtrMutComptimeConst;
21778 ptr_val->data.x_ptr.data.ref.pointee = create_const_vals(1);
21779 copy_const_val(ptr_val->data.x_ptr.data.ref.pointee, type_entry->data.array.sentinel, false);
21780 }
21781
21783 fields[2]->type = get_optional_type(ira->codegen, type_entry->data.array.child_type);
21784 fields[2]->data.x_optional = type_entry->data.array.sentinel;
2178221785 break;
2178321786 }
2178421787 case ZigTypeIdVector: {
......@@ -22290,15 +22293,18 @@ static ConstExprValue *get_const_field(IrAnalyze *ira, ConstExprValue *struct_va
2229022293 return struct_value->data.x_struct.fields[field_index];
2229122294}
2229222295
22293static ConstExprValue *get_const_field_variant(IrAnalyze *ira, ConstExprValue *struct_value,
22294 const char *name, size_t field_index)
22296static Error get_const_field_sentinel(IrAnalyze *ira, IrInstruction *source_instr, ConstExprValue *struct_value,
22297 const char *name, size_t field_index, ZigType *elem_type, ConstExprValue **result)
2229522298{
2229622299 ConstExprValue *field_val = get_const_field(ira, struct_value, name, field_index);
22297 assert(field_val->type->id == ZigTypeIdOptional);
22298 ConstExprValue *opt_val = field_val->data.x_optional;
22299 if (opt_val == nullptr) return nullptr;
22300 assert(opt_val->type->id == ZigTypeIdPointer);
22301 return const_ptr_pointee_unchecked(ira->codegen, opt_val);
22300 IrInstruction *field_inst = ir_const(ira, source_instr, field_val->type);
22301 IrInstruction *casted_field_inst = ir_implicit_cast(ira, field_inst,
22302 get_optional_type(ira->codegen, elem_type));
22303 if (type_is_invalid(casted_field_inst->value.type))
22304 return ErrorSemanticAnalyzeFail;
22305
22306 *result = casted_field_inst->value.data.x_optional;
22307 return ErrorNone;
2230222308}
2230322309
2230422310static bool get_const_field_bool(IrAnalyze *ira, ConstExprValue *struct_value, const char *name, size_t field_index)
......@@ -22323,6 +22329,7 @@ static ZigType *get_const_field_meta_type(IrAnalyze *ira, ConstExprValue *struct
2232322329}
2232422330
2232522331static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, ZigTypeId tagTypeId, ConstExprValue *payload) {
22332 Error err;
2232622333 switch (tagTypeId) {
2232722334 case ZigTypeIdInvalid:
2232822335 zig_unreachable();
......@@ -22364,8 +22371,16 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi
2236422371 assert(size_value->type == ir_type_info_get_type(ira, "Size", type_info_pointer_type));
2236522372 BuiltinPtrSize size_enum_index = (BuiltinPtrSize)bigint_as_u32(&size_value->data.x_enum_tag);
2236622373 PtrLen ptr_len = size_enum_index_to_ptr_len(size_enum_index);
22374 ZigType *elem_type = get_const_field_meta_type(ira, payload, "child", 4);
22375 ConstExprValue *sentinel;
22376 if ((err = get_const_field_sentinel(ira, instruction, payload, "sentinel", 6,
22377 elem_type, &sentinel)))
22378 {
22379 return nullptr;
22380 }
22381
2236722382 ZigType *ptr_type = get_pointer_to_type_extra2(ira->codegen,
22368 get_const_field_meta_type(ira, payload, "child", 4),
22383 elem_type,
2236922384 get_const_field_bool(ira, payload, "is_const", 1),
2237022385 get_const_field_bool(ira, payload, "is_volatile", 2),
2237122386 ptr_len,
......@@ -22373,22 +22388,26 @@ static ZigType *type_info_to_type(IrAnalyze *ira, IrInstruction *instruction, Zi
2237322388 0, // bit_offset_in_host
2237422389 0, // host_int_bytes
2237522390 get_const_field_bool(ira, payload, "is_allowzero", 5),
22376 VECTOR_INDEX_NONE,
22377 nullptr,
22378 get_const_field_variant(ira, payload, "sentinel", 6)
22379 );
22391 VECTOR_INDEX_NONE, nullptr, sentinel);
2238022392 if (size_enum_index != 2)
2238122393 return ptr_type;
2238222394 return get_slice_type(ira->codegen, ptr_type);
2238322395 }
22384 case ZigTypeIdArray:
22396 case ZigTypeIdArray: {
2238522397 assert(payload->special == ConstValSpecialStatic);
2238622398 assert(payload->type == ir_type_info_get_type(ira, "Array", nullptr));
22399 ZigType *elem_type = get_const_field_meta_type(ira, payload, "child", 1);
22400 ConstExprValue *sentinel;
22401 if ((err = get_const_field_sentinel(ira, instruction, payload, "sentinel", 2,
22402 elem_type, &sentinel)))
22403 {
22404 return nullptr;
22405 }
2238722406 return get_array_type(ira->codegen,
22388 get_const_field_meta_type(ira, payload, "child", 1),
22407 elem_type,
2238922408 bigint_as_u64(get_const_field_lit_int(ira, payload, "len", 0)),
22390 get_const_field_variant(ira, payload, "sentinel", 2)
22391 );
22409 sentinel);
22410 }
2239222411 case ZigTypeIdComptimeFloat:
2239322412 return ira->codegen->builtin_types.entry_num_lit_float;
2239422413 case ZigTypeIdComptimeInt:
src/parser.cpp+7-1
......@@ -848,7 +848,12 @@ static AstNode *ast_parse_container_field(ParseContext *pc) {
848848
849849 AstNode *type_expr = nullptr;
850850 if (eat_token_if(pc, TokenIdColon) != nullptr) {
851 type_expr = ast_expect(pc, ast_parse_type_expr);
851 Token *var_tok = eat_token_if(pc, TokenIdKeywordVar);
852 if (var_tok != nullptr) {
853 type_expr = ast_create_node(pc, NodeTypeVarFieldType, var_tok);
854 } else {
855 type_expr = ast_expect(pc, ast_parse_type_expr);
856 }
852857 }
853858 AstNode *align_expr = ast_parse_byte_align(pc);
854859 AstNode *expr = nullptr;
......@@ -3163,6 +3168,7 @@ void ast_visit_node_children(AstNode *node, void (*visit)(AstNode **, void *cont
31633168 visit_field(&node->data.suspend.block, visit, context);
31643169 break;
31653170 case NodeTypeEnumLiteral:
3171 case NodeTypeVarFieldType:
31663172 break;
31673173 }
31683174}
test/stage1/behavior/type.zig+1-1
......@@ -112,7 +112,7 @@ test "Type.Array" {
112112 .Array = TypeInfo.Array{
113113 .len = 2,
114114 .child = u32,
115 .sentinel = &0,
115 .sentinel = 0,
116116 },
117117 }));
118118 testTypes([_]type{ [1]u8, [30]usize, [7]bool });
test/stage1/behavior/type_info.zig+3-3
......@@ -46,7 +46,7 @@ fn testPointer() void {
4646 expect(u32_ptr_info.Pointer.is_volatile == false);
4747 expect(u32_ptr_info.Pointer.alignment == @alignOf(u32));
4848 expect(u32_ptr_info.Pointer.child == u32);
49 expect(u32_ptr_info.Pointer.is_null_terminated == false);
49 expect(u32_ptr_info.Pointer.sentinel == null);
5050}
5151
5252test "type info: unknown length pointer type info" {
......@@ -60,7 +60,7 @@ fn testUnknownLenPtr() void {
6060 expect(u32_ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
6161 expect(u32_ptr_info.Pointer.is_const == true);
6262 expect(u32_ptr_info.Pointer.is_volatile == true);
63 expect(u32_ptr_info.Pointer.is_null_terminated == false);
63 expect(u32_ptr_info.Pointer.sentinel == null);
6464 expect(u32_ptr_info.Pointer.alignment == @alignOf(f64));
6565 expect(u32_ptr_info.Pointer.child == f64);
6666}
......@@ -76,7 +76,7 @@ fn testNullTerminatedPtr() void {
7676 expect(ptr_info.Pointer.size == TypeInfo.Pointer.Size.Many);
7777 expect(ptr_info.Pointer.is_const == false);
7878 expect(ptr_info.Pointer.is_volatile == false);
79 expect(ptr_info.Pointer.is_null_terminated == true);
79 expect(ptr_info.Pointer.sentinel.? == 0);
8080
8181 expect(@typeInfo([:0]u8).Pointer.sentinel != null);
8282 expect(@typeInfo([10:0]u8).Array.sentinel != null);