authorgravatar for thatlemon@gmail.comLemonBoy <thatlemon@gmail.com> 2019-12-08 17:38:03+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-12-08 17:29:59-05:00
logd5e788072d8b207334c0eab0f1289317a55c9344
tree66fe3803e92c7926732f96f3c98c40f9f8ee4799
parent1cb19d1a461d5181c8e367cdd863720e5e695823
signature Commit is signed but in an unrecognized format.

Make array types (quasi-)lazy

Fixes #3843

4 files changed, 131 insertions(+), 58 deletions(-)

src/all_types.hpp+10
...@@ -322,6 +322,7 @@ enum LazyValueId {...@@ -322,6 +322,7 @@ enum LazyValueId {
322 LazyValueIdSliceType,322 LazyValueIdSliceType,
323 LazyValueIdFnType,323 LazyValueIdFnType,
324 LazyValueIdErrUnionType,324 LazyValueIdErrUnionType,
325 LazyValueIdArrayType,
325};326};
326327
327struct LazyValue {328struct LazyValue {
...@@ -355,6 +356,15 @@ struct LazyValueSliceType {...@@ -355,6 +356,15 @@ struct LazyValueSliceType {
355 bool is_allowzero;356 bool is_allowzero;
356};357};
357358
359struct LazyValueArrayType {
360 LazyValue base;
361
362 IrAnalyze *ira;
363 IrInstruction *sentinel; // can be null
364 IrInstruction *elem_type;
365 uint64_t length;
366};
367
358struct LazyValuePtrType {368struct LazyValuePtrType {
359 LazyValue base;369 LazyValue base;
360370
src/analyze.cpp+33
...@@ -1147,6 +1147,21 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent...@@ -1147,6 +1147,21 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent
1147 parent_type_val, is_zero_bits);1147 parent_type_val, is_zero_bits);
1148 }1148 }
1149 }1149 }
1150 case LazyValueIdArrayType: {
1151 LazyValueArrayType *lazy_array_type =
1152 reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
1153
1154 if (lazy_array_type->length < 1) {
1155 *is_zero_bits = true;
1156 return ErrorNone;
1157 }
1158
1159 if ((err = type_val_resolve_zero_bits(g, lazy_array_type->elem_type->value,
1160 parent_type, nullptr, is_zero_bits)))
1161 return err;
1162
1163 return ErrorNone;
1164 }
1150 case LazyValueIdOptType:1165 case LazyValueIdOptType:
1151 case LazyValueIdSliceType:1166 case LazyValueIdSliceType:
1152 case LazyValueIdErrUnionType:1167 case LazyValueIdErrUnionType:
...@@ -1181,6 +1196,7 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ZigValue *type_val, bool *is_o...@@ -1181,6 +1196,7 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ZigValue *type_val, bool *is_o
1181 case LazyValueIdFnType:1196 case LazyValueIdFnType:
1182 case LazyValueIdOptType:1197 case LazyValueIdOptType:
1183 case LazyValueIdErrUnionType:1198 case LazyValueIdErrUnionType:
1199 case LazyValueIdArrayType:
1184 *is_opaque_type = false;1200 *is_opaque_type = false;
1185 return ErrorNone;1201 return ErrorNone;
1186 }1202 }
...@@ -1208,6 +1224,10 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ZigValue *type...@@ -1208,6 +1224,10 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ZigValue *type
1208 LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);1224 LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);
1209 return type_val_resolve_requires_comptime(g, lazy_opt_type->payload_type->value);1225 return type_val_resolve_requires_comptime(g, lazy_opt_type->payload_type->value);
1210 }1226 }
1227 case LazyValueIdArrayType: {
1228 LazyValueArrayType *lazy_array_type = reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
1229 return type_val_resolve_requires_comptime(g, lazy_array_type->elem_type->value);
1230 }
1211 case LazyValueIdFnType: {1231 case LazyValueIdFnType: {
1212 LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(type_val->data.x_lazy);1232 LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(type_val->data.x_lazy);
1213 if (lazy_fn_type->is_generic)1233 if (lazy_fn_type->is_generic)
...@@ -1305,6 +1325,7 @@ start_over:...@@ -1305,6 +1325,7 @@ start_over:
1305 return ErrorNone;1325 return ErrorNone;
1306 case LazyValueIdOptType:1326 case LazyValueIdOptType:
1307 case LazyValueIdErrUnionType:1327 case LazyValueIdErrUnionType:
1328 case LazyValueIdArrayType:
1308 if ((err = ir_resolve_lazy(g, source_node, type_val)))1329 if ((err = ir_resolve_lazy(g, source_node, type_val)))
1309 return err;1330 return err;
1310 goto start_over;1331 goto start_over;
...@@ -1340,6 +1361,11 @@ Error type_val_resolve_abi_align(CodeGen *g, ZigValue *type_val, uint32_t *abi_a...@@ -1340,6 +1361,11 @@ Error type_val_resolve_abi_align(CodeGen *g, ZigValue *type_val, uint32_t *abi_a
1340 LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);1361 LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);
1341 return type_val_resolve_abi_align(g, lazy_opt_type->payload_type->value, abi_align);1362 return type_val_resolve_abi_align(g, lazy_opt_type->payload_type->value, abi_align);
1342 }1363 }
1364 case LazyValueIdArrayType: {
1365 LazyValueArrayType *lazy_array_type =
1366 reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
1367 return type_val_resolve_abi_align(g, lazy_array_type->elem_type->value, abi_align);
1368 }
1343 case LazyValueIdErrUnionType: {1369 case LazyValueIdErrUnionType: {
1344 LazyValueErrUnionType *lazy_err_union_type =1370 LazyValueErrUnionType *lazy_err_union_type =
1345 reinterpret_cast<LazyValueErrUnionType *>(type_val->data.x_lazy);1371 reinterpret_cast<LazyValueErrUnionType *>(type_val->data.x_lazy);
...@@ -1370,6 +1396,13 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV...@@ -1370,6 +1396,13 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV
1370 case LazyValueIdOptType: // it has the optional bit1396 case LazyValueIdOptType: // it has the optional bit
1371 case LazyValueIdFnType:1397 case LazyValueIdFnType:
1372 return OnePossibleValueNo;1398 return OnePossibleValueNo;
1399 case LazyValueIdArrayType: {
1400 LazyValueArrayType *lazy_array_type =
1401 reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
1402 if (lazy_array_type->length < 1)
1403 return OnePossibleValueYes;
1404 return type_val_resolve_has_one_possible_value(g, lazy_array_type->elem_type->value);
1405 }
1373 case LazyValueIdPtrType: {1406 case LazyValueIdPtrType: {
1374 Error err;1407 Error err;
1375 bool zero_bits;1408 bool zero_bits;
src/ir.cpp+79-58
...@@ -20551,73 +20551,28 @@ static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAs...@@ -20551,73 +20551,28 @@ static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAs
20551static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,20551static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
20552 IrInstructionArrayType *array_type_instruction)20552 IrInstructionArrayType *array_type_instruction)
20553{20553{
20554 Error err;20554 IrInstruction *result = ir_const(ira, &array_type_instruction->base, ira->codegen->builtin_types.entry_type);
20555 result->value->special = ConstValSpecialLazy;
20556
20557 LazyValueArrayType *lazy_array_type = allocate<LazyValueArrayType>(1, "LazyValueArrayType");
20558 lazy_array_type->ira = ira; ira_ref(ira);
20559 result->value->data.x_lazy = &lazy_array_type->base;
20560 lazy_array_type->base.id = LazyValueIdArrayType;
2055520561
20556 IrInstruction *size_value = array_type_instruction->size->child;20562 lazy_array_type->elem_type = array_type_instruction->child_type->child;
20557 uint64_t size;20563 if (ir_resolve_type_lazy(ira, lazy_array_type->elem_type) == nullptr)
20558 if (!ir_resolve_usize(ira, size_value, &size))
20559 return ira->codegen->invalid_instruction;20564 return ira->codegen->invalid_instruction;
2056020565
20561 IrInstruction *child_type_value = array_type_instruction->child_type->child;20566 if (!ir_resolve_usize(ira, array_type_instruction->size->child, &lazy_array_type->length))
20562 ZigType *child_type = ir_resolve_type(ira, child_type_value);
20563 if (type_is_invalid(child_type))
20564 return ira->codegen->invalid_instruction;20567 return ira->codegen->invalid_instruction;
2056520568
20566 ZigValue *sentinel_val;
20567 if (array_type_instruction->sentinel != nullptr) {20569 if (array_type_instruction->sentinel != nullptr) {
20568 IrInstruction *uncasted_sentinel = array_type_instruction->sentinel->child;20570 lazy_array_type->sentinel = array_type_instruction->sentinel->child;
20569 if (type_is_invalid(uncasted_sentinel->value->type))20571 if (ir_resolve_const(ira, lazy_array_type->sentinel, LazyOk) == nullptr)
20570 return ira->codegen->invalid_instruction;
20571 IrInstruction *sentinel = ir_implicit_cast(ira, uncasted_sentinel, child_type);
20572 if (type_is_invalid(sentinel->value->type))
20573 return ira->codegen->invalid_instruction;
20574 sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);
20575 if (sentinel_val == nullptr)
20576 return ira->codegen->invalid_instruction;20572 return ira->codegen->invalid_instruction;
20577 } else {
20578 sentinel_val = nullptr;
20579 }20573 }
2058020574
20581 switch (child_type->id) {20575 return result;
20582 case ZigTypeIdInvalid: // handled above
20583 zig_unreachable();
20584 case ZigTypeIdUnreachable:
20585 case ZigTypeIdUndefined:
20586 case ZigTypeIdNull:
20587 case ZigTypeIdArgTuple:
20588 case ZigTypeIdOpaque:
20589 ir_add_error_node(ira, array_type_instruction->base.source_node,
20590 buf_sprintf("array of type '%s' not allowed", buf_ptr(&child_type->name)));
20591 return ira->codegen->invalid_instruction;
20592 case ZigTypeIdMetaType:
20593 case ZigTypeIdVoid:
20594 case ZigTypeIdBool:
20595 case ZigTypeIdInt:
20596 case ZigTypeIdFloat:
20597 case ZigTypeIdPointer:
20598 case ZigTypeIdArray:
20599 case ZigTypeIdStruct:
20600 case ZigTypeIdComptimeFloat:
20601 case ZigTypeIdComptimeInt:
20602 case ZigTypeIdEnumLiteral:
20603 case ZigTypeIdOptional:
20604 case ZigTypeIdErrorUnion:
20605 case ZigTypeIdErrorSet:
20606 case ZigTypeIdEnum:
20607 case ZigTypeIdUnion:
20608 case ZigTypeIdFn:
20609 case ZigTypeIdBoundFn:
20610 case ZigTypeIdVector:
20611 case ZigTypeIdFnFrame:
20612 case ZigTypeIdAnyFrame:
20613 {
20614 if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown)))
20615 return ira->codegen->invalid_instruction;
20616 ZigType *result_type = get_array_type(ira->codegen, child_type, size, sentinel_val);
20617 return ir_const_type(ira, &array_type_instruction->base, result_type);
20618 }
20619 }
20620 zig_unreachable();
20621}20576}
2062220577
20623static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, IrInstructionSizeOf *instruction) {20578static IrInstruction *ir_analyze_instruction_size_of(IrAnalyze *ira, IrInstructionSizeOf *instruction) {
...@@ -29016,6 +28971,72 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) {...@@ -29016,6 +28971,72 @@ static Error ir_resolve_lazy_raw(AstNode *source_node, ZigValue *val) {
29016 // We can't free the lazy value here, because multiple other ZigValues might be pointing to it.28971 // We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
29017 return ErrorNone;28972 return ErrorNone;
29018 }28973 }
28974 case LazyValueIdArrayType: {
28975 LazyValueArrayType *lazy_array_type = reinterpret_cast<LazyValueArrayType *>(val->data.x_lazy);
28976 IrAnalyze *ira = lazy_array_type->ira;
28977
28978 ZigType *elem_type = ir_resolve_type(ira, lazy_array_type->elem_type);
28979 if (type_is_invalid(elem_type))
28980 return ErrorSemanticAnalyzeFail;
28981
28982 switch (elem_type->id) {
28983 case ZigTypeIdInvalid: // handled above
28984 zig_unreachable();
28985 case ZigTypeIdUnreachable:
28986 case ZigTypeIdUndefined:
28987 case ZigTypeIdNull:
28988 case ZigTypeIdArgTuple:
28989 case ZigTypeIdOpaque:
28990 ir_add_error(ira, lazy_array_type->elem_type,
28991 buf_sprintf("array of type '%s' not allowed",
28992 buf_ptr(&elem_type->name)));
28993 return ErrorSemanticAnalyzeFail;
28994 case ZigTypeIdMetaType:
28995 case ZigTypeIdVoid:
28996 case ZigTypeIdBool:
28997 case ZigTypeIdInt:
28998 case ZigTypeIdFloat:
28999 case ZigTypeIdPointer:
29000 case ZigTypeIdArray:
29001 case ZigTypeIdStruct:
29002 case ZigTypeIdComptimeFloat:
29003 case ZigTypeIdComptimeInt:
29004 case ZigTypeIdEnumLiteral:
29005 case ZigTypeIdOptional:
29006 case ZigTypeIdErrorUnion:
29007 case ZigTypeIdErrorSet:
29008 case ZigTypeIdEnum:
29009 case ZigTypeIdUnion:
29010 case ZigTypeIdFn:
29011 case ZigTypeIdBoundFn:
29012 case ZigTypeIdVector:
29013 case ZigTypeIdFnFrame:
29014 case ZigTypeIdAnyFrame:
29015 break;
29016 }
29017
29018 if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
29019 return err;
29020
29021 ZigValue *sentinel_val = nullptr;
29022 if (lazy_array_type->sentinel != nullptr) {
29023 if (type_is_invalid(lazy_array_type->sentinel->value->type))
29024 return ErrorSemanticAnalyzeFail;
29025 IrInstruction *sentinel = ir_implicit_cast(ira, lazy_array_type->sentinel, elem_type);
29026 if (type_is_invalid(sentinel->value->type))
29027 return ErrorSemanticAnalyzeFail;
29028 sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);
29029 if (sentinel_val == nullptr)
29030 return ErrorSemanticAnalyzeFail;
29031 }
29032
29033 assert(val->type->id == ZigTypeIdMetaType);
29034 val->data.x_type = get_array_type(ira->codegen, elem_type, lazy_array_type->length, sentinel_val);
29035 val->special = ConstValSpecialStatic;
29036
29037 // We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
29038 return ErrorNone;
29039 }
29019 case LazyValueIdOptType: {29040 case LazyValueIdOptType: {
29020 LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(val->data.x_lazy);29041 LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(val->data.x_lazy);
29021 IrAnalyze *ira = lazy_opt_type->ira;29042 IrAnalyze *ira = lazy_opt_type->ira;
test/stage1/behavior/struct.zig+9
...@@ -813,3 +813,12 @@ test "anon struct literal field value initialized with fn call" {...@@ -813,3 +813,12 @@ test "anon struct literal field value initialized with fn call" {
813 S.doTheTest();813 S.doTheTest();
814 comptime S.doTheTest();814 comptime S.doTheTest();
815}815}
816
817test "self-referencing struct via array member" {
818 const T = struct {
819 children: [1]*@This(),
820 };
821 var x: T = undefined;
822 x = T{ .children = .{&x} };
823 expect(x.children[0] == &x);
824}