On 11/18/2017 6:16 AM, Timon Gehr wrote:
On 18.11.2017 05:05, Walter Bright wrote:
On 11/17/2017 6:05 AM, Timon Gehr wrote:
There are type systems that do that, which is what is being proposed for C#. It's pretty straightforward: If I have a variable of class reference type C, it actually contains a reference to a class instance of type C.

One of the difficulties with this is you'll still need an "empty" instance of C for the non-null reference to point to.

Why would you need an empty instance?

Consider the ClassDeclaration in the DMD source. Each ClassDeclaration has a pointer to its base class, `baseClass`. Except for `Object`, which doesn't have a base class. This is represented to assigning `null` to `baseClass`.

So I can run up the base class list by:

    for (b = c; b; b = b.baseClass) { ... }

If it cannot be null, I just have to invent something else that does the same 
thing:

    for (b = c; b != nullInstanceOfClass; b = b.baseClass) { ... }

and nothing really has changed.

Just use a Nullable!C instead of a C if a special 'null' state is actually required.

What should the default initializer for a type do?


Any attempts to use a method on the empty instance should throw.

The idea is that the type system makes potential such attempts explicit while verifying that they don't occur in most of the cases. Then you can grep for potential null dereferences.

There are cases where the actual path taken guarantees initialization, but the graph of all paths does have uninitialized edges. Figuring out which are paths never taken is the halting problem. I found this out when testing my DFA (data flow analysis) algorithms.

  void test(int i) {
    int* p = null;
    if (i) p = &i;
    ...
    if (i) *p = 3;
    ...
  }

Note that the code is correct, but DFA says the *p could be a null dereference. (Replace (i) with any complex condition that there's no way the DFA can prove always produces the same result the second time.)

Reply via email to