Summary: An introduction to the non-null types feature
Nearby: SpecSharpIntroduction, HomePage

Non-null types


Whether a pointer may be null or is definitely not null is a very common specification. To make it easy to specify that pointers are non-null, Spec# provides non-null types. For any reference type T, the type T! denotes a reference to a T that is definitely non-null. Such non-null types can be used wherever types occur with a few exceptions.

The type checker ensures that when a context expects a non-null value, the program actually supplies one. For example, when passing a possibly null value as the argument to a method whose parameter has a non-null type, the checker will complain.


C# Version


The following C# program causes a ""NullPointerException"" at run time. The null dereference error is not detected by the C# compiler.

		 class [MyLibrary]
		 {
		    public static void Clear(int[] xs)
		    {
		       for (int i = 0; i < xs.Length; i++)   // NullPointerException!
		       {
		          xs[i] = 0;
		       }
		    }
		 }
		 class [ClientCode]
		 {
		    static void Main()
		    {
		       int[] xs = null;
		       [MyLibrary.Clear(xs);]
		    }
		 }
	

Spec# Version


If you feed the same program to the Spec# compiler, it will detect the possible null dereferences.

		 class [MyLibrary]
		 {
		    public static void Clear(int[] xs)
		    {
		       for (int i = 0; i < xs.Length; i++)   // Warning: Possible null dereference
		       {
		          xs[i] = 0;   // Warning: Possible null dereference
		       }
		    }
		 }
		 class [ClientCode]
		 {
		    static void Main()
		    {
		       int[] xs = null;
		       [MyLibrary.Clear(xs);]
		    }
		 }
	

If you decide that it's the caller's responsibility to make sure the argument is not null, Spec# allows you to record this decision concisely using an exclamation point. Spec# will also enforce the decision at call sites.

		 class [MyLibrary]
		 {
		    public static void Clear(int[]! xs) 
		    {
		       for (int i = 0; i < xs.Length; i++)   // OK
		       {
		          xs[i] = 0;   // OK
		       }
		    }
		 }
		 class [ClientCode]
		 {
		    static void Main()
		    {
		       int[] xs = null;
		       [MyLibrary.Clear(xs);]   // Error: null is not a valid argument
		    }
		 }
	

If you prefer to keep your source code C#-compatible, you can enclose the exclamation mark in special brackets (""/^"" and ""^/""). The C# compiler interprets this as a comment and ignores it; the Spec# compiler ignores just the brackets themselves.

		 class [MyLibrary]
		 {
		    public static void Clear(int[]/*^!^*/ xs) 
		    {
		       for (int i = 0; i < xs.Length; i++)   // OK
		       {
		          xs[i] = 0;   // OK
		       }
		    }
		 }
		 class [ClientCode]
		 {
		    static void Main()
		    {
		       int[] xs = null;
		       [MyLibrary.Clear(xs);]   // Error: null is not a valid argument
		    }
		 }
	
Microsoft Communities