Skip to content

Commit 5358170

Browse files
committedJul 28, 2022
Properly linearizing generated when guards.
1 parent 9011218 commit 5358170

File tree

2 files changed

+226
-4
lines changed

2 files changed

+226
-4
lines changed
 

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

+16-4
Original file line numberDiff line numberDiff line change
@@ -348,7 +348,7 @@ private Pair<JCBindingPattern, JCExpression> unrollRecordPattern(JCRecordPattern
348348
if (secondLevelChecks == null) {
349349
secondLevelChecks = nestedDesugared.snd;
350350
} else {
351-
secondLevelChecks = makeBinary(Tag.AND, secondLevelChecks, nestedDesugared.snd);
351+
secondLevelChecks = mergeConditions(secondLevelChecks, nestedDesugared.snd);
352352
}
353353
}
354354
nestedBinding = nestedDesugared.fst;
@@ -368,7 +368,7 @@ private Pair<JCBindingPattern, JCExpression> unrollRecordPattern(JCRecordPattern
368368
if (firstLevelChecks == null) {
369369
firstLevelChecks = firstLevelCheck;
370370
} else {
371-
firstLevelChecks = makeBinary(Tag.AND, firstLevelChecks, firstLevelCheck);
371+
firstLevelChecks = mergeConditions(firstLevelChecks, firstLevelCheck);
372372
}
373373
components = components.tail;
374374
nestedFullComponentTypes = nestedFullComponentTypes.tail;
@@ -379,12 +379,24 @@ private Pair<JCBindingPattern, JCExpression> unrollRecordPattern(JCRecordPattern
379379
if (firstLevelChecks != null) {
380380
guard = firstLevelChecks;
381381
if (secondLevelChecks != null) {
382-
guard = makeBinary(Tag.AND, guard, secondLevelChecks);
382+
guard = mergeConditions(guard, secondLevelChecks);
383383
}
384384
}
385385
return Pair.of((JCBindingPattern) make.BindingPattern(recordBindingVar).setType(recordBinding.type), guard);
386386
}
387387

388+
private JCExpression mergeConditions(JCExpression left, JCExpression right) {
389+
if (left instanceof JCBinary lastBinary) {
390+
while (lastBinary.rhs instanceof JCBinary nextBinary) {
391+
lastBinary = nextBinary;
392+
}
393+
lastBinary.rhs = makeBinary(Tag.AND, lastBinary.rhs, right);
394+
return left;
395+
} else {
396+
return makeBinary(Tag.AND, left, right);
397+
}
398+
}
399+
388400
private void handleSwitch(JCTree tree,
389401
JCExpression selector,
390402
List<JCCase> cases,
@@ -645,7 +657,7 @@ JCNewClass makeNewClass(Type ctype, List<JCExpression> args) {
645657
return tree;
646658
}
647659

648-
List<JCCase> processCases(JCTree currentSwitch, List<JCCase> inputCases) {
660+
public List<JCCase> processCases(JCTree currentSwitch, List<JCCase> inputCases) {
649661
interface AccummulatorResolver {
650662
public void resolve(VarSymbol commonBinding, JCExpression commonNestedExpression, VarSymbol commonNestedBinding);
651663
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
/*
2+
* Copyright (c) 2016, 2022, 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+
/**
25+
* @test
26+
* @summary Check expected translation of various pattern related constructs
27+
* @library /tools/lib
28+
* @modules jdk.compiler/com.sun.tools.javac.api
29+
* jdk.compiler/com.sun.tools.javac.comp
30+
* jdk.compiler/com.sun.tools.javac.main
31+
* jdk.compiler/com.sun.tools.javac.tree
32+
* jdk.compiler/com.sun.tools.javac.util
33+
* @build toolbox.ToolBox toolbox.JavacTask
34+
* @run main TranslationTest
35+
*/
36+
37+
import com.sun.tools.javac.api.JavacTaskImpl;
38+
import com.sun.tools.javac.comp.TransPatterns;
39+
import com.sun.tools.javac.tree.JCTree;
40+
import com.sun.tools.javac.tree.JCTree.JCCase;
41+
import com.sun.tools.javac.util.Context;
42+
import com.sun.tools.javac.util.Context.Factory;
43+
import java.io.IOException;
44+
import java.nio.file.Files;
45+
import java.nio.file.Path;
46+
import java.nio.file.Paths;
47+
import java.util.ArrayList;
48+
import java.util.List;
49+
50+
import toolbox.TestRunner;
51+
import toolbox.JavacTask;
52+
import toolbox.Task;
53+
import toolbox.ToolBox;
54+
55+
public class TranslationTest extends TestRunner {
56+
57+
private static final String JAVA_VERSION = System.getProperty("java.specification.version");
58+
59+
ToolBox tb;
60+
61+
public static void main(String... args) throws Exception {
62+
new TranslationTest().runTests();
63+
}
64+
65+
TranslationTest() {
66+
super(System.err);
67+
tb = new ToolBox();
68+
}
69+
70+
public void runTests() throws Exception {
71+
runTests(m -> new Object[] { Paths.get(m.getName()) });
72+
}
73+
74+
@Test
75+
public void testMultiComponent(Path base) throws Exception {
76+
doTest(base,
77+
new String[]{"""
78+
package lib;
79+
public record Pair(Object o1, Object o2) {}
80+
""",
81+
"""
82+
package lib;
83+
public record Triplet(Object o1, Object o2, Object o3) {}
84+
"""},
85+
"""
86+
package test;
87+
import lib.*;
88+
public class Test {
89+
private int test(Object obj) {
90+
return switch (obj) {
91+
case Pair(String c1, Pair(String o2, String s2)) -> 0;
92+
case Pair(String c1, Pair(String o2, Integer s2)) -> 0;
93+
case Pair(String c1, Pair(Integer o2, String s2)) -> 0;
94+
case Pair(String c1, Pair(Integer o2, Integer s2)) -> 0;
95+
96+
case Pair(Integer c1, Pair(String o2, String s2)) -> 0;
97+
case Pair(Integer c1, Pair(String o2, Integer s2)) -> 0;
98+
case Pair(Integer c1, Pair(Integer o2, String s2)) -> 0;
99+
case Pair(Integer c1, Pair(Integer o2, Integer s2)) -> 0;
100+
101+
default -> -1;
102+
};
103+
}
104+
}
105+
""",
106+
new ProcessedCasesValidator() {
107+
int invocation;
108+
@Override
109+
public void validateProcessedCases(int depth, List<JCCase> cases) {
110+
if (depth != 0) return ;
111+
if (invocation++ > 0) return ;
112+
if (cases.size() != 2) throw new AssertionError("Unexpected number of cases: " + cases);
113+
}
114+
});
115+
}
116+
117+
private void doTest(Path base, String[] libraryCode, String testCode, Validator validator) throws IOException {
118+
Path current = base.resolve(".");
119+
Path libClasses = current.resolve("libClasses");
120+
121+
Files.createDirectories(libClasses);
122+
123+
if (libraryCode.length != 0) {
124+
Path libSrc = current.resolve("lib-src");
125+
126+
for (String code : libraryCode) {
127+
tb.writeJavaFiles(libSrc, code);
128+
}
129+
130+
new JavacTask(tb)
131+
.options("--enable-preview",
132+
"-source", JAVA_VERSION)
133+
.outdir(libClasses)
134+
.files(tb.findJavaFiles(libSrc))
135+
.run();
136+
}
137+
138+
Path src = current.resolve("src");
139+
tb.writeJavaFiles(src, testCode);
140+
141+
Path classes = current.resolve("libClasses");
142+
143+
Files.createDirectories(libClasses);
144+
145+
List<Throwable> failures = new ArrayList<>();
146+
147+
new JavacTask(tb)
148+
.options("--enable-preview",
149+
"-source", JAVA_VERSION,
150+
"-Xlint:-preview",
151+
"--class-path", libClasses.toString(),
152+
"-XDshould-stop.at=FLOW")
153+
.outdir(classes)
154+
.files(tb.findJavaFiles(src))
155+
.callback(task -> {
156+
Context ctx = ((JavacTaskImpl) task).getContext();
157+
158+
TestTransPatterns.preRegister(ctx, validator, failures);
159+
})
160+
.run()
161+
.writeAll()
162+
.getOutputLines(Task.OutputKind.DIRECT);
163+
164+
if (!failures.isEmpty()) {
165+
var failure = new AssertionError("Testcase failed.");
166+
failures.forEach(t -> failure.addSuppressed(t));
167+
throw failure;
168+
}
169+
}
170+
171+
public interface Validator {
172+
public default void validateProcessedCases(int depth, List<JCCase> cases) {}
173+
}
174+
175+
public interface ProcessedCasesValidator extends Validator {
176+
public void validateProcessedCases(int depth, List<JCCase> cases);
177+
}
178+
179+
private static final class TestTransPatterns extends TransPatterns {
180+
181+
public static void preRegister(Context ctx, Validator validator, List<Throwable> failures) {
182+
ctx.put(transPatternsKey, (Factory<TransPatterns>) c -> new TestTransPatterns(c, validator, failures));
183+
}
184+
185+
private final Validator validator;
186+
private final List<Throwable> failures;
187+
188+
public TestTransPatterns(Context context, Validator validator, List<Throwable> failures) {
189+
super(context);
190+
this.validator = validator;
191+
this.failures = failures;
192+
}
193+
194+
int processCasesDepth;
195+
196+
@Override
197+
protected com.sun.tools.javac.util.List<JCTree.JCCase> processCases(
198+
JCTree currentSwitch, com.sun.tools.javac.util.List<JCTree.JCCase> inputCases) {
199+
processCasesDepth++;
200+
var result = super.processCases(currentSwitch, inputCases);
201+
try {
202+
validator.validateProcessedCases(--processCasesDepth, result);
203+
} catch (Throwable t) {
204+
failures.add(t);
205+
}
206+
return result;
207+
}
208+
209+
}
210+
}

0 commit comments

Comments
 (0)
Please sign in to comment.