Bug 22859 – Error: forward reference of variable `isAssignable` for mutually recursed `allSatisfy`

Status
RESOLVED
Resolution
FIXED
Severity
regression
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2022-03-08T06:03:08Z
Last change time
2022-03-27T02:24:31Z
Keywords
pull
Assigned to
No Owner
Creator
Tomoya Tanjo

Comments

Comment #0 by ttanjo — 2022-03-08T06:03:08Z
The following code works with dmd 2.098.1 but does not work with dmd 2.099.0 (beta). run.dlang.io: https://run.dlang.io/is/GlU8gA ```d import std.sumtype : SumType; struct None{} class C1 { SumType!(None, C2) field; } class C2 { SumType!(None, C1, C2) field; } void main() {} ``` dmd 2.099.0 shows the following message: ```console > rdmd playground.d /dlang/dmd-beta/linux/bin64/../../src/phobos/std/sumtype.d(551): Error: forward reference of variable `isAssignableTo` /dlang/dmd-beta/linux/bin64/../../src/druntime/import/core/internal/traits.d(193): Error: forward reference of variable `isAssignableTo` /dlang/dmd-beta/linux/bin64/../../src/phobos/std/sumtype.d(595): Error: template instance `core.internal.traits.allSatisfy!(isAssignableTo, None, C1, C2)` error instantiating onlineapp.d(12): instantiated from here: `SumType!(None, C1, C2)` /dlang/dmd-beta/linux/bin64/../../src/phobos/std/traits.d(5179): Error: template instance `std.traits.isRvalueAssignable!(C2, C2)` error instantiating /dlang/dmd-beta/linux/bin64/../../src/phobos/std/sumtype.d(256): instantiated from here: `isAssignable!(C2, C2)` /dlang/dmd-beta/linux/bin64/../../src/phobos/std/sumtype.d(551): instantiated from here: `isAssignableTo!(C2)` onlineapp.d(7): instantiated from here: `SumType!(None, C2)` /dlang/dmd-beta/linux/bin64/../../src/phobos/std/sumtype.d(595): Error: template instance `core.internal.traits.allSatisfy!(isAssignableTo, None, C2)` error instantiating onlineapp.d(7): instantiated from here: `SumType!(None, C2)` ```
Comment #1 by ttanjo — 2022-03-15T06:29:30Z
I reduced the code as follows. It uses `allSatisfy` and `isAssignable` but they are not changed since v2.098.1. It seems that the source of the problem is in dmd rather than phobos or druntime. run.dlang.io: https://run.dlang.io/is/ZPTIcH ```d import core.internal.traits : allSatisfy, isAssignable; struct None{} class C1 { static if(allSatisfy!(isAssignable, None, C2)) {} } class C2 { static if(allSatisfy!(isAssignable, None, C1, C2)) {} } void main() {} ```
Comment #2 by ttanjo — 2022-03-15T06:32:31Z
Here is the error message caused by the reduced code: ```console > rdmd playground.d /dlang/dmd/linux/bin64/../../src/druntime/import/core/internal/traits.d(193): Error: forward reference of variable `isAssignable` onlineapp.d(12): Error: template instance `core.internal.traits.allSatisfy!(isAssignable, None, C1, C2)` error instantiating /dlang/dmd/linux/bin64/../../src/druntime/import/core/internal/traits.d(193): Error: template instance `core.internal.traits.F!(C2, C2)` error instantiating onlineapp.d(7): instantiated from here: `allSatisfy!(isAssignable, None, C2)` ```
Comment #3 by ttanjo — 2022-03-18T12:51:24Z
I reduced it as follows: ```d private struct __InoutWorkaroundStruct {} @property T rvalueOf(T)(T val) { return val; } @property T rvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init); @property ref T lvalueOf(T)(inout __InoutWorkaroundStruct = __InoutWorkaroundStruct.init); // taken from std.traits.isAssignable template isAssignable(Lhs, Rhs = Lhs) { enum isAssignable = __traits(compiles, lvalueOf!Lhs = rvalueOf!Rhs) && __traits(compiles, lvalueOf!Lhs = lvalueOf!Rhs); } // taken from std.meta.allSatisfy template allSatisfy(alias F, T...) { static foreach (Ti; T) { static if (!is(typeof(allSatisfy) == bool) && // not yet defined !F!(Ti)) { enum allSatisfy = false; } } static if (!is(typeof(allSatisfy) == bool)) // if not yet defined { enum allSatisfy = true; } } struct None{} class C1 { static if(allSatisfy!(isAssignable, None, C2)) {} } class C2 { static if(allSatisfy!(isAssignable, None, C1, C2)) {} } void main() {} ``` Finally, I found that it was introduced by https://github.com/dlang/dmd/pull/13588. Here is an output of `git bisect`: ```console $ cat test.sh #!/bin/sh make -f posix.mak AUTO_BOOTSTRAP=1 -j ./generated/linux/release/64/dmd -c issue22859.d $ git bisect start v2.099.0 v2.089.1 $ git bisect run ./test.sh ... 5436d4d167e41f59b799071d8136bb051c87ae56 is the first bad commit commit 5436d4d167e41f59b799071d8136bb051c87ae56 Author: Iain Buclaw <[email protected]> Date: Sun Jan 30 16:42:45 2022 +0100 fix Issue 22714 - ICE: Assertion failure in ClassDeclaration::isBaseOf ... ``` Note: To make it bisectable, I fixed /workspaces/druntime/src/core/sys/darwin/mach/nlist.d (L225 only) to v2.098.1.
Comment #4 by dlang-bot — 2022-03-18T13:17:20Z
@ibuclaw created dlang/dmd pull request #13839 "fix Issue 22859 - Error: forward reference of variable 'isAssignable' for mutually recursed 'allSatisfy'" fixing this issue: - fix Issue 22859 - Error: forward reference of variable 'isAssignable' for mutually recursed 'allSatisfy' https://github.com/dlang/dmd/pull/13839
Comment #5 by dlang-bot — 2022-03-18T15:59:12Z
dlang/dmd pull request #13839 "fix Issue 22859 - Error: forward reference of variable 'isAssignable' for mutually recursed 'allSatisfy'" was merged into stable: - 7b1675e32eff8854f565ed25c235f5a6292b8595 by Iain Buclaw: fix Issue 22859 - Error: forward reference of variable 'isAssignable' for mutually recursed 'allSatisfy' https://github.com/dlang/dmd/pull/13839
Comment #6 by dlang-bot — 2022-03-27T02:24:31Z
dlang/dmd pull request #13892 "Merge stable into master" was merged into master: - 4b7a7c3a2ac34b0834f968b503c801ca203e4d01 by Iain Buclaw: fix Issue 22859 - Error: forward reference of variable 'isAssignable' for mutually recursed 'allSatisfy' https://github.com/dlang/dmd/pull/13892