ElectronWill
ElectronWill

Reputation: 823

Compilation fails when upper bound wildcard is used with a lower one

Situation: I'm making a configuration library, with a Config interface that represents the data, and a Parser interface like this:

public interface Parser<C extends D, D extends Config> {
    C parse(File f);
    void parse(File f, D destination);
}

The parser must be able to parse data into a new Config object (C), or an existing one (D). C extends D because it's logical that we can create C manually and parse data into it. And of course D extends Config because we parse configurations.

Let's say we have a class MyConfig that implements Config (but it could as well be a generic "T extends Config"), and we want a Parser that can create and parse it. Let's follow the PECS rule:

Therefore I end up with this:

Parser<? extends MyConfig, ? super MyConfig> parser;

But while IntelliJ doesn't complain about anything, the compilation (javac 1.8.0_131) fails with this error:

type argument ? extends package.MyConfig is not within bounds of type-variable C

Which is weird, because "some subtype of MyConfig" is obviously a subtype of "some supertype of MyConfig", right?

This issue arises only when both wildcards are used. Also, using another generic type instead of the upper bound works:

// All these are fine
Parser<? extends MyConfig, MyConfig>
Parser<MyConfig, ? super MyConfig>
<J extends MyConfig> void test(Parser<J, ? super MyConfig> parser)

What am I missing here? And what can I do with my producer-consumer Parser?

EDIT: I found something even more confusing: using a subinterface of Config instead of a subclass works, ie this compiles perfectly fine:

interface SpecialConfig extends Config {}
Parser<? extends SpecialConfig, ? super SpecialConfig> specialParser;

Upvotes: 3

Views: 118

Answers (0)

Related Questions