www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - What does this compile-time error mean?

reply Alexandr Druzhinin <drug2004 bk.ru> writes:
This code:

import std.stdio;
import std.container;
import std.range;

auto main_cont = redBlackTree(iota(0, 100, 10).array);

void main() {

    writeln(main_cont.array);
}

at compilation with dmd 2.062 generates:

D:\applications\D\dmd2\windows\bin\..\..\src\druntime\import
core\memory.d(316): 
Error: gc_malloc cannot be interpreted at compile time, because it has 
no available source code
D:\applications\D\dmd2\windows\bin\..\..\src\phobos\std\array.d(321): 
      called from here: malloc(_param_0 * 4u, 2u)
D:\applications\D\dmd2\windows\bin\..\..\src\phobos\std\array.d(272): 
      called from here: arrayAllocImpl(_param_0)
D:\applications\D\dmd2\windows\bin\..\..\src\phobos\std\array.d(45): 
     called from here: uninitializedArray(r.length())
src\main.d(5):        called from here: array(iota(0, 100, 10))
src\main.d(5):        called from here: redBlackTree(array(iota(0, 100, 
10)))

Is it my error?
Feb 24 2013
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, February 24, 2013 15:42:33 Alexandr Druzhinin wrote:
 This code:
 
 import std.stdio;
 import std.container;
 import std.range;
 
 auto main_cont = redBlackTree(iota(0, 100, 10).array);
 
 void main() {
 
     writeln(main_cont.array);
 }
 
 at compilation with dmd 2.062 generates:
 
 D:\applications\D\dmd2\windows\bin\..\..\src\druntime\import\core\memory.d(3
 16): Error: gc_malloc cannot be interpreted at compile time, because it has
 no available source code
 D:\applications\D\dmd2\windows\bin\..\..\src\phobos\std\array.d(321):
       called from here: malloc(_param_0 * 4u, 2u)
 D:\applications\D\dmd2\windows\bin\..\..\src\phobos\std\array.d(272):
       called from here: arrayAllocImpl(_param_0)
 D:\applications\D\dmd2\windows\bin\..\..\src\phobos\std\array.d(45):
      called from here: uninitializedArray(r.length())
 src\main.d(5):        called from here: array(iota(0, 100, 10))
 src\main.d(5):        called from here: redBlackTree(array(iota(0, 100,
 10)))
 
 Is it my error?
Because main_cont is module-level variable, it must be initialized with a value at compile time. Classes can be used at compile time (at least some of the time), but they cannot stick around between compile time and runtime, meaning that you could potentially use them in a CTFE function, but you can't initialize a module-level or static variable (or enum) with them, and you're attempting to initialize maint_cont with a RedBlackTree, which is a class. It won't work. Now, on top of that, given those particular errors, it looks like there may be other issues beyond that which prevent RedBlackTree and/or std.array.array from being used at compile time at all, but even if it were perfectly useable at compile time, it still couldn't persist after the code is compiled and therefore could not be assigned to maint_cont. If you want to have main_cont be a RedBlackTree, you need to iniatialize it at runtime. To do that, you could do that something like RedBlackTree!int main_cont; static this() { main_cont = redBlackTree(iota(0, 100, 10).array()); } - Jonathan M Davis
Feb 24 2013
next sibling parent Alexandr Druzhinin <drug2004 bk.ru> writes:
24.02.2013 15:59, Jonathan M Davis пишет:
 Because main_cont is module-level variable, it must be initialized with a
 value at compile time. Classes can be used at compile time (at least some of
 the time), but they cannot stick around between compile time and runtime,
 meaning that you could potentially use them in a CTFE function, but you can't
 initialize a module-level or static variable (or enum) with them, and you're
 attempting to initialize maint_cont with a RedBlackTree, which is a class. It
 won't work.

 Now, on top of that, given those particular errors, it looks like there may be
 other issues beyond that which prevent RedBlackTree and/or std.array.array
 from being used at compile time at all, but even if it were perfectly useable
 at compile time, it still couldn't persist after the code is compiled and
 therefore could not be assigned to maint_cont.

 If you want to have main_cont be a RedBlackTree, you need to iniatialize it at
 runtime. To do that, you could do that something like

 RedBlackTree!int main_cont;

 static this()
 {
      main_cont = redBlackTree(iota(0, 100, 10).array());
 }

 - Jonathan M Davis
I see. Thank you!
Feb 24 2013
prev sibling parent reply "Maxim Fomin" <maxim maxim-fomin.ru> writes:
On Sunday, 24 February 2013 at 09:00:17 UTC, Jonathan M Davis 
wrote:
 Because main_cont is module-level variable, it must be 
 initialized with a
 value at compile time. Classes can be used at compile time (at 
 least some of
 the time), but they cannot stick around between compile time 
 and runtime,
 meaning that you could potentially use them in a CTFE function, 
 but you can't
 initialize a module-level or static variable (or enum) with 
 them, and you're
 attempting to initialize maint_cont with a RedBlackTree, which 
 is a class. It
 won't work.

 - Jonathan M Davis
