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

Do not let 'null' children slip into the AST #5446

Merged

Conversation

keyboardDrummer
Copy link
Member

@keyboardDrummer keyboardDrummer commented May 15, 2024

Fixes #5357, #4129

Description

  • Prevent null from being returned by Node.Children

How has this been tested?

  • Added IDE tests that contain the code from the bug reports
  • Added a test that slowly types a large Dafny program from our test suite, triggering code completion and hover on each stroke, to see whether there are other instances where Dafny server can crash.

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

@keyboardDrummer keyboardDrummer enabled auto-merge (squash) May 15, 2024 13:18
Comment on lines 1977 to +1982
protected CollectionType(Type arg) {
this.arg = arg;
this.TypeArgs = new List<Type> { arg };
TypeArgs = new List<Type>(1);
if (arg != null) {
TypeArgs.Add(arg);
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Why would CollectionType ever be called with null? (Same for the next constructor.)

I imagine that many places in the code expects a CollectionType to have 1 (or 2, for a map) type arguments. So, allowing a null argument to the constructor would just seem to delay the crash.

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 parser passes in null when the type argument is left out, for different collection types, for code such as:

function Foo(): seq

I imagine that many places in the code expects a CollectionType to have 1 (or 2, for a map) type arguments. So, allowing a null argument to the constructor would just seem to delay the crash.

If arg == null, then the resolver will attempt to infer type arguments and insert them into TypeArgs.

I doubt this is a reliable design but I didn't want to change it. I think better might have been to have a class OmittedType : Type that is used instead of null, in cases where the user omits the type arguments.

Copy link
Collaborator

@fabiomadge fabiomadge left a comment

Choose a reason for hiding this comment

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

How do we make sure those new tests introduce new concurrency issues?

@@ -1949,16 +1950,20 @@ public abstract class CollectionType : NonProxyType {
Contract.Requires(1 <= this.TypeArgs.Count); // this is actually an invariant of all collection types
Copy link
Collaborator

Choose a reason for hiding this comment

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

Outdated?

this.TypeArgs[0] = arg;

Debug.Assert(TypeArgs.Count == 0);
TypeArgs.Add(arg);
}
public virtual void SetTypeArgs(Type arg, Type other) {
Contract.Requires(arg != null);
Contract.Requires(other != null);
Contract.Requires(this.TypeArgs.Count == 2);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Outdated?

@keyboardDrummer
Copy link
Member Author

How do we make sure those new tests introduce new concurrency issues?

I'm not sure what you're asking. This PR does not relate to concurrency issues, so the tests are not testing for them. The test EditDocumentTest will check whether code completion and hover operations of the IDE still work for various broken program states, without crashing the IDE, and it does this by incrementally typing a correct program and invoking those operations after each addition.

@fabiomadge
Copy link
Collaborator

Sure, but is it the case that only the tests that explicitly test for concurrency issues cause the issues we frequently experience?

@keyboardDrummer
Copy link
Member Author

Sure, but is it the case that only the tests that explicitly test for concurrency issues cause the issues we frequently experience?

No it's not.

Instability in tests is not limited to any particular test, and it can and does also occur outside of IDE tests. However, it most frequently occurs in IDE tests because the IDE has many concurrent parts. Instability in IDE tests usually comes from a bug in the IDE code, not the test, but sometimes also comes from the test. There are particular IDE tests that are more liable to instability, namely those that tests performance in some way. These tests generally only pass if a particular performance threshold is met, and will retry up to X times until they meet that threshold.

We protect ourselves against making changes, either in tests or in any other location, that cause IDE test instability, by running the IDE tests twice in the build. I think it would be good if we run them more often but obviously there's a trade-off there.

@fabiomadge
Copy link
Collaborator

fabiomadge commented May 24, 2024

That's probably a tangential discussion, but it seems to me that we have a decent idea about which PRs are more likely to introduce instability. Maybe we should try being more targeted about where we do repeat runs. If we do that, we could even afford doing more runs where necessary.

@keyboardDrummer keyboardDrummer merged commit 961ade9 into dafny-lang:master May 30, 2024
21 checks passed
@keyboardDrummer keyboardDrummer deleted the nullChildrenCodeCompletion branch May 30, 2024 12:34
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.

Request textDocument/completion failed in IDE
3 participants