This test:
import java.util.function.*;
class Test {
<Z> void m(Consumer<Z> c, Class<Z> cl) {
}
void test(boolean b, int i) {
m(s -> s.length(), String.class);
m(b ? s -> s.length() : s -> s.length(), String.class);
m(switch (i) {
case 0 -> s -> s.length();
default -> s -> s.length();
}, String.class);
}
}
Fails to compile:
Test.java:12: error: cannot find symbol
case 0 -> s -> s.length();
^
symbol: method length()
location: variable s of type Z
where Z is a type-variable:
Z extends Object declared in method <Z>m(Consumer<Z>,Class<Z>)
Test.java:13: error: cannot find symbol
default -> s -> s.length();
^
symbol: method length()
location: variable s of type Z
where Z is a type-variable:
Z extends Object declared in method <Z>m(Consumer<Z>,Class<Z>)
Test.java:11: error: incompatible types: inference variable Z has incompatible equality constraints String,Z
m(switch (i) {
^
where Z is a type-variable:
Z extends Object declared in method <Z>m(Consumer<Z>,Class<Z>)
3 errors
Note that the first call and the second compile without issues.
The problem is caused by the fact that DeferredAttr.PolyScanner does not look inside switch expression nodes. As a result, DeferredAttr.OverloadStuckPolicy and DefrredAttr.CheckStuckPolicy do not collect "stuck" type variables from functional interface targets required inside the arms of a switch expression (unlike what happens e.g. for conditionals). Because of that, Consumer<Z> is not detected as a non-concrete type; as such the compiler just tries to use it as a target, which generates the spurious errors seen above.
import java.util.function.*;
class Test {
<Z> void m(Consumer<Z> c, Class<Z> cl) {
}
void test(boolean b, int i) {
m(s -> s.length(), String.class);
m(b ? s -> s.length() : s -> s.length(), String.class);
m(switch (i) {
case 0 -> s -> s.length();
default -> s -> s.length();
}, String.class);
}
}
Fails to compile:
Test.java:12: error: cannot find symbol
case 0 -> s -> s.length();
^
symbol: method length()
location: variable s of type Z
where Z is a type-variable:
Z extends Object declared in method <Z>m(Consumer<Z>,Class<Z>)
Test.java:13: error: cannot find symbol
default -> s -> s.length();
^
symbol: method length()
location: variable s of type Z
where Z is a type-variable:
Z extends Object declared in method <Z>m(Consumer<Z>,Class<Z>)
Test.java:11: error: incompatible types: inference variable Z has incompatible equality constraints String,Z
m(switch (i) {
^
where Z is a type-variable:
Z extends Object declared in method <Z>m(Consumer<Z>,Class<Z>)
3 errors
Note that the first call and the second compile without issues.
The problem is caused by the fact that DeferredAttr.PolyScanner does not look inside switch expression nodes. As a result, DeferredAttr.OverloadStuckPolicy and DefrredAttr.CheckStuckPolicy do not collect "stuck" type variables from functional interface targets required inside the arms of a switch expression (unlike what happens e.g. for conditionals). Because of that, Consumer<Z> is not detected as a non-concrete type; as such the compiler just tries to use it as a target, which generates the spurious errors seen above.