Commit d5e788072d
Changed files (4)
test
stage1
behavior
src/all_types.hpp
@@ -322,6 +322,7 @@ enum LazyValueId {
LazyValueIdSliceType,
LazyValueIdFnType,
LazyValueIdErrUnionType,
+ LazyValueIdArrayType,
};
struct LazyValue {
@@ -355,6 +356,15 @@ struct LazyValueSliceType {
bool is_allowzero;
};
+struct LazyValueArrayType {
+ LazyValue base;
+
+ IrAnalyze *ira;
+ IrInstruction *sentinel; // can be null
+ IrInstruction *elem_type;
+ uint64_t length;
+};
+
struct LazyValuePtrType {
LazyValue base;
src/analyze.cpp
@@ -1147,6 +1147,21 @@ Error type_val_resolve_zero_bits(CodeGen *g, ZigValue *type_val, ZigType *parent
parent_type_val, is_zero_bits);
}
}
+ case LazyValueIdArrayType: {
+ LazyValueArrayType *lazy_array_type =
+ reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
+
+ if (lazy_array_type->length < 1) {
+ *is_zero_bits = true;
+ return ErrorNone;
+ }
+
+ if ((err = type_val_resolve_zero_bits(g, lazy_array_type->elem_type->value,
+ parent_type, nullptr, is_zero_bits)))
+ return err;
+
+ return ErrorNone;
+ }
case LazyValueIdOptType:
case LazyValueIdSliceType:
case LazyValueIdErrUnionType:
@@ -1181,6 +1196,7 @@ Error type_val_resolve_is_opaque_type(CodeGen *g, ZigValue *type_val, bool *is_o
case LazyValueIdFnType:
case LazyValueIdOptType:
case LazyValueIdErrUnionType:
+ case LazyValueIdArrayType:
*is_opaque_type = false;
return ErrorNone;
}
@@ -1208,6 +1224,10 @@ static ReqCompTime type_val_resolve_requires_comptime(CodeGen *g, ZigValue *type
LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);
return type_val_resolve_requires_comptime(g, lazy_opt_type->payload_type->value);
}
+ case LazyValueIdArrayType: {
+ LazyValueArrayType *lazy_array_type = reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
+ return type_val_resolve_requires_comptime(g, lazy_array_type->elem_type->value);
+ }
case LazyValueIdFnType: {
LazyValueFnType *lazy_fn_type = reinterpret_cast<LazyValueFnType *>(type_val->data.x_lazy);
if (lazy_fn_type->is_generic)
@@ -1305,6 +1325,7 @@ start_over:
return ErrorNone;
case LazyValueIdOptType:
case LazyValueIdErrUnionType:
+ case LazyValueIdArrayType:
if ((err = ir_resolve_lazy(g, source_node, type_val)))
return err;
goto start_over;
@@ -1340,6 +1361,11 @@ Error type_val_resolve_abi_align(CodeGen *g, ZigValue *type_val, uint32_t *abi_a
LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(type_val->data.x_lazy);
return type_val_resolve_abi_align(g, lazy_opt_type->payload_type->value, abi_align);
}
+ case LazyValueIdArrayType: {
+ LazyValueArrayType *lazy_array_type =
+ reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
+ return type_val_resolve_abi_align(g, lazy_array_type->elem_type->value, abi_align);
+ }
case LazyValueIdErrUnionType: {
LazyValueErrUnionType *lazy_err_union_type =
reinterpret_cast<LazyValueErrUnionType *>(type_val->data.x_lazy);
@@ -1370,6 +1396,13 @@ static OnePossibleValue type_val_resolve_has_one_possible_value(CodeGen *g, ZigV
case LazyValueIdOptType: // it has the optional bit
case LazyValueIdFnType:
return OnePossibleValueNo;
+ case LazyValueIdArrayType: {
+ LazyValueArrayType *lazy_array_type =
+ reinterpret_cast<LazyValueArrayType *>(type_val->data.x_lazy);
+ if (lazy_array_type->length < 1)
+ return OnePossibleValueYes;
+ return type_val_resolve_has_one_possible_value(g, lazy_array_type->elem_type->value);
+ }
case LazyValueIdPtrType: {
Error err;
bool zero_bits;
src/ir.cpp
@@ -20551,73 +20551,28 @@ static IrInstruction *ir_analyze_instruction_asm(IrAnalyze *ira, IrInstructionAs
static IrInstruction *ir_analyze_instruction_array_type(IrAnalyze *ira,
IrInstructionArrayType *array_type_instruction)
{
- Error err;
+ IrInstruction *result = ir_const(ira, &array_type_instruction->base, ira->codegen->builtin_types.entry_type);
+ result->value->special = ConstValSpecialLazy;
+
+ LazyValueArrayType *lazy_array_type = allocate<LazyValueArrayType>(1, "LazyValueArrayType");
+ lazy_array_type->ira = ira; ira_ref(ira);
+ result->value->data.x_lazy = &lazy_array_type->base;
+ lazy_array_type->base.id = LazyValueIdArrayType;
- IrInstruction *size_value = array_type_instruction->size->child;
- uint64_t size;
- if (!ir_resolve_usize(ira, size_value, &size))
+ lazy_array_type->elem_type = array_type_instruction->child_type->child;
+ if (ir_resolve_type_lazy(ira, lazy_array_type->elem_type) == nullptr)
return ira->codegen->invalid_instruction;
- IrInstruction *child_type_value = array_type_instruction->child_type->child;
- ZigType *child_type = ir_resolve_type(ira, child_type_value);
- if (type_is_invalid(child_type))
+ if (!ir_resolve_usize(ira, array_type_instruction->size->child, &lazy_array_type->length))
return ira->codegen->invalid_instruction;
- ZigValue *sentinel_val;
if (array_type_instruction->sentinel != nullptr) {
- IrInstruction *uncasted_sentinel = array_type_instruction->sentinel->child;
- if (type_is_invalid(uncasted_sentinel->value->type))
- return ira->codegen->invalid_instruction;
- IrInstruction *sentinel = ir_implicit_cast(ira, uncasted_sentinel, child_type);
- if (type_is_invalid(sentinel->value->type))
- return ira->codegen->invalid_instruction;
- sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);
- if (sentinel_val == nullptr)
+ lazy_array_type->sentinel = array_type_instruction->sentinel->child;
+ if (ir_resolve_const(ira, lazy_array_type->sentinel, LazyOk) == nullptr)
return ira->codegen->invalid_instruction;
- } else {
- sentinel_val = nullptr;
}
- switch (child_type->id) {
- case ZigTypeIdInvalid: // handled above
- zig_unreachable();
- case ZigTypeIdUnreachable:
- case ZigTypeIdUndefined:
- case ZigTypeIdNull:
- case ZigTypeIdArgTuple:
- case ZigTypeIdOpaque:
- ir_add_error_node(ira, array_type_instruction->base.source_node,
- buf_sprintf("array of type '%s' not allowed", buf_ptr(&child_type->name)));
- return ira->codegen->invalid_instruction;
- case ZigTypeIdMetaType:
- case ZigTypeIdVoid:
- case ZigTypeIdBool:
- case ZigTypeIdInt:
- case ZigTypeIdFloat:
- case ZigTypeIdPointer:
- case ZigTypeIdArray:
- case ZigTypeIdStruct:
- case ZigTypeIdComptimeFloat:
- case ZigTypeIdComptimeInt:
- case ZigTypeIdEnumLiteral:
- case ZigTypeIdOptional:
- case ZigTypeIdErrorUnion:
- case ZigTypeIdErrorSet:
- case ZigTypeIdEnum:
- case ZigTypeIdUnion:
- case ZigTypeIdFn:
- case ZigTypeIdBoundFn:
- case ZigTypeIdVector:
- case ZigTypeIdFnFrame:
- case ZigTypeIdAnyFrame:
- {
- if ((err = type_resolve(ira->codegen, child_type, ResolveStatusSizeKnown)))
- return ira->codegen->invalid_instruction;
- ZigType *result_type = get_array_type(ira->codegen, child_type, size, sentinel_val);
- return ir_const_type(ira, &array_type_instruction->base, result_type);
- }
- }
- zig_unreachable();
+ return result;
}
static 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) {
// We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
return ErrorNone;
}
+ case LazyValueIdArrayType: {
+ LazyValueArrayType *lazy_array_type = reinterpret_cast<LazyValueArrayType *>(val->data.x_lazy);
+ IrAnalyze *ira = lazy_array_type->ira;
+
+ ZigType *elem_type = ir_resolve_type(ira, lazy_array_type->elem_type);
+ if (type_is_invalid(elem_type))
+ return ErrorSemanticAnalyzeFail;
+
+ switch (elem_type->id) {
+ case ZigTypeIdInvalid: // handled above
+ zig_unreachable();
+ case ZigTypeIdUnreachable:
+ case ZigTypeIdUndefined:
+ case ZigTypeIdNull:
+ case ZigTypeIdArgTuple:
+ case ZigTypeIdOpaque:
+ ir_add_error(ira, lazy_array_type->elem_type,
+ buf_sprintf("array of type '%s' not allowed",
+ buf_ptr(&elem_type->name)));
+ return ErrorSemanticAnalyzeFail;
+ case ZigTypeIdMetaType:
+ case ZigTypeIdVoid:
+ case ZigTypeIdBool:
+ case ZigTypeIdInt:
+ case ZigTypeIdFloat:
+ case ZigTypeIdPointer:
+ case ZigTypeIdArray:
+ case ZigTypeIdStruct:
+ case ZigTypeIdComptimeFloat:
+ case ZigTypeIdComptimeInt:
+ case ZigTypeIdEnumLiteral:
+ case ZigTypeIdOptional:
+ case ZigTypeIdErrorUnion:
+ case ZigTypeIdErrorSet:
+ case ZigTypeIdEnum:
+ case ZigTypeIdUnion:
+ case ZigTypeIdFn:
+ case ZigTypeIdBoundFn:
+ case ZigTypeIdVector:
+ case ZigTypeIdFnFrame:
+ case ZigTypeIdAnyFrame:
+ break;
+ }
+
+ if ((err = type_resolve(ira->codegen, elem_type, ResolveStatusSizeKnown)))
+ return err;
+
+ ZigValue *sentinel_val = nullptr;
+ if (lazy_array_type->sentinel != nullptr) {
+ if (type_is_invalid(lazy_array_type->sentinel->value->type))
+ return ErrorSemanticAnalyzeFail;
+ IrInstruction *sentinel = ir_implicit_cast(ira, lazy_array_type->sentinel, elem_type);
+ if (type_is_invalid(sentinel->value->type))
+ return ErrorSemanticAnalyzeFail;
+ sentinel_val = ir_resolve_const(ira, sentinel, UndefBad);
+ if (sentinel_val == nullptr)
+ return ErrorSemanticAnalyzeFail;
+ }
+
+ assert(val->type->id == ZigTypeIdMetaType);
+ val->data.x_type = get_array_type(ira->codegen, elem_type, lazy_array_type->length, sentinel_val);
+ val->special = ConstValSpecialStatic;
+
+ // We can't free the lazy value here, because multiple other ZigValues might be pointing to it.
+ return ErrorNone;
+ }
case LazyValueIdOptType: {
LazyValueOptType *lazy_opt_type = reinterpret_cast<LazyValueOptType *>(val->data.x_lazy);
IrAnalyze *ira = lazy_opt_type->ira;
test/stage1/behavior/struct.zig
@@ -813,3 +813,12 @@ test "anon struct literal field value initialized with fn call" {
S.doTheTest();
comptime S.doTheTest();
}
+
+test "self-referencing struct via array member" {
+ const T = struct {
+ children: [1]*@This(),
+ };
+ var x: T = undefined;
+ x = T{ .children = .{&x} };
+ expect(x.children[0] == &x);
+}