Skip to content

Set extensionality cannot be proved because type of local variables is not assumed. #6304

@MikaelMayer

Description

@MikaelMayer

Dafny version

latest-nightly

Code to produce this issue

method SetInclusionHavoc() {
  ghost var A0: set<(object?, int)> := *;
  ghost var A1: set<(object?, int)> := *;
  assume {:axiom} allocated(A0);
  assume {:axiom} allocated(A1);
  assume {:axiom} forall r: (object?, int) :: r in A0 ==> r in A1;
  assert A0 <= A1; // Failing
}
method SetEqualityHavoc() {
  ghost var A0: set<(object?, int)> := *;
  ghost var A1: set<(object?, int)> := *;
  assume {:axiom} allocated(A0);
  assume {:axiom} allocated(A1);
  assume {:axiom} forall r: (object?, int) :: r in A0 <==> r in A1;
  assert A0 == A1; // Failing
}

method Set() returns (s: set<(object?, int)>)
method SetInclusionMethod() {
  ghost var A0: set<(object?, int)> := Set();
  ghost var A1: set<(object?, int)> := Set();
  assume {:axiom} forall r: (object?, int) :: r in A0 ==> r in A1;
  assert A0 <= A1;
}
method SetEqualityMethod() {
  ghost var A0: set<(object?, int)> := Set();
  ghost var A1: set<(object?, int)> := Set();
  assume {:axiom} forall r: (object?, int) :: r in A0 <==> r in A1;
  assert A0 == A1;
}

Command to run and resulting output

dafny verify

What happened?

The first two methods fail.

It often comes up that, despite proving set membership constraints on sets, one has to strangely call a lemma to obtain extensionality of sets, set equality and set inclusion.
I nailed it down to one axiom missing on local variables that does not say what the type of local variables are, but does it for input and output parameters of methods.
This axiom for the example above is the following:

$Is(A0#0, TSet(Tclass._System.Tuple2(Tclass._System.object?(), TInt)))

However that axiom is present in the variable definition under the format:

  var A0#0: Set
     where defass#A0#0
       ==> $Is(A0#0, TSet(Tclass._System.Tuple2(Tclass._System.object?(), TInt)))
         && $IsAlloc(A0#0, TSet(Tclass._System.Tuple2(Tclass._System.object?(), TInt)), $Heap);

Despite that, at the point the axiom is needed, with the following:

havoc A1#0;
    defass#A1#0 := true;
    assert {:id "id0"} defass#A0#0;
    assert defass#A0#0
       ==> $Is(A0#0, TSet(Tclass._System.Tuple2(Tclass._System.object?(), TInt))); // Fails

So it looks like the where clause is either never checked, nor assumable in Boogie. We need to investigate it in Boogie as well.

What type of operating system are you experiencing the problem on?

Windows

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind: bugCrashes, unsoundness, incorrect output, etc. If possible, add a `part:` label

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions