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: null pointer exception in the case of hovering local variables #2437

Merged
merged 14 commits into from
Jul 29, 2022

Conversation

MikaelMayer
Copy link
Member

@MikaelMayer MikaelMayer commented Jul 18, 2022

Fixes #2438

  • The variables are not cloned, but stay linked. That way, hovering them works.
  • I added a robustness check on the type to avoid the following problem: when hovering such variable, the IDE jumps to the internal error/crash, so it's disruptive when working on something that is not related to the hovering.

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

@MikaelMayer MikaelMayer self-assigned this Jul 18, 2022
@MikaelMayer MikaelMayer marked this pull request as ready for review July 18, 2022 19:02
@@ -12002,7 +12002,8 @@ private class RBranchExpr : RBranch {
// deep clone Patterns and Body
Copy link
Collaborator

@fabiomadge fabiomadge Jul 18, 2022

Choose a reason for hiding this comment

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

I'm somewhat hesitant about this change. We should probably come up with a different name and comment, if you really just want to clone part of it. What about CloneRBranchExpr? Also, the tests fail.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes :-(

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'm somewhat hesitant about this change. We should probably come up with a different name and comment, if you really just want to clone part of it. What about CloneRBranchExpr? Also, the tests fail.

I just pushed a more conservative version of the changes which prevent local variables from being cloned if their type is not yet assigned, that way, any type assigned later on a local variable of a cloned tree will make the original local variable (which is the same) have the same type.

Copy link
Collaborator

Choose a reason for hiding this comment

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

It's still not clear to me that this is safe. Couldn't we re-infer the type on all branches? Would you mind soliciting someone else's review?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, that's fair to ask. I'm very much puzzled by the code that deals with nested match statements. Let me ask @RustanLeino

Comment on lines 12005 to 12006
return new RBranchStmt(branch.Tok, branch.BranchID,
branch.Patterns.ConvertAll(x => cloner.CloneExtendedPattern(x)), new List<Statement>(branch.Body), cloner.CloneAttributes(branch.Attributes));
Copy link
Collaborator

Choose a reason for hiding this comment

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

Suggested change
return new RBranchStmt(branch.Tok, branch.BranchID,
branch.Patterns.ConvertAll(x => cloner.CloneExtendedPattern(x)), new List<Statement>(branch.Body), cloner.CloneAttributes(branch.Attributes));
return new RBranchStmt(branch.Tok, branch.BranchID, branch.Patterns.ConvertAll(x => cloner.CloneExtendedPattern(x)),
new List<Statement>(branch.Body), cloner.CloneAttributes(branch.Attributes));

@RustanLeino
Copy link
Collaborator

Is the following correct? The user hovers over the local variable, then the language server finds the cloned variable. The cloned variable at that time has no .type filled in, and this caused the crash?

The way NestedMatchStmt and NestedMatchExpr work today is that they are desugared by the resolver into simpler MatchStmt and MatchExpr AST nodes. I presume that's where the clone operation (which in this PR has been changed to the special cloner) happens. I'm wondering which one (NestedMatch... or Match...) is used by the language server's look-up. Could it be that the sugared match has the .type filled in, but the desugared one does not, or perhaps vice versa? If so, then a possible fix would be to change where the language server looks up this variable.

@MikaelMayer
Copy link
Member Author

Is the following correct? The user hovers over the local variable, then the language server finds the cloned variable. The cloned variable at that time has no .type filled in, and this caused the crash?

If by "cloned variable" you mean "the original variable before it was cloned", then your interpretation is correct.

Could it be that the sugared match has the .type filled in, but the desugared one does not, or perhaps vice versa?

It's the second time that I observe that the sugared match does not have .type filled in, but the desugared one has it.

I think your approach for the LSP would work (to look up for the desugared version and collect symbols there instead of the original NestedMatchStmt). But that fix alone has some problems. For compilers that don't rely on the desugaring (e.g. DafnyLite), they don't have access to the resolved type of local variables, which is problematic.

@RustanLeino
Copy link
Collaborator

Could it be that the sugared match has the .type filled in, but the desugared one does not, or perhaps vice versa?

It's the second time that I observe that the sugared match does not have .type filled in, but the desugared one has it.

I think your approach for the LSP would work (to look up for the desugared version and collect symbols there instead of the original NestedMatchStmt). But that fix alone has some problems. For compilers that don't rely on the desugaring (e.g. DafnyLite), they don't have access to the resolved type of local variables, which is problematic.

This may be okay for now. We've seen several issues with the fact that the desugaring happens here (as opposed to keeping the original "nested" match), so I predict we'll rewrite this in the near future.

RustanLeino
RustanLeino previously approved these changes Jul 20, 2022
@MikaelMayer MikaelMayer enabled auto-merge (squash) July 21, 2022 02:57
@MikaelMayer MikaelMayer merged commit d65085d into master Jul 29, 2022
@MikaelMayer MikaelMayer deleted the fix-hover-nullpointerexception branch July 29, 2022 18:50
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.

Hovering crashes the LSP (but recovers)
3 participants