ADDITIONAL SYSTEM INFORMATION :
Linux Mint 21.3, Adoptium 21.0.2
A DESCRIPTION OF THE PROBLEM :
When developing a custom library that utilizes Spring's WebClient, I encountered a weird issue with generics which involves a family of interfaces described in Spring's WebClient class. In short, source file would not compile if a method reference is used, but will compile just fine if that method reference was replaced with an identical lambda. To avoid complicating things, I've thrown together a minimal reproducible example which mimics the interface hierarchy of WebClient and illustrates the issue
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Compile the attached source code with a simple javac <path/to/file.java>
2. Observe that it compiles without issues
3. In the main method, comment out the line with a lambda and uncomment the line with a method reference
4. Compile the file again with a simple javac <path/to/file.java>
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Source file compiles without issues
ACTUAL -
The following error is reported:
<path/to/file.java>:24: error: method invoke in class ReproducibleExample cannot be applied to given types;
invoke(Receiver::getRootWithExtra);
^
required: Function<? super Receiver,? extends ES>
found: Receiver::[...]Extra
reason: inferred type does not conform to equality constraint(s)
inferred: S#2
equality constraints(s): CAP#1
where ES,S#1,S#2 are type-variables:
ES extends RootWithExtraInterface<S#1> declared in method <S#1,ES>invoke(Function<? super Receiver,? extends ES>)
S#1 extends RootInterface<S#1> declared in method <S#1,ES>invoke(Function<? super Receiver,? extends ES>)
S#2 extends RootInterface<S#2>
where CAP#1 is a fresh type-variable:
CAP#1 extends RootInterface<CAP#1> from capture of ?
1 error
---------- BEGIN SOURCE ----------
import java.util.function.Function;
public class ReproducibleExample {
// Stand-in for WebClient
private interface Receiver {
// Stand-in for get() (or any other method with the same return type)
RootWithExtraInterface<?> getRootWithExtra();
}
// Stand-in for RequestHeadersSpec
private interface RootInterface<S extends RootInterface<S>> {}
// Stand-in for UriSpec
private interface ExtraInterface<S extends RootInterface<?>> {}
// Stand-in for RequestHeadersUriSpec
private interface RootWithExtraInterface<S extends RootInterface<S>> extends RootInterface<S>, ExtraInterface<S> {}
private static <S extends RootInterface<S>, ES extends RootWithExtraInterface<S>> S invoke(
Function<? super Receiver, ? extends ES> function
) {
return null;
}
public static void main(String[] args) {
invoke(receiver -> receiver.getRootWithExtra());
// invoke(Receiver::getRootWithExtra);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Using lambda instead of a method reference and staring at a yellow wavy-line in your IDE which prompts you to convert it to a method reference.
FREQUENCY : always
Linux Mint 21.3, Adoptium 21.0.2
A DESCRIPTION OF THE PROBLEM :
When developing a custom library that utilizes Spring's WebClient, I encountered a weird issue with generics which involves a family of interfaces described in Spring's WebClient class. In short, source file would not compile if a method reference is used, but will compile just fine if that method reference was replaced with an identical lambda. To avoid complicating things, I've thrown together a minimal reproducible example which mimics the interface hierarchy of WebClient and illustrates the issue
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Compile the attached source code with a simple javac <path/to/file.java>
2. Observe that it compiles without issues
3. In the main method, comment out the line with a lambda and uncomment the line with a method reference
4. Compile the file again with a simple javac <path/to/file.java>
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Source file compiles without issues
ACTUAL -
The following error is reported:
<path/to/file.java>:24: error: method invoke in class ReproducibleExample cannot be applied to given types;
invoke(Receiver::getRootWithExtra);
^
required: Function<? super Receiver,? extends ES>
found: Receiver::[...]Extra
reason: inferred type does not conform to equality constraint(s)
inferred: S#2
equality constraints(s): CAP#1
where ES,S#1,S#2 are type-variables:
ES extends RootWithExtraInterface<S#1> declared in method <S#1,ES>invoke(Function<? super Receiver,? extends ES>)
S#1 extends RootInterface<S#1> declared in method <S#1,ES>invoke(Function<? super Receiver,? extends ES>)
S#2 extends RootInterface<S#2>
where CAP#1 is a fresh type-variable:
CAP#1 extends RootInterface<CAP#1> from capture of ?
1 error
---------- BEGIN SOURCE ----------
import java.util.function.Function;
public class ReproducibleExample {
// Stand-in for WebClient
private interface Receiver {
// Stand-in for get() (or any other method with the same return type)
RootWithExtraInterface<?> getRootWithExtra();
}
// Stand-in for RequestHeadersSpec
private interface RootInterface<S extends RootInterface<S>> {}
// Stand-in for UriSpec
private interface ExtraInterface<S extends RootInterface<?>> {}
// Stand-in for RequestHeadersUriSpec
private interface RootWithExtraInterface<S extends RootInterface<S>> extends RootInterface<S>, ExtraInterface<S> {}
private static <S extends RootInterface<S>, ES extends RootWithExtraInterface<S>> S invoke(
Function<? super Receiver, ? extends ES> function
) {
return null;
}
public static void main(String[] args) {
invoke(receiver -> receiver.getRootWithExtra());
// invoke(Receiver::getRootWithExtra);
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Using lambda instead of a method reference and staring at a yellow wavy-line in your IDE which prompts you to convert it to a method reference.
FREQUENCY : always