jdk-24/test/langtools/tools/javac/patterns/PrimitivePatternsSwitch.java
2024-03-18 13:16:29 +00:00

642 lines
19 KiB
Java

/*
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/*
* @test
* @bug 8304487
* @summary Compiler Implementation for Primitive types in patterns, instanceof, and switch (Preview)
* @enablePreview
* @compile PrimitivePatternsSwitch.java
* @run main/othervm PrimitivePatternsSwitch
*/
public class PrimitivePatternsSwitch {
public static void main(String[] args) {
assertEquals(1, primitiveSwitch(42));
assertEquals(2, primitiveSwitch(123));
assertEquals(1, primitiveSwitchUnnamed(42));
assertEquals(2, primitiveSwitchUnnamed(123));
assertEquals(42, primitiveSwitch2());
assertEquals(42, primitiveSwitch3());
assertEquals(1, primitiveSwitch4(0.0f));
assertEquals(2, primitiveSwitch4(1.0f));
assertEquals(1, primitiveSwitchUnconditionallyExact(Byte.MAX_VALUE));
assertEquals(42, exhaustive0());
assertEquals(1, exhaustive1WithDefault());
assertEquals(2, exhaustive2WithDefault());
assertEquals(1, exhaustive1());
assertEquals(1, exhaustive2());
assertEquals(1, exhaustive3());
assertEquals(1, exhaustive4());
assertEquals(2, exhaustive5());
assertEquals(1, exhaustive6());
assertEquals(1, exhaustive7(true));
assertEquals(1, exhaustive7s(true));
assertEquals(1, exhaustive8(true));
assertEquals(1, exhaustive9(true));
assertEquals(1, exhaustive9(false));
assertEquals(1, exhaustiveWithRecords1());
assertEquals(1, exhaustiveWithRecords2());
assertEquals(1, exhaustiveWithRecords4());
assertEquals(1, exhaustiveWithRecords5());
assertEquals(1, exhaustiveWithRecords6());
assertEquals(2, ensureProperSelectionWithRecords());
assertEquals(1, ensureProperSelectionWithRecords2());
assertEquals(3, ensureProperSelectionWithRecords3());
assertEquals(42, switchAndDowncastFromObjectPrimitive());
assertEquals(42, dominationBetweenBoxedAndPrimitive());
assertEquals(2, wideningAndUnboxing());
assertEquals(2, wideningAndUnboxingInRecord());
assertEquals(2, wideningAndInferredUnboxingInRecord());
assertEquals(5f, switchOverBoxedFloat(0f));
assertEquals(7f, switchOverBoxedFloat(1f));
assertEquals(9f, switchOverBoxedFloat(2f));
assertEquals(9f, switchOverBoxedFloat(2f));
assertEquals(5f, switchOverPrimitiveDouble(0d));
assertEquals(7f, switchOverPrimitiveDouble(1d));
assertEquals(9f, switchOverPrimitiveDouble(2d));
assertEquals(1, switchOverPrimitiveChar('a'));
assertEquals(-1, switchOverPrimitiveChar('x'));
assertTrue(switchOverBoxedBooleanWithUnconditional(Boolean.valueOf(true)));
assertTrue(switchOverBoxedBooleanWithUnconditional(true));
assertTrue(!switchOverBoxedBooleanWithUnconditional(false));
assertEquals(1, switchOverPrimitiveBooleanWithDefault(true));
assertEquals(2, switchOverPrimitiveBooleanWithDefault(false));
assertEquals(1, switchOverPrimitiveBoolean(true));
assertEquals(2, switchOverPrimitiveBoolean(false));
assertEquals(1, switchOverPrimitiveFloat(0.0f/0.0f));
assertEquals(2, switchOverPrimitiveFloat((float) Math.pow(0.0f/0.0f, 0)));
assertEquals(3, switchOverPrimitiveFloat(0.0f));
assertEquals(4, switchOverPrimitiveFloat(-0.0f));
assertEquals(1, switchRedirectedExactnessMethods1('a'));
assertEquals(-1, switchRedirectedExactnessMethods1('\u03A9'));
assertEquals(1, switchRedirectedExactnessMethods2('\u03A9'));
assertEquals(-1, switchRedirectedExactnessMethods2('\uFFFF'));
assertEquals(1, switchLongAndUnconditional(32778L));
assertEquals(2, switchLongAndUnconditional(42L));
assertEquals(1, switchByte((byte) 128));
assertEquals(2, switchByte((byte) 42));
assertEquals(1, switchShort((short) 32778));
assertEquals(2, switchShort((short) 42));
assertEquals(1, switchInt(32778));
assertEquals(2, switchInt(42));
assertEquals(1, switchChar( '\u0010'));
assertEquals(2, switchChar('a'));
assertEquals(1, testIntInNonEnhancedSwitchStatement(1));
assertEquals(0, testIntInNonEnhancedSwitchStatement(0));
assertEquals(1, testFloatInEnhancedSwitchStatement(1.0f));
assertEquals(0, testFloatInEnhancedSwitchStatement(0.0f));
assertEquals(1, testDoubleInEnhancedSwitchStatement(1.0d));
assertEquals(0, testDoubleInEnhancedSwitchStatement(0.0d));
assertEquals(1, testLongInEnhancedSwitchStatement(1l));
assertEquals(0, testLongInEnhancedSwitchStatement(0l));
assertEquals(1, testBooleanInEnhancedSwitchStatement(true));
assertEquals(0, testBooleanInEnhancedSwitchStatement(false));
assertEquals(1, testByteWrapperToIntUnconditionallyExact());
assertEquals(1, testIntegerWrapperToFloat());
assertEquals(-1, testIntegerWrapperToFloatInexact());
assertEquals(Character.MAX_VALUE, testUnboxingAndWideningCharacter1(Character.MAX_VALUE));
assertEquals(Character.MAX_VALUE, testUnboxingAndWideningCharacter2(Character.MAX_VALUE));
assertEquals(Character.MAX_VALUE, testUnboxingAndWideningCharacter3(Character.MAX_VALUE));
assertEquals(Float.MAX_VALUE, testUnboxingAndWideningFloat(Float.MAX_VALUE));
assertEquals(Float.MAX_VALUE, testUnboxingAndWideningFloatExplicitCast(Float.MAX_VALUE));
assertEquals(42f, testUnboxingAndWideningLong(42L));
assertEquals(2, testUnboxingAndWideningLong(Long.MAX_VALUE));
}
public static int primitiveSwitch(int i) {
return switch (i) {
case int j when j == 42-> 1;
case int j -> 2;
};
}
public static int primitiveSwitchUnnamed(int i) {
return switch (i) {
case int _ when i == 42-> 1;
case int _ -> 2;
};
}
public static int primitiveSwitch2() {
Object o = Integer.valueOf(42);
switch (o) {
case int i: return i;
default: break;
}
return -1;
}
public static int primitiveSwitch3() {
int i = 42;
switch (i) {
case Integer ii: return ii;
}
}
public static int primitiveSwitch4(float f) {
return switch (f) {
case 0.0f -> 1;
case Float fi when fi == 1f -> 2;
case Float fi -> 3;
};
}
public static int primitiveSwitchUnconditionallyExact(byte c) {
return switch (c) {
case short _ -> 1;
};
}
public static int exhaustive0() {
Integer i = 42;
switch (i) {
case int j: return j;
}
}
public static int exhaustive1WithDefault() {
int i = 42;
return switch (i) {
case byte b -> 1;
default -> 2;
};
}
public static int exhaustive2WithDefault() {
int i = 30000;
return switch (i) {
case byte b -> 1;
case short s -> 2;
default -> 3;
};
}
public static int exhaustive1() {
int i = 42;
return switch (i) {
case Integer p -> 1;
};
}
public static int exhaustive2() {
int i = 42;
return switch (i) {
case long d -> 1;
};
}
public static int exhaustive3() {
int i = 42;
return switch (i) {
case double d -> 1;
};
}
public static int exhaustive4() {
int i = 127;
return switch (i) {
case byte b -> 1;
case double d -> 2;
};
}
public static int exhaustive5() {
int i = 127 + 1;
return switch (i) {
case byte b -> 1;
case double d -> 2;
};
}
public static int exhaustive6() {
Integer i = Integer.valueOf(42);
return switch (i) {
case int p -> 1;
};
}
public static int exhaustive7(Boolean b) {
switch (b) {
case true: return 1;
case false: return 2; // with reminder, null, OK
}
}
public static int exhaustive7s(Boolean b) {
return switch (b) {
case true -> 1;
case false -> 2; // with reminder, null, OK
};
}
public static int exhaustive8(Boolean b) {
switch (b) {
case boolean bb: return 1;
}
}
public static int exhaustive9(boolean b) {
switch (b) {
case Boolean bb: return 1;
}
}
public static int exhaustiveWithRecords1() {
R_int r = new R_int(42);
return switch (r) {
// exhaustive, because Integer exhaustive at type int
case R_int(Integer x) -> 1;
};
}
public static int exhaustiveWithRecords2() {
R_int r = new R_int(42);
return switch (r) {
// exhaustive, because double unconditional at int
case R_int(double x) -> 1;
};
}
public static int exhaustiveWithRecords4() {
R_Integer r = new R_Integer(42);
return switch (r) {
// exhaustive, because R_Integer(int) exhaustive at type R_Integer(Integer), because int exhaustive at type Integer
case R_Integer(int x) -> 1;
};
}
public static int exhaustiveWithRecords5() {
R_Integer r = new R_Integer(42);
return switch (r) {
// exhaustive, because double exhaustive at Integer
case R_Integer(double x) -> 1;
};
}
public static int exhaustiveWithRecords6() {
R_int r = new R_int(42);
return switch (r) {
case R_int(byte x) -> 1;
case R_int(int x) -> 2;
};
}
public static int ensureProperSelectionWithRecords() {
R_int r = new R_int(4242);
return switch (r) {
case R_int(byte x) -> 1;
case R_int(int x) -> 2;
};
}
public static int ensureProperSelectionWithRecords2() {
R_double r = new R_double(42);
switch (r) {
case R_double(int i):
return meth_int(i);
case R_double(double x):
return meth_double(x);
}
}
public static int ensureProperSelectionWithRecords3() {
R_int r = new R_int(4242);
return switch (r) {
case R_int(byte x) -> 1;
case R_int(int x) when x == 236 -> 2;
case R_int(int x) -> 3;
};
}
public static int meth_int(int i) { return 1; }
public static int meth_double(double d) { return 2;}
public static int switchAndDowncastFromObjectPrimitive() {
Object i = 42;
return switch (i) {
case Integer ib -> ib;
default -> -1;
};
}
public static int dominationBetweenBoxedAndPrimitive() {
Object i = 42;
return switch (i) {
case Integer ib -> ib;
case byte ip -> ip;
default -> -1;
};
}
static int wideningAndUnboxing() {
Number o = Integer.valueOf(42);
return switch (o) {
case byte b -> 1;
case int i -> 2;
case float f -> 3;
default -> 4;
};
}
static int wideningAndUnboxingInRecord() {
Box<Number> box = new Box<>(Integer.valueOf(42));
return switch (box) {
case Box<Number>(byte b) -> 1;
case Box<Number>(int i) -> 2;
case Box<Number>(float f) -> 3;
default -> 4;
};
}
static int wideningAndInferredUnboxingInRecord() {
Box<Number> box = new Box<>(Integer.valueOf(42));
return switch (box) {
case Box(byte b) -> 1;
case Box(int i) -> 2;
case Box(float f) -> 3;
default -> 4;
};
}
public static float switchOverBoxedFloat(Float f) {
return switch (f) {
case 0f -> 5f + 0f;
case Float fi when fi == 1f -> 6f + fi;
case Float fi -> 7f + fi;
};
}
public static double switchOverPrimitiveDouble(Double d) {
return switch (d) {
case 0d -> 5d + 0d;
case Double di when di == 1d -> 6d + di;
case Double di -> 7d + di;
};
}
public static boolean switchOverBoxedBooleanWithUnconditional(Boolean b) {
return switch (b) {
case true -> true;
case Boolean bi -> bi;
};
}
public static int switchOverPrimitiveBooleanWithDefault(boolean b) {
return switch (b) {
case true -> 1;
default -> 2;
};
}
public static int switchOverPrimitiveBoolean(boolean b) {
return switch (b) {
case true -> 1;
case false -> 2;
};
}
public static int switchOverPrimitiveChar(char c) {
return switch (c) {
case 'a' -> 1;
default -> -1;
};
}
public static final float NaNconstant = Float.NaN;
public static int switchOverPrimitiveFloat(float f) {
return switch (f) {
case NaNconstant -> 1;
case 1.0f -> 2;
case 0.0f -> 3;
case -0.0f -> 4;
default -> -1;
};
}
// tests that Exactness.char_byte is properly redirected to int_byte
public static int switchRedirectedExactnessMethods1(char c) {
return switch (c) {
case byte _ -> 1;
default -> -1;
};
}
// tests that Exactness.char_short is properly redirected to int_short
public static int switchRedirectedExactnessMethods2(char c) {
return switch (c) {
case short _ -> 1;
default -> -1;
};
}
// tests that Exactness.short_byte is properly redirected to int_byte
public static int switchRedirectedExactnessMethods2(short c) {
return switch (c) {
case byte _ -> 1;
default -> -1;
};
}
public static int switchLongAndUnconditional(long l) {
return switch (l) {
case 32778L -> 1;
case long c -> 2;
};
}
public static int switchByte(byte b) {
return switch (b) {
case (byte)128 -> 1;
case byte c -> 2;
};
}
public static int switchShort(short s) {
return switch (s) {
case (short)32778 -> 1;
case short c -> 2;
};
}
public static int switchInt(int i) {
return switch (i) {
case 32778 -> 1;
case int c -> 2;
};
}
public static int switchChar(char c) {
return switch (c) {
case '\u0010' -> 1;
case char cc -> 2;
};
}
public static int testIntInNonEnhancedSwitchStatement(int v1) {
int i = 0;
switch (v1) {
case 1:
i = 1;
break;
}
return i;
}
public static int testFloatInEnhancedSwitchStatement(float v1) {
int i = 0;
switch (v1) {
case 1.0f:
i = 1;
break;
default:
i = 0;
}
return i;
}
public static int testDoubleInEnhancedSwitchStatement(double v1) {
int i = 0;
switch (v1) {
case 1d:
i = 1;
break;
default:
i = 0;
}
return i;
}
public static int testLongInEnhancedSwitchStatement(long v1) {
int i = 0;
switch (v1) {
case 1l:
i = 1;
break;
default:
i = 0;
}
return i;
}
public static int testBooleanInEnhancedSwitchStatement(boolean v1) {
int i = 0;
switch (v1) {
case true:
i = 1;
break;
default:
i = 0;
}
return i;
}
public static int testByteWrapperToIntUnconditionallyExact() {
Byte b = Byte.valueOf((byte) 42);
return switch (b) {
case int p -> 1;
};
}
public static int testIntegerWrapperToFloat() {
Integer i = Integer.valueOf(42);
return switch (i) {
case float p -> 1;
default -> -1;
};
}
public static int testIntegerWrapperToFloatInexact() {
Integer i = Integer.valueOf(Integer.MAX_VALUE);
return switch (i) {
case float p -> 1;
default -> -1;
};
}
public static char testUnboxingAndWideningCharacter1(Character test) {
return switch (test) {
case char c -> c;
};
}
public static int testUnboxingAndWideningCharacter2(Character test) {
return switch (test) {
case int c -> c;
};
}
public static float testUnboxingAndWideningCharacter3(Character test) {
return switch (test) {
case float f -> f;
};
}
public static float testUnboxingAndWideningLong(Long test) {
return switch (test) {
case float y -> y;
default -> 2;
};
}
public static double testUnboxingAndWideningFloat(Float test) {
return switch (test) {
case double y -> y;
default -> 2;
};
}
public static double testUnboxingAndWideningFloatExplicitCast(Object test) {
return switch ((Float) test) {
case double y -> y;
default -> 2;
};
}
record R_Integer(Integer x) {}
record R_int(int x) {}
record R_double(double x) {}
record Box<N extends Number>(N num) {}
static void assertEquals(int expected, int actual) {
if (expected != actual) {
throw new AssertionError("Expected: " + expected + ", actual: " + actual);
}
}
static void assertEquals(float expected, float actual) {
if (Float.compare(expected, actual) != 0) {
throw new AssertionError("Expected: " + expected + ", but got: " + actual);
}
}
static void assertEquals(double expected, double actual) {
if (Double.compare(expected, actual) != 0) {
throw new AssertionError("Expected: " + expected + ", but got: " + actual);
}
}
static void assertTrue(boolean actual) {
if (!actual) {
throw new AssertionError("Expected: true, but got false");
}
}
}