Void-safety (and related things)

Jason House jason.james.house at gmail.com
Tue Aug 11 05:58:21 PDT 2009


I've recently convinced myself that nullability should be the exception instead of the norm. So much of the code I write in C#/D uses reference objects assuming they're non-null. Only in certain special cases do I handle null explicitly. The issue is that if any special case is missed/mishandled, it can spread to other code.

I'm also too lazy to write non-null contracts in D. They also have far less value since violations are not caught at compile time (or better yet, in my IDE as I write code).

It may be as simple as having the following 3 types:
T // non-nullable
T? // nullable, safe
T* //  nullable, unsafe

I'd also like to remove all default initialization in favor of use of uninitialized variable errors. Default initialization in D is cute, but it is not a solution for programmer oversight. Single-threaded code will reproducibly do the wrong thing, but may be harder to notice in the first place. The very fact that the signalling nan change has made it into D shows that people want this type of behavior!


bearophile Wrote:

> Found on Lambda the Ultimate blog, Void-safety in Eiffel language, another attempt at solving this problem:
> http://docs.eiffel.com/sites/default/files/void-safe-eiffel.pdf
> 
> 
> I think to solve this problem a language like D can use three different strategies at the same time. Three kinds of object references can be defined:
> 1) the default one (its syntax is the shorter one, they are defined using the like current ones) is the "non nullable object reference". Many objects in a program are like this. The type system assures the code to be correct, you don't need to test such references for null. As in C# the compiler keeps eyes open to avoid the usage of uninitialized references of such kind. (this is a situation where "good" is better than "perfect". C# seems to work well enough in its ability to spot uninitialized variables).
> 2) The second kind is the current one, "unsafe nullabile object reference", it's faster, its syntax is a bit longer, to be used only where max performance is necessary.
> 3) The third kind is the "safe nullabile object reference". You can define it like using the syntax "Foo? f;". It's a "fat" reference, so beside the pointer this reference contains an integer number that represents the class. If your program has 500 classes, you need 500 different values for it. On the other hand usually in a program a specific reference can't be of 500 different classes, so the maximum number can be decreased, and you can keep at runtime sono conversion tables that convert some subsets of such numbers into a full pointer to class info. Such tables are a bit slow to use (but they don't need too much memory), but the program uses them only when a reference (of the third kind) is null, so it's not a bit problem. On 64-bit systems such numeric tag can be put into the most significant bits of the pointer itself (so when such pointer isn't null you just need a test and a mask, the shift is required only in the uncommon case of null). This also means that the max number of possible class instances decreases, but not so much (you can have some conversion tables to reduce such such numeric tag to 2-5 bits in most programs). When the code uses a method of a null reference of such kind the program may call the correct method of a "default" instance of that class (or even a user-specified instance).
> 
> Do you like? :-)
> 
> Bye,
> bearophile




More information about the Digitalmars-d mailing list