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