Comment #0 by bearophile_hugs — 2014-03-08T07:02:11Z
import std.array: array;
struct Foo1 {
int i;
}
struct Foo2 {
immutable int i;
}
void main() {
enum r1 = [Foo1(1)].array; // OK
enum r2 = [Foo2(1)].array; // Error
}
dmd 2.066alpha gives:
...\dmd2\src\phobos\std\conv.d(3908,23): Error: memcpy cannot be interpreted at compile time, because it has no available source code
...\dmd2\src\phobos\std\array.d(45,23): called from here: emplaceRef(result[i], e)
temp.d(10,24): called from here: array([Foo2(1)])
Comment #1 by peter.alexander.au — 2014-03-09T05:00:05Z
Changing this to dmd CTFE bug. I can't think of any way to solve it in Phobos without more compiler support.
Comment #2 by bearophile_hugs — 2014-03-09T05:26:20Z
(In reply to comment #1)
> Changing this to dmd CTFE bug. I can't think of any way to solve it in Phobos
> without more compiler support.
This seems to work:
import std.traits: ForeachType;
ForeachType!R[] myArray(R)(R r) {
if (__ctfe) {
typeof(return) result;
foreach (item; r)
result ~= r;
return result;
} else {
// ...
assert(0);
}
}
struct Foo1 {
int i;
}
struct Foo2 {
immutable int i;
}
void main() {
enum r1 = [Foo1(1)].myArray; // OK
enum r2 = [Foo2(1)].myArray; // OK
}
Comment #3 by peter.alexander.au — 2014-03-09T06:46:00Z
(In reply to comment #2)
> (In reply to comment #1)
> > Changing this to dmd CTFE bug. I can't think of any way to solve it in Phobos
> > without more compiler support.
>
> This seems to work:
... why didn't I think of that :-)
I'll make the pull.
Comment #4 by bearophile_hugs — 2014-03-09T06:59:29Z
(In reply to comment #3)
> I'll make the pull.
There are also assumeSafeAppend, reserve/capacity, and so on. I don't know if they speedup the code at compile-time too.
Comment #5 by peter.alexander.au — 2014-03-09T07:01:52Z
Comment #6 by bearophile_hugs — 2014-03-09T07:11:11Z
(In reply to comment #5)
> There are also assumeSafeAppend, reserve/capacity, and so on. I don't know if
> they speedup the code at compile-time too.
It seems code like this doesn't yet work:
import std.traits: ForeachType;
import std.range: hasLength;
ForeachType!R[] myArray(R)(R r) {
if (__ctfe) {
typeof(return) result;
static if (hasLength!R)
result.reserve = r.length;
foreach (item; r)
result ~= r;
return result;
} else {
// ...
assert(0);
}
}
struct Foo1 {
int i;
}
struct Foo2 {
immutable int i;
}
void main() {
enum r1 = [Foo1(1)].myArray; // OK
enum r2 = [Foo2(1)].myArray; // OK
}
Comment #7 by github-bugzilla — 2014-03-09T12:06:52Z
Reopening because I'm not sure it's worth filing something new, but `Appender` will also CTFE fail on the same types.
Comment #9 by dlang-bugzilla — 2017-07-02T02:22:09Z
(In reply to monarchdodra from comment #8)
> Reopening because I'm not sure it's worth filing something new, but
> `Appender` will also CTFE fail on the same types.
Can't reproduce this:
import std.array;
struct Foo1 {
int i;
}
struct Foo2 {
immutable int i;
}
T[] fun(T)()
{
auto a = appender!(T[]);
return a.data;
}
enum foo1 = fun!Foo1();
enum foo2 = fun!Foo2();
In any case, it should be filed as a separate bug.