null and type safety

Michel Fortin michel.fortin at michelf.com
Wed Nov 5 04:31:57 PST 2008


On 2008-11-05 03:18:50 -0500, Walter Bright <newshound1 at digitalmars.com> said:

> I don't see what you've gained here. The compiler certainly can do flow 
> analysis in some cases to know that a pointer isn't null, but that 
> isn't generalizable. If a function takes a pointer parameter, no flow 
> analysis will tell you if it is null or not.

I'm not sure how you're reading things, but to me having two kinds of 
pointers (nullable and non-nullable) is exactly what you need to enable 
nullness flow analysis across function boundaries.

Basically, if you declare some pointer to be restricted to not-null in 
a function signature, and then try to call the function by passing it a 
possibly null pointer, the compiler can tell you that you need to check 
for null at the call site before calling the function.

It then ensue that when given a non-nullable pointer you can call a 
function requiring a non-nullable pointer directly without any check 
for null, because you know the pointer you recieved can't be null.

Currently, you can acheive this with proper documentation of functions 
saying whether arguments accept null and if return values can return 
null, and write your code with those assumptions in mind. Most often 
than not however there is no such documentation and you find yourself 
checking for null a lot more than necessary. If this property about 
pointers in function parameters and return values were known to the 
compiler, the compiler could check for you that you're doing things 
correctly, warn you whenever you're forgetting a null check, and 
optimise away checks for null on these pointers.

I know the null-dereferencing problem can generally be caught easily at 
runtime, but sometime your null comes from far away in the program 
(someone set a global to null for instance) and you're left to wonder 
who put a null value there in the first place. Non-nullable pointers 
would help a lot in those cases because you no longer have to test 
every code path and the error of giving a null value would be caught at 
the source (with the compiler telling you to check against null), not 
only where it's being dereferenced.

 - - -

That said, I think this could be done using an template. Consider this:

	struct NotNullPtr(Type) {
		private Type* ptr;
		this(Type* ptr) {
			opAssign(ptr);
		}
		void opAssign(Type* ptr) {
			// if this gets inlined and you have already checked for null, then
			// hopefully the optimizer will remove this redundant check.
			if (ptr)
				this.ptr = ptr;
			else
				throw new Exception("Unacceptable null value.");
		}
		void opAssign(NotNullPtr other) {
			this.ptr = other.ptr;
		}
		Type* opCast() {
			return ptr;
		}
		ref Type opDeref() {
			return &ptr;
		}
		alias opDeref opStar;
		// ... implement the rest yourself
	}

(not tested)

You could use this template everywhere you want to be sure a pointer 
isn't null. It guarenties that its value will never be null, and will 
throw an exception at the source where you attempt to put a null value 
in it, not when you attempt to dereference it later, when it's too late 
and your program has already been put in an incorrect state.

	NotNullPtr!(int) globalThatShouldNotBeNull;

	int* foo();
	globalThatShouldBeNull = foo(); // will throw if you attempt to set it 
to null.

	void bar(NotNullPtr!(int) arg);
	bar(globalThatShouldNotBeNull); // no need to check for null.

The greatest downside to this template is that since it isn't part of 
the language, almost no one will use it in their function prototypes 
and return types. That's not counting that its syntax is verbose and 
not very appealing (although it's not much worse than boost::shared_ptr 
or std::auto_ptr).

But still, if you have a global or member variable that must not be 
null, it can be of use; and if you have a function where you want to 
put the burden of checking for null on the caller, it can be of use.

-- 
Michel Fortin
michel.fortin at michelf.com
http://michelf.com/




More information about the Digitalmars-d mailing list