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