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 }