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 }