I would say that it is arbitrary restriction class C { } struct S { int[] array; this(int val[]) { array = val; } } //can issue call to runtime allocator enum EA : int[] { //does not complain that gc_malloc() is absent A = [1, 6] } //can evaluate dynamically allocated referenced type at CT static assert(EA.init == [1, 6]); // can have module-level object // evaluated to non-trivial CTFE initializer EA ea; enum ES : S { //can issue call to constructor A = S([2, 9]) } // can evaluate this static assert (ES.init.array == [2, 9]); // can have module-level object // evaluated to non-trivial CTFE initializer ES es; //but classes don't work enum EC : C { // B = new C //NG - why not here? // why cannot call ga_malloc here? A = null } void main() { assert(ea == [1, 6]); assert(es.array == [2, 9]); C c; int[] arr; assert (c is null && arr is null); EA e; assert(e !is null && e == [1, 6]); } In short, if interpreter can dynamically allocate reference types like dynamic arrays, store them in TLS storage and interpret trivial CTFE struct constructor, it can handle classes. At least it can work without gc_malloc source.
Feb 24 2013
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 02/24/2013 01:59 PM, Maxim Fomin wrote:
 On Sunday, 24 February 2013 at 09:00:17 UTC, Jonathan M Davis wrote:
 Because main_cont is module-level variable, it must be initialized with a
 value at compile time. Classes can be used at compile time (at least
 some of
 the time), but they cannot stick around between compile time and runtime,
 meaning that you could potentially use them in a CTFE function, but
 you can't
 initialize a module-level or static variable (or enum) with them, and
 you're
 attempting to initialize maint_cont with a RedBlackTree, which is a
 class. It
 won't work.

 - Jonathan M Davis
I would say that it is arbitrary restriction ...
Yes, IIRC Don once stated that it is a problem with DMD's architecture.
Feb 24 2013
parent reply Jonathan M Davis <jmdavisProg gmx.com> writes:
On Sunday, February 24, 2013 14:05:26 Timon Gehr wrote:
 On 02/24/2013 01:59 PM, Maxim Fomin wrote:
 On Sunday, 24 February 2013 at 09:00:17 UTC, Jonathan M Davis wrote:
 Because main_cont is module-level variable, it must be initialized with a
 value at compile time. Classes can be used at compile time (at least
 some of
 the time), but they cannot stick around between compile time and runtime,
 meaning that you could potentially use them in a CTFE function, but
 you can't
 initialize a module-level or static variable (or enum) with them, and
 you're
 attempting to initialize maint_cont with a RedBlackTree, which is a
 class. It
 won't work.
 
 - Jonathan M Davis
I would say that it is arbitrary restriction ...
Yes, IIRC Don once stated that it is a problem with DMD's architecture.
Most restrictions in CTFE are a limitation of the current implementation rather than being something that's literally impossible to do (though some like the lack of source code aren't). In the case of a class, I believe that it would have to basically serialize the class at compile time and then deserialize it at runtime to do it. That's certainly possible to do in theory, but it's well beyond what the current CTFE implementation can do. - Jonathan M Davis
Feb 24 2013
parent "Don" <turnyourkidsintocash nospam.com> writes:
On Sunday, 24 February 2013 at 19:13:47 UTC, Jonathan M Davis 
wrote:
 On Sunday, February 24, 2013 14:05:26 Timon Gehr wrote:
 On 02/24/2013 01:59 PM, Maxim Fomin wrote:
 On Sunday, 24 February 2013 at 09:00:17 UTC, Jonathan M 
 Davis wrote:
 Because main_cont is module-level variable, it must be 
 initialized with a
 value at compile time. Classes can be used at compile time 
 (at least
 some of
 the time), but they cannot stick around between compile 
 time and runtime,
 meaning that you could potentially use them in a CTFE 
 function, but
 you can't
 initialize a module-level or static variable (or enum) with 
 them, and
 you're
 attempting to initialize maint_cont with a RedBlackTree, 
 which is a
 class. It
 won't work.
 
 - Jonathan M Davis
I would say that it is arbitrary restriction ...
Yes, IIRC Don once stated that it is a problem with DMD's architecture.
Most restrictions in CTFE are a limitation of the current implementation rather than being something that's literally impossible to do (though some like the lack of source code aren't). In the case of a class, I believe that it would have to basically serialize the class at compile time and then deserialize it at runtime to do it. That's certainly possible to do in theory, but it's well beyond what the current CTFE implementation can do. - Jonathan M Davis
Yeah, this one is a limitation of the runtime, not of CTFE. CTFE has no problem with it.
Feb 25 2013