-
Bug
-
Resolution: Not an Issue
-
P4
-
None
-
21.0.2
-
generic
-
generic
ADDITIONAL SYSTEM INFORMATION :
Fedora Linux Release 38
A DESCRIPTION OF THE PROBLEM :
Code of the form m1(m2(lamba)) can sometimes give a compile-time error, even though the type returned by m2 matches the parameter type of m1. This can occur when m2 is a generic method, but seems to depend on how many type parameters m2 has.
The attached simplified test program shows that the compiler may or may not reject,
System.out.println(method(withLambda));
although it accepts the use of a temporary variable,
var x = method(withLambda);
System.out.println(x);
The compiler correctly determines that,
two("ab", s -> s + "cd")
returns a String. The error messages confirm it. And if the result is cast to a String, the compiler warns the cast is redundant. Yet without the cast it complains that println(String) is ambiguous.
This is also reproduceable with types other than String. The problem is always with,
<T,R> R two(T t, Function<T,R> fn)
whereas
<R> R one(Supplier<R> fn)
always works.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Attempt to compile the attached code.
It will fail at the line
System.out.println(two("ab", s -> s + "cd"));
Remove that line and the remaining code will compile and give correct results at runtime.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The code
System.out.println(two("ab", s -> s + "cd"))
should compile and work the same as
var x2 = two("ab", s -> s + "cd");
System.out.println(x2);
ACTUAL -
MaybeBug.java:25: error: reference to println is ambiguous
System.out.println(two("ab", s -> s + "cd"));
^
both method println(char[]) in PrintStream and method println(String) in PrintStream match
MaybeBug.java:25: error: method println in class PrintStream cannot be applied to given types;
System.out.println(two("ab", s -> s + "cd"));
^
required: char[]
found: String
reason: argument mismatch; inference variable R has incompatible bounds
upper bounds: char[],Object
lower bounds: String
where R,T are type-variables:
R extends Object declared in method <T,R>two(T,Function<T,R>)
T extends Object declared in method <T,R>two(T,Function<T,R>)
2 errors
---------- BEGIN SOURCE ----------
import java.util.function.*;
public class MaybeBug {
static <R> R one(Supplier<R> fn) {
return fn.get();
}
static <T,R> R two(T t, Function<T,R> fn) {
return fn.apply(t);
}
public static void main (String[] args) {
//this prints "abcd" as expected...
var x1 = one(() -> "abcd");
System.out.println(x1);
//so does this...
System.out.println(one(() -> "abcd"));
//and so does this...
var x2 = two("ab", s -> s + "cd");
System.out.println(x2);
//BUT THIS DOESN'T COMPILE...
System.out.println(two("ab", s -> s + "cd"));
//although this does compile, albeit with a redundant cast warning...
System.out.println((String)two("ab", s -> s + "cd"));
//and so does this...
System.out.println(MaybeBug.<String,String>two("ab", s -> s + "cd"));
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Cast the String to a String:
@SuppressWarnings("cast")
. . . .
System.out.println((String)two("ab", s -> s + "cd"));
FREQUENCY : always
Fedora Linux Release 38
A DESCRIPTION OF THE PROBLEM :
Code of the form m1(m2(lamba)) can sometimes give a compile-time error, even though the type returned by m2 matches the parameter type of m1. This can occur when m2 is a generic method, but seems to depend on how many type parameters m2 has.
The attached simplified test program shows that the compiler may or may not reject,
System.out.println(method(withLambda));
although it accepts the use of a temporary variable,
var x = method(withLambda);
System.out.println(x);
The compiler correctly determines that,
two("ab", s -> s + "cd")
returns a String. The error messages confirm it. And if the result is cast to a String, the compiler warns the cast is redundant. Yet without the cast it complains that println(String) is ambiguous.
This is also reproduceable with types other than String. The problem is always with,
<T,R> R two(T t, Function<T,R> fn)
whereas
<R> R one(Supplier<R> fn)
always works.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Attempt to compile the attached code.
It will fail at the line
System.out.println(two("ab", s -> s + "cd"));
Remove that line and the remaining code will compile and give correct results at runtime.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The code
System.out.println(two("ab", s -> s + "cd"))
should compile and work the same as
var x2 = two("ab", s -> s + "cd");
System.out.println(x2);
ACTUAL -
MaybeBug.java:25: error: reference to println is ambiguous
System.out.println(two("ab", s -> s + "cd"));
^
both method println(char[]) in PrintStream and method println(String) in PrintStream match
MaybeBug.java:25: error: method println in class PrintStream cannot be applied to given types;
System.out.println(two("ab", s -> s + "cd"));
^
required: char[]
found: String
reason: argument mismatch; inference variable R has incompatible bounds
upper bounds: char[],Object
lower bounds: String
where R,T are type-variables:
R extends Object declared in method <T,R>two(T,Function<T,R>)
T extends Object declared in method <T,R>two(T,Function<T,R>)
2 errors
---------- BEGIN SOURCE ----------
import java.util.function.*;
public class MaybeBug {
static <R> R one(Supplier<R> fn) {
return fn.get();
}
static <T,R> R two(T t, Function<T,R> fn) {
return fn.apply(t);
}
public static void main (String[] args) {
//this prints "abcd" as expected...
var x1 = one(() -> "abcd");
System.out.println(x1);
//so does this...
System.out.println(one(() -> "abcd"));
//and so does this...
var x2 = two("ab", s -> s + "cd");
System.out.println(x2);
//BUT THIS DOESN'T COMPILE...
System.out.println(two("ab", s -> s + "cd"));
//although this does compile, albeit with a redundant cast warning...
System.out.println((String)two("ab", s -> s + "cd"));
//and so does this...
System.out.println(MaybeBug.<String,String>two("ab", s -> s + "cd"));
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Cast the String to a String:
@SuppressWarnings("cast")
. . . .
System.out.println((String)two("ab", s -> s + "cd"));
FREQUENCY : always