Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't prove modifies clause #3265

Open
MikaelMayer opened this issue Dec 23, 2022 · 2 comments · May be fixed by #3336
Open

Can't prove modifies clause #3265

MikaelMayer opened this issue Dec 23, 2022 · 2 comments · May be fixed by #3336
Assignees
Labels
area: error-reporting Clarity of the error reporting incompleteness Things that Dafny should be able to prove, but can't

Comments

@MikaelMayer
Copy link
Member

Dafny version

3.10.0

Code to produce this issue

datatype K = K(ghost MainSet: set<object>, Element: object)

datatype KUp = KUp(ghost MainSet: set<object>, Element: object, k: K) {
  method DoIt()
    modifies MainSet - {Element}
  {
    var p := MainSet - {Element};
    var c := k.MainSet - {k.Element};
    assume c <= p;
    assert forall o: object | o in c ::
             o in p;  // Verified
    assert c == k.MainSet - {k.Element}; // Verified
    modify k.MainSet - {k.Element}; // Modify error
  }
}

Command to run and resulting output

Just open this file in VSCode.

What happened?

The modify statement fails, although if you replace k.MainSet - {k.Element} by c; it suddenly verifies. But these two expressions are equal !
The workaround thus is to use c but this error is disturbing, as I found no way for Dafny to verify the modify statement without having a single variable.

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

Windows

@MikaelMayer MikaelMayer added kind: bug Crashes, unsoundness, incorrect output, etc. If possible, add a `part:` label area: error-reporting Clarity of the error reporting incompleteness Things that Dafny should be able to prove, but can't and removed kind: bug Crashes, unsoundness, incorrect output, etc. If possible, add a `part:` label labels Dec 23, 2022
@RustanLeino
Copy link
Collaborator

Here is a smaller repro:

method M(A: set<object>, B: set<object>, C: set<object>, D: set<object>)
  requires C - D <= A - B
  modifies A - B
{
  var cd := C - D;
  if * {
    modify C - D; // does not verify
  } else {
    modify cd; // verifies
  }
}

The problem is that the verifier sometimes tries to be "helpful" in rewriting some proof obligations. In particular, of o in X - Y is a proof obligation, then it rewrites that into o in X && o !in Y. It does this for proof obligations involving modifies A - B and it also does it in translating modify C - D. But it keeps the set-difference operators used in the precondition above and also keep the set-difference operator in the assignment to cd.

By the time things reach the SMT solver, the definition of the subset operator (<=) in the precondition turns into

forall o :: o in SetDifference(C, D) ==> o in SetDifference(A, B)

but that means that conditions like ... in A, ... in B, ... in C, and ... in D do not match the triggers for this quantifier, so it never gets used. In contrast, the proof obligation for modify cd does not go through any rewrite, so the o in cd that proof obligation remains, and since the SMT solver knows cd == SetDifference(C, D), it in effect gets a term o in SetDifference(C, D) and this causes the precondition to trigger.

These "helpful" rewrites seemed innovative in the first year or so of Dafny, which was long before Dafny's auto-triggers were added. Maybe we should get ride of these "helpful" rewrites now, and instead add the following tweak to auto-triggers: if a trigger looks like ..., o in X - Y, ..., then also add the triggers ..., o in X, ... and ..., o in Y, ... (provided those new triggers are legal).

@MikaelMayer
Copy link
Member Author

Great that's helpful. I also verified that, replacing

requires C - D <= A - B

by

requires forall a | a in C && a !in D :: a in A && a !in B

everything verifies as expected, which matches your insights. At least, we now have two workarounds.

MikaelMayer added a commit that referenced this issue Jan 6, 2023
@MikaelMayer MikaelMayer self-assigned this Apr 18, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area: error-reporting Clarity of the error reporting incompleteness Things that Dafny should be able to prove, but can't
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants