-
Notifications
You must be signed in to change notification settings - Fork 9
Improve annotations on some java.util.concurrent collections.
#9
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
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -581,7 +581,7 @@ public E getLast() { | |
| } | ||
| } | ||
|
|
||
| public boolean removeFirstOccurrence(Object o) { | ||
| public boolean removeFirstOccurrence(@Nullable Object o) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should this change (and the ones to
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. My impression has been that these files haven't quite reached a consistent state.
...which at best implies that The methods I'm annotating in this PR are similar. So I think it would be defensible to remove the annotation on I can do that, but I'll wait for confirmation just in case. But probably nothing I've said above will come as a surprise :)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It unfortunately looks like there is some inconsistency here about which methods take |
||
| if (o == null) return false; | ||
| final ReentrantLock lock = this.lock; | ||
| lock.lock(); | ||
|
|
@@ -598,7 +598,7 @@ public boolean removeFirstOccurrence(Object o) { | |
| } | ||
| } | ||
|
|
||
| public boolean removeLastOccurrence(Object o) { | ||
| public boolean removeLastOccurrence(@Nullable Object o) { | ||
| if (o == null) return false; | ||
| final ReentrantLock lock = this.lock; | ||
| lock.lock(); | ||
|
|
@@ -790,7 +790,7 @@ public E pop() { | |
| * @param o element to be removed from this deque, if present | ||
| * @return {@code true} if this deque changed as a result of the call | ||
| */ | ||
| public boolean remove(Object o) { | ||
| public boolean remove(@Nullable Object o) { | ||
| return removeFirstOccurrence(o); | ||
| } | ||
|
|
||
|
|
@@ -1344,15 +1344,15 @@ public boolean removeIf(Predicate<? super E> filter) { | |
| /** | ||
| * @throws NullPointerException {@inheritDoc} | ||
| */ | ||
| public boolean removeAll(Collection<? extends @NonNull Object> c) { | ||
| public boolean removeAll(Collection<?> c) { | ||
| Objects.requireNonNull(c); | ||
| return bulkRemove(e -> c.contains(e)); | ||
| } | ||
|
|
||
| /** | ||
| * @throws NullPointerException {@inheritDoc} | ||
| */ | ||
| public boolean retainAll(Collection<? extends @NonNull Object> c) { | ||
| public boolean retainAll(Collection<?> c) { | ||
|
wmdietl marked this conversation as resolved.
|
||
| Objects.requireNonNull(c); | ||
| return bulkRemove(e -> !c.contains(e)); | ||
| } | ||
|
|
||
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.
Why is this change desirable (same for
lastIndexOfbelow)? If the collection only accepts non-null elements, why allow checking with a null value? It won't throw an NPE, but it will always be false.The
indexOfvariant that takes anObjectneeds to take an@Nullable Objectparameter to allow both instantiations of the collection, but that doesn't apply here.If you think they are indeed correct, having a
@CFCommentwould be useful.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.
Part of my goal here is consistency, too:
containsalready has a@Nullableparameter. So let's make them all@Nullableor all not@Nullable.The broader question is still a good one. As in our
retainAlldiscussion, I've been operating under the principle of "accept the most general type that can't lead to NPE," but of course we're well aware that the principles here are controversial :) (That's not necessarily even my personal favored principle.)I probably should have sent the
pollandpeekchanges (which probably actually affect users) separately from the more complicated changes. It would be nice to get those in. But for the changes we've been discussing, I don't think we're affected much by what we decide to do, so we can continue discussing or just drop them, as you prefer.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.
containstakes anObjectparameter, so that discussion should go along with the otherObjectvs.@Nullable Objectmethods.For methods that take the type parameter, I don't see a benefit in allowing null. I agree that it wouldn't cause an NPE, but it would just allow calls that will return false. Is there a particular pattern where this would be much more convenient?
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.
Ah, thanks, I had forgotten about the distinction of
Objectvs.E. I am a bit surprised that they useEhere, given the precedent ofList.indexOf, but of course there are good arguments for not permitting calls that will always returnfalse(compare https://errorprone.info/bugpattern/CollectionIncompatibleType). And if their goal is to useEto forbid such calls, then it's natural to extend that argument to keeping the type asEinstead of@Nullable E.I might still lean toward
@Nullable Eif we were writing The Official JSpecify Stubs: The theory would be that, if we didn't, tools could choose to insert runtime null checks for code that callsindexOfon aCopyOnWriteArrayList<@NonNull String>. But my recollection is that the only tool in common use that inserts such checks, Kotlin, does not insert checks in that particular case.But for Checker Framework users (and for all non-hypothetical use cases), I'm not aware of examples in which
@Nullablewould improve anyone's life.