The reason that T is nullable and T! is non-nullable is that Spec# is designed on-top of C#, where all objects are nullable, so changing that semantic would break the backwards compatibly. C# chose that because it inherits from C++ where NULL is always a valid pointer and C/C++ doesn't have a concept of non-nullable pointers.
Your idea is basically a good one, but you are underestimating the difficulty of writing a good verifier - the problem with your idea is when we hit either recursive functions, subordinate calls or loop-constructs that can significantly obfuscate the control flow to make verification hard - take the following function for instance:
string Foo(object o)
{
for(int i = 0; i < 7; i++)
{
if(i == 1) { o = new object(); }
if(i == 2) { return o.ToString(); }
}
throw new NotImplementedException();
}
The verifier would really struggle to prove that in this particular instance it doesn't matter that o can be null (or indeed anything) because by the time o is used it will be guaranteed to be valid. This makes some of the "smarts" that people often want in verifiers hard to implement in worst-case scenarios. The Spec# verifier tries to play it dumb by asking the author to give some hints so that it only has to prove that the contracts are valid, rather than try to compute a minimal requirement for the function.
Thread Closed
This thread is kinda stale and has been closed but if you'd like to continue the conversation, please create a new thread in our Forums,
or Contact Us and let us know.