Bug 7940 – CTFE wrong-code for opAssign and std.array.Appender
Status
RESOLVED
Resolution
FIXED
Severity
critical
Priority
P2
Component
dmd
Product
D
Version
D2
Platform
All
OS
All
Creation time
2012-04-18T21:12:00Z
Last change time
2015-06-09T05:10:43Z
Keywords
CTFE, wrong-code
Assigned to
nobody
Creator
iteronvexor
Comments
Comment #0 by iteronvexor — 2012-04-18T21:12:05Z
DMD 2.059 64-bit Gnu/Linux
----------------8<----------------8<----------------
import std.typecons : Tuple;
import std.array : appender;
import std.algorithm : sort;
import std.stdio : writeln;
alias double Real;
struct S {
Tuple!(uint, Real)[] _data;
alias _data this;
}
private auto gen(K, V)(V[K] data) {
alias Tuple!(K, V) T;
auto app = appender!(T[]);
foreach(k, v; data)
app.put(T(k, v));
sort(app.data);
return app.data;
}
auto s(Real[uint] data) {
return S(gen!(uint, Real)(data));
}
static S s1 = s([1: 12.0, 5: 4.6, 3: 9.99]);
void main() {
S s2 = s([1: 12.0, 5: 4.6, 3: 9.99]);
// prints [Tuple!(uint,double)(0, nan), Tuple!(uint,double)(0, nan), Tuple!(uint,double)(0, nan)]
writeln(s1);
// prints [Tuple!(uint,double)(1, 12), Tuple!(uint,double)(3, 9.99), Tuple!(uint,double)(5, 4.6)]
writeln(s2);
}
---------------->8---------------->8----------------
Comment #1 by lovelydear — 2012-04-21T13:07:06Z
Same code as above, very slightly simplified.
-----------------
import std.typecons : Tuple;
import std.array : appender;
import std.stdio : writeln;
struct S {
Tuple!(uint, double)[] _data;
alias _data this;
}
private auto gen(K, V)(V[K] data) {
alias Tuple!(K, V) T;
auto app = appender!(T[]);
foreach(k, v; data) app.put(T(k, v));
return app.data;
}
auto s(double[uint] data) {
return S(gen!(uint, double)(data));
}
void main() {
static S s1 = s([1: 12.0, 5: 4.6, 3: 9.99]);
S s2 = s([1: 12.0, 5: 4.6, 3: 9.99]);
writeln(s1);
writeln(s2);
}
------------------
PS E:\DigitalMars\dmd2\samples> rdmd -g bug.d
[Tuple!(uint,double)(0, nan), Tuple!(uint,double)(0, nan), Tuple!(uint,double)(0, nan)]
[Tuple!(uint,double)(1, 12), Tuple!(uint,double)(3, 9.99), Tuple!(uint,double)(5, 4.6)]
If we remove the static, it works.
If we replace the appender by an array in:
import std.typecons : Tuple;
import std.array : appender;
import std.stdio : writeln;
struct S {
Tuple!(uint, double)[] _data;
alias _data this;
}
private auto gen(K, V)(V[K] data) {
alias Tuple!(K, V) T;
T[] app;
foreach(k, v; data) app ~= T(k, v);
return app;
}
auto s(double[uint] data) {
return S(gen!(uint, double)(data));
}
void main() {
static S s1 = s([1: 12.0, 5: 4.6, 3: 9.99]);
S s2 = s([1: 12.0, 5: 4.6, 3: 9.99]);
writeln(s1);
writeln(s2);
}
PS E:\DigitalMars\dmd2\samples> rdmd -g bug.d
[Tuple!(uint,double)(1, 12), Tuple!(uint,double)(5, 4.6), Tuple!(uint,double)(3, 9.99)]
[Tuple!(uint,double)(1, 12), Tuple!(uint,double)(3, 9.99), Tuple!(uint,double)(5, 4.6)]
If we remove the static:
PS E:\DigitalMars\dmd2\samples> rdmd -g bug.d
[Tuple!(uint,double)(1, 12), Tuple!(uint,double)(3, 9.99), Tuple!(uint,double)(5, 4.6)]
[Tuple!(uint,double)(1, 12), Tuple!(uint,double)(3, 9.99), Tuple!(uint,double)(5, 4.6)]
Comment #2 by clugdbug — 2012-06-26T23:42:55Z
Could be a CTFE compiler bug, but more likely to
be a bug in the if (__ctfe) code in std.array.Appender.
I don't trust array.Appender anyway. I see no reason for it not be @safe.
It shouldn't be using pointers at all.
Reduced test case:
-----------------
import std.array : appender;
struct Bug7940 {
int field0;
void opAssign(Bug7940 rhs) {
field0 = rhs.field0;
}
}
Bug7940[] gen() {
alias Bug7940 T;
auto app = appender!(T[]);
app.put(T(12));
assert(app.data[0].field0 == 12);
return app.data;
}
void main() {
static const ww = gen();
}
Comment #3 by clugdbug — 2012-11-06T08:42:28Z
Reduced test case shows it's a subtle CTFE bug, involving assignment to a member of a struct which is an element of a slice inside a struct.
----------
struct Bug7940 {
int m;
}
struct App7940 {
Bug7940[] x;
}
int bug7940() {
Bug7940[2] y;
App7940 app;
app.x = y[0..1];
app.x[0].m = 12;
assert(y[0].m == 12);
assert(app.x[0].m == 12); // also fails
return 1;
}
static assert(bug7940());
Comment #4 by github-bugzilla — 2012-11-07T16:29:55Z