DateTime trying to do it at compile time.

Jonathan M Davis newsgroup.d at jmdavisprog.com
Thu Oct 26 21:18:54 UTC 2017


On Thursday, October 26, 2017 17:55:05 Mr. Jonse via Digitalmars-d-learn 
wrote:
> C:\D\dmd2\windows\bin\..\..\src\phobos\std\concurrency.d(2395):
> Error: variable lock cannot be modified at compile time
> C:\D\dmd2\windows\bin\..\..\src\phobos\std\concurrency.d(2422):
>       called from here: initOnceLock()
> C:\D\dmd2\windows\bin\..\..\src\phobos\std\concurrency.d(2422):
>       called from here: initOnce(delegate shared(bool)() =>
> init(), initOnceLock())
> C:\D\dmd2\windows\bin\..\..\src\phobos\std\datetime\timezone.d(1128):
>   called from here: initOnce(delegate shared(bool)() => (*function () =>
> true)())
> C:\D\dmd2\windows\bin\..\..\src\phobos\std\datetime\timezone.d(583):
>   called from here: (*& singleton)()
> C:\D\dmd2\windows\bin\..\..\src\phobos\std\datetime\systime.d(64):
> called from here: opCall()
>
> when calling Clock.currTime() in a this() in a class. I have no
> idea why it is trying to do it at compile time and failing. I
> thought if ctfe couldn't compile it would do it at run time
> anyways? Seems like a bug.

It's very black and white with CTFE. The compiler never does CTFE unless it
has to (e.g. you're initializing a enum, or you're directly initializing a
static variable or member variable). So, it's not going to do CTFE as an
optimization anywhere (though a number of folks mistakenly think that it
will). And if it does CTFE, then CTFE must succeed. The compiler is never
going to decide that something failed at CTFE, so it will just do it at
runtime instead. It's doing CTFE, because it requires a result that must be
known at compile time.

So, clearly, the class that calls Clock.currTime in its constructor is being
constructed at compile time, which isn't going to work, because
Clock.currTime accesses the system's C API to get the time (and you almost
certainly wouldn't want the time the code was compiled anyway). I'd guess
that Rene's suggestion is correct and that you're directly initializing a
member variable somewhere that's of this class type. It's either that or
you're directly initializing a module-level variable, a static variable, or
an enum of that class type - _or_ you're doing something else at CTFE that
ultimately calls a function that is constructing an instance of one of these
classes.

Ultimately, you either need to not be constructing an instance of this class
at compile time, or you need to make it so that it will work at compile time
without getting the current time (or doing anything else that can't be done
at compile time).

if(__ctfe)
{}

can be used to create branches that do something different during CTFE so
that they can function during CTFE even though they would normally do
something that wouldn't work during CTFE (e.g. if you have an algorithm that
uses pointer arithmetic for performance, you could provide an alternate
implementation for compile time that was slower, because it didn't use
pointer arithmetic, but at least it would then work at compile time).

I'd guess though that in this case, you're simply directly initializing a
variable whose value must be known at compile time, in which case, the
solution would likely be to not directly initialize it.

- Jonathan M Davis



More information about the Digitalmars-d-learn mailing list