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

Fix: Modifies clauses with set operations can now be proven #3336

Open
wants to merge 45 commits into
base: master
Choose a base branch
from

Conversation

MikaelMayer
Copy link
Member

This PR fixes #3265
I added the corresponding test.

By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.

@@ -1772,6 +1772,7 @@ public ExpressionTranslator(ExpressionTranslator etran, string modifiesFrame)
bool pr;
if (s is BinaryExpr && aggressive) {
BinaryExpr bin = (BinaryExpr)s;
/*
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it ok to remove this code?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, unless the test suite shows us otherwise.
When you do remove it, please also remove the unused variable pr on L1772.

Test/git-issues/git-issue-3265.dfy Outdated Show resolved Hide resolved
Test/git-issues/git-issue-3265.dfy Outdated Show resolved Hide resolved
Test/git-issues/git-issue-3265.dfy Outdated Show resolved Hide resolved
Comment on lines 1902 to 1904
case BinaryExpr.ResolvedOpcode.Union:
case BinaryExpr.ResolvedOpcode.Intersection:
case BinaryExpr.ResolvedOpcode.SetDifference:
case BinaryExpr.ResolvedOpcode.MultiSetUnion:
case BinaryExpr.ResolvedOpcode.MultiSetIntersection:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be good to do the analogous change also for multisets. You could do that in this same PR, in a separate PR, or, if nothing else, file an Issue that reminds us that this would be a good change to make in the future.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll do this in this PR if it's not too hard

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it would be good to do the analogous change also for multisets

Done ! That wasn't too hard. The only difference was that the trigger expressions were of the form (A + B)[x] and so this is what I split into two new triggers A[x] and B[x] (if the bound variables are the same of course!)

Source/DafnyCore/Triggers/TriggersCollector.cs Outdated Show resolved Hide resolved
@@ -390,6 +390,37 @@ internal class TriggersCollector {
return new TriggerAnnotation(children_contain_killers || expr_is_killer, new_term.Variables, collected_terms);
}

private IEnumerable<TriggerTerm> CollectInSetOperations(Expression new_expr, Expression original_expr) {
yield return new TriggerTerm { Expr = new_expr, OriginalExpr = original_expr, Variables = CollectVariables(original_expr) };
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand the role of OriginalExpr, but I note that the previous L384 added just new_expr, not a TriggerTerm wrapped around new_expr. Is that as intended?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I note that the previous L384 added just new_expr, not a TriggerTerm wrapped around new_expr. Is that as intended?

I'm not sure of what you see but here is the diff I see on my side.

         if (!children_contain_killers) {
           // Add only if the children are not killers; the head has been cleaned up into non-killer form
-          collected_terms.Add(new_term);
+          collected_terms.AddRange(CollectInSetOperations(new_expr, expr));
         }

So it looks like we were previously adding the same thing that I add now, except that now I generate more triggers. Could you elaborate a bit more?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My point was that, previously, collected_terms.Add(new_term); adds new_term, where the new collected_terms.AddRange(CollectInSetOperations(new_expr, expr)); adds

  • nothing, or
  • new TriggerTerm { Expr = newExpr, OriginalExpr = originalExpr, Variables = CollectVariables(newExpr) } (which is the thing that has a TriggerTerm wrapped around the newExpr), or
  • that new TriggerTerm... plus additional triggers.

This is probably fine. I'm just clarifying what I had tried to comment on.

@MikaelMayer MikaelMayer self-assigned this Apr 18, 2023
Source/DafnyCore/Triggers/TriggersCollector.cs Outdated Show resolved Hide resolved
Source/DafnyCore/Triggers/TriggersCollector.cs Outdated Show resolved Hide resolved
Comment on lines 1908 to 1909
//case BinaryExpr.ResolvedOpcode.MultiSetUnion:
//case BinaryExpr.ResolvedOpcode.MultiSetIntersection:
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If these are no longer needed, delete the lines. But why are the multiset operations excluded and the set operations still included?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The set operations are still included because there is a flag that can be turned on for sets (aggressive) which is used for frame conditions.
Without these, the tests compiling the Dafny runtime failed, see here
https://github.com/dafny-lang/dafny/actions/runs/4734312552/jobs/8403056164
I found that by reverting this code to its original form, the dafny runtime would verify again. Do you have an idea why?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was unable to reproduce the failure. However, I think it is correct to omit the multiset operations here, because RewriteInExpr is supposed to be in synch with TrInMultiSet_Aux, which only rewrites MultiSetDisplayExpr.

RustanLeino
RustanLeino previously approved these changes May 5, 2023
Copy link
Collaborator

@RustanLeino RustanLeino left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work!

@MikaelMayer MikaelMayer enabled auto-merge (squash) May 17, 2023 14:56
@MikaelMayer MikaelMayer disabled auto-merge May 17, 2023 21:36
@MikaelMayer MikaelMayer enabled auto-merge (squash) May 18, 2023 21:43
@MikaelMayer
Copy link
Member Author

Variability tests show that this PR does not incur any meaningful difference, so I'm setting up auto-merge.

auto-merge was automatically disabled April 8, 2024 09:18

Merge queue setting changed

@MikaelMayer MikaelMayer enabled auto-merge (squash) July 5, 2024 22:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Can't prove modifies clause
2 participants