-
Notifications
You must be signed in to change notification settings - Fork 381
Sound or unsound treatment of collection Object parameters; fixes #3040 #3063
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
Changes from all commits
82fe235
87cf12f
fc080f5
1008c46
2e9faf3
3b7f7f8
32a27d4
a10b515
d22b3ce
8b4af81
63c769b
ee5fb48
9777f18
403f025
0959297
b3ccca3
357f675
4e088d3
3733d2f
0ffc372
c9165e7
a64988b
eb831a1
bfe897f
63217b6
e06d403
70d6cef
9dc1317
c3ffb51
62267cf
55d0135
96054e6
e2f6d93
33585cb
637f3a2
c1f94f5
bcc1f37
b83458f
9e3247b
dd9f7b1
4d9706c
0b20ce6
5acf574
cfedbe3
b9487c0
247c937
efd1432
e6b0d63
28bf0ab
bba953f
9ab716b
8c5267a
63da138
2b03433
9c95225
8117a00
3bc6a89
0cad1d8
1b5f672
6646119
dd35cf4
fcd119e
aa819ad
6016b5d
6dfb181
4ceecd3
718beb6
b602b15
a4584ac
4127317
bec0f6e
bf40649
b79bb1f
8b506c6
4d3428b
0e1ba02
286f343
dfb5694
8846ffd
fa96a42
36407fa
02847d3
88b9850
7a7795e
5214be0
e43a439
da0c86c
60a2749
ab98b3b
50aec65
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 |
|---|---|---|
|
|
@@ -119,7 +119,7 @@ public boolean isEmpty() { | |
| * @throws NullPointerException {@inheritDoc} | ||
| */ | ||
| @Pure | ||
| public boolean containsValue(@Nullable Object value) { | ||
| public boolean containsValue(Object value) { | ||
| Iterator<Entry<K,V>> i = entrySet().iterator(); | ||
| if (value==null) { | ||
| while (i.hasNext()) { | ||
|
|
@@ -153,7 +153,7 @@ public boolean containsValue(@Nullable Object value) { | |
| */ | ||
| @Pure | ||
| @EnsuresKeyForIf(result=true, expression="#1", map="this") | ||
| public boolean containsKey(@Nullable Object key) { | ||
| public boolean containsKey(Object key) { | ||
|
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. Other methods in this class that would benefit from 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.
|
||
| Iterator<Map.Entry<K,V>> i = entrySet().iterator(); | ||
| if (key==null) { | ||
| while (i.hasNext()) { | ||
|
|
@@ -186,7 +186,7 @@ public boolean containsKey(@Nullable Object key) { | |
| * @throws NullPointerException {@inheritDoc} | ||
| */ | ||
| @Pure | ||
| public @Nullable V get(@Nullable Object key) { | ||
| public @Nullable V get(Object key) { | ||
| Iterator<Entry<K,V>> i = entrySet().iterator(); | ||
| if (key==null) { | ||
| while (i.hasNext()) { | ||
|
|
@@ -246,7 +246,7 @@ public boolean containsKey(@Nullable Object key) { | |
| * @throws ClassCastException {@inheritDoc} | ||
| * @throws NullPointerException {@inheritDoc} | ||
| */ | ||
| public @Nullable V remove(@Nullable Object key) { | ||
| public @Nullable V remove(Object key) { | ||
| Iterator<Entry<K,V>> i = entrySet().iterator(); | ||
| Entry<K,V> correctEntry = null; | ||
| if (key==null) { | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,11 +1,13 @@ | ||
| package java.util; | ||
| import org.checkerframework.dataflow.qual.Pure; | ||
|
|
||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||
| import org.checkerframework.checker.nullness.qual.Nullable; | ||
| import org.checkerframework.dataflow.qual.Pure; | ||
|
|
||
| // Subclasses of this interface/class may opt to prohibit null elements | ||
| public abstract class AbstractSet<E> extends AbstractCollection<E> implements Set<E> { | ||
| protected AbstractSet() {} | ||
| @Pure public boolean equals(@Nullable Object a1) { throw new RuntimeException("skeleton method"); } | ||
| @Pure public int hashCode() { throw new RuntimeException("skeleton method"); } | ||
| public boolean removeAll(Collection<?> a1) { throw new RuntimeException("skeleton method"); } | ||
| public boolean removeAll(Collection<? extends @NonNull Object> a1) { throw new RuntimeException("skeleton method"); } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -29,6 +29,7 @@ | |
| import java.util.stream.Stream; | ||
| import java.util.stream.StreamSupport; | ||
|
|
||
| import org.checkerframework.checker.nullness.qual.NonNull; | ||
| import org.checkerframework.checker.nullness.qual.Nullable; | ||
| import org.checkerframework.checker.nullness.qual.PolyNull; | ||
| import org.checkerframework.dataflow.qual.Pure; | ||
|
|
@@ -185,7 +186,7 @@ public interface Collection<E> extends Iterable<E> { | |
| * (<a href="#optional-restrictions">optional</a>) | ||
| */ | ||
| @Pure | ||
| boolean contains(@Nullable Object o); | ||
| boolean contains(Object o); | ||
|
|
||
| /** | ||
| * Returns an iterator over the elements in this collection. There are no | ||
|
|
@@ -323,7 +324,7 @@ public interface Collection<E> extends Iterable<E> { | |
| * @throws UnsupportedOperationException if the <tt>remove</tt> operation | ||
| * is not supported by this collection | ||
| */ | ||
| boolean remove(@Nullable Object o); | ||
| boolean remove(Object o); | ||
|
|
||
|
|
||
| // Bulk Operations | ||
|
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. We'd probably want for That also goes for the redeclarations on 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. Great point! I overlooked those methods. Thanks for pointing them out. |
||
|
|
@@ -347,7 +348,7 @@ public interface Collection<E> extends Iterable<E> { | |
| * @see #contains(Object) | ||
| */ | ||
| @Pure | ||
| boolean containsAll(Collection<?> c); | ||
| boolean containsAll(Collection<? extends @NonNull Object> c); | ||
|
|
||
| /** | ||
| * Adds all of the elements in the specified collection to this collection | ||
|
|
@@ -398,7 +399,7 @@ public interface Collection<E> extends Iterable<E> { | |
| * @see #remove(Object) | ||
| * @see #contains(Object) | ||
| */ | ||
| boolean removeAll(Collection<?> c); | ||
| boolean removeAll(Collection<? extends @NonNull Object> c); | ||
|
|
||
| /** | ||
| * Removes all of the elements of this collection that satisfy the given | ||
|
|
@@ -457,7 +458,7 @@ default boolean removeIf(Predicate<? super E> filter) { | |
| * @see #remove(Object) | ||
| * @see #contains(Object) | ||
| */ | ||
| boolean retainAll(Collection<?> c); | ||
| boolean retainAll(Collection<? extends @NonNull Object> c); | ||
|
|
||
| /** | ||
| * Removes all of the elements from this collection (optional operation). | ||
|
|
||
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.
At a high level, I see 3 cases:
List)AbstractList)ArrayList)For (1), we're here exactly because we're aiming to make conservative assumptions by default (though allow them to be loosened with stub files). So we don't want
@Nullableon parameters there.Jumping ahead to (3), I would have guessed that classes like
ArrayListwould have@Nullableon their parameters, since their implementations support null inputs and their docs reflect this (and the Checker Framework supports generalizing parameter types). I can see a couple possible arguments against that, though I have reservations about each:ArrayList, anyway, so the annotations onArrayListitself rarely matter. (The argument about static types might become somewhat less true as users adoptvar.)ArrayListand override this method to reject null inputs. Taken to the extreme, this seems like an argument against putting@Nullableon a parameter of any extensible method -- and an argument for putting@Nullableon the return value of every extensible method (since anyone might override it to returnnull). So I think at some point we have to take a stand on which of those overrides are valid and which aren't. Given thatArrayListdoesn't document that its methods throwNullPointerException, I'd expect us to permitnullhere (unless the other argument above this one holds sway).Coming back to (2), I think that's more like (1): Even though a given implementation might support null, the classes that override it might not, and the docs reflect this.
So the interesting question is likely to be (3).
Uh oh!
There was an error while loading. Please reload this page.
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.
My analysis is similar to yours:
@Nullableon any class that makes a commitment to handle null, such asArrayList, but not on classes that don't make a commitment (like most interfaces and abstract classes).You are right that
ArrayListshould have@Nullableon its parameters. Sorry for that mistake; I have corrected it. (It looks like I overlooked it because it uses slightly different wording about null than other classes.)Are there any other classes that are incorrectly annotated?