-
Notifications
You must be signed in to change notification settings - Fork 7
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) { | ||
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 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 :) 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.
Show resolved
Hide 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
lastIndexOf
below)? 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
indexOf
variant that takes anObject
needs to take an@Nullable Object
parameter to allow both instantiations of the collection, but that doesn't apply here.If you think they are indeed correct, having a
@CFComment
would 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:
contains
already has a@Nullable
parameter. So let's make them all@Nullable
or all not@Nullable
.The broader question is still a good one. As in our
retainAll
discussion, 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
poll
andpeek
changes (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.
contains
takes anObject
parameter, so that discussion should go along with the otherObject
vs.@Nullable Object
methods.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
Object
vs.E
. I am a bit surprised that they useE
here, 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 useE
to forbid such calls, then it's natural to extend that argument to keeping the type asE
instead of@Nullable E
.I might still lean toward
@Nullable E
if 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 callsindexOf
on 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
@Nullable
would improve anyone's life.