diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/GuardedPattern.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/GuardedPattern.java index 6db84d30b35..921d5dc6851 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/GuardedPattern.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/GuardedPattern.java @@ -210,6 +210,10 @@ public void wrapupGeneration(CodeStream codeStream) { this.primaryPattern.wrapupGeneration(codeStream); } @Override + public void fullWrapupGeneration(CodeStream codeStream) { + this.primaryPattern.fullWrapupGeneration(codeStream); + } + @Override protected void generatePatternVariable(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel) { this.primaryPattern.generatePatternVariable(currentScope, codeStream, trueLabel, falseLabel); diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java index 0cb159691b4..7f15fe694bc 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java @@ -117,7 +117,7 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean int pc = codeStream.position; - if (this.elementVariable != null) { + if (this.elementVariable != null || this.pattern != null) { addAssignment(currentScope, codeStream, this.secretInstanceOfPatternExpressionValue); codeStream.load(this.secretInstanceOfPatternExpressionValue); } else { @@ -125,7 +125,22 @@ public void generateCode(BlockScope currentScope, CodeStream codeStream, boolean } codeStream.instance_of(this.type, this.type.resolvedType); - if (this.elementVariable != null) { + if (this.pattern != null) { + BranchLabel trueLabel = new BranchLabel(codeStream); + BranchLabel falseLabel = new BranchLabel(codeStream); + BranchLabel continueLabel = new BranchLabel(codeStream); + codeStream.ifeq(falseLabel); + codeStream.load(this.secretInstanceOfPatternExpressionValue); + this.pattern.generateOptimizedBoolean(currentScope, codeStream, trueLabel, falseLabel); + this.pattern.fullWrapupGeneration(codeStream); + codeStream.removeVariable(this.secretInstanceOfPatternExpressionValue); + trueLabel.place(); + codeStream.iconst_1(); + codeStream.goto_(continueLabel); + falseLabel.place(); + codeStream.iconst_0(); + continueLabel.place(); + } else if (this.elementVariable != null) { BranchLabel actionLabel = new BranchLabel(codeStream); codeStream.dup(); codeStream.ifeq(actionLabel); diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/Pattern.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/Pattern.java index 19b2b994eeb..9bbecb7a59f 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/Pattern.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/Pattern.java @@ -118,6 +118,11 @@ public void resumeVariables(CodeStream codeStream, BlockScope scope) { protected abstract void generatePatternVariable(BlockScope currentScope, CodeStream codeStream, BranchLabel trueLabel, BranchLabel falseLabel); protected abstract void wrapupGeneration(CodeStream codeStream); + /** + * Clean up all variables (actual and secret) used in this pattern and child patterns. + */ + protected abstract void fullWrapupGeneration(CodeStream codeStream); + public TypeReference getType() { return null; } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/RecordPattern.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/RecordPattern.java index 48d4b5aabfe..c1eed49c471 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/RecordPattern.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/RecordPattern.java @@ -413,6 +413,13 @@ public void wrapupGeneration(CodeStream codeStream) { super.wrapupGeneration(codeStream); } @Override + public void fullWrapupGeneration(CodeStream codeStream) { + for (Pattern p : this.patterns) { + p.fullWrapupGeneration(codeStream); + } + super.fullWrapupGeneration(codeStream); + } + @Override public void suspendVariables(CodeStream codeStream, BlockScope scope) { codeStream.removeNotDefinitelyAssignedVariables(scope, this.thenInitStateIndex1); } diff --git a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TypePattern.java b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TypePattern.java index bbae1d167a5..75fe39ba885 100644 --- a/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TypePattern.java +++ b/org.eclipse.jdt.core.compiler.batch/src/org/eclipse/jdt/internal/compiler/ast/TypePattern.java @@ -136,6 +136,13 @@ public void wrapupGeneration(CodeStream codeStream) { codeStream.removeVariable(this.secretPatternVariable); } @Override + public void fullWrapupGeneration(CodeStream codeStream) { + this.wrapupGeneration(codeStream); + if (this.local != null) { + codeStream.removeVariable(this.local.binding); + } + } + @Override public LocalDeclaration getPatternVariable() { return this.local; } @@ -269,7 +276,7 @@ private static LocalVariableBinding getNewLocalVariableBinding(BlockScope scope, // int delta = ((TypeBinding.equalsEquals(type, TypeBinding.LONG)) || // (TypeBinding.equalsEquals(type, TypeBinding.DOUBLE))) ? // 2 : 1; - l.resolvedPosition = scope.localIndex; + l.resolvedPosition = scope.startIndex + scope.localIndex; return l; } diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordPatternTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordPatternTest.java index d18bdda60c6..d7ab328fdab 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordPatternTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/RecordPatternTest.java @@ -3952,4 +3952,148 @@ public static void main(String[] args) { "s = switch on null\n" + "s = default threw exception"); } + public void testIssue1804_0() { + runConformTest(new String[] { "X.java", """ + public class X { + record Paper(int color) {} + record Box(T a) {} + public static void main(String[] args) { + Box b = new Box<>(null); + boolean res = b instanceof Box(Paper a); + if (res) { + System.out.println("res is true"); + } else { + System.out.println("res is false"); + } + } + } + """ }, "res is false"); + } + public void testIssue1804_1() { + runConformTest(new String[] { "X.java", """ + public class X { + record Paper(int color) {} + record Box(T a) {} + public static void main(String[] args) { + Box b = new Box<>(new Paper(0)); + boolean res = b instanceof Box(Paper a); + if (res) { + System.out.println("res is true"); + } else { + System.out.println("res is false"); + } + } + } + """ }, "res is true"); + } + public void testIssue1804_2() { + runConformTest(new String[] { "X.java", """ + public class X { + record Paper(int color) {} + record Box(T a) {} + public static void main(String[] args) { + Box b = new Box<>(new Paper(0)); + boolean res = b instanceof Box(Paper a) && a == null; + if (res) { + System.out.println("res is true"); + } else { + System.out.println("res is false"); + } + } + } + """ }, "res is false"); + } + public void testIssue1804_3() { + runConformTest(new String[] { "X.java", """ + public class X { + record Paper(int color) {} + record Box(T a) {} + public static void main(String[] args) { + Box b = new Box<>(null); + System.out.println(b instanceof Box(Paper a)); + System.out.println(b instanceof Box(Object a)); + } + } + """ }, "false\ntrue"); + } + public void testIssue1804_4() { + runConformTest(new String[] { "X.java", """ + public class X { + record Paper(int color) {} + record Box(T a) {} + public static void main(String argv[]) { + foo(null, null); + } + public static void foo(String abc, String def) { + Box p = new Box<>(new Paper(0)); + boolean b = false; + switch (p) { + case Box(Paper a) -> { + b = true; + break; + } + default -> { + b = false; + break; + } + } + System.out.println(b); + } + } + """ }, "true"); + } + public void testIssue1804_5() { + runConformTest(new String[] { "X.java", """ + public class X { + record Paper(int color) {} + record Box(T a) {} + public static void main(String argv[]) { + foo(null, null); + } + public static void foo(String abc, String def) { + Box p = new Box<>(null); + boolean b = false; + switch (p) { + case Box(Paper a) -> { + b = true; + break; + } + default -> { + b = false; + break; + } + } + System.out.println(b); + } + } + """ }, "false"); + } + public void testIssue1804_6() { + runConformTest(new String[] { "X.java", """ + public class X { + record Paper(int color) {} + record Box(T a, T b) {} + public static void main(String argv[]) { + foo(null, null); + } + public static void foo(String abc, String def) { + Box p = new Box<>(new Paper(0), new Paper(1)); + boolean c = false; + switch (p) { + case Box(Paper a, Paper b) -> { + System.out.println(a.color); + System.out.println(b.color); + c = true; + break; + } + default -> { + c = false; + break; + } + } + System.out.println(c); + } + } + """ }, "0\n1\ntrue"); + } }