1 /*
2 * Copyright (c) 2023, 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 * @bug 8304246
27 * @summary Compiler Implementation for Unnamed patterns and variables
28 * @compile Unnamed.java
29 * @run main Unnamed
30 * @ignore Verifier error
31 */
32
33 import java.util.Objects;
34 import java.lang.annotation.ElementType;
35 import java.lang.annotation.Retention;
36 import java.lang.annotation.RetentionPolicy;
37 import java.lang.annotation.Target;
38
39 public class Unnamed {
40 public static void main(String[] args) throws Throwable {
41 new Unnamed().run();
42 }
43
44 public void run() {
45 assertEquals(1, testMultiValuesTopLevel(new R1()));
46 assertEquals(2, testMultiValuesTopLevel(new R3()));
47 assertEquals(1, testMultiValuesTopLevel2(new R1()));
48 assertEquals(2, testMultiValuesTopLevel2(new R2()));
49 assertEquals(2, testMultiValuesTopLevel2(new R4()));
50 assertEquals(1, testMultiValuesNested(new Box<>(new R1())));
51 assertEquals(1, testMultiValuesNested(new Box<>(new R2())));
52 assertEquals(2, testMultiValuesNested(new Box<>(new R3())));
53 assertEquals(3, testMultiValuesNested(new Box<>(new R4())));
54 assertEquals(1, testMultiValuesNestedUnnamedVarAndPattern(new Box<>(new R1())));
55 assertEquals(2, testMultiValuesNestedUnnamedVarAndPattern(new Box<>(new R4())));
56 assertEquals(1, testMultiValuesNestedMix(new Box<>(new R1())));
57 assertEquals(1, testMultiValuesNestedMix(new Box2<>(new R1())));
58 assertEquals(1, testMultiValuesNestedMix2(new Box<>(new R1())));
59 assertEquals(1, testMultiValuesNestedMix2("BOX"));
60 assertEquals(2, testMultiValuesNestedMix2(new Box2<>(new R1())));
61 assertEquals(1, testMultiValuesStatementBlock(42));
62 assertEquals(1, testMultiValuesStatementBlock(42.0f));
63 assertEquals(2, testMultiValuesStatementBlock("BOX"));
64 assertEquals(1, testMultiValuesStatementBlock2(new Box<>(new R1())));
65 assertEquals(1, testMultiValuesStatementBlock2("BOX"));
66 assertEquals(2, testMultiValuesStatementBlock2(new Box2<>(new R1())));
67 assertEquals(2, testMultiValuesGuards(new R3(), 1));
68 assertEquals(3, testMultiValuesGuards(new R4(), 42));
69 assertEquals(3, testMultiValuesGuards(new R3(), 42));
70 assertEquals(1, testMultiValuesNestedGuards(new Box(new R2()), 42));
71 assertEquals(2, testMultiValuesNestedGuards(new Box(new R3()), 1));
72 assertEquals(1, testMixUnconditionalAndConditional(new R1()));
73 assertEquals(2, testMixUnconditionalAndConditional(new R2()));
74 assertEquals(2, testMixUnconditionalAndConditional(new R3()));
75 assertEquals(1, testMultipleExpr(new Box<>(new R1())));
76 assertEquals(1, testUnrolledExpr(new Box<>(new R1())));
77 assertEquals(1, testMultipleStat(new Box<>(new R1())));
78 assertEquals(1, testUnrolledStat(new Box<>(new R1())));
79 assertEquals(2, testMixVarWithExplicit(new Box<>(new R2())));
80 assertEquals("binding", unnamedGuardAddsBindings("match1", "binding"));
81 assertEquals("any", unnamedGuardAddsBindings(42, 42));
82 assertEquals(true, testUnnamedPrimitiveAndExhaustiveness(new Prim1(4)));
83 assertEquals(false, testUnnamedPrimitiveAndExhaustiveness(new Prim2(5)));
84
85 unnamedTest();
86 }
87
88 private void unnamedTest() {
89 int _ = 0;
90 int _ = 1;
91 try (Lock _ = null) {
92 try (Lock _ = null) {
93 } catch (Exception _) {
94 try {
95 } catch (Exception _) {}
96 }
97 }
98 try (final Lock _ = null) { }
99 try (@Foo Lock _ = null) { }
100
101 try (Lock _ = null) { }
102 catch (Exception | Error _) { }
103
104 String[] strs = new String[] { "str1", "str2" };
105 for (var _ : strs) {
106 for (var _ : strs) {
107 }
108 }
109 TwoParams p1 = (_, _) -> {};
110 TwoParams p2 = (var _, var _) -> {};
111 TwoIntParams p3 = (int _, int b) -> {};
112 TwoIntParams p4 = (int _, int _) -> {};
113 TwoIntParamsIntRet p5 = (int _, int _) -> { return 1; };
114
115 p1.run(1, 2);
116 p2.run(1, 2);
117 p3.run(1, 2);
118 p4.run(1, 2);
119 p5.run(1, 2);
120
121 R r = new R(null);
122 if (r instanceof R _) {}
123 if (r instanceof R(_)) {}
124 for (int _ = 0, _ = 1, x = 1; x <= 1 ; x++) {}
125 }
126
127 int testMultiValuesTopLevel(Object o) {
128 return switch (o) {
129 case R1 _, R2 _ -> 1;
130 default -> 2;
131 };
132 }
133
134 int testMultiValuesTopLevel2(Base o) {
135 return switch (o) {
136 case R1 r -> 1;
137 case R2 _, R3 _, R4 _ -> 2;
138 };
139 }
140
141 int testMultiValuesNested(Box<?> b) {
142 return switch (b) {
143 case Box(R1 _), Box(R2 _) -> 1;
144 case Box(R3 _) -> 2;
145 case Box(_) -> 3;
146 };
147 }
148
149 int testMultiValuesNestedUnnamedVarAndPattern(Box<?> b) {
150 return switch (b) {
151 case Box(R1 _), Box(R2 _) -> 1;
152 case Box(R3 _), Box(_) -> 2;
153 };
154 }
155
156 int testMultiValuesNestedMix(Object b) {
157 return switch (b) {
158 case Box(_), Box2(_) -> 1;
159 default -> 2;
160 };
161 }
162
163 int testMultiValuesNestedMix2(Object b) {
164 return switch (b) {
165 case Box(_), String _ -> 1;
166 default -> 2;
167 };
168 }
169
170 int testMultiValuesStatementBlock(Object o) {
171 switch (o) {
172 case Integer _:
173 case Number _:
174 return 1;
175 default:
176 return 2;
177 }
178 }
179
180 int testMultiValuesStatementBlock2(Object o) {
181 switch (o) {
182 case Box(_):
183 case String _:
184 return 1;
185 default:
186 return 2;
187 }
188 }
189
190 int testMultiValuesGuards(Base b, int x) {
191 return switch (b) {
192 case R1 r -> 1;
193 case R2 _, R3 _, R4 _ when x == 1 -> 2;
194 case R2 _, R3 _, R4 _ -> 3;
195 };
196 }
197
198 int testMultiValuesNestedGuards(Box<?> b, int x) {
199 return switch (b) {
200 case Box(R1 _), Box(R2 _) -> 1;
201 case Box(R3 _), Box(_) when x == 1 -> 2;
202 case Box(_) -> 3;
203 };
204 }
205
206 int testMixUnconditionalAndConditional(Base t) {
207 return switch(t) {
208 case R1 _ -> 1;
209 case R2 _, Base _-> 2;
210 };
211 }
212
213 int testMultipleExpr(Box<?> t) {
214 return switch(t) {
215 case Box(R1 _), Box(R2 _) -> 1;
216 default -> -2;
217 };
218 }
219
220 int testUnrolledExpr(Box<?> t) {
221 return switch(t) {
222 case Box(R1 _) -> 1;
223 case Box(R2 _) -> 0;
224 default -> -2;
225 };
226 }
227
228 int testMultipleStat(Box<?> t) {
229 int ret = -1;
230 switch(t) {
231 case Box(R1 _), Box(R2 _):
232 ret = 1;
233 break;
234 default:
235 ret = -2;
236 }
237 return ret;
238 }
239
240 int testUnrolledStat(Box<?> t) {
241 int ret = -1;
242 switch(t) {
243 case Box(R1 _):
244 ret = 1;
245 break;
246 case Box(R2 _):
247 ret = 0;
248 break;
249 default:
250 ret = -2;
251 }
252 return ret;
253 }
254
255 int testMixVarWithExplicit(Box<?> t) {
256 int success = -1;
257 success = switch(t) {
258 case Box(R1 _) : {
259 yield 1;
260 }
261 case Box(R2 _), Box(var _) : {
262 yield 2;
263 }
264 default : {
265 yield -2;
266 }
267 };
268 return success;
269 }
270
271 String unnamedGuardAddsBindings(Object o1, Object o2) {
272 return switch (o1) {
273 case String _, Object _ when o2 instanceof String s: yield s;
274 case Object _: yield "any";
275 };
276 }
277
278 boolean testUnnamedPrimitiveAndExhaustiveness(RecordWithPrimitive a) {
279 boolean r1 = switch (a) {
280 case Prim1(var _) -> true;
281 case Prim2(_) -> false;
282 };
283
284 boolean r2 = switch (a) {
285 case Prim1(var _) -> true;
286 case Prim2(var _) -> false;
287 };
288
289 boolean r3 = switch (a) {
290 case Prim1(_) -> true;
291 case Prim2(_) -> false;
292 };
293
294 return r1 && r2 && r3;
295 }
296
297 sealed interface RecordWithPrimitive permits Prim1, Prim2 {};
298 record Prim1(int n1) implements RecordWithPrimitive {};
299 record Prim2(int n2) implements RecordWithPrimitive {};
300
301 // JEP 443 examples
302 record Point(int x, int y) { }
303 enum Color { RED, GREEN, BLUE }
304 record ColoredPoint(Point p, Color c) { }
305
306 void jep443examples(ColoredPoint r) {
307 if (r instanceof ColoredPoint(Point(int x, int y), _)) { }
308 if (r instanceof ColoredPoint(_, Color c)) { }
309 if (r instanceof ColoredPoint(Point(int x, _), _)) { }
310 if (r instanceof ColoredPoint(Point(int x, int _), Color _)) { }
311 if (r instanceof ColoredPoint _) { }
312 }
313
314 class Lock implements AutoCloseable {
315 @Override
316 public void close() {}
317 }
318 interface TwoParams {
319 public void run(Object o1, Object o2);
320 }
321 interface TwoIntParams {
322 public void run(int o1, int o2);
323 }
324 interface TwoIntParamsIntRet {
325 public int run(int a, int b);
326 }
327 record R(Object o) {}
328 @Target(ElementType.LOCAL_VARIABLE)
329 @Retention(RetentionPolicy.RUNTIME)
330 public @interface Foo { }
331
332 sealed abstract class Base permits R1, R2, R3, R4 { }
333 final class R1 extends Base { }
334 final class R2 extends Base { }
335 final class R3 extends Base { }
336 final class R4 extends Base { }
337 record Box<T extends Base>(T content) { }
338 record Box2<T extends Base>(T content) { }
339 void assertEquals(Object expected, Object actual) {
340 if (!Objects.equals(expected, actual)) {
341 throw new AssertionError("Expected: " + expected + ", but got: " + actual);
342 }
343 }
344 }
--- EOF ---