Bug 20025 – alias this combined with a copy constructor seems to lead to undefined behaviour.
Status
RESOLVED
Resolution
FIXED
Severity
normal
Priority
P1
Component
dmd
Product
D
Version
D2
Platform
x86_64
OS
Linux
Creation time
2019-07-04T07:08:35Z
Last change time
2019-07-04T12:20:14Z
Keywords
pull
Assigned to
No Owner
Creator
big.friendian
Comments
Comment #0 by big.friendian — 2019-07-04T07:08:35Z
Running the following code prints a random integer every time. If the copy constructor is removed, the code functions as expected (prints '77').
import std.stdio;
struct B
{
static int value = 77;
alias value this;
this(ref return scope inout B rhs) inout { }
}
void test(int x)
{
writefln("x: %s", x);
}
int main()
{
B b;
test(b);
return 0;
}
Comment #1 by simen.kjaras — 2019-07-04T08:16:10Z
A slightly more elucidating example:
struct B {
static int value = 77;
alias value this;
int i = 13;
this(ref B rhs) { }
}
void test(ref int x, ref B b) {
import std.stdio : writeln;
writeln("x: ", &x, " = ", x);
writeln("b: ", &b);
}
unittest {
B b;
test(b, b);
}
x is now consistently 13, and &x == &b. IOW, alias this is somehow forgetting that value is a static field, and treats it as non-static.
Comment #2 by big.friendian — 2019-07-04T08:56:38Z
The 'static' might be a bit of a red herring, in the code I wrote, I get the same behaviour whether 'value' is static or not.
Comment #3 by dlang-bot — 2019-07-04T09:12:30Z
@RazvanN7 created dlang/dmd pull request #10137 "Fix Issue 20025 - alias this combined with a copy constructor seems to lead to undefined behaviour." fixing this issue:
- Fix Issue 20025 - alias this combined with a copy constructor seems to lead to undefined behaviour.
https://github.com/dlang/dmd/pull/10137
Comment #4 by simen.kjaras — 2019-07-04T09:28:07Z
There seems to be a lot inconsistencies here. This code:
struct S(bool _static, bool _field) {
static if (_static) static int value = 77;
else int value = 77;
static if (_field) int field = 13;
alias value this;
this(ref S rhs) { }
string toString() { return (_static ? "static, " : "non-static, ") ~ (_field ? "field" : "empty"); }
}
void test(T)(int i, ref int j, T t) {
import std.stdio;
writeln(t, ":");
writeln(" by val: ", i);
writeln(" by ref: ", j);
}
void test(T)(T t) {
test(t, t, t);
}
unittest {
test(S!(true, true)());
test(S!(true, false)());
test(S!(false, true)());
test(S!(false, false)());
}
Prints this on my machine (2.087.0):
static, field:
by val: 77
by ref: 13
static, empty:
by val: 7771469
by ref: 0
non-static, field:
by val: 77
by ref: 77
non-static, empty:
by val: 77
by ref: 77
And this on run.dlang.io (also 2.087.0):
static, field:
by val: 2007830860
by ref: 13
static, empty:
by val: 2007830868
by ref: 0
non-static, field:
by val: 2007830848
by ref: 77
non-static, empty:
by val: 2007830860
by ref: 77
The correct behavior, of course, is what's seen on my machine for both the non-static cases.
Comment #5 by dlang-bot — 2019-07-04T12:20:14Z
dlang/dmd pull request #10137 "Fix Issue 20025 - alias this combined with a copy constructor seems to lead to undefined behaviour." was merged into stable:
- dde9964028a7cddcda7effb54dba384f358a1bb6 by RazvanN7:
Fix Issue 20025 - alias this combined with a copy constructor seems to lead to undefined behaviour.
https://github.com/dlang/dmd/pull/10137