From c00d0885ae3c99c0ebacec0bd7de7382ee954dc1 Mon Sep 17 00:00:00 2001 From: "Archie L. Cobbs" Date: Thu, 23 Mar 2023 15:59:51 +0000 Subject: [PATCH] 8043179: Lambda expression can mutate final field Reviewed-by: vromero --- .../classes/com/sun/tools/javac/comp/Flow.java | 5 +++++ .../lambda/8043179/LambdaMutateFinalField.java | 13 +++++++++++++ .../javac/lambda/8043179/LambdaMutateFinalField.out | 2 ++ .../javac/lambda/8043179/LambdaMutateFinalVar.java | 13 +++++++++++++ .../javac/lambda/8043179/LambdaMutateFinalVar.out | 2 ++ 5 files changed, 35 insertions(+) create mode 100644 test/langtools/tools/javac/lambda/8043179/LambdaMutateFinalField.java create mode 100644 test/langtools/tools/javac/lambda/8043179/LambdaMutateFinalField.out create mode 100644 test/langtools/tools/javac/lambda/8043179/LambdaMutateFinalVar.java create mode 100644 test/langtools/tools/javac/lambda/8043179/LambdaMutateFinalVar.out diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java index 35096c89083..70bab056c5a 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java @@ -2856,6 +2856,11 @@ public class Flow { int nextadrPrev = nextadr; ListBuffer prevPending = pendingExits; try { + // JLS 16.1.10: No rule allows V to be definitely unassigned before a lambda + // body. This is by design: a variable that was definitely unassigned before the + // lambda body may end up being assigned to later on, so we cannot conclude that + // the variable will be unassigned when the body is executed. + uninits.excludeFrom(firstadr); returnadr = nextadr; pendingExits = new ListBuffer<>(); for (List l = tree.params; l.nonEmpty(); l = l.tail) { diff --git a/test/langtools/tools/javac/lambda/8043179/LambdaMutateFinalField.java b/test/langtools/tools/javac/lambda/8043179/LambdaMutateFinalField.java new file mode 100644 index 00000000000..c464fcbe191 --- /dev/null +++ b/test/langtools/tools/javac/lambda/8043179/LambdaMutateFinalField.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @summary Verify lambda expression can't mutate a final field + * @bug 8043179 + * @compile/fail/ref=LambdaMutateFinalField.out -XDrawDiagnostics LambdaMutateFinalField.java + */ +class LambdaMutateFinalField { + final String x; + LambdaMutateFinalField() { + Runnable r1 = () -> x = "not ok"; + this.x = "ok"; + } +} diff --git a/test/langtools/tools/javac/lambda/8043179/LambdaMutateFinalField.out b/test/langtools/tools/javac/lambda/8043179/LambdaMutateFinalField.out new file mode 100644 index 00000000000..c3d1cb2c9ba --- /dev/null +++ b/test/langtools/tools/javac/lambda/8043179/LambdaMutateFinalField.out @@ -0,0 +1,2 @@ +LambdaMutateFinalField.java:10:29: compiler.err.var.might.already.be.assigned: x +1 error diff --git a/test/langtools/tools/javac/lambda/8043179/LambdaMutateFinalVar.java b/test/langtools/tools/javac/lambda/8043179/LambdaMutateFinalVar.java new file mode 100644 index 00000000000..41736b54876 --- /dev/null +++ b/test/langtools/tools/javac/lambda/8043179/LambdaMutateFinalVar.java @@ -0,0 +1,13 @@ +/* + * @test /nodynamiccopyright/ + * @summary Verify lambda expression can't mutate a final variable + * @bug 8043179 + * @compile/fail/ref=LambdaMutateFinalVar.out -XDrawDiagnostics LambdaMutateFinalVar.java + */ +class LambdaMutateFinalVar { + LambdaMutateFinalVar() { + final String x; + Runnable r1 = () -> x = "not ok"; + x = "ok"; + } +} diff --git a/test/langtools/tools/javac/lambda/8043179/LambdaMutateFinalVar.out b/test/langtools/tools/javac/lambda/8043179/LambdaMutateFinalVar.out new file mode 100644 index 00000000000..bb73b182197 --- /dev/null +++ b/test/langtools/tools/javac/lambda/8043179/LambdaMutateFinalVar.out @@ -0,0 +1,2 @@ +LambdaMutateFinalVar.java:10:29: compiler.err.var.might.already.be.assigned: x +1 error