Non-nullable references, again

Daniel Keep daniel.keep.lists at gmail.com
Tue Dec 30 21:37:56 PST 2008



dsimcha wrote:
>>> 50% of the bugs that people run into today, coding with C# in our
>>> platform, and the same is true of Java for that matter, are probably
>>> null reference exceptions.
> 
> Yes, but even if this is accurate, it's misleading.  Very seldom are null
> references difficult-to-find, time-consuming bugs.  Most other things in D and
> other languages that are designed to prevent specific classes of bugs are designed
> to prevent extremely aggravating, hard to track down bugs.
> 
> For example, GC was invented because tracking down memory leaks is a huge PITA.
> Bounds checking was invented because off-by-one errors can be subtle and hard to
> find.  Null reference errors, on the other hand, manifest themselves in a
> predictable way (segfaults), and if you're using the safe memory model, i.e.
> bounds checking, no pointers, that's about the only thing a segfault could mean.
> Furthermore, null checking could be added to an implementation kind of like bounds
> checking without changing the language spec.  I haven't made up my mind fully yet,
> but I question whether adding lots of complexity to the language to prevent a very
> easy to track down class of bugs, even if it's a common one, is justified.

I find this counterpoint to be a bit iffy.  The problem with null 
dereference problems isn't knowing that they're there: that's the easy 
part.  You helpfully get an exception to the face when that happens. 
The hard part is figuring out *where* the problem originally occurred. 
It's not when the exception is thrown that's the issue; it's the point 
at which you placed a null reference in a slot where you shouldn't have.

Yes, we have invariants and contracts; but inevitably you're going to 
forget one, and it's that one slip-up that's going to bite you in the rear.

One could use roughly the same argument for non-null references as for 
const: you could document it, but documentation is inevitably wrong or 
out of date.  :P

That said, I wonder what's stopping us from implementing them today. 
Last time I checked (admittedly, that was like a year ago) we didn't 
have the compile-time magic necessary to completely and transparently 
proxy any given object.

Ideally, we should be able to do this:

class Foo
{
   void bar() { writefln("OH HAI WURLD!"); }
}

NonNull!(Foo) foo = new Foo;
foo.bar();
Foo baz = foo;

Off the top of my head, NonNull would require an opAssign, 
opImplicitCast to the templated type, and a way to build a full proxy of 
the underlying type.

It also just occured to me that this would probably break scope.  Damn.

A nicer syntax would be appreciated, but probably isn't a requirement.  :)

   -- Daniel



More information about the Digitalmars-d mailing list