A reduced test case:
mixin ("enum E {", S.attr, "}");
struct S
{
E e;
enum attr = "a";
}
void main()
{
}
onlineapp.d(7): Error: undefined identifier `E`
The test case compiles if the enum is wrapped in a template:
template E()
{
mixin ("enum E {", S.attr, "}");
}
struct S
{
E!() e;
enum attr = "a";
}
Comment #1 by maxsamukha — 2022-04-04T07:49:39Z
(In reply to Max Samukha from comment #0)
> The test case compiles if the enum is wrapped in a template:
However, it doesn't if the template instance is aliased:
template E_()
{
mixin ("enum E_ {", S.attr, "}");
}
alias E = E_!();
struct S
{
E e;
enum attr = "a";
}
onlineapp.d(12): Error: template instance `onlineapp.E_!()` is used as a type
onlineapp.d(8): Error: template instance `onlineapp.E_!()` error instantiating
Comment #2 by maxsamukha — 2022-04-04T07:51:16Z
> However, it does if the template instance is aliased inside the type:
template E_()
{
mixin ("enum E_ {", S.attr, "}");
}
struct S
{
alias E = E_!();
E e;
enum attr = "a";
}
Comment #3 by maxsamukha — 2022-04-04T07:59:49Z
(In reply to Max Samukha from comment #2)
> > However, it does if the template instance is aliased inside the type:
That wasn't supposed to be a quotation
Comment #4 by b2.temp — 2022-04-30T08:28:44Z
I think that the compiler should perform a "pre-dsymbolsem" pass in aggregate decls, that pass would only target `enum` and other `static` declarations.
That could kill the fake cycle on `E` and other similar bugs.
Comment #5 by maxsamukha — 2022-04-30T16:04:29Z
(In reply to Basile-z from comment #4)
> I think that the compiler should perform a "pre-dsymbolsem" pass in
> aggregate decls, that pass would only target `enum` and other `static`
> declarations.
>
> That could kill the fake cycle on `E` and other similar bugs.
I am not competent to comment on this. FWIW, attributes, which are conceptually similar to static members, don't have this issue:
mixin ("enum E {", __traits(getAttributes, S)[0], "}");
@("a")
struct S
{
E e;
}
void main()
{
}
Comment #6 by b2.temp — 2022-04-30T16:15:40Z
(In reply to Max Samukha from comment #5)
> I am not competent to comment on this. FWIW, attributes, which are
> conceptually similar to static members, don't have this issue:
>
> mixin ("enum E {", __traits(getAttributes, S)[0], "}");
>
> @("a")
> struct S
> {
> E e;
> }
>
> void main()
> {
> }
Nah, attribs have the same problem, it's just that your test case does not reproduce it.
For attribs this is more like
```
mixin ("enum E {", __traits(getAttributes, S)[0], "}");
@(S.a)
struct S
{
E e;
enum a = "dfgdf";
}
void main()
{
}
```
output is then the same as the original test case, i.e
> Error: undefined identifier `E`
Comment #7 by b2.temp — 2022-04-30T16:22:39Z
In `S` the non static member `E e` create a cycle but actually with a pass dedicated to "static members - only" , the internal enum `S.a` would not require `S` semantic to be complete.
Comment #8 by b2.temp — 2022-04-30T16:25:34Z
(In reply to Basile-z from comment #7)
> In `S` the non static member `E e` create a cycle but actually with a pass
> dedicated to "static members - only" , the internal enum `S.a` would not
> require `S` semantic to be complete.
reduced more
```
@(S.a)
struct S
{
E e;
enum a = "dfgdf";
}
```
Comment #9 by b2.temp — 2022-04-30T16:29:22Z
even better
```
enum E { e1 = S.a }
struct S
{
E e;
enum a = "string";
}
```
> /tmp/temp_7F3BFB9249F0.d:6:14: Error: cannot implicitly convert expression `"string"` of type `string` to `int`
Comment #10 by b2.temp — 2022-04-30T16:36:50Z
looks like enum being integral is assumed too early ;)
for example if you change the infered type of S.a
```
enum E { e1 = S.a }
struct S
{
E e;
enum a = 123; // vs enum a = "string"
}
```
no problems anymore
Comment #11 by maxsamukha — 2022-04-30T17:27:44Z
(In reply to Basile-z from comment #7)
> In `S` the non static member `E e` create a cycle but actually with a pass
> dedicated to "static members - only" , the internal enum `S.a` would not
> require `S` semantic to be complete.
Yes, I understand this. I meant UDAs are similar *in concept* to static members - they are things associated with the type's name but are not related to values of that type. Before D acquired proper UDAs, we used to emulate them with static fields and introspection.
Comment #12 by maxsamukha — 2022-04-30T17:31:15Z
(In reply to Basile-z from comment #10)
> looks like enum being integral is assumed too early ;)
>
> for example if you change the infered type of S.a
>
> ```
> enum E { e1 = S.a }
>
> struct S
> {
> E e;
> enum a = 123; // vs enum a = "string"
> }
> ```
>
> no problems anymore
Seems to be unrelated to the original issue. In the original test case, the enum is integral - it is the member's name that is mixed-in.
Comment #13 by b2.temp — 2022-04-30T23:37:59Z
alright, I'll open another one ;)
Comment #14 by maxsamukha — 2022-05-01T07:49:57Z
(In reply to Basile-z from comment #13)
> alright, I'll open another one ;)
Great, thanks!
Comment #15 by dlang-bot — 2023-01-16T01:26:08Z
@ibuclaw created dlang/dmd pull request #14826 "dmd.aggregate: Define importAll override for AggregateDeclaration" fixing this issue:
- fix Issue 22981 - Another forward reference bug involving a string mixin
https://github.com/dlang/dmd/pull/14826
Comment #16 by robert.schadek — 2024-12-13T19:22:00Z