JDK-8073842 : Invalid method reference when referencing a method on a wildcard type
  • Type: Bug
  • Component: tools
  • Sub-Component: javac
  • Affected Version: 8u31
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: linux
  • CPU: x86_64
  • Submitted: 2015-02-17
  • Updated: 2023-10-16
  • Resolved: 2015-02-27
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 9
9 b54Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0_31"
Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
Java HotSpot(TM) 64-Bit Server VM (build 25.31-b07, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Linux jacek 3.2.0-4-amd64 #1 SMP Debian 3.2.63-2+deb7u2 x86_64 GNU/Linux

A DESCRIPTION OF THE PROBLEM :
Invalid method reference thrown by javac when making a reference to a method on an upper bounded wildcard generic type.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
1. Create a file named Sample.java containing the attached source code for class Sample
2. Compile: javac Sample.java 


EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
File compiles OK.
ACTUAL -
Compilation error occurs 

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Sample.java:8: error: invalid method reference
    Stream<Runnable> r = s.map(o -> o::work);
                                    ^
  cannot find symbol
    symbol:   method work()
    location: bound of type variable CAP#1
  where CAP#1 is a fresh type-variable:
    CAP#1 extends Sample from capture of ? extends Sample
1 error


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.stream.Stream;
public class Sample {

  void work() { }

  void process(Stream<? extends Sample> s) {
    Stream<Runnable> r = s.map(o -> o::work);
  }
}
---------- END SOURCE ----------


Comments
URL: http://hg.openjdk.java.net/jdk9/jdk9/langtools/rev/218d589184d3 User: lana Date: 2015-03-11 02:21:17 +0000
11-03-2015

URL: http://hg.openjdk.java.net/jdk9/dev/langtools/rev/218d589184d3 User: mcimadamore Date: 2015-02-27 18:24:22 +0000
27-02-2015

The problem is that javac is unable to perform method lookup on type-variables sites; in all cases where lookup occurs, javac tries to lift the receiver type to a class type, by repeatedly calling getUpperBound() on the receiver; this is not done for method reference lookup, which results in spurious accessibility issues.
25-02-2015

The input stream contains Sample - meaning that the argument to map() should be something like Function<Simple, Runnable>. The lambda is not pertinent to applicability (as its return expression isn't) but that doesn't constitute an issue, as there's no overloading of Stream.map. So, from invocation type inference, we should be able to establish that the target type of the nested method reference is a Runnable, which should be compatible with the method reference (as work() is a void method). This is a bug.
25-02-2015

Checked this for JDK 8u31 and 8u40 ea b23 and could notice the error: >javac Sample.java Sample.java:7: error: invalid method reference Stream<Runnable> r = s.map(o -> o::work); ^ cannot find symbol symbol: method work() location: bound of type variable CAP#1 where CAP#1 is a fresh type-variable: CAP#1 extends Sample from capture of ? extends Sample 1 error
25-02-2015