Skip to content

@typeName returns struct definition for tuples #23292

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
TheArchitect4855 opened this issue Mar 18, 2025 · 6 comments
Closed

@typeName returns struct definition for tuples #23292

TheArchitect4855 opened this issue Mar 18, 2025 · 6 comments
Labels
bug Observed behavior contradicts documented or intended behavior

Comments

@TheArchitect4855
Copy link

TheArchitect4855 commented Mar 18, 2025

Zig Version

0.15.0-dev.64+2a4e06bcb

Steps to Reproduce and Observed Behavior

Compiling and running the following source will reproduce the unexpected behaviour:

const std = @import("std");

const Foo = struct {f32};
const Bar = struct {f: f32};

pub fn main() void {
    const foo = @typeName(Foo);
    const bar = @typeName(Bar);
    std.debug.print("{s}\n{s}\n", .{foo, bar});
}

Output when run:

struct { f32 }
test.Bar

Expected Behavior

The tuple struct should be named, just like a regular struct. Expected output:

test.Foo
test.Bar

I first noticed this bug in 0.14. I would expect that @typeName returns the name of the tuple, instead of its definition. Some motivation as to why this matters for me: I'm writing an ECS and I want the end-user to be able to use any type for a component. Thus, I need an ID that is unique per-type at runtime. Since Zig does not have a type ID builtin, I figured @typeName should do the trick. This works perfectly for structs, but not for tuple structs.

@TheArchitect4855 TheArchitect4855 added the bug Observed behavior contradicts documented or intended behavior label Mar 18, 2025
@tauoverpi
Copy link
Contributor

tauoverpi commented Mar 18, 2025

see #19858 (comment) on generating a type ID. Note that @typeName is not a reliable source for IDs at all.

$ tree
.
├── a
│   └── b.zig
└── b.zig

2 directories, 2 files
$ zig build-obj --dep foo -Mroot=b.zig -Mfoo=a/b.zig
b.zig:5:5: error: found compile log statement
    @compileLog(@typeName(Foo));
    ^~~~~~~~~~~~~~~~~~~~~~~~~~~

Compile Log Output:
@as(*const [5:0]u8, "b.Foo")
@as(*const [5:0]u8, "b.Foo")
$ cat b.zig
const Bar = @import("foo").Foo;
const Foo = opaque {};

comptime {
    @compileLog(@typeName(Foo));
    @compileLog(@typeName(Bar));
}

Also, do you really need a type ID or can you require that the user must specify all components they wish to use upfront then take a MultiArrayList approach?

@nektro
Copy link
Contributor

nektro commented Mar 18, 2025

this behavior is likely expected because tuples exhibit structural equality and are not unique to the declaration where theyre defined.

@mlugg
Copy link
Member

mlugg commented Mar 18, 2025

Working as intended.

Please refrain from using @typeName to create type IDs. The builtin is implementation-defined, currently unstable in practice, and can return the same name for distinct types in many situations. It's not entirely clear whether it will even remain in the language.

@mlugg mlugg closed this as not planned Won't fix, can't repro, duplicate, stale Mar 18, 2025
@TheArchitect4855
Copy link
Author

TheArchitect4855 commented Mar 19, 2025

I think this raises a deeper issue: It would be really cool if Zig had a way to uniquely identify named types at runtime. The recommended way of generating a type ID does not actually work: if I have two separate tuple structs with the same definition, they generate the same type ID. While there is an argument to be made that this is intended because the types are the same, I think it is also totally reasonable to want differently-named types to have different IDs.

For now, I think I'll just add a constant u64 field for a "unique ID", but obviously this is flaky and error-prone. imho, a @typeId builtin or similar should be more seriously considered.

Update: Adding an ID field is not actually possible! Tuples do not allow declarations.

@linusg
Copy link
Collaborator

linusg commented Mar 19, 2025

Please refrain from using @typeName to create type IDs.

How else would you recommend doing safety-checked any-pointer-to-known-type casting? This is something people rely on in the wild: https://github.com/ikskuh/any-pointer (I'm using this to implement ECMAScript's [[HostDefined]] fields in Kiesel)

@nektro
Copy link
Contributor

nektro commented Mar 19, 2025

@tauoverpi's comment links to code that can be used to generate type ids. are there ways this falls short for you?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior
Projects
None yet
Development

No branches or pull requests

5 participants