mirror of
https://github.com/ziglang/zig.git
synced 2026-02-16 14:28:57 +00:00
implement anon struct literal syntax
This implements stage1 parser support for anonymous struct literal syntax (see #685), as well as semantic analysis support for anonymous struct literals and anonymous list literals (see #208). The semantic analysis works when there is a type coercion in the result location; inferring the struct type based on the values in the literal is not implemented yet. Also remaining to do is zig fmt support for this new syntax and documentation updates.
This commit is contained in:
parent
de30438ed2
commit
5b27943498
@ -90,40 +90,11 @@ pub const Mode = enum {
|
||||
ReleaseSmall,
|
||||
};
|
||||
|
||||
/// This data structure is used by the Zig language code generation and
|
||||
/// therefore must be kept in sync with the compiler implementation.
|
||||
pub const TypeId = enum {
|
||||
Type,
|
||||
Void,
|
||||
Bool,
|
||||
NoReturn,
|
||||
Int,
|
||||
Float,
|
||||
Pointer,
|
||||
Array,
|
||||
Struct,
|
||||
ComptimeFloat,
|
||||
ComptimeInt,
|
||||
Undefined,
|
||||
Null,
|
||||
Optional,
|
||||
ErrorUnion,
|
||||
ErrorSet,
|
||||
Enum,
|
||||
Union,
|
||||
Fn,
|
||||
BoundFn,
|
||||
ArgTuple,
|
||||
Opaque,
|
||||
Frame,
|
||||
AnyFrame,
|
||||
Vector,
|
||||
EnumLiteral,
|
||||
};
|
||||
pub const TypeId = @TagType(TypeInfo);
|
||||
|
||||
/// This data structure is used by the Zig language code generation and
|
||||
/// therefore must be kept in sync with the compiler implementation.
|
||||
pub const TypeInfo = union(TypeId) {
|
||||
pub const TypeInfo = union(enum) {
|
||||
Type: void,
|
||||
Void: void,
|
||||
Bool: void,
|
||||
|
||||
@ -1237,6 +1237,7 @@ struct TypeStructField {
|
||||
enum ResolveStatus {
|
||||
ResolveStatusUnstarted,
|
||||
ResolveStatusInvalid,
|
||||
ResolveStatusBeingInferred,
|
||||
ResolveStatusZeroBitsKnown,
|
||||
ResolveStatusAlignmentKnown,
|
||||
ResolveStatusSizeKnown,
|
||||
@ -1285,6 +1286,7 @@ struct ZigTypeStruct {
|
||||
bool requires_comptime;
|
||||
bool resolve_loop_flag_zero_bits;
|
||||
bool resolve_loop_flag_other;
|
||||
bool is_inferred;
|
||||
};
|
||||
|
||||
struct ZigTypeOptional {
|
||||
@ -2812,7 +2814,7 @@ struct IrInstructionElemPtr {
|
||||
|
||||
IrInstruction *array_ptr;
|
||||
IrInstruction *elem_index;
|
||||
IrInstruction *init_array_type;
|
||||
AstNode *init_array_type_source_node;
|
||||
PtrLen ptr_len;
|
||||
bool safety_check_on;
|
||||
};
|
||||
@ -2909,11 +2911,11 @@ struct IrInstructionResizeSlice {
|
||||
struct IrInstructionContainerInitList {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *container_type;
|
||||
IrInstruction *elem_type;
|
||||
size_t item_count;
|
||||
IrInstruction **elem_result_loc_list;
|
||||
IrInstruction *result_loc;
|
||||
AstNode *init_array_type_source_node;
|
||||
};
|
||||
|
||||
struct IrInstructionContainerInitFieldsField {
|
||||
@ -2926,7 +2928,6 @@ struct IrInstructionContainerInitFieldsField {
|
||||
struct IrInstructionContainerInitFields {
|
||||
IrInstruction base;
|
||||
|
||||
IrInstruction *container_type;
|
||||
size_t field_count;
|
||||
IrInstructionContainerInitFieldsField *fields;
|
||||
IrInstruction *result_loc;
|
||||
|
||||
@ -140,7 +140,6 @@ void init_scope(CodeGen *g, Scope *dest, ScopeId id, AstNode *source_node, Scope
|
||||
static ScopeDecls *create_decls_scope(CodeGen *g, AstNode *node, Scope *parent, ZigType *container_type,
|
||||
ZigType *import, Buf *bare_name)
|
||||
{
|
||||
assert(node == nullptr || node->type == NodeTypeContainerDecl || node->type == NodeTypeFnCallExpr);
|
||||
ScopeDecls *scope = allocate<ScopeDecls>(1);
|
||||
init_scope(g, &scope->base, ScopeIdDecls, node, parent);
|
||||
scope->decl_table.init(4);
|
||||
@ -346,6 +345,8 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
|
||||
switch (status) {
|
||||
case ResolveStatusInvalid:
|
||||
zig_unreachable();
|
||||
case ResolveStatusBeingInferred:
|
||||
zig_unreachable();
|
||||
case ResolveStatusUnstarted:
|
||||
case ResolveStatusZeroBitsKnown:
|
||||
return true;
|
||||
@ -362,6 +363,8 @@ bool type_is_resolved(ZigType *type_entry, ResolveStatus status) {
|
||||
switch (status) {
|
||||
case ResolveStatusInvalid:
|
||||
zig_unreachable();
|
||||
case ResolveStatusBeingInferred:
|
||||
zig_unreachable();
|
||||
case ResolveStatusUnstarted:
|
||||
return true;
|
||||
case ResolveStatusZeroBitsKnown:
|
||||
@ -6132,6 +6135,8 @@ static Error resolve_async_frame(CodeGen *g, ZigType *frame_type) {
|
||||
continue;
|
||||
if (instruction->ref_count == 0)
|
||||
continue;
|
||||
if ((err = type_resolve(g, instruction->value.type, ResolveStatusZeroBitsKnown)))
|
||||
return ErrorSemanticAnalyzeFail;
|
||||
if (!type_has_bits(instruction->value.type))
|
||||
continue;
|
||||
if (scope_needs_spill(instruction->scope)) {
|
||||
@ -6271,6 +6276,8 @@ Error type_resolve(CodeGen *g, ZigType *ty, ResolveStatus status) {
|
||||
switch (status) {
|
||||
case ResolveStatusUnstarted:
|
||||
return ErrorNone;
|
||||
case ResolveStatusBeingInferred:
|
||||
zig_unreachable();
|
||||
case ResolveStatusInvalid:
|
||||
zig_unreachable();
|
||||
case ResolveStatusZeroBitsKnown:
|
||||
@ -9038,4 +9045,3 @@ Error analyze_import(CodeGen *g, ZigType *source_import, Buf *import_target_str,
|
||||
*out_import = add_source_file(g, target_package, resolved_path, import_code, source_kind);
|
||||
return ErrorNone;
|
||||
}
|
||||
|
||||
|
||||
@ -821,7 +821,9 @@ static void render_node_extra(AstRender *ar, AstNode *node, bool grouped) {
|
||||
break;
|
||||
}
|
||||
case NodeTypeContainerInitExpr:
|
||||
render_node_ungrouped(ar, node->data.container_init_expr.type);
|
||||
if (node->data.container_init_expr.type != nullptr) {
|
||||
render_node_ungrouped(ar, node->data.container_init_expr.type);
|
||||
}
|
||||
if (node->data.container_init_expr.kind == ContainerInitKindStruct) {
|
||||
fprintf(ar->f, "{\n");
|
||||
ar->indent += ar->indent_size;
|
||||
|
||||
204
src/ir.cpp
204
src/ir.cpp
@ -1350,18 +1350,17 @@ static IrInstruction *ir_build_return_ptr(IrAnalyze *ira, IrInstruction *source_
|
||||
|
||||
static IrInstruction *ir_build_elem_ptr(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||
IrInstruction *array_ptr, IrInstruction *elem_index, bool safety_check_on, PtrLen ptr_len,
|
||||
IrInstruction *init_array_type)
|
||||
AstNode *init_array_type_source_node)
|
||||
{
|
||||
IrInstructionElemPtr *instruction = ir_build_instruction<IrInstructionElemPtr>(irb, scope, source_node);
|
||||
instruction->array_ptr = array_ptr;
|
||||
instruction->elem_index = elem_index;
|
||||
instruction->safety_check_on = safety_check_on;
|
||||
instruction->ptr_len = ptr_len;
|
||||
instruction->init_array_type = init_array_type;
|
||||
instruction->init_array_type_source_node = init_array_type_source_node;
|
||||
|
||||
ir_ref_instruction(array_ptr, irb->current_basic_block);
|
||||
ir_ref_instruction(elem_index, irb->current_basic_block);
|
||||
if (init_array_type != nullptr) ir_ref_instruction(init_array_type, irb->current_basic_block);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
@ -1575,17 +1574,16 @@ static IrInstruction *ir_build_un_op(IrBuilder *irb, Scope *scope, AstNode *sour
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||
IrInstruction *container_type, size_t item_count, IrInstruction **elem_result_loc_list,
|
||||
IrInstruction *result_loc)
|
||||
size_t item_count, IrInstruction **elem_result_loc_list, IrInstruction *result_loc,
|
||||
AstNode *init_array_type_source_node)
|
||||
{
|
||||
IrInstructionContainerInitList *container_init_list_instruction =
|
||||
ir_build_instruction<IrInstructionContainerInitList>(irb, scope, source_node);
|
||||
container_init_list_instruction->container_type = container_type;
|
||||
container_init_list_instruction->item_count = item_count;
|
||||
container_init_list_instruction->elem_result_loc_list = elem_result_loc_list;
|
||||
container_init_list_instruction->result_loc = result_loc;
|
||||
container_init_list_instruction->init_array_type_source_node = init_array_type_source_node;
|
||||
|
||||
ir_ref_instruction(container_type, irb->current_basic_block);
|
||||
for (size_t i = 0; i < item_count; i += 1) {
|
||||
ir_ref_instruction(elem_result_loc_list[i], irb->current_basic_block);
|
||||
}
|
||||
@ -1595,17 +1593,14 @@ static IrInstruction *ir_build_container_init_list(IrBuilder *irb, Scope *scope,
|
||||
}
|
||||
|
||||
static IrInstruction *ir_build_container_init_fields(IrBuilder *irb, Scope *scope, AstNode *source_node,
|
||||
IrInstruction *container_type, size_t field_count, IrInstructionContainerInitFieldsField *fields,
|
||||
IrInstruction *result_loc)
|
||||
size_t field_count, IrInstructionContainerInitFieldsField *fields, IrInstruction *result_loc)
|
||||
{
|
||||
IrInstructionContainerInitFields *container_init_fields_instruction =
|
||||
ir_build_instruction<IrInstructionContainerInitFields>(irb, scope, source_node);
|
||||
container_init_fields_instruction->container_type = container_type;
|
||||
container_init_fields_instruction->field_count = field_count;
|
||||
container_init_fields_instruction->fields = fields;
|
||||
container_init_fields_instruction->result_loc = result_loc;
|
||||
|
||||
ir_ref_instruction(container_type, irb->current_basic_block);
|
||||
for (size_t i = 0; i < field_count; i += 1) {
|
||||
ir_ref_instruction(fields[i].result_loc, irb->current_basic_block);
|
||||
}
|
||||
@ -3084,7 +3079,7 @@ static IrInstruction *ir_build_resolve_result(IrBuilder *irb, Scope *scope, AstN
|
||||
instruction->result_loc = result_loc;
|
||||
instruction->ty = ty;
|
||||
|
||||
ir_ref_instruction(ty, irb->current_basic_block);
|
||||
if (ty != nullptr) ir_ref_instruction(ty, irb->current_basic_block);
|
||||
|
||||
return &instruction->base;
|
||||
}
|
||||
@ -6127,28 +6122,42 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
|
||||
AstNodeContainerInitExpr *container_init_expr = &node->data.container_init_expr;
|
||||
ContainerInitKind kind = container_init_expr->kind;
|
||||
|
||||
IrInstruction *container_type = nullptr;
|
||||
IrInstruction *elem_type = nullptr;
|
||||
if (container_init_expr->type->type == NodeTypeInferredArrayType) {
|
||||
elem_type = ir_gen_node(irb, container_init_expr->type->data.inferred_array_type.child_type, scope);
|
||||
if (elem_type == irb->codegen->invalid_instruction)
|
||||
return elem_type;
|
||||
} else {
|
||||
container_type = ir_gen_node(irb, container_init_expr->type, scope);
|
||||
if (container_type == irb->codegen->invalid_instruction)
|
||||
return container_type;
|
||||
}
|
||||
|
||||
switch (kind) {
|
||||
case ContainerInitKindStruct: {
|
||||
if (elem_type != nullptr) {
|
||||
ResultLocCast *result_loc_cast = nullptr;
|
||||
ResultLoc *child_result_loc;
|
||||
AstNode *init_array_type_source_node;
|
||||
if (container_init_expr->type != nullptr) {
|
||||
IrInstruction *container_type;
|
||||
if (container_init_expr->type->type == NodeTypeInferredArrayType) {
|
||||
if (kind == ContainerInitKindStruct) {
|
||||
add_node_error(irb->codegen, container_init_expr->type,
|
||||
buf_sprintf("initializing array with struct syntax"));
|
||||
return irb->codegen->invalid_instruction;
|
||||
}
|
||||
IrInstruction *elem_type = ir_gen_node(irb,
|
||||
container_init_expr->type->data.inferred_array_type.child_type, scope);
|
||||
if (elem_type == irb->codegen->invalid_instruction)
|
||||
return elem_type;
|
||||
size_t item_count = container_init_expr->entries.length;
|
||||
IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count);
|
||||
container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type);
|
||||
} else {
|
||||
container_type = ir_gen_node(irb, container_init_expr->type, scope);
|
||||
if (container_type == irb->codegen->invalid_instruction)
|
||||
return container_type;
|
||||
}
|
||||
|
||||
IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc,
|
||||
container_type);
|
||||
result_loc_cast = ir_build_cast_result_loc(irb, container_type, parent_result_loc);
|
||||
child_result_loc = &result_loc_cast->base;
|
||||
init_array_type_source_node = container_type->source_node;
|
||||
} else {
|
||||
child_result_loc = parent_result_loc;
|
||||
init_array_type_source_node = parent_result_loc->source_instruction->source_node;
|
||||
}
|
||||
|
||||
switch (kind) {
|
||||
case ContainerInitKindStruct: {
|
||||
IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc,
|
||||
nullptr);
|
||||
|
||||
size_t field_count = container_init_expr->entries.length;
|
||||
IrInstructionContainerInitFieldsField *fields = allocate<IrInstructionContainerInitFieldsField>(field_count);
|
||||
@ -6176,29 +6185,27 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
|
||||
fields[i].source_node = entry_node;
|
||||
fields[i].result_loc = field_ptr;
|
||||
}
|
||||
IrInstruction *init_fields = ir_build_container_init_fields(irb, scope, node, container_type,
|
||||
field_count, fields, container_ptr);
|
||||
IrInstruction *result = ir_build_container_init_fields(irb, scope, node, field_count,
|
||||
fields, container_ptr);
|
||||
|
||||
return ir_lval_wrap(irb, scope, init_fields, lval, parent_result_loc);
|
||||
if (result_loc_cast != nullptr) {
|
||||
result = ir_build_implicit_cast(irb, scope, node, result, result_loc_cast);
|
||||
}
|
||||
return ir_lval_wrap(irb, scope, result, lval, parent_result_loc);
|
||||
}
|
||||
case ContainerInitKindArray: {
|
||||
size_t item_count = container_init_expr->entries.length;
|
||||
|
||||
if (container_type == nullptr) {
|
||||
IrInstruction *item_count_inst = ir_build_const_usize(irb, scope, node, item_count);
|
||||
container_type = ir_build_array_type(irb, scope, node, item_count_inst, elem_type);
|
||||
}
|
||||
|
||||
IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, parent_result_loc,
|
||||
container_type);
|
||||
IrInstruction *container_ptr = ir_build_resolve_result(irb, scope, node, child_result_loc,
|
||||
nullptr);
|
||||
|
||||
IrInstruction **result_locs = allocate<IrInstruction *>(item_count);
|
||||
for (size_t i = 0; i < item_count; i += 1) {
|
||||
AstNode *expr_node = container_init_expr->entries.at(i);
|
||||
|
||||
IrInstruction *elem_index = ir_build_const_usize(irb, scope, expr_node, i);
|
||||
IrInstruction *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr, elem_index,
|
||||
false, PtrLenSingle, container_type);
|
||||
IrInstruction *elem_ptr = ir_build_elem_ptr(irb, scope, expr_node, container_ptr,
|
||||
elem_index, false, PtrLenSingle, init_array_type_source_node);
|
||||
ResultLocInstruction *result_loc_inst = allocate<ResultLocInstruction>(1);
|
||||
result_loc_inst->base.id = ResultLocIdInstruction;
|
||||
result_loc_inst->base.source_instruction = elem_ptr;
|
||||
@ -6213,9 +6220,12 @@ static IrInstruction *ir_gen_container_init_expr(IrBuilder *irb, Scope *scope, A
|
||||
|
||||
result_locs[i] = elem_ptr;
|
||||
}
|
||||
IrInstruction *init_list = ir_build_container_init_list(irb, scope, node, container_type,
|
||||
item_count, result_locs, container_ptr);
|
||||
return ir_lval_wrap(irb, scope, init_list, lval, parent_result_loc);
|
||||
IrInstruction *result = ir_build_container_init_list(irb, scope, node, item_count,
|
||||
result_locs, container_ptr, init_array_type_source_node);
|
||||
if (result_loc_cast != nullptr) {
|
||||
result = ir_build_implicit_cast(irb, scope, node, result, result_loc_cast);
|
||||
}
|
||||
return ir_lval_wrap(irb, scope, result, lval, parent_result_loc);
|
||||
}
|
||||
}
|
||||
zig_unreachable();
|
||||
@ -7935,14 +7945,14 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o
|
||||
static Buf *get_anon_type_name(CodeGen *codegen, IrExecutable *exec, const char *kind_name,
|
||||
Scope *scope, AstNode *source_node, Buf *out_bare_name)
|
||||
{
|
||||
if (exec->name) {
|
||||
if (exec != nullptr && exec->name) {
|
||||
ZigType *import = get_scope_import(scope);
|
||||
Buf *namespace_name = buf_alloc();
|
||||
append_namespace_qualification(codegen, namespace_name, import);
|
||||
buf_append_buf(namespace_name, exec->name);
|
||||
buf_init_from_buf(out_bare_name, exec->name);
|
||||
return namespace_name;
|
||||
} else if (exec->name_fn != nullptr) {
|
||||
} else if (exec != nullptr && exec->name_fn != nullptr) {
|
||||
Buf *name = buf_alloc();
|
||||
buf_append_buf(name, &exec->name_fn->symbol_name);
|
||||
buf_appendf(name, "(");
|
||||
@ -15541,11 +15551,7 @@ static bool ir_result_has_type(ResultLoc *result_loc) {
|
||||
static IrInstruction *ir_resolve_no_result_loc(IrAnalyze *ira, IrInstruction *suspend_source_instr,
|
||||
ResultLoc *result_loc, ZigType *value_type, bool force_runtime, bool non_null_comptime)
|
||||
{
|
||||
Error err;
|
||||
|
||||
IrInstructionAllocaGen *alloca_gen = ir_build_alloca_gen(ira, suspend_source_instr, 0, "");
|
||||
if ((err = type_resolve(ira->codegen, value_type, ResolveStatusZeroBitsKnown)))
|
||||
return ira->codegen->invalid_instruction;
|
||||
alloca_gen->base.value.type = get_pointer_to_type_extra(ira->codegen, value_type, false, false,
|
||||
PtrLenSingle, 0, 0, 0, false);
|
||||
set_up_result_loc_for_inferred_comptime(&alloca_gen->base);
|
||||
@ -15750,6 +15756,7 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
|
||||
return casted_value;
|
||||
}
|
||||
|
||||
bool old_parent_result_loc_written = result_cast->parent->written;
|
||||
IrInstruction *parent_result_loc = ir_resolve_result(ira, suspend_source_instr, result_cast->parent,
|
||||
dest_type, casted_value, force_runtime, non_null_comptime, true);
|
||||
if (parent_result_loc == nullptr || type_is_invalid(parent_result_loc->value.type) ||
|
||||
@ -15775,6 +15782,22 @@ static IrInstruction *ir_resolve_result_raw(IrAnalyze *ira, IrInstruction *suspe
|
||||
parent_ptr_type->data.pointer.is_const, parent_ptr_type->data.pointer.is_volatile, PtrLenSingle,
|
||||
parent_ptr_align, 0, 0, parent_ptr_type->data.pointer.allow_zero);
|
||||
|
||||
{
|
||||
// we also need to check that this cast is OK.
|
||||
ConstCastOnly const_cast_result = types_match_const_cast_only(ira,
|
||||
parent_result_loc->value.type, ptr_type,
|
||||
result_cast->base.source_instruction->source_node, false);
|
||||
if (const_cast_result.id == ConstCastResultIdInvalid)
|
||||
return ira->codegen->invalid_instruction;
|
||||
if (const_cast_result.id != ConstCastResultIdOk) {
|
||||
// We will not be able to provide a result location for this value. Create
|
||||
// a new result location.
|
||||
result_cast->parent->written = old_parent_result_loc_written;
|
||||
return ir_resolve_no_result_loc(ira, suspend_source_instr, result_loc, value_type,
|
||||
force_runtime, non_null_comptime);
|
||||
}
|
||||
}
|
||||
|
||||
result_loc->written = true;
|
||||
result_loc->resolved_loc = ir_analyze_ptr_cast(ira, suspend_source_instr, parent_result_loc,
|
||||
ptr_type, result_cast->base.source_instruction, false);
|
||||
@ -15902,10 +15925,33 @@ static IrInstruction *ir_resolve_result(IrAnalyze *ira, IrInstruction *suspend_s
|
||||
return result_loc;
|
||||
}
|
||||
|
||||
static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira, IrInstructionResolveResult *instruction) {
|
||||
ZigType *implicit_elem_type = ir_resolve_type(ira, instruction->ty->child);
|
||||
if (type_is_invalid(implicit_elem_type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
static IrInstruction *ir_analyze_instruction_resolve_result(IrAnalyze *ira,
|
||||
IrInstructionResolveResult *instruction)
|
||||
{
|
||||
ZigType *implicit_elem_type;
|
||||
if (instruction->ty == nullptr) {
|
||||
if (instruction->result_loc->id == ResultLocIdCast) {
|
||||
implicit_elem_type = ir_resolve_type(ira,
|
||||
instruction->result_loc->source_instruction->child);
|
||||
if (type_is_invalid(implicit_elem_type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
} else {
|
||||
Buf *bare_name = buf_alloc();
|
||||
Buf *name = get_anon_type_name(ira->codegen, nullptr, container_string(ContainerKindStruct),
|
||||
instruction->base.scope, instruction->base.source_node, bare_name);
|
||||
|
||||
ZigType *inferred_struct_type = get_partial_container_type(ira->codegen,
|
||||
instruction->base.scope, ContainerKindStruct, instruction->base.source_node,
|
||||
buf_ptr(name), bare_name, ContainerLayoutAuto);
|
||||
inferred_struct_type->data.structure.is_inferred = true;
|
||||
inferred_struct_type->data.structure.resolve_status = ResolveStatusBeingInferred;
|
||||
implicit_elem_type = inferred_struct_type;
|
||||
}
|
||||
} else {
|
||||
implicit_elem_type = ir_resolve_type(ira, instruction->ty->child);
|
||||
if (type_is_invalid(implicit_elem_type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
IrInstruction *result_loc = ir_resolve_result(ira, &instruction->base, instruction->result_loc,
|
||||
implicit_elem_type, nullptr, false, true, true);
|
||||
if (result_loc != nullptr)
|
||||
@ -17837,7 +17883,9 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
|
||||
if (array_ptr_val == nullptr)
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
if (array_ptr_val->special == ConstValSpecialUndef && elem_ptr_instruction->init_array_type != nullptr) {
|
||||
if (array_ptr_val->special == ConstValSpecialUndef &&
|
||||
elem_ptr_instruction->init_array_type_source_node != nullptr)
|
||||
{
|
||||
if (array_type->id == ZigTypeIdArray || array_type->id == ZigTypeIdVector) {
|
||||
array_ptr_val->data.x_array.special = ConstArraySpecialNone;
|
||||
array_ptr_val->data.x_array.data.s_none.elements = create_const_vals(array_type->data.array.len);
|
||||
@ -17851,11 +17899,13 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
|
||||
elem_val->parent.data.p_array.elem_index = i;
|
||||
}
|
||||
} else if (is_slice(array_type)) {
|
||||
ZigType *actual_array_type = ir_resolve_type(ira, elem_ptr_instruction->init_array_type->child);
|
||||
ir_assert(array_ptr->value.type->id == ZigTypeIdPointer, &elem_ptr_instruction->base);
|
||||
ZigType *actual_array_type = array_ptr->value.type->data.pointer.child_type;
|
||||
|
||||
if (type_is_invalid(actual_array_type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
if (actual_array_type->id != ZigTypeIdArray) {
|
||||
ir_add_error(ira, elem_ptr_instruction->init_array_type,
|
||||
ir_add_error_node(ira, elem_ptr_instruction->init_array_type_source_node,
|
||||
buf_sprintf("expected array type or [_], found slice"));
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
@ -17879,7 +17929,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
|
||||
false);
|
||||
array_ptr_val->data.x_struct.fields[slice_ptr_index].data.x_ptr.mut = ConstPtrMutInfer;
|
||||
} else {
|
||||
ir_add_error(ira, elem_ptr_instruction->init_array_type,
|
||||
ir_add_error_node(ira, elem_ptr_instruction->init_array_type_source_node,
|
||||
buf_sprintf("expected array type or [_], found '%s'",
|
||||
buf_ptr(&array_type->name)));
|
||||
return ira->codegen->invalid_instruction;
|
||||
@ -18012,7 +18062,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
|
||||
if (orig_array_ptr_val->data.x_ptr.mut == ConstPtrMutInfer) {
|
||||
result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,
|
||||
elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index,
|
||||
false, elem_ptr_instruction->ptr_len, elem_ptr_instruction->init_array_type);
|
||||
false, elem_ptr_instruction->ptr_len, nullptr);
|
||||
result->value.type = return_type;
|
||||
result->value.special = ConstValSpecialStatic;
|
||||
} else {
|
||||
@ -18073,7 +18123,7 @@ static IrInstruction *ir_analyze_instruction_elem_ptr(IrAnalyze *ira, IrInstruct
|
||||
|
||||
IrInstruction *result = ir_build_elem_ptr(&ira->new_irb, elem_ptr_instruction->base.scope,
|
||||
elem_ptr_instruction->base.source_node, array_ptr, casted_elem_index, safety_check_on,
|
||||
elem_ptr_instruction->ptr_len, elem_ptr_instruction->init_array_type);
|
||||
elem_ptr_instruction->ptr_len, nullptr);
|
||||
result->value.type = return_type;
|
||||
return result;
|
||||
}
|
||||
@ -18223,6 +18273,7 @@ static IrInstruction *ir_analyze_container_field_ptr(IrAnalyze *ira, Buf *field_
|
||||
Error err;
|
||||
|
||||
ZigType *bare_type = container_ref_type(container_type);
|
||||
|
||||
if ((err = type_resolve(ira->codegen, bare_type, ResolveStatusZeroBitsKnown)))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
@ -20124,14 +20175,18 @@ static IrInstruction *ir_analyze_container_init_fields(IrAnalyze *ira, IrInstruc
|
||||
static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
|
||||
IrInstructionContainerInitList *instruction)
|
||||
{
|
||||
ZigType *container_type = ir_resolve_type(ira, instruction->container_type->child);
|
||||
if (type_is_invalid(container_type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
ir_assert(instruction->result_loc != nullptr, &instruction->base);
|
||||
IrInstruction *result_loc = instruction->result_loc->child;
|
||||
if (type_is_invalid(result_loc->value.type))
|
||||
return result_loc;
|
||||
ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base);
|
||||
|
||||
ZigType *container_type = result_loc->value.type->data.pointer.child_type;
|
||||
|
||||
size_t elem_count = instruction->item_count;
|
||||
|
||||
if (is_slice(container_type)) {
|
||||
ir_add_error(ira, instruction->container_type,
|
||||
ir_add_error_node(ira, instruction->init_array_type_source_node,
|
||||
buf_sprintf("expected array type or [_], found slice"));
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
@ -20160,12 +20215,6 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
|
||||
return ira->codegen->invalid_instruction;
|
||||
}
|
||||
|
||||
ir_assert(instruction->result_loc != nullptr, &instruction->base);
|
||||
IrInstruction *result_loc = instruction->result_loc->child;
|
||||
if (type_is_invalid(result_loc->value.type))
|
||||
return result_loc;
|
||||
ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base);
|
||||
|
||||
ZigType *child_type = container_type->data.array.child_type;
|
||||
if (container_type->data.array.len != elem_count) {
|
||||
ZigType *literal_type = get_array_type(ira->codegen, child_type, elem_count);
|
||||
@ -20262,16 +20311,14 @@ static IrInstruction *ir_analyze_instruction_container_init_list(IrAnalyze *ira,
|
||||
static IrInstruction *ir_analyze_instruction_container_init_fields(IrAnalyze *ira,
|
||||
IrInstructionContainerInitFields *instruction)
|
||||
{
|
||||
IrInstruction *container_type_value = instruction->container_type->child;
|
||||
ZigType *container_type = ir_resolve_type(ira, container_type_value);
|
||||
if (type_is_invalid(container_type))
|
||||
return ira->codegen->invalid_instruction;
|
||||
|
||||
ir_assert(instruction->result_loc != nullptr, &instruction->base);
|
||||
IrInstruction *result_loc = instruction->result_loc->child;
|
||||
if (type_is_invalid(result_loc->value.type))
|
||||
return result_loc;
|
||||
|
||||
ir_assert(result_loc->value.type->id == ZigTypeIdPointer, &instruction->base);
|
||||
ZigType *container_type = result_loc->value.type->data.pointer.child_type;
|
||||
|
||||
return ir_analyze_container_init_fields(ira, &instruction->base, container_type,
|
||||
instruction->field_count, instruction->fields, result_loc);
|
||||
}
|
||||
@ -24607,6 +24654,10 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
|
||||
ZigType *src_type = ptr->value.type;
|
||||
assert(!type_is_invalid(src_type));
|
||||
|
||||
if (src_type == dest_type) {
|
||||
return ptr;
|
||||
}
|
||||
|
||||
// We have a check for zero bits later so we use get_src_ptr_type to
|
||||
// validate src_type and dest_type.
|
||||
|
||||
@ -24656,6 +24707,9 @@ static IrInstruction *ir_analyze_ptr_cast(IrAnalyze *ira, IrInstruction *source_
|
||||
IrInstruction *result;
|
||||
if (ptr->value.data.x_ptr.mut == ConstPtrMutInfer) {
|
||||
result = ir_build_ptr_cast_gen(ira, source_instr, dest_type, ptr, safety_check_on);
|
||||
|
||||
if ((err = type_resolve(ira->codegen, dest_type, ResolveStatusZeroBitsKnown)))
|
||||
return ira->codegen->invalid_instruction;
|
||||
} else {
|
||||
result = ir_const(ira, source_instr, dest_type);
|
||||
}
|
||||
|
||||
@ -731,7 +731,6 @@ static void ir_print_phi(IrPrint *irp, IrInstructionPhi *phi_instruction) {
|
||||
}
|
||||
|
||||
static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerInitList *instruction) {
|
||||
ir_print_other_instruction(irp, instruction->container_type);
|
||||
fprintf(irp->f, "{");
|
||||
if (instruction->item_count > 50) {
|
||||
fprintf(irp->f, "...(%" ZIG_PRI_usize " items)...", instruction->item_count);
|
||||
@ -743,11 +742,11 @@ static void ir_print_container_init_list(IrPrint *irp, IrInstructionContainerIni
|
||||
ir_print_other_instruction(irp, result_loc);
|
||||
}
|
||||
}
|
||||
fprintf(irp->f, "}");
|
||||
fprintf(irp->f, "}result=");
|
||||
ir_print_other_instruction(irp, instruction->result_loc);
|
||||
}
|
||||
|
||||
static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerInitFields *instruction) {
|
||||
ir_print_other_instruction(irp, instruction->container_type);
|
||||
fprintf(irp->f, "{");
|
||||
for (size_t i = 0; i < instruction->field_count; i += 1) {
|
||||
IrInstructionContainerInitFieldsField *field = &instruction->fields[i];
|
||||
@ -755,7 +754,8 @@ static void ir_print_container_init_fields(IrPrint *irp, IrInstructionContainerI
|
||||
fprintf(irp->f, "%s.%s = ", comma, buf_ptr(field->name));
|
||||
ir_print_other_instruction(irp, field->result_loc);
|
||||
}
|
||||
fprintf(irp->f, "} // container init");
|
||||
fprintf(irp->f, "}result=");
|
||||
ir_print_other_instruction(irp, instruction->result_loc);
|
||||
}
|
||||
|
||||
static void ir_print_unreachable(IrPrint *irp, IrInstructionUnreachable *instruction) {
|
||||
|
||||
@ -216,9 +216,9 @@ pub fn addCases(cases: *tests.CompileErrorContext) void {
|
||||
\\ const obj = AstObject{ .lhsExpr = lhsExpr };
|
||||
\\}
|
||||
,
|
||||
"tmp.zig:4:19: error: union 'AstObject' depends on itself",
|
||||
"tmp.zig:2:5: note: while checking this field",
|
||||
"tmp.zig:1:17: error: struct 'LhsExpr' depends on itself",
|
||||
"tmp.zig:5:5: note: while checking this field",
|
||||
"tmp.zig:2:5: note: while checking this field",
|
||||
);
|
||||
|
||||
cases.add(
|
||||
|
||||
@ -1214,7 +1214,7 @@ test "spill target expr in a for loop" {
|
||||
}
|
||||
|
||||
const Foo = struct {
|
||||
slice: []i32,
|
||||
slice: []const i32,
|
||||
};
|
||||
|
||||
fn atest(foo: *Foo) i32 {
|
||||
@ -1245,7 +1245,7 @@ test "spill target expr in a for loop, with a var decl in the loop body" {
|
||||
}
|
||||
|
||||
const Foo = struct {
|
||||
slice: []i32,
|
||||
slice: []const i32,
|
||||
};
|
||||
|
||||
fn atest(foo: *Foo) i32 {
|
||||
|
||||
@ -709,3 +709,23 @@ test "packed struct field passed to generic function" {
|
||||
var loaded = S.genericReadPackedField(&p.b);
|
||||
expect(loaded == 29);
|
||||
}
|
||||
|
||||
test "anonymous struct literal syntax" {
|
||||
const S = struct {
|
||||
const Point = struct {
|
||||
x: i32,
|
||||
y: i32,
|
||||
};
|
||||
|
||||
fn doTheTest() void {
|
||||
var p: Point = .{
|
||||
.x = 1,
|
||||
.y = 2,
|
||||
};
|
||||
expect(p.x == 1);
|
||||
expect(p.y == 2);
|
||||
}
|
||||
};
|
||||
S.doTheTest();
|
||||
comptime S.doTheTest();
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user