<!DOCTYPE html><html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
</head>
<body>
<p>Hi Tagir!</p>
<p>Nice cacth.</p>
<p>Here's a slightly different example which reveals a bit more of
what's happening:</p>
<p>```<br>
interface Main {<br>
interface X<T> {<br>
X<T> self();<br>
}<br>
<br>
static X<?> makeX() {return null;}<br>
<br>
static <R> X<R> create(Supplier<? extends R>
supplier) {return null;}<br>
<br>
static X<X<?>> methodRef() {<br>
var s = (String)create(Main::makeX);<br>
}<br>
<br>
static X<X<?>> lambda() {<br>
var s = (String)create(() -> makeX());<br>
}<br>
}<br>
```</p>
<p>This prints:</p>
<p>```<br>
error: incompatible types: X<X<?>> cannot be converted
to String<br>
var s = (String)create(Main::makeX);<br>
^<br>
error: incompatible types: X<X<CAP#1>> cannot be
converted to String<br>
var s = (String)create(() -> makeX());<br>
^<br>
where CAP#1 is a fresh type-variable:<br>
CAP#1 extends Object from capture of ?<br>
```</p>
<p>So, the main difference between the two examples is that in the
lambda case, the return type of the makeX call is captured. But in
the method refreene case no capture occurs.</p>
<p>I believe the lambda case works as expected, but the method
reference case does not.</p>
<p>The JLS mandates a capture of the resolved method return type
(JLS 15.13.2, emphasis mine):</p>
<p>
<blockquote type="cite">A method reference expression is <span class="emphasis"><em>congruent</em></span> with a function
type if both of the following are true:
<div class="norm">
<ul class="norm" style="list-style-type: disc; ">
<li class="listitem">
<p class="norm-static">The function type identifies a
single compile-time declaration corresponding to the
reference. </p>
</li>
<li class="listitem">
<p class="norm-static"> One of the following is true: </p>
<div class="norm">
<ul class="norm" style="list-style-type: circle; ">
<li class="listitem">
<p class="norm-static">The result of the function
type is <code class="literal">void</code>. </p>
</li>
<li class="listitem">
<p class="norm-static"> The result of the function
type is <span class="type">R</span>, <b>and the
result of applying capture conversion (<a class="xref" href="https://docs.oracle.com/javase/specs/jls/se25/html/jls-5.html#jls-5.1.10" title="5.1.10. Capture Conversion">§5.1.10</a>)
to the return type of the invocation type (<a class="xref" href="https://docs.oracle.com/javase/specs/jls/se25/html/jls-15.html#jls-15.12.2.6" title="15.12.2.6. Method Invocation Type">§15.12.2.6</a>)
of the chosen compile-time declaration is <span class="type">R</span>'</b> (where <span class="type">R</span> is the target type that
may be used to infer <span class="type">R</span>'),
and neither <span class="type">R</span> nor <span class="type">R</span>' is <code class="literal">void</code>,
and <span class="type">R</span>' is compatible
with <span class="type">R</span> in an assignment
context. </p>
</li>
</ul>
</div>
</li>
</ul>
</div>
</blockquote>
</p>
<p>It seems like javac is missing this capture conversion and,
because of that, the behavior of the two examples diverge.</p>
<p>Cheers<br>
Maurizio<br>
</p>
<p><br>
</p>
<p><br>
</p>
<p><br>
</p>
<p><br>
</p>
<div class="moz-cite-prefix">On 07/10/2025 17:12, Tagir Valeev
wrote:<br>
</div>
<blockquote type="cite" cite="mid:CAE+3fjb4EM9=TstxTO1_4dHJ6Gc=bt6qw=r_9QRkmsC6AraXzQ@mail.gmail.com">
<div dir="ltr">Hello!
<div><br>
</div>
<div>I'm investigating a seemingly weird compilation case.
Consider the following Java interface:</div>
<div><br>
</div>
<div>import java.util.function.Supplier;<br>
<br>
interface Main {<br>
interface X<T> {<br>
X<T> self();<br>
}<br>
<br>
static X<?> makeX() {return null;}<br>
<br>
static <R> X<R> create(Supplier<? extends
R> supplier) {return null;}<br>
<br>
static X<X<?>> methodRef() {<br>
return create(Main::makeX).self();<br>
}<br>
<br>
static X<X<?>> lambda() {<br>
return create(() -> makeX()).self();<br>
}<br>
}</div>
<div><br>
</div>
<div>I expect that either both methods 'methodRef' and 'lambda'
should be compilable or both should be non-compilable.
However, while 'methodRef' compiles, 'lambda' is rejected by
compiler (using javac build 25+36-3489):</div>
<div><br>
Main.java:17: error: incompatible types:
X<X<CAP#1>> cannot be converted to
X<X<?>><br>
return create(() -> makeX()).self();<br>
^<br>
where CAP#1 is a fresh type-variable:<br>
CAP#1 extends Object from capture of ?<br>
1 error<br>
error: compilation failed</div>
<div><br>
</div>
<div>Could you please help me and clarify whether this is an
expected behavior or not?</div>
<div><br>
</div>
<div>With best regards,</div>
<div>Tagir Valeev</div>
</div>
</blockquote>
</body>
</html>