This one took me a long time to reduce. Marking it as a blocker, as I haven't found an acceptable workaround yet.
----
alias aliases(a...) = a;
template sort(alias f, a...)
{
static if (a.length > 0) // (1)
{
alias x = f!(a[1]);
alias sort = a;
}
else
alias sort = a;
}
alias SortedItems = sort!(isDependencyOf, Top, String); // (2)
pragma (msg, "1: ", SortedItems);
enum isDependencyOf(Item) = Item.DirectDependencies.length == 0;
struct Top
{
alias DirectDependencies = aliases!();
}
struct String
{
alias DirectDependencies = aliases!();
pragma(msg, "2: ", SortedItems);
enum l = SortedItems.length; // (3)
static assert(is(typeof(SortedItems.length) == size_t)); // (4)
}
----
Error: no property `length` for `sort!(isDependencyOf, Top, String)` of type `void`
The SortedItems tuple at (2) is (Top, String), which is correct, but at (3) it is broken. However, at (4) it is correct again - the assert passes if (3) is commented out. This may have something to do with the 'static if' at (1), as the error goes away if the 'static if' and the 'else' branch are commented out.
Comment #1 by ibuclaw — 2023-01-04T12:57:49Z
Related to issue 23595, and a WIP patch I have in the works fixes this test case too.
Comment #2 by maxsamukha — 2023-01-04T13:11:59Z
(In reply to Iain Buclaw from comment #1)
> Related to issue 23595, and a WIP patch I have in the works fixes this test
> case too.
Great! Thanks!
Comment #3 by dlang-bot — 2023-01-16T01:26:10Z
@ibuclaw created dlang/dmd pull request #14826 "dmd.aggregate: Define importAll override for AggregateDeclaration" fixing this issue:
- fix Issue 23598 - Another nasty forward reference bug
https://github.com/dlang/dmd/pull/14826
Comment #4 by bugzilla — 2023-01-19T05:11:12Z
Doing a shrink on the test case:
alias aliases(a...) = a;
template sort(alias f, a...) {
static if (a.length > 0) {
alias x = f!(a[0]);
alias sort = a;
}
else
alias sort = a;
}
alias SortedItems = sort!(isDependencyOf, String);
enum isDependencyOf(Item) = Item.DirectDependencies.length == 0;
struct String {
alias DirectDependencies = aliases!();
enum l = SortedItems.length; // no property `length`
}
If SortedItems is moved last, it compiles successfully.
Comment #5 by bugzilla — 2023-01-19T05:22:16Z
I suspect that when the sort template is instantiated, it is too eager to evaluate its arguments. It should just go as far as seeing String is a struct, and not attempt to semantic its contents.
Comment #6 by bugzilla — 2023-01-19T09:09:14Z
What seems to be happening is the first time it goes through `template sort`, it cannot set `aliasdecl` because the two `alias sort` assignments are hidden behind conditional compilation.
Hence `aliasdecl` is null.
So, in semantic for `struct String` it encounters `SortedItems.length`. The `aliasdecl` is null, so `SortedItems` becomes `sort!(...)` which becomes `void` and there is no `length` for `void`.
Comment #7 by bugzilla — 2023-01-19T09:25:53Z
Perhaps I can make this work by noticing if the `static if` member is the only member of the template, so it can be eagerly evaluated?
Comment #8 by bugzilla — 2023-01-19T09:29:48Z
Looking at expandMembers, perhaps this could be done in two passes - once for the top level conditional compilation, then check oneMember, then again for the rest.
Comment #9 by maxsamukha — 2023-01-20T08:31:40Z
(In reply to Walter Bright from comment #8)
> Looking at expandMembers, perhaps this could be done in two passes - once
> for the top level conditional compilation, then check oneMember, then again
> for the rest.
I guess doing this won't solve the general problem. Perhaps, I should humble myself and resort to other means instead of trying to get from the compiler what it can't give.
Comment #10 by dlang-bot — 2023-01-20T09:10:35Z
@WalterBright created dlang/dmd pull request #14838 "fix Issue 23598 - Circular reference bug with static if and eponymous…" fixing this issue:
- fix Issue 23598 - Circular reference bug with static if and eponymous templates
https://github.com/dlang/dmd/pull/14838
Comment #11 by bugzilla — 2023-01-20T09:14:16Z
Circular references that depend on the arms of a `static if` are always a likely source of chicken-egg problems.
Comment #12 by dlang-bot — 2023-01-26T09:28:58Z
dlang/dmd pull request #14838 "fix Issue 23598 - Circular reference bug with static if and eponymous…" was merged into master:
- 9295ea950c3b1badc8662aff40b3ce868ff142cf by Walter Bright:
fix Issue 23598 - Circular reference bug with static if and eponymous templates
https://github.com/dlang/dmd/pull/14838