-
Notifications
You must be signed in to change notification settings - Fork 356
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
Add support for opt.map(type::method) pattern. #6370
Conversation
checker/src/main/java/org/checkerframework/checker/optional/OptionalAnnotatedTypeFactory.java
Outdated
Show resolved
Hide resolved
@@ -14,6 +15,7 @@ | |||
// @NonNull, make the return type have type @Present. | |||
@RelevantJavaTypes(Optional.class) | |||
@StubFiles({"javaparser.astub"}) | |||
@SupportedOptions("optionalMapAssumeNonNull") |
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 think a better name would be "assumeNullAnnotated" or the like. This isn't specific to Optional.map, and it's about the assumption that nullness annotations are available for method references.
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.
The code as implemented is specific to Optional.map. (And is specific to method references.)
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 have a suggestion about clarifying code & documentation. Thanks!
checker/src/main/java/org/checkerframework/checker/optional/OptionalAnnotatedTypeFactory.java
Outdated
Show resolved
Hide resolved
…amework into optional-map-nullable
@smillst I added a failing test case. |
* @param memberReferenceTree a member reference | ||
* @return true if the return type of the function type of {@code memberReferenceTree} is non-null | ||
*/ | ||
private boolean returnsNonNull(MemberReferenceTree memberReferenceTree) { |
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 find returnsNonNull
(and the documentation above) a bit misleading. The given function can return null, but only if it is passed null. Another way to say this is that the function never introduces a new null value. Could you please adjust the method name and documentation accordingly? Thank you!
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.
This method is only checking that the return type does not have an explicit nullable annotation. If the return type is annotated with @PolyNull
, then it still may return null even if the argument is non-null. Here's an example method signature with that property.
@PolyNull Integer convertPoly(List<@PolyNull String> s);
I renamed to the method to make it clear that it is only checking from the lack of a Nullable annotation.
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.
Thanks! That renaming is helpful.
There is an inconsistency between the documentation (which says "true if @Nullable
") and the name (which says "true if not @Nullable
"). I suspect this is just a typo, Could you make them consistent? My preference would be to avoid negation in method names (& specifications), because negation makes reasoning more difficult.
Regarding the semantics: is there a difference between "is not annotated as @Nullable
" and "never introduces a new null value"? I think they are the same, assuming that the code is fully annotated. Noting this equivalence (or explicitly disclaiming it, if I am mistaken) would help to clarify the effect of the code.
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.
Regarding the semantics: is there a difference between "is not annotated as @nullable" and "never introduces a new null value"? I think they are the same, assuming that the code is fully annotated. Noting this equivalence (or explicitly disclaiming it, if I am mistaken) would help to clarify the effect of the code.
I don't know what "never introduces a new null value" means. (What's a new null value? How does a method reference introduce a null value?) I think you mean that the function only returns null if its argument is also null. That is not the same a method whose return type is not annotated with a nullable annotation. Here's an example of method that is not annotated with a nullable annotation and returns null when its argument in non-null:
@PolyNull Integer convertPoly(List<@PolyNull String> s) {
for (String ins : s) {
if (ins == null) {
return null;
}
}
return 0;
}
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.
Thank you for this example! It is helpful. I indeed meant that the function only returns null if its argument is also null. But, as you point out, @PolyNull
might not be written on the formal parameter. I had overlooked that. That would need to be checked.
Could you add a note about this to the documentation? Thanks.
The tests still pass, so I'm not sure what's failing. |
I was testing locally without the extra command-line argument. Sorry for the false alarm! |
…amework into optional-map-nullable
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.
Thank you for this feature!
Pass
-AoptionalMapAssumeNonNull
to use.