-
Notifications
You must be signed in to change notification settings - Fork 285
fix: Forbid recursive function uses in decreases clauses #6045
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
Conversation
Note, the “function specification” SelectWF check was never reached (and was not in the test suite).
| } | ||
| } | ||
| } | ||
| } No newline at end of file |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need new line here.
|
|
||
| namespace Microsoft.Dafny; | ||
|
|
||
| class FunctionEntanglementChecks_Visitor : ResolverBottomUpVisitor { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor Nitpick: Not sure Entanglement is the right word here. Following the implementation, two functions are entangled when they are in the same SCC and one uses the other either in a naked fashion or in a decreases clause. But the fact that they are in the SCC means that they depend on one another and already feel entangled. Maybe DetectUnsoundFunctionReferences or DUFR (pronounced as duffer 😂)
# Conflicts: # Source/IntegrationTests/TestFiles/LitTests/LitTest/examples/parser_combinators.dfy.expect # Source/IntegrationTests/TestFiles/LitTests/LitTest/git-issues/git-issue-847.dfy.expect # Source/IntegrationTests/TestFiles/LitTests/LitTest/hofs/Naked.dfy.expect
|
Looks good! |
|
|
||
| namespace Microsoft.Dafny; | ||
|
|
||
| class DetectUnsoundFunctionReferences_Visitor : ResolverBottomUpVisitor { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the _ in the name? I think that's outside of C# conventions. Does Rider not suggest to remove it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had followed the convention used by other _Visitor classes in the Dafny sources. But I agree that's outside C# conventions. So, I now renamed all classes in Dafny to remove _'s.
|
|
||
| class DetectUnsoundFunctionReferences_Visitor : ResolverBottomUpVisitor { | ||
| private readonly ICallable context; | ||
| public bool DoDecreasesChecks; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know it doesn't matter much, but I think C# developers generally prefer auto properties over public fields, at least I do. One example: you can put a breakpoint on a property getter/setter, but not on a field read/write.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I made it private, as per the suggestion below.
| } | ||
| } | ||
|
|
||
| if (DoDecreasesChecks && expr is FunctionCallExpr callExpr) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please merge the conditions to reduce nesting, and consider inverting the condition to get an early return and fully remove the nesting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I unnested the if's.
| FillInPostConditionsAndBodiesOfPrefixLemmas(declarations); | ||
| } | ||
|
|
||
| // A function is not allowed to be used naked in its own SCC. Also, a function is not allowed to be used |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What does the term naked here mean?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It means the function name is used without applying it to arguments. (This nomenclature is not new in this PR.) I clarified in the comment.
| // in any way inside a "decreases" clause its its own SCC. | ||
| foreach (var function in ModuleDefinition.AllFunctions(declarations)) { | ||
| var visitor = new DetectUnsoundFunctionReferences_Visitor(this, function); | ||
| visitor.Visit(function); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this visit/doDecreasesChecks/visit pattern is the only correct way to use DetectUnsoundFunctionReferences_Visitor, then it would be better to move this into a static method in that class, and make the constructor and DoDecreasesChecks field private.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea.
| TailCalls.dfy(126,19): Error: the recursive call to 'Compute' is not tail recursive because the actual type argument is not the formal type parameter 'G' | ||
| TailCalls.dfy(139,17): Error: the recursive call to 'Run' is not tail recursive because the actual type argument 1 is not the formal type parameter 'G' | ||
| 30 resolution/type errors detected in TailCalls.dfy | ||
| TailCalls.dfy(171,13): Error: cannot use naked function in recursive setting. Possible solution: eta expansion. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we avoid the use of the word naked here? Can I find more information on what the problem is and the possible solution? Maybe add a reference to documentation?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left this as is. This PR does not introduce the phrase "naked function". It would be good to revisit, and indeed to say something about it in the documentation.
Because `CanCall` is now used everywhere, the Boogie variable `$FunctionContextHeight` is no longer needed. This PR also removes the variable `$ModuleContextHeight`, which has been unused for some time now. Depends on #6045 <small>By submitting this pull request, I confirm that my contribution is made under the terms of the [MIT license](https://github.com/dafny-lang/dafny/blob/master/LICENSE.txt).</small>
Fixes #6043
This PR changes two verification checks into resolution checks:
decreasesclause in the function's SCCThe first of these was omitted in the recent
CanCallPR. Hence, this PR fixes that regression.By submitting this pull request, I confirm that my contribution is made under the terms of the MIT license.