Skip to content

Commit ea5eb74

Browse files
biboudislahodaj
andcommittedMay 14, 2024
8326404: Assertion error when trying to compile switch with fallthrough with pattern
Co-authored-by: Jan Lahoda <jlahoda@openjdk.org> Reviewed-by: vromero
1 parent beea530 commit ea5eb74

File tree

2 files changed

+169
-6
lines changed

2 files changed

+169
-6
lines changed
 

‎src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java

+12-6
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,9 @@ private void handleSwitch(JCTree tree,
458458
newCases.add(c.head);
459459
appendBreakIfNeeded(tree, cases, c.head);
460460
}
461-
cases = processCases(tree, newCases.toList());
461+
cases = newCases.toList();
462+
patchCompletingNormallyCases(cases);
463+
cases = processCases(tree, cases);
462464
ListBuffer<JCStatement> statements = new ListBuffer<>();
463465
VarSymbol temp = new VarSymbol(Flags.SYNTHETIC,
464466
names.fromString("selector" + variableIndex++ + target.syntheticNameChar() + "temp"),
@@ -523,8 +525,6 @@ private void handleSwitch(JCTree tree,
523525
boolean previousCompletesNormally = false;
524526
boolean hasDefault = false;
525527

526-
patchCompletingNormallyCases(cases);
527-
528528
for (var c : cases) {
529529
List<JCCaseLabel> clearedPatterns = c.labels;
530530
boolean hasJoinedNull =
@@ -685,7 +685,7 @@ private static void patchCompletingNormallyCases(List<JCCase> cases) {
685685
if (currentCase.caseKind == CaseKind.STATEMENT &&
686686
currentCase.completesNormally &&
687687
cases.tail.nonEmpty() &&
688-
cases.tail.head.guard != null) {
688+
(cases.tail.head.guard != null || cases.tail.head.labels.stream().anyMatch(cl -> cl instanceof JCPatternCaseLabel p && p.syntheticGuard != null))) {
689689
ListBuffer<JCStatement> newStatements = new ListBuffer<>();
690690
List<JCCase> copyFrom = cases;
691691

@@ -700,6 +700,7 @@ private static void patchCompletingNormallyCases(List<JCCase> cases) {
700700
};
701701

702702
currentCase.stats = newStatements.toList();
703+
currentCase.completesNormally = false;
703704
}
704705

705706
cases = cases.tail;
@@ -948,10 +949,12 @@ public void resolve(VarSymbol commonBinding,
948949
JCExpression commonNestedExpression = null;
949950
VarSymbol commonNestedBinding = null;
950951
boolean previousNullable = false;
952+
boolean previousCompletesNormally = false;
951953

952954
for (List<JCCase> c = inputCases; c.nonEmpty(); c = c.tail) {
953955
VarSymbol currentBinding = null;
954956
boolean currentNullable = false;
957+
boolean currentCompletesNormally = c.head.completesNormally;
955958
JCExpression currentNestedExpression = null;
956959
VarSymbol currentNestedBinding = null;
957960

@@ -986,6 +989,8 @@ public void resolve(VarSymbol commonBinding,
986989
commonBinding.isUnnamedVariable() == currentBinding.isUnnamedVariable() &&
987990
!previousNullable &&
988991
!currentNullable &&
992+
!previousCompletesNormally &&
993+
!currentCompletesNormally &&
989994
new TreeDiffer(List.of(commonBinding), List.of(currentBinding))
990995
.scan(commonNestedExpression, currentNestedExpression)) {
991996
accummulator.add(c.head);
@@ -1001,6 +1006,7 @@ public void resolve(VarSymbol commonBinding,
10011006
commonNestedBinding = currentNestedBinding;
10021007
}
10031008
previousNullable = currentNullable;
1009+
previousCompletesNormally = currentCompletesNormally;
10041010
}
10051011
resolveAccummulator.resolve(commonBinding, commonNestedExpression, commonNestedBinding);
10061012
return result.toList();
@@ -1473,8 +1479,8 @@ List<JCStatement> bindingVars(int diagPos) {
14731479
ListBuffer<JCStatement> stats = new ListBuffer<>();
14741480
for (Entry<BindingSymbol, VarSymbol> e : hoistedVarMap.entrySet()) {
14751481
JCVariableDecl decl = makeHoistedVarDecl(diagPos, e.getValue());
1476-
if (!e.getKey().isPreserved() ||
1477-
!parent.tryPrepend(e.getKey(), decl)) {
1482+
if (!e.getValue().isUnnamedVariable() &&
1483+
(!e.getKey().isPreserved() || !parent.tryPrepend(e.getKey(), decl))) {
14781484
stats.add(decl);
14791485
}
14801486
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
/*
2+
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
/**
24+
* @test
25+
* @bug 8326404
26+
* @summary Assertion error when trying to compile switch with fallthrough with pattern
27+
* @compile T8326404.java
28+
* @run main T8326404
29+
*/
30+
public class T8326404 {
31+
private static final record R<T>(T a) {}
32+
33+
public static void main(String[] args) {
34+
assertEquals(4, run1(""));
35+
assertEquals(3, run1(new R("")));
36+
assertEquals(2, run1(new R(42)));
37+
38+
assertEquals(2, run1_break1(""));
39+
assertEquals(1, run1_break1(new R("")));
40+
assertEquals(2, run1_break1(new R(42)));
41+
42+
assertEquals(3, run2(""));
43+
assertEquals(4, run2(new R("")));
44+
assertEquals(2, run2(new R(42)));
45+
46+
assertEquals(1, run2_break1(""));
47+
assertEquals(2, run2_break1(new R("")));
48+
assertEquals(2, run2_break1(new R(42)));
49+
50+
assertEquals(2, run3(""));
51+
assertEquals(4, run3(new R("")));
52+
assertEquals(3, run3(new R(42)));
53+
54+
assertEquals(2, run3_break1(""));
55+
assertEquals(2, run3_break1(new R("")));
56+
assertEquals(1, run3_break1(new R(42)));
57+
}
58+
59+
private static int run1(Object o) {
60+
int i = 0;
61+
switch (o) {
62+
case String _:
63+
i++;
64+
case R(String _):
65+
i++;
66+
case R(Integer _):
67+
i++;
68+
default:
69+
i++;
70+
}
71+
return i;
72+
}
73+
74+
private static int run1_break1(Object o) {
75+
int i = 0;
76+
switch (o) {
77+
case String s:
78+
i++;
79+
case R(String _):
80+
i++;
81+
break;
82+
case R(Integer _):
83+
i++;
84+
default:
85+
i++;
86+
}
87+
return i;
88+
}
89+
90+
private static int run2(Object o) {
91+
int i = 0;
92+
switch (o) {
93+
case R(String _):
94+
i++;
95+
case String _:
96+
i++;
97+
case R(Integer _):
98+
i++;
99+
default:
100+
i++;
101+
}
102+
return i;
103+
}
104+
105+
private static int run2_break1(Object o) {
106+
int i = 0;
107+
switch (o) {
108+
case R(String _):
109+
i++;
110+
case String _:
111+
i++;
112+
break;
113+
case R(Integer _):
114+
i++;
115+
default:
116+
i++;
117+
}
118+
return i;
119+
}
120+
121+
private static int run3(Object o) {
122+
int i = 0;
123+
switch (o) {
124+
case R(String _):
125+
i++;
126+
case R(Integer _):
127+
i++;
128+
case String _:
129+
i++;
130+
default:
131+
i++;
132+
}
133+
return i;
134+
}
135+
136+
private static int run3_break1(Object o) {
137+
int i = 0;
138+
switch (o) {
139+
case R(String _):
140+
i++;
141+
case R(Integer _):
142+
i++;
143+
break;
144+
case String _:
145+
i++;
146+
default:
147+
i++;
148+
}
149+
return i;
150+
}
151+
152+
static void assertEquals(int expected, int actual) {
153+
if (expected != actual) {
154+
throw new AssertionError("Expected: " + expected + ", but got: " + actual);
155+
}
156+
}
157+
}

0 commit comments

Comments
 (0)