D issues are now tracked on GitHub. This Bugzilla instance remains as a read-only archive.
Issue 6114 - immutable class variable not properly initialized when the constructor initializing it is non-shared
Summary: immutable class variable not properly initialized when the constructor initia...
Status: RESOLVED DUPLICATE of issue 4923
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 normal
Assignee: No Owner
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-06-05 23:31 UTC by Jonathan M Davis
Modified: 2017-07-07 14:09 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Jonathan M Davis 2011-06-05 23:31:52 UTC
This is related to bug# 6113. If you go into std.datetime and change the static constructors which initialize UTC._utc or LocalTime._localTime (search for "_utc =" or "_localTime =" - minus the quotes - to find them quickly), then this code will fail:

import std.datetime;

shared static this()
{
  assert(UTC() !is null);
  assert(LocalTime() !is null);
}

void main()
{}


As long as those static constructors are shared, then this code is fine. But if they're not shared, then the assertions fail. I believe that this is related to bug# 4923 and the fact that immutable global variables and immutable static variables are implicitly shared. I really think that the language should be altered such that it be an error to attempt to initialize an immutable global variable or immutable static variable in a non-shared constructor. Since, they're implicitly shared, it doesn't make sense to initialize them in a thread-local manner anyway. And it's obviously causing problems as-is.
Comment 1 Brad Roberts 2011-06-06 00:21:37 UTC
While you've framed this as related to immutable (and I agree with your assessment), there's a broader problem of the definition of order of initialization.  For the main thread, is it one or two passes?
Comment 2 Steven Schveighoffer 2011-06-08 10:41:02 UTC
I agree with Jonathan, immutables should not be assignable in non-shared ctors.

The runtime works like this:

1. program startup
2. run all shared static ctors
3. run all thread-local static ctors
4. run application
   4a. on thread creation, run all thread-local static ctors
   4b. on thread destruction, run all thread-local static dtors
5. run all thread-local static dtors
6. run all shared static dtors.
7. end program

So everything is unraveled the same way it was, um... raveled :)

I think since immutable means 'store globally', it should be only assignable from a shared ctor.  Otherwise, you run into issues.
Comment 3 Vladimir Panteleev 2017-07-05 16:30:03 UTC
Jonathan, if this is still an issue, could you please post a complete self-contained minimal example?
Comment 4 Jonathan M Davis 2017-07-05 17:14:59 UTC
Really, the larger issue is this one bug# 4923, and maybe this should be closed given that this is really just another manifestation of that, though if I can fix the example for this so that it's self-contained, it's a different sort of example for why immutable globals need to be initialized in shared, static constructors rather than thread-local ones.
Comment 5 Jonathan M Davis 2017-07-05 17:20:53 UTC
Okay, self-contained example:

bug.d
--------
class C
{
}

immutable C theC;

static this()
{
    theC = new immutable C;
}
--------

test.d
--------
import bug;

shared static this()
{
    assert(theC !is null);
}

void main()
{
}
--------

The assertion fails, but if you make the static constructor in bug.d shared, then it doesn't.
Comment 6 Steven Schveighoffer 2017-07-06 19:12:15 UTC
The example isn't exactly pointing out the error.

There are 2 problems here, one is an expectation that a non-shared static ctor might run before the shared one (it doesn't, the order is clearly defined). That's not really a bug.

The second is that immutable (shared) data is changing from one thread to the next.

I think this should be closed as a dup of 4923.

*** This issue has been marked as a duplicate of issue 4923 ***
Comment 7 Vladimir Panteleev 2017-07-07 06:45:59 UTC
Thanks!
Comment 8 Jonathan M Davis 2017-07-07 14:09:23 UTC
(In reply to Steven Schveighoffer from comment #6)
> The example isn't exactly pointing out the error.
> 
> There are 2 problems here, one is an expectation that a non-shared static
> ctor might run before the shared one (it doesn't, the order is clearly
> defined). That's not really a bug.
> 
> The second is that immutable (shared) data is changing from one thread to
> the next.

Really. what this shows is a side effect of the fact that it's currently possible to instantiate an object that's treated as shared in a non-shared, static constructor. It's the fact that the compiler let's you initialize non-local immutable variables in a non-shared, static constructor that's the bug. And once that's fixed, this problem goes away.

> I think this should be closed as a dup of 4923.

They're different symptoms of the same bug. So, I have no problem with that.