-
Notifications
You must be signed in to change notification settings - Fork 301
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
Support records #374
Comments
The approach sounds reasonable. A PR would be welcome when it makes sense. Thanks @michaelhixson |
michaelhixson
added a commit
to michaelhixson/NullAway
that referenced
this issue
Jan 5, 2020
Fixes uber#374 Avoid throwing exceptions when the source code contains records. Since records are a new kind of class, refactor the switch statements that make assertions about which elements and trees represent classes. Use general purpose `isClassElement` and `isClassTree` methods that are forward-compatible with records instead of enumerating `ElementKind` or `Tree.Kind` constants. Refactor `checkFieldInitialization` to ignore final fields. This check was wrongly flagging records because it couldn't analyze record constructors properly. Without the change to ignore final fields, this check runs into two kinds of trouble with records: 1. It doesn't inspect record constructors at all because they are generated. `NullAway.isConstructor(MethodTree)` returns false and so those trees are skipped. 2. The trees for the generated constructors don't contain explicit field assignments. That's just not how those were implemented. Something else is reponsible for assigning the fields at runtime, apparently. Rather than trying to teach NullAway about record constructors specifically, count on javac to verify that all final fields are initialized. Presumably, if NullAway were to complain that a constructor did not initialize a final field, that complaint would be redundant (with the error that javac would produce) at best and incorrect otherwise.
Merged
I'm getting and exception when using records with JDK15. It seems like #377 would have fixed the exception:
|
@pentlander #377 never landed. I think it might make sense to re-open and land now. Let me re-open. |
michaelhixson
added a commit
to michaelhixson/NullAway
that referenced
this issue
Mar 29, 2021
Fixes uber#374 Avoid throwing exceptions when the source code contains records. Since records are a new kind of class, refactor the switch statements that make assertions about which elements and trees represent classes. Use general purpose `isClassElement` and `isClassTree` methods that are forward-compatible with records instead of enumerating `ElementKind` or `Tree.Kind` constants. Refactor `checkFieldInitialization` to ignore final fields. This check was wrongly flagging records because it couldn't analyze record constructors properly. Without the change to ignore final fields, this check runs into two kinds of trouble with records: 1. It doesn't inspect record constructors at all because they are generated. `NullAway.isConstructor(MethodTree)` returns false and so those trees are skipped. 2. The trees for the generated constructors don't contain explicit field assignments. That's just not how those were implemented. Something else is reponsible for assigning the fields at runtime, apparently. Rather than trying to teach NullAway about record constructors specifically, count on javac to verify that all final fields are initialized. Presumably, if NullAway were to complain that a constructor did not initialize a final field, that complaint would be redundant (with the error that javac would produce) at best and incorrect otherwise.
michaelhixson
added a commit
to michaelhixson/NullAway
that referenced
this issue
Mar 29, 2021
Fixes uber#374 Avoid throwing exceptions when the source code contains records. Since records are a new kind of class, refactor the switch statements that make assertions about which elements and trees represent classes. Use general purpose `isClassElement` and `isClassTree` methods that are forward-compatible with records instead of enumerating `ElementKind` or `Tree.Kind` constants. Refactor `checkFieldInitialization` to ignore final fields. This check was wrongly flagging records because it couldn't analyze record constructors properly. Without the change to ignore final fields, this check runs into two kinds of trouble with records: 1. It doesn't inspect record constructors at all because they are generated. `NullAway.isConstructor(MethodTree)` returns false and so those trees are skipped. 2. The trees for the generated constructors don't contain explicit field assignments. That's just not how those were implemented. Something else is reponsible for assigning the fields at runtime, apparently. Rather than trying to teach NullAway about record constructors specifically, count on javac to verify that all final fields are initialized. Presumably, if NullAway were to complain that a constructor did not initialize a final field, that complaint would be redundant (with the error that javac would produce) at best and incorrect otherwise.
lazaroclapp
pushed a commit
that referenced
this issue
Apr 2, 2021
Fixes #374 Avoid throwing exceptions when the source code contains records. Since records are a new kind of class, refactor the switch statements that make assertions about which elements and trees represent classes. Use general purpose `isClassElement` and `isClassTree` methods that are forward-compatible with records instead of enumerating `ElementKind` or `Tree.Kind` constants. Refactor `checkFieldInitialization` to ignore final fields. This check was wrongly flagging records because it couldn't analyze record constructors properly. Without the change to ignore final fields, this check runs into two kinds of trouble with records: 1. It doesn't inspect record constructors at all because they are generated. `NullAway.isConstructor(MethodTree)` returns false and so those trees are skipped. 2. The trees for the generated constructors don't contain explicit field assignments. That's just not how those were implemented. Something else is responsible for assigning the fields at runtime, apparently. Rather than trying to teach NullAway about record constructors specifically, count on javac to verify that all final fields are initialized. Presumably, if NullAway were to complain that a constructor did not initialize a final field, that complaint would be redundant (with the error that javac would produce) at best and incorrect otherwise. Co-authored-by: Manu Sridharan <msridhar@gmail.com>
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add support for JEP 359: Records (Preview) to NullAway.
This depends on upstream support in Checker Framework.
I don't think that support for records in Error Prone is strictly required. There are bug patterns that will throw exceptions or print incorrect warnings when compiling code with records. However, since those bug patterns can be disabled, I don't think that NullAway depends on those issues being fixed in the same way it depends on the issues in Checker Framework being fixed.
As I mentioned in the upstream issue, my modified copy of NullAway is giving me useful feedback about records.
That's a toy example, but it's also working with real examples. I changed all of my record-like classes in one project to be actual records -- 30 classes or so with a mix of nullable and non-null properties -- and the compile-time feedback regarding nulls seems to be as good as it was before. If I introduce an error like removing a null check on a property of a record before dereferencing that property, NullAway correctly identifies the error.
To give a sense of scope, these are the changes I made to NullAway to get there.
Not too bad, right? I'm sure that I've missed corner cases and there'll be more to it, but for the most part it seems like records can be treated like regular classes.
The text was updated successfully, but these errors were encountered: