Skip to content
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

False positive NonNull requirement for generic input #6382

Open
spacether opened this issue Dec 22, 2023 · 1 comment
Open

False positive NonNull requirement for generic input #6382

spacether opened this issue Dec 22, 2023 · 1 comment
Assignees

Comments

@spacether
Copy link

spacether commented Dec 22, 2023

Thanks for submitting an issue.
As explained in the instructions for submitting an issue at https://checkerframework.org/manual/#reporting-bugs, please include four pieces of information:

  • commands (that can be cut-and-pasted into a command shell),
  • inputs,
  • outputs, and
  • expectation.

Hi there. I have some code that makes a map, where the type of the Map is determined by the input map <K, V> entries.
Here is my mapmaker code:

public class MapMaker {
    @SafeVarargs
    @SuppressWarnings("varargs")
    public static <K, V> Map<K, V> makeMap(Map.Entry<K, V>... entries) {
        Map<K, V> map = new HashMap<>();
        for (Map.Entry<K, V> entry : entries) {
            map.put(entry.getKey(), entry.getValue());
        }
        return map;
    }

    @Covariant({0, 1})
    public static class SimpleEntry<K, V> implements Map.Entry<K, V> {
        private final K key;
        private V value;

        public SimpleEntry(K key, V value) {
            this.key   = key;
            this.value = value;
        }

        public K getKey() {
            return key;
        }

        @Override
        public V getValue() {
            return value;
        }

        @Override
        public V setValue(V value) throws UnsupportedOperationException {
            throw new UnsupportedOperationException();
        }

    }
}

And here is my code that uses it:

            MapMaker.makeMap(
                new MapMaker.SimpleEntry<>(
                    "foo",
                    "quux"
                ),
                new MapMaker.SimpleEntry<>(
                    "baz",
                    null
                )
            )

When running type checker it complains:

java: [argument] incompatible argument for parameter value of SimpleEntry.
  found   : null (NullType)
  required: @Initialized @NonNull String

But the docs for type checker state that:

 <T>
    Any type argument may be supplied for T.

    It is equivalent to <T extends @Nullable Object>, because @Nullable Object is the top type in the type hierarchy.

So null should be allowed here.
Conservative type checking should make
"foo", "qux" -> Entry<String, @NonNull String> -> convert to Entry<String, @Nullable String> because the value is covariant in the SimpleEntry
"baz", null -> Entry<String, @Nullable Object> -> convert to Entry<String, @Nullable String>

Is this an actual bug or is one of my steps above wrong?

@spacether spacether changed the title False positive null requirement for generic input False positive NonNull requirement for generic input Dec 23, 2023
@spacether
Copy link
Author

One can get this working by manually setting the types in MapMaker.SimpleEntry
For code generation contexts, it takes extra work to determine that type info.
The java compiler + intelij are able to figure out the types without this extra info, it would be great if the type checker framework could do this too.

@smillst smillst self-assigned this Jan 17, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants