JDK-8165756 : java compiler regression in nested varags
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 9
  • Priority: P2
  • Status: Closed
  • Resolution: Duplicate
  • OS: generic
  • CPU: generic
  • Submitted: 2016-09-09
  • Updated: 2016-09-09
  • Resolved: 2016-09-09
Related Reports
Duplicate :  
Description
Please refer to the following sample code.
This file can be compiled before jdk 9 b94 (JDK 8 can compile too). It looks a regression in javac (type inference?). I can reproduce on both Linux/mac, so looks to be OS independent.

I saw a bunch of changes on javac were integrated in jdk 9 b94. The following items may be related: 
JDK-8067767
JDK-8046685
JDK-8142931

import java.util.stream.Stream;

public class TypeInfer {
    public static <E extends Exception> void perform(Func<? extends E>... args) throws E {
        perform(Stream.of(args));
    }

    public static <E extends Exception> void perform(Func<? extends E> args) throws E {
        perform(Stream.of(args));
    }

    public static <E extends Exception> void perform(Stream<Func<? extends E>> list) throws E {
    }

    public interface Func<E extends Exception> {
        void func();// throws E;
    }
}


Javac output with jdk 9 after b94:
TypeInfer.java:4: error: unreported exception Exception; must be caught or declared to be thrown
                perform(Stream.of(args));
                       ^
Note: TypeInfer.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
1 error
2 warnings

Comments
The behavior pre b94 was definitively buggy - after overload resolution, javac picked up a spurious lower bound for E, so that E had two lower bounds, namely #CAP1 and #CAP2, with both #CAP1 <: Z and #CAP2 <: Z - this would cause javac to apply a lub(#CAP1, #CAP2) which would then return Z, and that would have made the program pass. Moreover, javac inferred two different answers during applicability and during invocation inference - during applicablity, E = Exception was inferred, but during invocation inference E = Z would be inferred. This is clearly unsound. As stated above, there's nothing in the spec that says as to whether this specific program should compile or not. The program used to compile by accident: the fact that the old incorporation scheme kept checking same bounds over and over caused generation of spurious bounds, and such 'redundancy' in this case caused 'lub' to accidentally do the right thing.
09-09-2016