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
Calling Map/Collection methods with arguments that are not compatible with type parameters #106
Comments
Original comment posted by wasserman.louis on 2013-03-05 at 08:38 PM These are not this way for compatibility reasons, but because it's genuinely necessary. See e.g. http://smallwig.blogspot.com/2007/12/why-does-setcontains-take-object-not-e.html for details. Josh Bloch explains the original logic at http://youtu.be/wDN_EYUvUq0?t=6m41s. |
Original comment posted by alexeagle@google.com on 2013-04-27 at 07:37 PM Issue #127 has been merged into this issue. |
Original comment posted by fixpoint@google.com on 2013-04-28 at 08:24 PM wasserman.louis, I understand how this is a tradeoff between type discipline and convenience. Nevertheless, the check would help avoid some bugs (like the mentioned example of passing and Integer to Set<Long>.contains()). |
Original comment posted by mdempsky@google.com on 2013-11-05 at 07:45 PM Louis: I interpret Josh's argument as Set.contains() has to take an Object because of JLS limitations; i.e., there's no way to define that Set<? extends V>.contains() should allow any "V" argument, not just a "? extends V" argument. Are there cases where you'd actually want to call Set<? extends V>.contains() with an object that isn't assignable to V? If not, I think it's reasonable for error-prone to provide special case generic handling logic for cases like these though (maybe just a warning initially). |
Original comment posted by lowasser@google.com on 2013-11-05 at 07:48 PM One example would be calling Map<ArrayList<Integer>, String>.get(ImmutableList<Integer>). |
Original comment posted by mdempsky@google.com on 2013-11-05 at 07:52 PM Ah, because you're relying on ArrayList and ImmutableList being comparable for equality? I suppose the check is only safe to make into an error when the container only uses reference equality, otherwise you need some extra logic (e.g., ArrayList and ImmutableList both implement List, so they should still be comparable with equals()). |
Original comment posted by eaftan@google.com on 2013-11-05 at 07:53 PM FYI the existing CollectionIncompatibleType does some of this but needs work. |
Original comment posted by eaftan@google.com on 2013-11-08 at 07:52 PM FindBugs detects this problem for the following methods. We should support as many of these as we can, as long as it doesn't increase our false positive rate. java.util.Collection<E>: java.util.Deque<E>: java.util.List<E>: java.util.Vector<E>: java.util.Map<K,V>: java.util.Hashtable<K,V>: java.util.concurrent.ConcurrentHashMap<K,V>: java.util.concurrent.ConcurrentMap<K,V>: com.google.common.collect.Multimap<K,V>: com.google.common.cache.Cache<K,V>: com.google.common.collect.Multiset<E>: com.google.common.collect.Table<R,C,V>: Static methods com.google.common.collect.Sets: com.google.common.collect.Iterables: com.google.common.collect.Iterators: Owner: amshali@google.com |
Original comment posted by amshali@google.com on 2013-11-08 at 08:23 PM Alright. I will add these with caution. Status: Accepted |
Original comment posted by amshali@google.com on 2014-03-25 at 06:07 PM I am gonna take a new look at this. |
Original comment posted by kevinb@google.com on 2014-09-25 at 04:30 PM FYI, I think this has to be one of the top 3 highest-value checks not yet enabled. |
What if, instead of hardcoding the giant list of Guava methods, we annotated Guava like so: interface Multimap<K, V> { Of course, you'd want to give a compile error for Multimap.java itself if the "K" doesn't match a type parameter name. Some name ideas... @CompatibleWith The last one is a bit confusing. It may sound like you have to actually know that all possible instances are castable to that type; but if that were the case then you'd just accept K and users would actually make that cast. We only want to know that some instance could exist that is castable. |
|
Comparable, as well as being taken, doesn't seem to describe the concept we're talking about very well. |
+1 for convertible or castable. I think castable is the most accurate, in the sense that the language would let you to attempt the cast, not necessarily that it would succeed without CCE. |
I vote for Question: what about methods like |
We could just make it a generic method. Oh, but it's a little worse than that:
This is nowhere expressing that it's the type parameter of One copout is just to say that methods like this still have to be hardcoded in the checker, at least until Java 8 gives us possible new possibilities for doing this with a type annotation maybe... |
Type annotation seems like the right approach for the case where we need to check the type parameter of the argument. Seems reasonable to hardcode until we support Java 8. |
This happened: http://errorprone.info/bugpattern/CollectionIncompatibleType |
Original issue created by fixpoint@google.com on 2013-03-05 at 03:23 PM
There are some methods on Map<K,V> or Collection<V> that accept Object because of compatibility reasons, while in fact they should accept <V>. We can check that arguments passed to those methods are compatible with V.
Example:
Map<MyProto, Integer> map = ...;
MyProto.Builder proto = MyProto.newBuilder()...;
if (map.get(proto)) { ... };
Following checks can be introduced for all "Map<K,V> map" and "T arg" variables:
Following checks can be introduced for all "Collection<V> coll" and "T arg" variables:
Same for List.indexOf, List.lastIndexOf.
The text was updated successfully, but these errors were encountered: