java:S1602 false positive: collapsing block lambda breaks void MethodHandle.invokeExact

What language is this for?
Java

Which rule?
java:S1602 “Lambdas containing only one statement should not nest this statement in a block”

Why do you believe it’s a false-positive?
S1602 recommends rewriting () -> { stmt; } as () -> stmt, but when stmt is an invokeExact/invoke call on a void MethodHandle, the rewrite is not semantics-preserving. It compiles but throws WrongMethodTypeException at runtime. invokeExact is signature-polymorphic and infers its return type from the call site: as a statement in a block lambda it’s a void context (matches a (…)void handle), but as an expression lambda targeting a void-returning functional interface, javac infers the return type as Object, so the site becomes (…)Object and no longer matches the handle. S1602 should not raise (or offer the quick-fix) for this construct.

Are you using:

  • SonarQube Cloud? Yes (SonarQube Cloud / SonarCloud)

How can we reproduce the problem?

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;

public class S1602Repro {

    // Functional interface whose single abstract method returns void (e.g. a "run and log on failure" helper).
    interface ThrowingRunnable {
        void run() throws Throwable;
    }

    static void call(ThrowingRunnable action) throws Throwable {
        action.run();
    }

    public static void main(String[] args) throws Throwable {
        MethodHandle voidHandle = MethodHandles.empty(MethodType.methodType(void.class)); // type ()void

        // Block lambda: invokeExact is a statement (void context) -> return type inferred as void -> OK
        call(() -> { voidHandle.invokeExact(); });
        System.out.println("block lambda: OK");

        // S1602 flags the block above and suggests collapsing the braces to this expression lambda.
        // It compiles, but throws at runtime:
        //   java.lang.invoke.WrongMethodTypeException: handle's method type ()void but found ()Object
        call(() -> voidHandle.invokeExact());
        System.out.println("expression lambda: OK"); // never reached
    }
}

Running it prints block lambda: OK, then throws WrongMethodTypeException at the expression-lambda call. Real-world impact: a mechanical S1602 cleanup reintroduced this exact runtime regression in OSHI (freeing a Windows BSTR) — FFM free string failed on windows · Issue #3422 · oshi/oshi · GitHub

I verified this reproducer throws on a stock JDK (25).