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

feat: Generate a warning when 'old' has no effect #2610

Merged
merged 27 commits into from
Sep 2, 2022

Conversation

RustanLeino
Copy link
Collaborator

Depends on PRs #2606 and #2607
Fixes #1989

If the argument to old has no dereferences of the mutable heap, generate a warning saying that the old has no effect. This has been a common source of errors and confusion.

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

@keyboardDrummer keyboardDrummer self-assigned this Aug 23, 2022
@mschlaipfer
Copy link
Member

Thanks for implementing this!

@keyboardDrummer
Copy link
Member

Could you resolve the conflicts with master?

@@ -10622,6 +10624,8 @@ public enum FrameExpressionUse { Reads, Modifies, Unchanged }
void CreateIteratorMethodSpecs(IteratorDecl iter) {
Contract.Requires(iter != null);

var tok = new AutoGeneratedToken(iter.tok);
Copy link
Member

@keyboardDrummer keyboardDrummer Aug 30, 2022

Choose a reason for hiding this comment

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

Could we run 'the old has no effect' detection after we generate the iterator method specs? This works as well, but I'm curious what the best ordering of operations is. Maybe CreateIteratorMethodSpecs should not be part of the main resolution phase, but instead be part of the code-gen phase?

Can FreeVariableUtil.ComputeFreeVariables not be called before resolution? Maybe we should specify that in a comment on the before.

Side note: the AutoGeneratedToken concept seems strange to me. In generated code I wouldn't expect warnings/errors, and I wouldn't expect any non-nullish tokens there.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The linter is run after resolution. At that time (and not before that time), we have information about heap usage and variable definitions. For example, we know whether s[i] is referring to a sequence element or an array element. The free-variable machinery already has the ability to detect heap usage, so it made sense to call it from the linter.

There are a number of desugaring tasks (match, datatype update, iterators, ...) that are being done quite early. Creating new AST nodes is easier pre-resolution, because then the resolution pass will fill in type information. To my taste, some of that desugaring is done too early, or perhaps shouldn't be done at all. It would be good to have a discussion and redesign of all of that sometime. But for iterators, the desugaring does need to be done early, because the iterator desugaring introduces names that the program is allowed to call. So, this means iterator desugaring is necessarily done before the linter runs.

One could consider making the iterator desugaring more clever, so that it never generates useless old expressions. But this is difficult to determine before resolution (cf. my s[i] example above).

Therefore, to avoid linter warnings from such generated code, we need some way to keep track of which expressions have been automatically generated. We already had a mechanism for this, which is to put some information into the tokens. This is not perfect, and I'm not sure that we're using nested token wrappers correctly. For linter warnings, any such imperfections seem okay, since at worst we'd generate bad warnings or omit some warnings.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks for the info. This approach seems good :)


namespace Microsoft.Dafny {

class Linter : IRewriter {
Copy link
Member

Choose a reason for hiding this comment

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

Please use a more specific name while this class does a specific thing.

@keyboardDrummer keyboardDrummer enabled auto-merge (squash) September 2, 2022 09:45
@keyboardDrummer keyboardDrummer merged commit d731efa into dafny-lang:master Sep 2, 2022
@RustanLeino RustanLeino deleted the issue-1989 branch September 2, 2022 20:48
@davidcok
Copy link
Collaborator

Added a sentence in the RM about this warning.

@davidcok
Copy link
Collaborator

Does this solve #320 as well?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Linter rule: old should only refer to heap values
4 participants