2

I wonder if this is a bug in ECJ or a valid interpretation of the JLS.

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.function.Supplier;

public class GenericsTest {
    public void testInference() {
        Set<Object> set1 = getCollection(HashSet::new);
        Set<Object> set2 = getCollection2(HashSet::new);
    }

    public static <E, C extends Collection<E>> C getCollection(Supplier<C> collectionSupplier) {
        return collectionSupplier.get();
    }

    public static <E, C extends Collection<E>> C getCollection2(CollectionSupplier<E, C> collectionSupplier) {
        return collectionSupplier.get();
    }

    public interface CollectionSupplier<E, C extends Collection<E>> {
        C get();
    }
}

Javac (11.0.11) compiles everything (correctly, I would say).

ECJ (4.20.0) fails to compile the getCollection2(HashSet::new) call with error "Type mismatch: cannot convert from Collection to Set".

The getCollection(HashSet::new) call is not a problem for any compiler.

If I apply the suggested quickfix and insert a cast to HashSet<Object>, I get a different error from ECJ: "Problem detected during type inference: Unknown error at invocation of getCollection2(GenericsTest.CollectionSupplier<Object,Collection>)"

There are lots of similar questions here and bugs at bugs.eclipse.org, but most examples seemed to involve ?.

Dan Berindei
  • 7,054
  • 3
  • 41
  • 48
  • 1
    There are pretty few people who know the spec well enough to know for sure. In the past I've known ECJ to often be more strict (and more correct) in their interpretation of the JSL so if there was a difference, then it tended to be a javac bug and ECJ was correct. I don't know if that's still true, especially when it comes to the "new" type inference rules. I'd file a bug with ECJ, as javac is effectively the reference implementation, so it's up to them to argue if/why they are correct in differing from what it does. – Joachim Sauer Aug 04 '21 at 13:00
  • @JoachimSauer `javac` is not the reference implementation and is up to the bug reporter to argue why this is a bug according to JLS. Eclipse is open source so it's _us_, not _them_. – howlger Aug 04 '21 at 14:31
  • @howlger: both OpenJDK and Eclipse are open source and I (and I suspect OP as well) aren't actively working on either, so it is "them". And yes, `javac` is not the official reference implementation, but it is the de-facto reference by virtue of being the one that's developed "closest" to the standard. Any way: both the Eclipse and the javac people will be better able to judge which one is wrong here than I am and one has to pick one (or report to both and mention the other report in both). – Joachim Sauer Aug 04 '21 at 15:18
  • @JoachimSauer I agree with your on the first part of your first comment. But it is not fair to misuse bug reports to ask whether a given code is valid Java code. It's up to the reporter to argue why a bug is a bug. I encourage everyone to contribute to the open source software they use, [which can be done in many ways](https://www.eclipse.org/contribute/) and which starts by realizing that it is _us_ and not _them_. – howlger Aug 05 '21 at 08:22
  • @howlger: Of course it's up to the bug reporter to argue why they think it's wrong. I just think that "javac accepts it" is a reasonable argument. And it might *still* be a bug in javac instead of ECJ, but I'm saying I'm not qualified to judge that. And the guys at the ECJ project *are*. And I don't know why you latch onto the "them" so much: All I'm saying is that I'm not an active contributor to ECJ. I've filed bug reports with them before, but not enough to consider myself "part of the project". "Them" is not always about excluding others. – Joachim Sauer Aug 05 '21 at 09:20
  • @howlger: having re-read my initial comment I see how "It's up to them to argue" could easily be interpreted in a way I didn't intend. What I wanted to say is "they will look at it and know if ECJ is wrong here or if javac is." Because *one of them* has to be wrong, as the spec is pretty specific (yes, there's a chance that the spec itself is incomplete here and both are conforming, but I don't think I've ever seen that case). I didn't mean to imply that "they have to defend themselves". – Joachim Sauer Aug 05 '21 at 09:24
  • @JoachimSauer I'm just concerned about the limited developer resources of Eclipse (see e.g. [here](https://objectteams.wordpress.com/2021/04/05/retrospective-of-an-old-man/)) and would like to see more people contributing to open source they use. As someone answering questions about Eclipse, I consider you as an active Eclipse contributor and as part of _us_. ;) – howlger Aug 06 '21 at 13:15

1 Answers1

1

Please report the issue you get with the cast to Eclipse JDT.

As a workaround, you can give the Eclipse compiler a hint as follows:

Set<Object> set2 = getCollection2((CollectionSupplier<Object, Set<Object>>) HashSet::new);

The tricky part for the compiler is to check whether what getCollection2 returns is compatible to Set<Object>. But to be able to do that, the type parameter of the HashSet::new has to be known, and this is determined from Set<Object> (in this case, HashSet::new creates an instance of HashSet<Object>). So, the type parameter must be determined from the opposite direction than checking whether the return type is compatible with the declared type for which the type parameter is required.

It seems, Eclipse fails to compute the type parameter of HashSet::new. ObjectHashSet::new with static class ObjectHashSet extends HashSet<Object> {} works. GenericsTest::newObjectHashSet with static Set<Object> newObjectHashSet() { return new HashSet<Object>(); } works also, but fails with static <T> Set<T> newObjectHashSet() { return new HashSet<T>(); }.

howlger
  • 31,050
  • 11
  • 59
  • 99
  • I wanted to report the bug, but I was not able to log into bugs.eclipse.org either with my old account or with a new one I created now (or at least I think I created, the reset password form says it doesn't exist and the create form says it does exist). – Dan Berindei Aug 08 '21 at 06:31