I think you found this bug in the compiler: JDK-8029718 (or this similar one in Eclipse: 434642).
Compare to JLS §15.12.2.1. Identify Potentially Applicable Methods:
…
A lambda expression (§15.27) is potentially compatible with a functional interface type (§9.8) if all of the following are true:
The arity of the target type's function type is the same as the arity of the lambda expression.
If the target type's function type has a void return, then the lambda body is either a statement expression (§14.8) or a void-compatible block (§15.27.2).
If the target type's function type has a (non-void) return type, then the lambda body is either an expression or a value-compatible block (§15.27.2).
Note the clear distinction between “void
compatible blocks” and “value-compatible blocks”. While a block might be both in certain cases, the section §15.27.2. Lambda Body clearly states that an expression like () -> {}
is a “void
compatible block”, as it completes normally without returning a value. And it should be obvious that i -> {}
is a “void
compatible block” too.
And according to the section cited above, the combination of a lambda with a block that is not value-compatible and target type with a (non-void
) return type is not a potential candidate for the method overload resolution. So your intuition is right, there should be no ambiguity here.
Examples for ambiguous blocks are
() -> { throw new RuntimeException(); }
() -> { while (true); }
as they don’t complete normally, but this is not the case in your question.