18

The following simple code will yield an "invariant unproven" warning by the static checker of Code Contracts, although there is no way _foo can be null. The warning is for the return statement inside UncalledMethod.

public class Node
{
    public Node(string s1, string s2, string s3, string s4, object o,
                string s5)
    {
    }
}

public class Bar
{
    private readonly string _foo;

    public Bar()
    {
        _foo = "foo";
    }

    private object UncalledMethod()
    {
        return new Node(string.Empty, string.Empty, string.Empty, string.Empty,
                        GetNode(), string.Empty);
    }

    private Node GetNode()
    {
        return null;
    }

    public string Foo
    {
        get
        {
            Contract.Ensures(Contract.Result<string>() != null);
            return _foo;
        }
    }

    [ContractInvariantMethod]
    private void Invariants()
    {
        Contract.Invariant(_foo != null);
    }
}

Apart from the fact, that the warning is simply invalid, it only occures in certain specific circumstances. Changing any of the following will make the warning go away:

  1. Inline GetNode so the return statement looks like this:

    return new Node(string.Empty, string.Empty, string.Empty, string.Empty, null,
                    string.Empty);
    
  2. Remove any of the parameters s1 to s5 from the constructor of Node.
  3. Change the type of any of the parameters s1 to s5 from the constructor of Node to object.
  4. Use a temporary variable for the result of GetNode:

        var node = GetNode();
        return new Node(string.Empty, string.Empty, string.Empty, string.Empty,
                        node, string.Empty);
    
  5. Changing the order of the parameters of the constructor of Node.
  6. Checking the option "Show assumptions" in the code contracts settings pane in the project settings.

Am I missing something obvious here or is this simply a bug in the static checker?


My settings:

My output:

C:\{path}\Program.cs(20,9): message : CodeContracts: Suggested ensures: Contract.Ensures(this._foo != null);
C:\{path}\Program.cs(41,17): message : CodeContracts: Suggested ensures: Contract.Ensures(Contract.Result<System.String>() == this._foo);
C:\{path}\Program.cs(33,13): message : CodeContracts: Suggested ensures: Contract.Ensures(Contract.Result<ConsoleApplication3.Program+Node>() == null);
C:\{path}\Program.cs(27,13): message : CodeContracts: Suggested ensures: Contract.Ensures(Contract.Result<System.Object>() != null);
C:\{path}\Program.cs(55,13): message : CodeContracts: Suggested ensures: Contract.Ensures(Contract.ForAll(0, args.Length, __k__ => args[__k__] != 0));
CodeContracts: ConsoleApplication3: Validated:  92,3%
CodeContracts: ConsoleApplication3: Contract density: 1,81
CodeContracts: ConsoleApplication3: Total methods analyzed 8
CodeContracts: ConsoleApplication3: Methods with 0 warnings 7
CodeContracts: ConsoleApplication3: Total method analysis read from the cache 8
CodeContracts: ConsoleApplication3: Total time 2,522sec. 315ms/method
CodeContracts: ConsoleApplication3: Retained 0 preconditions after filtering
CodeContracts: ConsoleApplication3: Inferred 0 object invariants
CodeContracts: ConsoleApplication3: Retained 0 object invariants after filtering
CodeContracts: ConsoleApplication3: Detected 0 code fixes
CodeContracts: ConsoleApplication3: Proof obligations with a code fix: 0
C:\{path}\Program.cs(27,13): warning : CodeContracts: invariant unproven: _foo != null
C:\{path}\Program.cs(49,13): warning :   + location related to previous warning
C:\windows\system32\ConsoleApplication3.exe(1,1): message : CodeContracts: Checked 13 assertions: 12 correct 1 unknown
CodeContracts: ConsoleApplication3: 
CodeContracts: ConsoleApplication3: Background contract analysis done.
Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443
  • What if you add `Contract.Requires(_foo != null)` in the constructor of `Bar`? – John Willemse Feb 19 '13 at 14:27
  • @JohnWillemse: You can't add a requires for a field in the constructor. Furthermore, it doesn't really make sense as it would mean that `_foo` has to be not null when the constructor is called. That's impossible. Adding a `Contract.Ensures(_foo != null);` to the ctor doesn't fix the warning. – Daniel Hilgarth Feb 19 '13 at 14:34
  • Yes, sorry. I had a similar issue, but the constructor had a parameter to set `_foo` in that case; I overlooked that here. – John Willemse Feb 19 '13 at 14:37
  • @JohnWillemse: I guess it's a bug. It just doesn't make any sense. – Daniel Hilgarth Feb 19 '13 at 14:37
  • I agree. Especially with so many different conditions that can make it go away...weird. – John Willemse Feb 19 '13 at 14:46
  • @Damien_The_Unbeliever: I am using 1.4.51019.0 with VS2010 Ultimate. You might want to upgrade. However, there is something you could do: Make sure that "Show Assumptions" is un-checked in the CC settings. (See point 6 in my list on how to make the warning go away). – Daniel Hilgarth Feb 19 '13 at 15:03
  • @Damien_The_Unbeliever: Marking it as `Pure` indeed makes the warning go away. But why? – Daniel Hilgarth Feb 19 '13 at 15:08
  • @Damien_The_Unbeliever: Man, thanks for the hint with `Pure`. I knew it existed, but never even thought about applying it to this problem. It even solves many other problems I am having! – Daniel Hilgarth Feb 19 '13 at 15:16
  • @Damien_The_Unbeliever: Please have a look at my settings. Make sure yours are the same. – Daniel Hilgarth Feb 19 '13 at 15:24
  • @DanielHilgarth - Done. I now get 11 assertions, 11 correct. And 5 suggestions. But no other issues. I'd say it must be a bug of some kind, but not sure where to look. The `Pure` idea was just another thing to eliminate. – Damien_The_Unbeliever Feb 19 '13 at 15:26
  • @Damien_The_Unbeliever: Strange. I added my output to the question. Could you please compare it to yours? As you can probably infer from the last suggestion, Program.cs also has a `Main` method. – Daniel Hilgarth Feb 19 '13 at 15:33
  • I've tried everything I can to match your situation, and I can't find it. I agree it must be a bug somewhere, but it's tricky to work out how to diagnose it further. – Damien_The_Unbeliever Feb 19 '13 at 19:35
  • Have you contacted Microsoft Research about this possible bug? – Richard Cook Mar 01 '13 at 08:57
  • @RichardCook: [In a way, yes](http://social.msdn.microsoft.com/Forums/en-US/codecontracts/thread/8d18d734-f0b0-4204-9490-6d804962b763). But my experience with them is pretty bad. My requests have all been ignored completely. – Daniel Hilgarth Mar 01 '13 at 09:00
  • @Damien_The_Unbeliever: Sorry for not getting back to you earlier. I am just now preparing a solution that contains all the problems I found and - after upgrading to the now current version "1.4.60221.11" - I can't reproduce it either. Maybe it was some kind of glitch in my installation. – Daniel Hilgarth Mar 05 '13 at 10:43

1 Answers1

1

This is no longer a problem with the latest version.

Daniel Hilgarth
  • 171,043
  • 40
  • 335
  • 443