Bug 19084 – Symbol not resolved in string mixin in template struct

Status
RESOLVED
Resolution
INVALID
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2018-07-13T17:45:50Z
Last change time
2018-09-07T06:52:19Z
Assigned to
No Owner
Creator
Robert Schadek

Comments

Comment #0 by rburners — 2018-07-13T17:45:50Z
I have this code ``` import std.format : format; struct Bar(T) { mixin(format("%s foo;", T.stringof)); // a) Error // T foo; // b) Compiles } unittest { struct Foo { } Bar!Foo bar; } ``` which fails to compile with "Error: undefined identifier Foo, did you mean variable foo?" When I change a) to b) it compiles. Not sure if this is a bug or not.
Comment #1 by johnnymarler — 2018-08-24T03:45:43Z
This is not supposed to compile. I've actually run into this before, but using T.stringof to mixin code for a type name is not supported. When I've asked about adding support for this, no one was interested. I tried to find my forum posts on this but the post is so old I couldn't find it in search. What happens is you mixin the string "Foo", but that type doesn't mean anyting in the scope of Bar. The actual type name is something like "__unittest__20.Foo", however, even if you got the fully qualified type name it won't work because the type is private and can't be accessed outside of the unittest using the symbol name. You have to access the type by "alias". The `bitfields` function in phobos suffers from this same problem and I created a PR in phobos to add bitfields2 to workaround this issue by using a "mixin template" instead of a normal "mixin": https://github.com/dlang/phobos/pull/5490 > [QUOTE FROM THE PR] > The main advantage of bitfields2 is that it is able to reference the field types by alias, whereas the current implementation converts each field type alias to a string and then mixes in the type name. I know the example you've provided is contrived so I'm not sure how to help you with your exact situation. Maybe I can help you find a solution with a bit more detail?
Comment #2 by dfj1esp02 — 2018-08-24T08:32:52Z
You can reference the symbol directly: import std.format : format; struct Bar(T) { mixin("T foo;"); } unittest { struct Foo { } Bar!Foo bar; }
Comment #3 by johnnymarler — 2018-08-24T13:29:25Z
struct Bar(T) { mixin("T foo;"); } T in this case is not a "symbol name string", it is an alias to a symbol. But don't be confused, you can't actually create T with an alias, meaning `alias T = Foo` won't work. You have to use the fully qualified name of `Foo` but because `Foo` is inside a unittest, it's prvate and you cannot access it. The only way to access the type is if the code inside unittest "passes" the type alias to you through a template type parameter: unittest { struct Foo { } Bar!Foo bar; // passing Foo to Bar so it can access it } // out here we cannot access Foo because it is private to the unittest // the only way we can access it is if code inside of unittest passes it // us through a template type parameter