From 240af028c5c79f58dd5e1dd784d490b546e9082f Mon Sep 17 00:00:00 2001 From: Chris Povirk Date: Mon, 7 Oct 2024 11:31:48 -0400 Subject: [PATCH] Annotate the bulk methods of `ConcurrentHashMap`. (#71) It looks we just hadn't tried to annotate these yet. They do use `` but only because that's what our CF-stub-conversion tool produced from the `` in the CF stubs; the resulting unbounded type parameter doesn't seem to have been anyone's conscious choice. --- .../util/concurrent/ConcurrentHashMap.java | 62 +++++++++++-------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java index c17acb0a2c0..809ae36f9b9 100644 --- a/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java +++ b/src/java.base/share/classes/java/util/concurrent/ConcurrentHashMap.java @@ -3742,8 +3742,13 @@ public void forEach(long parallelismThreshold, * @param the return type of the transformer * @since 1.8 */ - public void forEach(long parallelismThreshold, - BiFunction transformer, + // JSpecify: We could instead use `` along with `@NonNull U`. + // Advantages to our current approach include: + // - calls out the null support in an otherwise null-hostile class + // - is consistent with the declarations for `search` and `reduce` + // - saves the user from a decision: https://github.com/jspecify/jspecify/issues/525 + public void forEach(long parallelismThreshold, + BiFunction transformer, Consumer action) { if (transformer == null || action == null) throw new NullPointerException(); @@ -3768,8 +3773,8 @@ public void forEach(long parallelismThreshold, * function on each (key, value), or null if none * @since 1.8 */ - public U search(long parallelismThreshold, - BiFunction searchFunction) { + public @Nullable U search(long parallelismThreshold, + BiFunction searchFunction) { if (searchFunction == null) throw new NullPointerException(); return new SearchMappingsTask (null, batchFor(parallelismThreshold), 0, 0, table, @@ -3792,8 +3797,8 @@ public void forEach(long parallelismThreshold, * of all (key, value) pairs * @since 1.8 */ - public U reduce(long parallelismThreshold, - BiFunction transformer, + public @Nullable U reduce(long parallelismThreshold, + BiFunction transformer, BiFunction reducer) { if (transformer == null || reducer == null) throw new NullPointerException(); @@ -3909,8 +3914,9 @@ public void forEachKey(long parallelismThreshold, * @param the return type of the transformer * @since 1.8 */ - public void forEachKey(long parallelismThreshold, - Function transformer, + // JSpecify: See discussion on `forEach` above. + public void forEachKey(long parallelismThreshold, + Function transformer, Consumer action) { if (transformer == null || action == null) throw new NullPointerException(); @@ -3935,8 +3941,8 @@ public void forEachKey(long parallelismThreshold, * function on each key, or null if none * @since 1.8 */ - public U searchKeys(long parallelismThreshold, - Function searchFunction) { + public @Nullable U searchKeys(long parallelismThreshold, + Function searchFunction) { if (searchFunction == null) throw new NullPointerException(); return new SearchKeysTask (null, batchFor(parallelismThreshold), 0, 0, table, @@ -3954,7 +3960,7 @@ public void forEachKey(long parallelismThreshold, * reducer to combine values, or null if none * @since 1.8 */ - public K reduceKeys(long parallelismThreshold, + public @Nullable K reduceKeys(long parallelismThreshold, BiFunction reducer) { if (reducer == null) throw new NullPointerException(); return new ReduceKeysTask @@ -3978,8 +3984,8 @@ public K reduceKeys(long parallelismThreshold, * of all keys * @since 1.8 */ - public U reduceKeys(long parallelismThreshold, - Function transformer, + public @Nullable U reduceKeys(long parallelismThreshold, + Function transformer, BiFunction reducer) { if (transformer == null || reducer == null) throw new NullPointerException(); @@ -4096,8 +4102,9 @@ public void forEachValue(long parallelismThreshold, * @param the return type of the transformer * @since 1.8 */ - public void forEachValue(long parallelismThreshold, - Function transformer, + // JSpecify: See discussion on `forEach` above. + public void forEachValue(long parallelismThreshold, + Function transformer, Consumer action) { if (transformer == null || action == null) throw new NullPointerException(); @@ -4122,8 +4129,8 @@ public void forEachValue(long parallelismThreshold, * function on each value, or null if none * @since 1.8 */ - public U searchValues(long parallelismThreshold, - Function searchFunction) { + public @Nullable U searchValues(long parallelismThreshold, + Function searchFunction) { if (searchFunction == null) throw new NullPointerException(); return new SearchValuesTask (null, batchFor(parallelismThreshold), 0, 0, table, @@ -4140,7 +4147,7 @@ public void forEachValue(long parallelismThreshold, * @return the result of accumulating all values * @since 1.8 */ - public V reduceValues(long parallelismThreshold, + public @Nullable V reduceValues(long parallelismThreshold, BiFunction reducer) { if (reducer == null) throw new NullPointerException(); return new ReduceValuesTask @@ -4164,8 +4171,8 @@ public V reduceValues(long parallelismThreshold, * of all values * @since 1.8 */ - public U reduceValues(long parallelismThreshold, - Function transformer, + public @Nullable U reduceValues(long parallelismThreshold, + Function transformer, BiFunction reducer) { if (transformer == null || reducer == null) throw new NullPointerException(); @@ -4280,8 +4287,9 @@ public void forEachEntry(long parallelismThreshold, * @param the return type of the transformer * @since 1.8 */ - public void forEachEntry(long parallelismThreshold, - Function, ? extends U> transformer, + // JSpecify: See discussion on `forEach` above. + public void forEachEntry(long parallelismThreshold, + Function, ? extends @Nullable U> transformer, Consumer action) { if (transformer == null || action == null) throw new NullPointerException(); @@ -4306,8 +4314,8 @@ public void forEachEntry(long parallelismThreshold, * function on each entry, or null if none * @since 1.8 */ - public U searchEntries(long parallelismThreshold, - Function, ? extends U> searchFunction) { + public @Nullable U searchEntries(long parallelismThreshold, + Function, ? extends @Nullable U> searchFunction) { if (searchFunction == null) throw new NullPointerException(); return new SearchEntriesTask (null, batchFor(parallelismThreshold), 0, 0, table, @@ -4324,7 +4332,7 @@ public void forEachEntry(long parallelismThreshold, * @return the result of accumulating all entries * @since 1.8 */ - public Map.Entry reduceEntries(long parallelismThreshold, + public Map.@Nullable Entry reduceEntries(long parallelismThreshold, BiFunction, Map.Entry, ? extends Map.Entry> reducer) { if (reducer == null) throw new NullPointerException(); return new ReduceEntriesTask @@ -4348,8 +4356,8 @@ public Map.Entry reduceEntries(long parallelismThreshold, * of all entries * @since 1.8 */ - public U reduceEntries(long parallelismThreshold, - Function, ? extends U> transformer, + public @Nullable U reduceEntries(long parallelismThreshold, + Function, ? extends @Nullable U> transformer, BiFunction reducer) { if (transformer == null || reducer == null) throw new NullPointerException();