Skip to content

ReplaceLambdaWithMethodReference produces invalid Objects::nonNull method reference #873

@protocol7

Description

@protocol7

What version of OpenRewrite are you using?

  • org.openrewrite:rewrite-core:8.81.1
  • org.openrewrite.recipe:rewrite-static-analysis:2.34.0

What is the smallest, simplest way to reproduce the problem?

ReplaceLambdaWithMethodReference rewrites a zero-argument lambda that captures a field into Objects::nonNull, but the target functional interface takes no arguments.

@Test
void zeroArgNullCheckLambdaCannotBecomeObjectsNonNull() {
  rewriteRun(
      spec -> spec.recipe(new ReplaceLambdaWithMethodReference()),
      // language=java
      java(
          """
          package com.helloworld;

          import java.util.concurrent.Callable;

          public class Main {
            private Object importerSource;

            void awaitReady(final ConditionFactory await) {
              await.until(() -> importerSource != null);
            }

            interface ConditionFactory {
              void until(Callable<Boolean> condition);
            }
          }
          """));
}

What did you see instead?

The recipe rewrites the lambda to Objects::nonNull:

 package com.helloworld;

+import java.util.Objects;
 import java.util.concurrent.Callable;

 public class Main {
   private Object importerSource;

   void awaitReady(final ConditionFactory await) {
-    await.until(() -> importerSource != null);
+    await.until(Objects::nonNull);
   }

   interface ConditionFactory {
     void until(Callable<Boolean> condition);
   }
 }

The rewritten source no longer compiles because Callable<Boolean> has a zero-argument call() method, while Objects.nonNull(Object) requires one argument.

What did you expect to see?

The recipe should leave this lambda unchanged. A lambda like () -> importerSource != null captures state and is compatible with a zero-argument functional interface, but Objects::nonNull is only valid when the target functional interface supplies the object argument.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions