mirror of
https://github.com/ziglang/zig.git
synced 2026-02-13 21:08:36 +00:00
stage1: fix anon struct naming in certain cases
- generic "struct:L:C" naming if rloc is NodeTypeStructValueField - generic "struct:L:C" naming if rloc is NodeTypeFnCallExpr - move some tests from test/behavior/misc to test/behavior/typename closes #4330 closes #9339
This commit is contained in:
parent
15bec20b00
commit
ed174b7386
@ -3454,7 +3454,7 @@ static Stage1ZirInst *astgen_merge_err_sets(Stage1AstGen *ag, Scope *scope, AstN
|
||||
|
||||
// TODO only pass type_name when the || operator is the top level AST node in the var decl expr
|
||||
Buf bare_name = BUF_INIT;
|
||||
Buf *type_name = get_anon_type_name(ag->codegen, ag->exec, "error", scope, node, &bare_name);
|
||||
Buf *type_name = get_anon_type_name(ag->codegen, ag->exec, "error", scope, node, &bare_name, nullptr);
|
||||
|
||||
return ir_build_merge_err_sets(ag, scope, node, op1, op2, type_name);
|
||||
}
|
||||
@ -7588,42 +7588,73 @@ static bool render_instance_name_recursive(CodeGen *codegen, Buf *name, Scope *o
|
||||
}
|
||||
|
||||
Buf *get_anon_type_name(CodeGen *codegen, Stage1Zir *exec, const char *kind_name,
|
||||
Scope *scope, AstNode *source_node, Buf *out_bare_name)
|
||||
Scope *scope, AstNode *source_node, Buf *out_bare_name, ResultLoc *result_loc)
|
||||
{
|
||||
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 != nullptr && exec->name_fn != nullptr) {
|
||||
Buf *name = buf_alloc();
|
||||
buf_append_buf(name, &exec->name_fn->symbol_name);
|
||||
buf_appendf(name, "(");
|
||||
render_instance_name_recursive(codegen, name, &exec->name_fn->fndef_scope->base, exec->begin_scope);
|
||||
buf_appendf(name, ")");
|
||||
buf_init_from_buf(out_bare_name, name);
|
||||
return name;
|
||||
} else {
|
||||
ZigType *import = get_scope_import(scope);
|
||||
Buf *namespace_name = buf_alloc();
|
||||
append_namespace_qualification(codegen, namespace_name, import);
|
||||
RootStruct *root_struct = source_node->owner->data.structure.root_struct;
|
||||
TokenLoc tok_loc = root_struct->token_locs[source_node->main_token];
|
||||
buf_appendf(namespace_name, "%s:%u:%u", kind_name,
|
||||
tok_loc.line + 1, tok_loc.column + 1);
|
||||
buf_init_from_buf(out_bare_name, namespace_name);
|
||||
return namespace_name;
|
||||
// See https://ziglang.org/documentation/master/#Struct-Naming .
|
||||
bool force_generic = false;
|
||||
if (result_loc != nullptr
|
||||
&& result_loc->source_instruction != nullptr
|
||||
&& result_loc->source_instruction->source_node != nullptr
|
||||
) {
|
||||
switch (result_loc->source_instruction->source_node->type) {
|
||||
case NodeTypeVariableDeclaration: {
|
||||
ZigType *import = get_scope_import(scope);
|
||||
Buf *name = buf_alloc();
|
||||
append_namespace_qualification(codegen, name, import);
|
||||
const auto &basename = result_loc->source_instruction->source_node->data.variable_declaration.symbol;
|
||||
buf_append_buf(name, basename);
|
||||
buf_init_from_buf(out_bare_name, basename);
|
||||
return name;
|
||||
}
|
||||
case NodeTypeFnCallExpr:
|
||||
case NodeTypeStructValueField:
|
||||
force_generic = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!force_generic) {
|
||||
if (exec != nullptr && exec->name != nullptr) {
|
||||
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;
|
||||
}
|
||||
if (exec != nullptr && exec->name_fn != nullptr) {
|
||||
Buf *name = buf_alloc();
|
||||
buf_append_buf(name, &exec->name_fn->symbol_name);
|
||||
buf_appendf(name, "(");
|
||||
render_instance_name_recursive(codegen, name, &exec->name_fn->fndef_scope->base, exec->begin_scope);
|
||||
buf_appendf(name, ")");
|
||||
buf_init_from_buf(out_bare_name, name);
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
ZigType *import = get_scope_import(scope);
|
||||
Buf *namespace_name = buf_alloc();
|
||||
append_namespace_qualification(codegen, namespace_name, import);
|
||||
RootStruct *root_struct = source_node->owner->data.structure.root_struct;
|
||||
TokenLoc tok_loc = root_struct->token_locs[source_node->main_token];
|
||||
buf_appendf(namespace_name, "%s:%u:%u", kind_name,
|
||||
tok_loc.line + 1, tok_loc.column + 1);
|
||||
buf_init_from_buf(out_bare_name, namespace_name);
|
||||
return namespace_name;
|
||||
}
|
||||
|
||||
static Stage1ZirInst *astgen_container_decl(Stage1AstGen *ag, Scope *parent_scope, AstNode *node) {
|
||||
static Stage1ZirInst *astgen_container_decl(Stage1AstGen *ag, Scope *parent_scope,
|
||||
AstNode *node, ResultLoc *result_loc)
|
||||
{
|
||||
assert(node->type == NodeTypeContainerDecl);
|
||||
|
||||
ContainerKind kind = node->data.container_decl.kind;
|
||||
Buf *bare_name = buf_alloc();
|
||||
Buf *name = get_anon_type_name(ag->codegen, ag->exec, container_string(kind), parent_scope, node, bare_name);
|
||||
Buf *name = get_anon_type_name(ag->codegen,
|
||||
ag->exec, container_string(kind), parent_scope, node, bare_name, result_loc);
|
||||
|
||||
ContainerLayout layout = node->data.container_decl.layout;
|
||||
ZigType *container_type = get_partial_container_type(ag->codegen, parent_scope,
|
||||
@ -7653,7 +7684,7 @@ static Stage1ZirInst *astgen_err_set_decl(Stage1AstGen *ag, Scope *parent_scope,
|
||||
uint32_t err_count = node->data.err_set_decl.decls.length;
|
||||
|
||||
Buf bare_name = BUF_INIT;
|
||||
Buf *type_name = get_anon_type_name(ag->codegen, ag->exec, "error", parent_scope, node, &bare_name);
|
||||
Buf *type_name = get_anon_type_name(ag->codegen, ag->exec, "error", parent_scope, node, &bare_name, nullptr);
|
||||
ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
|
||||
buf_init_from_buf(&err_set_type->name, type_name);
|
||||
err_set_type->data.error_set.err_count = err_count;
|
||||
@ -7963,7 +7994,7 @@ static Stage1ZirInst *astgen_node_raw(Stage1AstGen *ag, AstNode *node, Scope *sc
|
||||
case NodeTypeCatchExpr:
|
||||
return astgen_catch(ag, scope, node, lval, result_loc);
|
||||
case NodeTypeContainerDecl:
|
||||
return ir_lval_wrap(ag, scope, astgen_container_decl(ag, scope, node), lval, result_loc);
|
||||
return ir_lval_wrap(ag, scope, astgen_container_decl(ag, scope, node, result_loc), lval, result_loc);
|
||||
case NodeTypeFnProto:
|
||||
return ir_lval_wrap(ag, scope, astgen_fn_proto(ag, scope, node), lval, result_loc);
|
||||
case NodeTypeErrorSetDecl:
|
||||
|
||||
@ -32,6 +32,6 @@ void destroy_instruction_src(Stage1ZirInst *inst);
|
||||
|
||||
bool ir_should_inline(Stage1Zir *exec, Scope *scope);
|
||||
Buf *get_anon_type_name(CodeGen *codegen, Stage1Zir *exec, const char *kind_name,
|
||||
Scope *scope, AstNode *source_node, Buf *out_bare_name);
|
||||
Scope *scope, AstNode *source_node, Buf *out_bare_name, ResultLoc *result_loc);
|
||||
|
||||
#endif
|
||||
|
||||
@ -10423,7 +10423,7 @@ static Stage1AirInst *ir_analyze_tuple_cat(IrAnalyze *ira, Scope *scope, AstNode
|
||||
|
||||
Buf *bare_name = buf_alloc();
|
||||
Buf *name = get_anon_type_name(ira->codegen, nullptr, container_string(ContainerKindStruct),
|
||||
scope, source_node, bare_name);
|
||||
scope, source_node, bare_name, nullptr);
|
||||
ZigType *new_type = get_partial_container_type(ira->codegen, scope,
|
||||
ContainerKindStruct, source_node, buf_ptr(name), bare_name, ContainerLayoutAuto);
|
||||
new_type->data.structure.special = StructSpecialInferredTuple;
|
||||
@ -10755,7 +10755,7 @@ static Stage1AirInst *ir_analyze_tuple_mult(IrAnalyze *ira, Scope *scope, AstNod
|
||||
|
||||
Buf *bare_name = buf_alloc();
|
||||
Buf *name = get_anon_type_name(ira->codegen, nullptr, container_string(ContainerKindStruct),
|
||||
scope, source_node, bare_name);
|
||||
scope, source_node, bare_name, nullptr);
|
||||
ZigType *new_type = get_partial_container_type(ira->codegen, scope,
|
||||
ContainerKindStruct, source_node, buf_ptr(name), bare_name, ContainerLayoutAuto);
|
||||
new_type->data.structure.special = StructSpecialInferredTuple;
|
||||
@ -12277,7 +12277,7 @@ static Stage1AirInst *ir_analyze_instruction_resolve_result(IrAnalyze *ira, Stag
|
||||
if (implicit_elem_type == ira->codegen->builtin_types.entry_anytype) {
|
||||
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);
|
||||
instruction->base.scope, instruction->base.source_node, bare_name, nullptr);
|
||||
|
||||
StructSpecial struct_special = StructSpecialInferredStruct;
|
||||
if (instruction->base.source_node->type == NodeTypeContainerInitExpr &&
|
||||
@ -18898,7 +18898,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
|
||||
|
||||
Buf *bare_name = buf_alloc();
|
||||
Buf *full_name = get_anon_type_name(ira->codegen,
|
||||
ira->zir, "opaque", scope, source_node, bare_name);
|
||||
ira->zir, "opaque", scope, source_node, bare_name, nullptr);
|
||||
return get_opaque_type(ira->codegen,
|
||||
scope, source_node, buf_ptr(full_name), bare_name);
|
||||
}
|
||||
@ -18945,7 +18945,8 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
|
||||
assert(is_slice(slice->type));
|
||||
ZigType *err_set_type = new_type_table_entry(ZigTypeIdErrorSet);
|
||||
Buf bare_name = BUF_INIT;
|
||||
buf_init_from_buf(&err_set_type->name, get_anon_type_name(ira->codegen, ira->zir, "error", scope, source_node, &bare_name));
|
||||
buf_init_from_buf(&err_set_type->name,
|
||||
get_anon_type_name(ira->codegen, ira->zir, "error", scope, source_node, &bare_name, nullptr));
|
||||
err_set_type->size_in_bits = ira->codegen->builtin_types.entry_global_error_set->size_in_bits;
|
||||
err_set_type->abi_align = ira->codegen->builtin_types.entry_global_error_set->abi_align;
|
||||
err_set_type->abi_size = ira->codegen->builtin_types.entry_global_error_set->abi_size;
|
||||
@ -19024,7 +19025,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
|
||||
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdStruct);
|
||||
buf_init_from_buf(&entry->name,
|
||||
get_anon_type_name(ira->codegen, ira->zir, "struct", scope, source_node, &entry->name));
|
||||
get_anon_type_name(ira->codegen, ira->zir, "struct", scope, source_node, &entry->name, nullptr));
|
||||
entry->data.structure.decl_node = source_node;
|
||||
entry->data.structure.fields = alloc_type_struct_fields(fields_len);
|
||||
entry->data.structure.fields_by_name.init(fields_len);
|
||||
@ -19134,7 +19135,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
|
||||
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdEnum);
|
||||
buf_init_from_buf(&entry->name,
|
||||
get_anon_type_name(ira->codegen, ira->zir, "enum", scope, source_node, &entry->name));
|
||||
get_anon_type_name(ira->codegen, ira->zir, "enum", scope, source_node, &entry->name, nullptr));
|
||||
entry->data.enumeration.decl_node = source_node;
|
||||
entry->data.enumeration.tag_int_type = tag_type;
|
||||
entry->data.enumeration.decls_scope = create_decls_scope(
|
||||
@ -19216,7 +19217,7 @@ static ZigType *type_info_to_type(IrAnalyze *ira, Scope *scope, AstNode *source_
|
||||
|
||||
ZigType *entry = new_type_table_entry(ZigTypeIdUnion);
|
||||
buf_init_from_buf(&entry->name,
|
||||
get_anon_type_name(ira->codegen, ira->zir, "union", scope, source_node, &entry->name));
|
||||
get_anon_type_name(ira->codegen, ira->zir, "union", scope, source_node, &entry->name, nullptr));
|
||||
entry->data.unionation.decl_node = source_node;
|
||||
entry->data.unionation.fields = heap::c_allocator.allocate<TypeUnionField>(fields_len);
|
||||
entry->data.unionation.fields_by_name.init(fields_len);
|
||||
|
||||
@ -436,30 +436,6 @@ const AUnion = union {
|
||||
Two: void,
|
||||
};
|
||||
|
||||
test "@typeName" {
|
||||
const Struct = struct {};
|
||||
const Union = union {
|
||||
unused: u8,
|
||||
};
|
||||
const Enum = enum {
|
||||
Unused,
|
||||
};
|
||||
comptime {
|
||||
try expect(mem.eql(u8, @typeName(i64), "i64"));
|
||||
try expect(mem.eql(u8, @typeName(*usize), "*usize"));
|
||||
// https://github.com/ziglang/zig/issues/675
|
||||
try expect(mem.eql(u8, "behavior.misc.TypeFromFn(u8)", @typeName(TypeFromFn(u8))));
|
||||
try expect(mem.eql(u8, @typeName(Struct), "Struct"));
|
||||
try expect(mem.eql(u8, @typeName(Union), "Union"));
|
||||
try expect(mem.eql(u8, @typeName(Enum), "Enum"));
|
||||
}
|
||||
}
|
||||
|
||||
fn TypeFromFn(comptime T: type) type {
|
||||
_ = T;
|
||||
return struct {};
|
||||
}
|
||||
|
||||
test "double implicit cast in same expression" {
|
||||
var x = @as(i32, @as(u16, nine()));
|
||||
try expect(x == 9);
|
||||
|
||||
@ -2,6 +2,113 @@ const std = @import("std");
|
||||
const expect = std.testing.expect;
|
||||
const expectEqualSlices = std.testing.expectEqualSlices;
|
||||
|
||||
test "slice" {
|
||||
try expectEqualSlices(u8, "[]u8", @typeName([]u8));
|
||||
// Most tests here can be comptime but use runtime so that a stacktrace
|
||||
// can show failure location.
|
||||
//
|
||||
// Note certain results of `@typeName()` expect `behavior.zig` to be the
|
||||
// root file. Running a test against this file as root will result in
|
||||
// failures.
|
||||
|
||||
// CAUTION: this test is source-location sensitive.
|
||||
test "anon fn param - source-location sensitive" {
|
||||
// https://github.com/ziglang/zig/issues/9339
|
||||
try expectEqualSlices(u8, @typeName(TypeFromFn(struct {})), "behavior.typename.TypeFromFn(behavior.typename.struct:15:52)");
|
||||
try expectEqualSlices(u8, @typeName(TypeFromFn(union { unused: u8 })), "behavior.typename.TypeFromFn(behavior.typename.union:16:52)");
|
||||
try expectEqualSlices(u8, @typeName(TypeFromFn(enum { unused })), "behavior.typename.TypeFromFn(behavior.typename.enum:17:52)");
|
||||
|
||||
try expectEqualSlices(
|
||||
u8,
|
||||
@typeName(TypeFromFn3(struct {}, union { unused: u8 }, enum { unused })),
|
||||
"behavior.typename.TypeFromFn3(behavior.typename.struct:21:31,behavior.typename.union:21:42,behavior.typename.enum:21:64)",
|
||||
);
|
||||
}
|
||||
|
||||
// CAUTION: this test is source-location sensitive.
|
||||
test "anon field init" {
|
||||
const Foo = .{
|
||||
.T1 = struct {},
|
||||
.T2 = union { unused: u8 },
|
||||
.T3 = enum { unused },
|
||||
};
|
||||
|
||||
try expectEqualSlices(u8, @typeName(Foo.T1), "behavior.typename.struct:29:15");
|
||||
try expectEqualSlices(u8, @typeName(Foo.T2), "behavior.typename.union:30:15");
|
||||
try expectEqualSlices(u8, @typeName(Foo.T3), "behavior.typename.enum:31:15");
|
||||
}
|
||||
|
||||
test "basic" {
|
||||
try expectEqualSlices(u8, @typeName(i64), "i64");
|
||||
try expectEqualSlices(u8, @typeName(*usize), "*usize");
|
||||
try expectEqualSlices(u8, @typeName([]u8), "[]u8");
|
||||
}
|
||||
|
||||
test "top level decl" {
|
||||
try expectEqualSlices(u8, @typeName(A_Struct), "A_Struct");
|
||||
try expectEqualSlices(u8, @typeName(A_Union), "A_Union");
|
||||
try expectEqualSlices(u8, @typeName(A_Enum), "A_Enum");
|
||||
|
||||
// regular fn, without error
|
||||
try expectEqualSlices(u8, @typeName(@TypeOf(regular)), "fn() void");
|
||||
// regular fn inside struct, with error
|
||||
try expectEqualSlices(u8, @typeName(@TypeOf(B.doTest)), "fn() @typeInfo(@typeInfo(@TypeOf(behavior.typename.B.doTest)).Fn.return_type.?).ErrorUnion.error_set!void");
|
||||
// generic fn
|
||||
try expectEqualSlices(u8, @typeName(@TypeOf(TypeFromFn)), "fn(type) anytype");
|
||||
}
|
||||
|
||||
const A_Struct = struct {};
|
||||
const A_Union = union {
|
||||
unused: u8,
|
||||
};
|
||||
const A_Enum = enum {
|
||||
unused,
|
||||
};
|
||||
|
||||
fn regular() void {}
|
||||
|
||||
test "fn body decl" {
|
||||
try B.doTest();
|
||||
}
|
||||
|
||||
const B = struct {
|
||||
fn doTest() !void {
|
||||
const B_Struct = struct {};
|
||||
const B_Union = union {
|
||||
unused: u8,
|
||||
};
|
||||
const B_Enum = enum {
|
||||
unused,
|
||||
};
|
||||
|
||||
try expectEqualSlices(u8, @typeName(B_Struct), "B_Struct");
|
||||
try expectEqualSlices(u8, @typeName(B_Union), "B_Union");
|
||||
try expectEqualSlices(u8, @typeName(B_Enum), "B_Enum");
|
||||
}
|
||||
};
|
||||
|
||||
test "fn param" {
|
||||
// https://github.com/ziglang/zig/issues/675
|
||||
try expectEqualSlices(u8, @typeName(TypeFromFn(u8)), "behavior.typename.TypeFromFn(u8)");
|
||||
try expectEqualSlices(u8, @typeName(TypeFromFn(A_Struct)), "behavior.typename.TypeFromFn(behavior.typename.A_Struct)");
|
||||
try expectEqualSlices(u8, @typeName(TypeFromFn(A_Union)), "behavior.typename.TypeFromFn(behavior.typename.A_Union)");
|
||||
try expectEqualSlices(u8, @typeName(TypeFromFn(A_Enum)), "behavior.typename.TypeFromFn(behavior.typename.A_Enum)");
|
||||
|
||||
try expectEqualSlices(u8, @typeName(TypeFromFn2(u8, bool)), "behavior.typename.TypeFromFn2(u8,bool)");
|
||||
}
|
||||
|
||||
fn TypeFromFn(comptime T: type) type {
|
||||
_ = T;
|
||||
return struct {};
|
||||
}
|
||||
|
||||
fn TypeFromFn2(comptime T1: type, comptime T2: type) type {
|
||||
_ = T1;
|
||||
_ = T2;
|
||||
return struct {};
|
||||
}
|
||||
|
||||
fn TypeFromFn3(comptime T1: type, comptime T2: type, comptime T3: type) type {
|
||||
_ = T1;
|
||||
_ = T2;
|
||||
_ = T3;
|
||||
return struct {};
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user