Skip to content

FinalizePrivateFields produces uncompilable code when field is captured by a lambda in an instance field initializer #861

@protocol7

Description

@protocol7

What version of OpenRewrite are you using?

  • org.openrewrite:rewrite-core:8.79.2
  • org.openrewrite.recipe:rewrite-static-analysis:2.32.0

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

FinalizePrivateFields finalizes a private field that is only assigned in the constructor, without checking whether that field is read by a lambda (or anonymous class) captured in another instance field initializer declared earlier. Instance field initializers run in declaration order before the constructor body, so when the field is made final, Java's definite-assignment analysis rejects the read inside the lambda and the rewritten source no longer compiles.

  @Test
  void finalizePrivateFieldCapturedByLambdaInInstanceInitializer() {
    rewriteRun(
        spec -> spec.recipe(new FinalizePrivateFields()),
        // language=java
        java(
            """
            import java.util.function.Function;

            public class Foo {
              private String name;
              protected Function<Throwable, Void> logAndAccept =
                  throwable -> {
                    System.out.println(name);
                    return null;
                  };

              public Foo(String name) {
                this.name = name;
              }
            }
            """));
  }

After the recipe runs, name is finalized and javac fails:

Foo.java:6: error: variable name might not have been initialized
        System.out.println(name);
                           ^

The recipe should skip fields that are read from inside a lambda or anonymous class captured by an instance field initializer whose declaration precedes the field's single constructor assignment.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type
No fields configured for issues without a type.

Projects

Status
Done

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions