Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
90 commits
Select commit Hold shift + click to select a range
82fe235
Stub file for assuming object parameters in collections may be null
mernst Jan 18, 2020
87cf12f
Stub file for assuming object parameters in collections may be null
mernst Jan 18, 2020
fc080f5
Add documentation
mernst Jan 18, 2020
1008c46
Update comment
mernst Jan 18, 2020
2e9faf3
Update tests
mernst Jan 18, 2020
3b7f7f8
New version of JDK
mernst Jan 18, 2020
32a27d4
Update tests
mernst Jan 18, 2020
a10b515
Remove commented-out annotation
mernst Jan 18, 2020
d22b3ce
Merge ../checker-framework-fork-mernst-branch-collection-object-param…
mernst Jan 18, 2020
8b4af81
Nullness annotations on return types
mernst Jan 18, 2020
63c769b
Undo changes after fixing stub file
mernst Jan 18, 2020
ee5fb48
Fix library annotation
mernst Jan 18, 2020
9777f18
Merge github.com:typetools/checker-framework into collection-object-p…
mernst Jan 19, 2020
403f025
Merge github.com:typetools/checker-framework into collection-object-p…
mernst Jan 19, 2020
0959297
Fix typo
mernst Jan 23, 2020
b3ccca3
Merge ../checker-framework-branch-master into collection-object-param…
mernst Jan 23, 2020
357f675
Merge ../checker-framework-branch-master into collection-object-param…
mernst Jan 23, 2020
4e088d3
Comment out @StubFiles, which causes failure when building the JDK
mernst Jan 23, 2020
3733d2f
Update has for JDK
mernst Jan 23, 2020
0ffc372
Merge branch 'collection-object-parameters-may-be-null' of github.com…
mernst Jan 24, 2020
c9165e7
Use more standard name for test
mernst Jan 24, 2020
a64988b
Adapt to upstream changes
mernst Jan 24, 2020
eb831a1
Adapt tests
mernst Jan 24, 2020
bfe897f
Merge ../checker-framework-branch-master into collection-object-param…
mernst Jan 24, 2020
63217b6
Tweaks to tests
mernst Jan 24, 2020
e06d403
Fix failing test
mernst Jan 24, 2020
70d6cef
Clone the JDK, for JDK 11 jobs
mernst Jan 25, 2020
9dc1317
Less code duplication
mernst Jan 25, 2020
c3ffb51
Use full path to script
mernst Jan 25, 2020
62267cf
Use full path to script
mernst Jan 25, 2020
55d0135
Merge ../checker-framework-fork-mernst-branch-collection-object-param…
mernst Jan 25, 2020
96054e6
HashMap permits null keys and values
mernst Jan 25, 2020
e2f6d93
Nullness improvement
mernst Jan 25, 2020
33585cb
Add Javadoc
mernst Jan 25, 2020
637f3a2
Move Javadoc text
mernst Jan 25, 2020
c1f94f5
Merge ../checker-framework-branch-master into collection-object-param…
mernst Jan 25, 2020
bcc1f37
Merge ../checker-framework-branch-master into collection-object-param…
mernst Jan 25, 2020
b83458f
Add comment
mernst Jan 25, 2020
9e3247b
Merge ../checker-framework-branch-master into collection-object-param…
mernst Jan 25, 2020
dd9f7b1
Merge ../checker-framework-branch-master into collection-object-param…
mernst Jan 25, 2020
4d9706c
Merge ../checker-framework-branch-master into collection-object-param…
mernst Jan 29, 2020
0b20ce6
Merge ../checker-framework-branch-master into collection-object-param…
mernst Jan 30, 2020
5acf574
Merge ../checker-framework-branch-master into collection-object-param…
mernst Jan 30, 2020
cfedbe3
ArrayList permits null elements
mernst Jan 30, 2020
b9487c0
Annotate two LinkedList methods
mernst Jan 30, 2020
247c937
Merge ../checker-framework-branch-master into collection-object-param…
mernst Mar 9, 2020
efd1432
Merge ../checker-framework-branch-master into collection-object-param…
mernst Mar 9, 2020
e6b0d63
Set jdkShaHash
mernst Mar 9, 2020
28bf0ab
Use git-clone-related
mernst Mar 9, 2020
bba953f
Use full path to script
mernst Mar 9, 2020
9ab716b
Use git-clone-related
mernst Mar 9, 2020
8c5267a
Handle lack of git.properties file
mernst Mar 9, 2020
63da138
Merge ../checker-framework-branch-master into collection-object-param…
mernst Mar 10, 2020
2b03433
Merge ../checker-framework-branch-master into collection-object-param…
mernst Mar 11, 2020
9c95225
Merge ../checker-framework-branch-master into collection-object-param…
mernst Mar 11, 2020
8117a00
Merge ../checker-framework-branch-master into collection-object-param…
mernst Mar 12, 2020
3bc6a89
Add documentation
mernst Mar 12, 2020
0cad1d8
Checkpoint
mernst Mar 12, 2020
1b5f672
Fix syntax error
mernst Mar 12, 2020
6646119
Add import statements
mernst Mar 12, 2020
dd35cf4
Make null-friendly classes null-friendly
mernst Mar 12, 2020
fcd119e
Complete JDK annotations about collection Object parameters
mernst Mar 12, 2020
aa819ad
Merge ../checker-framework-branch-master into collection-object-param…
mernst Mar 12, 2020
6016b5d
Undo an undesirable change
mernst Mar 12, 2020
6dfb181
Update JDK SHA hash
mernst Mar 12, 2020
4ceecd3
Update stub file to reflect changes in annotated JDK
mernst Mar 12, 2020
718beb6
Add notes about how I confirmed the JDK annotations
mernst Mar 13, 2020
b602b15
Fix URL
mernst Mar 13, 2020
a4584ac
Merge ../checker-framework-branch-master into collection-object-param…
mernst Mar 13, 2020
4127317
Merge ../checker-framework-branch-master into collection-object-param…
mernst Mar 16, 2020
bec0f6e
Forbid null elements
mernst Mar 16, 2020
bf40649
Add import statement
mernst Mar 16, 2020
b79bb1f
Merge ../checker-framework-branch-master into collection-object-param…
mernst Mar 25, 2020
8b506c6
Vector accepts null
mernst Mar 25, 2020
4d3428b
Concurrent bulk operations forbid null elements
mernst Mar 25, 2020
0e1ba02
Remove annotations that are redundant with the annotated JDK
mernst Mar 25, 2020
286f343
Simplify syntax and remove a wrong annotation
mernst Mar 25, 2020
dfb5694
More consistent interpretation of "such that o.equals(e)"
mernst Mar 25, 2020
8846ffd
Fix annotations
mernst Mar 25, 2020
fa96a42
Remove comment
mernst Mar 25, 2020
36407fa
Clean up BlockingQueue and BlockingDeque
mernst Mar 25, 2020
02847d3
Fix ConcurrentSkipListSet
mernst Mar 25, 2020
88b9850
Remove stray space
mernst Mar 25, 2020
7a7795e
Merge ../checker-framework-branch-master into collection-object-param…
mernst Mar 26, 2020
5214be0
Don't change spec if method is documented to definitely throw NPE
mernst Mar 26, 2020
e43a439
Permit more nulls where specifications indicate
mernst Mar 26, 2020
da0c86c
Update JDK SHA hash
mernst Mar 26, 2020
60a2749
Code review feedback
mernst Mar 27, 2020
ab98b3b
Document the EnumSet exception
mernst Mar 27, 2020
50aec65
Undo an unrelated change
mernst Mar 27, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@ Renamings:
-AuseDefaultsForUncheckedCode to -AuseConservativeDefaultsForUncheckedCode
The old name works temporarily but will be removed in a future release.

For collection methods with `Object` formal parameter type, such as
contains, indexOf, and remove, the annotated JDK now forbids null as an
argument. To make the Nullness Checker permit null, pass
`-Astubs=checker.jar/collection-object-parameters-may-be-null.astub`.

Implementation details:
* Removed `@DefaultInUncheckedCodeFor` and
`@DefaultQualifierInHierarchyInUncheckedCode`.
Expand Down
2 changes: 1 addition & 1 deletion checker/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ ext {
// See instructions for updating jdk8.jar at
// https://github.com/typetools/annotated-libraries/blob/master/README.md .
// Set jdkShaHash to 'local' to use a locally-built version of jdk8.jar .
jdkShaHash = '03c7d2f752fde145ecc1f5232cae0ae9c22019d4'
jdkShaHash = '672035d415d27dbdebc6ddf8ab4a6c519f65d49a'
if (rootProject.hasProperty("useLocalJdk")) {
jdkShaHash = 'local'
}
Expand Down
12 changes: 7 additions & 5 deletions checker/jdk/nullness/src/java/util/AbstractCollection.java
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
package java.util;

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;
Expand All @@ -17,23 +19,23 @@ protected AbstractCollection() {}
@Override
@Pure public boolean isEmpty() { throw new RuntimeException("skeleton method"); }
@Override
@Pure public boolean contains(@Nullable Object a1) { throw new RuntimeException("skeleton method"); }
@Pure public boolean contains(Object a1) { throw new RuntimeException("skeleton method"); }
@Override
@SideEffectFree public Object [] toArray() { throw new RuntimeException("skeleton method"); }
@Override
@SideEffectFree public <T> @Nullable T @PolyNull [] toArray(@Nullable T @PolyNull [] a1) { throw new RuntimeException("skeleton method"); }
@Override
public boolean add(E a1) { throw new RuntimeException("skeleton method"); }
@Override
public boolean remove(@Nullable Object a1) { throw new RuntimeException("skeleton method"); }
public boolean remove(Object a1) { throw new RuntimeException("skeleton method"); }
@Override
@Pure public boolean containsAll(Collection<?> a1) { throw new RuntimeException("skeleton method"); }
@Pure public boolean containsAll(Collection<? extends @NonNull Object> c) { throw new RuntimeException("skeleton method"); }
@Override
public boolean addAll(Collection<? extends E> a1) { throw new RuntimeException("skeleton method"); }
@Override
public boolean removeAll(Collection<?> a1) { throw new RuntimeException("skeleton method"); }
public boolean removeAll(Collection<? extends @NonNull Object> c) { throw new RuntimeException("skeleton method"); }
@Override
public boolean retainAll(Collection<?> a1) { throw new RuntimeException("skeleton method"); }
public boolean retainAll(Collection<? extends @NonNull Object> c) { throw new RuntimeException("skeleton method"); }
@Override
public void clear() { throw new RuntimeException("skeleton method"); }
@Override
Expand Down
4 changes: 2 additions & 2 deletions checker/jdk/nullness/src/java/util/AbstractList.java
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ public E remove(int index) {
* @throws NullPointerException {@inheritDoc}
*/
@Pure
public int indexOf(@Nullable Object o) {
public int indexOf(Object o) {
Copy link
Contributor

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:

  1. the interfaces themselves (like List)
  2. the skeletal abstract classes (like AbstractList)
  3. the concrete implementations (like 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 @Nullable on parameters there.

Jumping ahead to (3), I would have guessed that classes like ArrayList would have @Nullable on 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:

  • First, users rarely store objects in variables/fields whose static type is ArrayList, anyway, so the annotations on ArrayList itself rarely matter. (The argument about static types might become somewhat less true as users adopt var.)
  • Second, users can extend ArrayList and override this method to reject null inputs. Taken to the extreme, this seems like an argument against putting @Nullable on a parameter of any extensible method -- and an argument for putting @Nullable on the return value of every extensible method (since anyone might override it to return null). So I think at some point we have to take a stand on which of those overrides are valid and which aren't. Given that ArrayList doesn't document that its methods throw NullPointerException, I'd expect us to permit null here (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).

Copy link
Member Author

@mernst mernst Jan 30, 2020

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: @Nullable on any class that makes a commitment to handle null, such as ArrayList, but not on classes that don't make a commitment (like most interfaces and abstract classes).

You are right that ArrayList should have @Nullable on 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.)

users can extend ArrayList and override this method to reject null inputs.
Subtypes of ArrayList must also permit null values. If a subclass of ArrayList were to forbid null elements, it would violate a commitment made by ArrayList, would violate behavioral subtyping, and the Nullness Checker would yield an error when type-checking it.

Are there any other classes that are incorrectly annotated?

ListIterator<E> it = listIterator();
if (o==null) {
while (it.hasNext())
Expand All @@ -207,7 +207,7 @@ public int indexOf(@Nullable Object o) {
* @throws NullPointerException {@inheritDoc}
*/
@Pure
public int lastIndexOf(@Nullable Object o) {
public int lastIndexOf(Object o) {
ListIterator<E> it = listIterator(size());
if (o==null) {
while (it.hasPrevious())
Expand Down
8 changes: 4 additions & 4 deletions checker/jdk/nullness/src/java/util/AbstractMap.java
Original file line number Diff line number Diff line change
Expand Up @@ -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()) {
Expand Down Expand Up @@ -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) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Other methods in this class that would benefit from @Nullable Object parameters: containsValue, get, remove.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AbstractMap specifies that a NullPointerException is possible from all of those methods. :-(

Iterator<Map.Entry<K,V>> i = entrySet().iterator();
if (key==null) {
while (i.hasNext()) {
Expand Down Expand Up @@ -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()) {
Expand Down Expand Up @@ -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) {
Expand Down
6 changes: 4 additions & 2 deletions checker/jdk/nullness/src/java/util/AbstractSet.java
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"); }
}
4 changes: 2 additions & 2 deletions checker/jdk/nullness/src/java/util/ArrayDeque.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ public class ArrayDeque<E extends @NonNull Object> extends AbstractCollection<E>
public E getLast() { throw new RuntimeException("skeleton method"); }
public @Nullable E peekFirst() { throw new RuntimeException("skeleton method"); }
public @Nullable E peekLast() { throw new RuntimeException("skeleton method"); }
public boolean removeFirstOccurrence(Object a1) { throw new RuntimeException("skeleton method"); }
public boolean removeLastOccurrence(Object a1) { throw new RuntimeException("skeleton method"); }
public boolean removeFirstOccurrence(@Nullable Object a1) { throw new RuntimeException("skeleton method"); }
public boolean removeLastOccurrence(@Nullable Object a1) { throw new RuntimeException("skeleton method"); }
public boolean add(E a1) { throw new RuntimeException("skeleton method"); }
public boolean offer(E a1) { throw new RuntimeException("skeleton method"); }
public E remove() { throw new RuntimeException("skeleton method"); }
Expand Down
11 changes: 6 additions & 5 deletions checker/jdk/nullness/src/java/util/Collection.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'd probably want for containsAll, removeAll, and retainAll to require Collection<? extends Object> (or Collection<? extends @NonNull Object> if it's necessary to be explicit here, but I don't think so?).

That also goes for the redeclarations on List and Set.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great point! I overlooked those methods. Thanks for pointing them out.

Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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).
Expand Down
45 changes: 23 additions & 22 deletions checker/jdk/nullness/src/java/util/Collections.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import org.checkerframework.checker.nullness.qual.NonNull;
import org.checkerframework.checker.nullness.qual.EnsuresKeyFor;
import org.checkerframework.checker.nullness.qual.EnsuresKeyForIf;
import org.checkerframework.checker.nullness.qual.Nullable;
Expand Down Expand Up @@ -1133,16 +1134,16 @@ public boolean remove(Object o) {
throw new UnsupportedOperationException();
}

public boolean containsAll(Collection<?> coll) {
public boolean containsAll(Collection<? extends @NonNull Object> coll) {
return c.containsAll(coll);
}
public boolean addAll(Collection<? extends E> coll) {
throw new UnsupportedOperationException();
}
public boolean removeAll(Collection<?> coll) {
public boolean removeAll(Collection<? extends @NonNull Object> coll) {
throw new UnsupportedOperationException();
}
public boolean retainAll(Collection<?> coll) {
public boolean retainAll(Collection<? extends @NonNull Object> coll) {
throw new UnsupportedOperationException();
}
public void clear() {
Expand Down Expand Up @@ -1799,7 +1800,7 @@ public boolean contains(Object o) {
* an unscrupulous List whose contains(Object o) method senses
* when o is a Map.Entry, and calls o.setValue.
*/
public boolean containsAll(Collection<?> coll) {
public boolean containsAll(Collection<? extends @NonNull Object> coll) {
for (Object e : coll) {
if (!contains(e)) // Invokes safe contains() above
return false;
Expand Down Expand Up @@ -2141,16 +2142,16 @@ public boolean remove(Object o) {
synchronized (mutex) {return c.remove(o);}
}

public boolean containsAll(Collection<?> coll) {
public boolean containsAll(Collection<? extends @NonNull Object> coll) {
synchronized (mutex) {return c.containsAll(coll);}
}
public boolean addAll(Collection<? extends E> coll) {
synchronized (mutex) {return c.addAll(coll);}
}
public boolean removeAll(Collection<?> coll) {
public boolean removeAll(Collection<? extends @NonNull Object> coll) {
synchronized (mutex) {return c.removeAll(coll);}
}
public boolean retainAll(Collection<?> coll) {
public boolean retainAll(Collection<? extends @NonNull Object> coll) {
synchronized (mutex) {return c.retainAll(coll);}
}
public void clear() {
Expand Down Expand Up @@ -3185,13 +3186,13 @@ private String badElementMsg(Object o) {
public boolean remove(Object o) { return c.remove(o); }
public void clear() { c.clear(); }

public boolean containsAll(Collection<?> coll) {
public boolean containsAll(Collection<? extends @NonNull Object> coll) {
return c.containsAll(coll);
}
public boolean removeAll(Collection<?> coll) {
public boolean removeAll(Collection<? extends @NonNull Object> coll) {
return c.removeAll(coll);
}
public boolean retainAll(Collection<?> coll) {
public boolean retainAll(Collection<? extends @NonNull Object> coll) {
return c.retainAll(coll);
}

Expand Down Expand Up @@ -3963,7 +3964,7 @@ public boolean contains(Object o) {
* against an unscrupulous collection whose contains(Object o)
* method senses when o is a Map.Entry, and calls o.setValue.
*/
public boolean containsAll(Collection<?> c) {
public boolean containsAll(Collection<? extends @NonNull Object> c) {
for (Object o : c)
if (!contains(o)) // Invokes safe contains() above
return false;
Expand All @@ -3977,13 +3978,13 @@ public boolean remove(Object o) {
<>((Map.Entry<?,?>)o));
}

public boolean removeAll(Collection<?> c) {
public boolean removeAll(Collection<? extends @NonNull Object> c) {
return batchRemove(c, false);
}
public boolean retainAll(Collection<?> c) {
public boolean retainAll(Collection<? extends @NonNull Object> c) {
return batchRemove(c, true);
}
private boolean batchRemove(Collection<?> c, boolean complement) {
private boolean batchRemove(Collection<? extends @NonNull Object> c, boolean complement) {
Objects.requireNonNull(c);
boolean modified = false;
Iterator<Map.Entry<K,V>> it = iterator();
Expand Down Expand Up @@ -4477,7 +4478,7 @@ private static class EmptySet<E>
public boolean isEmpty() {return true;}

public boolean contains(Object obj) {return false;}
public boolean containsAll(Collection<?> c) { return c.isEmpty(); }
public boolean containsAll(Collection<? extends @NonNull Object> c) { return c.isEmpty(); }

@SideEffectFree
public @PolyNull Object[] toArray(EmptySet<@PolyNull E> this) { return new Object[0]; }
Expand Down Expand Up @@ -4604,7 +4605,7 @@ public ListIterator<E> listIterator() {
public boolean isEmpty() {return true;}

public boolean contains(Object obj) {return false;}
public boolean containsAll(Collection<?> c) { return c.isEmpty(); }
public boolean containsAll(Collection<? extends @NonNull Object> c) { return c.isEmpty(); }

@SideEffectFree
public @PolyNull Object[] toArray(EmptyList<@PolyNull E> this) { return new Object[0]; }
Expand Down Expand Up @@ -5661,9 +5662,9 @@ private static class SetFromMap<E> extends AbstractSet<E>
public String toString() { return s.toString(); }
public int hashCode() { return s.hashCode(); }
public boolean equals(@Nullable Object o) { return o == this || s.equals(o); }
public boolean containsAll(Collection<?> c) {return s.containsAll(c);}
public boolean removeAll(Collection<?> c) {return s.removeAll(c);}
public boolean retainAll(Collection<?> c) {return s.retainAll(c);}
public boolean containsAll(Collection<? extends @NonNull Object> c) {return s.containsAll(c);}
public boolean removeAll(Collection<? extends @NonNull Object> c) {return s.removeAll(c);}
public boolean retainAll(Collection<? extends @NonNull Object> c) {return s.retainAll(c);}
// addAll is the only inherited implementation

// Override default methods in Collection
Expand Down Expand Up @@ -5744,9 +5745,9 @@ static class AsLIFOQueue<E> extends AbstractQueue<E>
@SideEffectFree
public <T> T[] toArray(T[] a) { return q.toArray(a); }
public String toString() { return q.toString(); }
public boolean containsAll(Collection<?> c) {return q.containsAll(c);}
public boolean removeAll(Collection<?> c) {return q.removeAll(c);}
public boolean retainAll(Collection<?> c) {return q.retainAll(c);}
public boolean containsAll(Collection<? extends @NonNull Object> c) {return q.containsAll(c);}
public boolean removeAll(Collection<? extends @NonNull Object> c) {return q.removeAll(c);}
public boolean retainAll(Collection<? extends @NonNull Object> c) {return q.retainAll(c);}
// We use inherited addAll; forwarding addAll would be wrong

// Override default methods in Collection
Expand Down
4 changes: 2 additions & 2 deletions checker/jdk/nullness/src/java/util/Deque.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,8 @@ public interface Deque<E> extends Queue<E> {
public abstract @Nullable E peek();
public abstract void push(E a1);
public abstract E pop();
public abstract boolean remove(@Nullable Object a1);
@Pure public abstract boolean contains(@Nullable Object a1);
public abstract boolean remove(Object a1);
@Pure public abstract boolean contains(Object a1);
@Pure public abstract int size();
@SideEffectFree
public abstract Iterator<E> iterator();
Expand Down
2 changes: 1 addition & 1 deletion checker/jdk/nullness/src/java/util/Dictionary.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public abstract class Dictionary<K, V> {
@Pure public abstract boolean isEmpty();
public abstract Enumeration<K> keys();
public abstract Enumeration<V> elements();
@Pure public abstract @Nullable V get(@Nullable Object a1);
@Pure public abstract @Nullable V get(Object a1);
@EnsuresKeyFor(value="#1", map="this")
public abstract @Nullable V put(K a1, V a2);
public abstract @Nullable V remove(Object a1);
Expand Down
Loading