In the last post on this topic i talked about how it was critical that by the time a non-null type was used it was provably assigned some non-null value.  The cases that came up were specifically instance fields in classes.  In that post i showed how would could change how types were initialized to ensure that that these non-null constraints could be met.

However, there is another type of field out there: static fields.   And it turns out that these fields are  much harder to deal with than instance fields.  Why?  Well, let's take a look at a simple example:
class Person {
public static string! name;
}
How do we initialize that field?  Well, we could start with a static constructor like so:
class Person {
public static string! name;

static Person() {
a = new Cyrus().name;
}
}

class Cyrus {
public static string! name = "cyrus";
}

Ok.  Seems like this would work out and you'd end up with all non-null "name"'s being assigned a value.  However, let's extend that a little further:
class Cyrus {
public static string! name = "cyrus";

public Cyrus() {
Cyrus.name = Person.name;
}
}

Uh oh.  Now we've got a problem.  Everything looks typesafe, but when the Person class loads, it will call the 'Cyrus' constructor which will then access the "Person.name" field before it has been initialized!  Not good!

As it turns out this is the same problem as the instance-field issue from the last post.  As i mentioned there, determining the set of code that is dependent on a constraint is extremely difficult and so we need a more restrictive set of rules that we can work with in order to be able to reason about this properly.

In order to support the instance fields case we placed the restriction that before the "this" pointer could be used, it has to be the case that all the non-nullable fields had been assigned to.  Can we extend that idea out to static fields?  Since there is no "this" pointer we would have to say something like "before you can use the actual type containing the static field, all fields must be assigned to".  

This is a much more limiting set of circumstances, and far harder to enforce.  With instance fields you at least have access to a rich set of inputs to initialize them with.  You can use static data in the system, or you can use parameters passed into a constructor.  With static fields things are not so clear cut.  As you can see above, arbitrary code can't be run as that code might statically access the type being constructed.  Also, as static constructors don't take any parameters it's hard to find inputs to assign to these fields.

So what can be done about this?  It's not clear to me what the best solution is.  The easiest solution is to simply disallow static non-nullable types.  But that would suck since i think that people really want them.  The next easiest would be to have non-nullable static fields, but guard all read/writes to them to check for null.  That would put the onus on the programmer to ensure that it's value is set before use, but it means that suddenly accessing this field could fail at runtime.  Ugh*2.  The final thing that i can think would be a solution like the following inside the runtime:

  1. When loading a type that has non-nullable static fields, start executing the static cosntructor
  2. When the static constructor enters, set a bit saying that the type is currently being constructed.  Then, if a static non-nullable field in that type is ever accessed by anyone else, throw an exception saying that this type wasn't fully initialized and it's invalid to access non-null static state yet.
  3. If the code executed in the static constructor then causes something like the above situation to happen, then you'll immediately fail at typeload time.
This has the unfortunate outcome that the checking is still done at runtime.  however, it will most likely occur early on when all your types are being loaded, and not much later on the first access of one of these fields.

In essence, what we've done is enforce a quasi ordering on how types are loaded in the runtime.  As a type loads it can access static non-nullable fields in any fully loaded type, but not in a type that is still being loaded.

It's ugly, but i can't think of anything better.  Do you guys have any ideas?