diff --git a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java
index f4d8259584221..15d7433ed779a 100644
--- a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java
+++ b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java
@@ -770,7 +770,7 @@ private static String typeSwitchClassName(Class> targetClass) {
return name + "$$TypeSwitch";
}
- // this method should be in sync with com.sun.tools.javac.code.Types.checkUnconditionallyExactPrimitives
+ // this method should be in sync with com.sun.tools.javac.code.Types.isUnconditionallyExactPrimitives
private static boolean unconditionalExactnessCheck(Class> selectorType, Class> targetType) {
Wrapper selectorWrapper = Wrapper.forBasicType(selectorType);
Wrapper targetWrapper = Wrapper.forBasicType(targetType);
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeTag.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeTag.java
index 0b97b119119c0..b2771556eb21e 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeTag.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeTag.java
@@ -26,7 +26,7 @@
package com.sun.tools.javac.code;
import com.sun.source.tree.Tree.Kind;
-
+import java.lang.runtime.ExactConversionsSupport;
import javax.lang.model.type.TypeKind;
import static com.sun.tools.javac.code.TypeTag.NumericClasses.*;
@@ -186,6 +186,10 @@ public boolean isInSuperClassesOf(TypeTag tag) {
return (this.numericClass & tag.superClasses) != 0;
}
+ public boolean isNumeric() {
+ return this.numericClass != 0;
+ }
+
/** Returns the number of type tags.
*/
public static int getTypeTagCount() {
@@ -247,11 +251,11 @@ public boolean checkRange(int value) {
case BOOLEAN:
return 0 <= value && value <= 1;
case BYTE:
- return Byte.MIN_VALUE <= value && value <= Byte.MAX_VALUE;
+ return ExactConversionsSupport.isIntToByteExact(value);
case CHAR:
- return Character.MIN_VALUE <= value && value <= Character.MAX_VALUE;
+ return ExactConversionsSupport.isIntToCharExact(value);
case SHORT:
- return Short.MIN_VALUE <= value && value <= Short.MAX_VALUE;
+ return ExactConversionsSupport.isIntToShortExact(value);
case INT:
return true;
default:
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
index 0c155caa56da7..5fc3bce6a303b 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Types.java
@@ -26,6 +26,7 @@
package com.sun.tools.javac.code;
import java.lang.ref.SoftReference;
+import java.lang.runtime.ExactConversionsSupport;
import java.util.HashSet;
import java.util.HashMap;
import java.util.Locale;
@@ -5054,14 +5055,25 @@ public Type visitCapturedType(CapturedType t, S s) {
//
//
- /** Check unconditionality between any combination of reference or primitive types.
+ /** Check unconditionality between any combination of reference or primitive
+ * types.
*
- * Rules:
- * an identity conversion
- * a widening reference conversion
- * a widening primitive conversion (delegates to `checkUnconditionallyExactPrimitives`)
- * a boxing conversion
- * a boxing conversion followed by a widening reference conversion
+ * The following are unconditionally exact regardless of the input
+ * expression:
+ *
+ * - an identity conversion
+ * - a widening reference conversion
+ * - an exact widening primitive conversion
+ * - a boxing conversion
+ * - a boxing conversion followed by a widening reference conversion
+ *
+ * Additionally, the following can be unconditionally exact if the source
+ * primitive is a constant expression and the conversions is exact for that
+ * constant expression:
+ *
+ * - a narrowing primitive conversion
+ * - a widening and narrowing primitive conversion
+ * - a widening primitive conversion that is not exact
*
* @param source Source primitive or reference type
* @param target Target primitive or reference type
@@ -5071,28 +5083,80 @@ public boolean isUnconditionallyExact(Type source, Type target) {
return true;
}
- return target.isPrimitive()
- ? isUnconditionallyExactPrimitives(source, target)
- : isSubtype(boxedTypeOrType(erasure(source)), target);
+ if (target.isPrimitive()) {
+ if (source.isPrimitive() &&
+ ((source.getTag().isStrictSubRangeOf(target.getTag())) &&
+ !((source.hasTag(BYTE) && target.hasTag(CHAR)) ||
+ (source.hasTag(INT) && target.hasTag(FLOAT)) ||
+ (source.hasTag(LONG) && (target.hasTag(DOUBLE) || target.hasTag(FLOAT)))))) return true;
+ else {
+ return false;
+ }
+ } else {
+ return isSubtype(boxedTypeOrType(erasure(source)), target);
+ }
}
+ // where
+ public boolean isUnconditionallyExactConstantPrimitives(Type source, Type target) {
+ if (!(source.constValue() instanceof Number value) || !target.getTag().isNumeric()) return false;
- /** Check unconditionality between primitive types.
- *
- * - widening from one integral type to another,
- * - widening from one floating point type to another,
- * - widening from byte, short, or char to a floating point type,
- * - widening from int to double.
- *
- * @param selectorType Type of selector
- * @param targetType Target type
- */
- public boolean isUnconditionallyExactPrimitives(Type selectorType, Type targetType) {
- return isSameType(selectorType, targetType) ||
- (selectorType.isPrimitive() && targetType.isPrimitive()) &&
- ((selectorType.getTag().isStrictSubRangeOf(targetType.getTag())) &&
- !((selectorType.hasTag(BYTE) && targetType.hasTag(CHAR)) ||
- (selectorType.hasTag(INT) && targetType.hasTag(FLOAT)) ||
- (selectorType.hasTag(LONG) && (targetType.hasTag(DOUBLE) || targetType.hasTag(FLOAT)))));
+ switch (source.getTag()) {
+ case BYTE:
+ switch (target.getTag()) {
+ case CHAR: return ExactConversionsSupport.isIntToCharExact(value.intValue());
+ }
+ break;
+ case CHAR:
+ switch (target.getTag()) {
+ case BYTE: return ExactConversionsSupport.isIntToByteExact(value.intValue());
+ case SHORT: return ExactConversionsSupport.isIntToShortExact(value.intValue());
+ }
+ break;
+ case SHORT:
+ switch (target.getTag()) {
+ case BYTE: return ExactConversionsSupport.isIntToByteExact(value.intValue());
+ case CHAR: return ExactConversionsSupport.isIntToCharExact(value.intValue());
+ }
+ break;
+ case INT:
+ switch (target.getTag()) {
+ case BYTE: return ExactConversionsSupport.isIntToByteExact(value.intValue());
+ case CHAR: return ExactConversionsSupport.isIntToCharExact(value.intValue());
+ case SHORT: return ExactConversionsSupport.isIntToShortExact(value.intValue());
+ case FLOAT: return ExactConversionsSupport.isIntToFloatExact(value.intValue());
+ }
+ break;
+ case FLOAT:
+ switch (target.getTag()) {
+ case BYTE: return ExactConversionsSupport.isFloatToByteExact(value.floatValue());
+ case CHAR: return ExactConversionsSupport.isFloatToCharExact(value.floatValue());
+ case SHORT: return ExactConversionsSupport.isFloatToShortExact(value.floatValue());
+ case INT: return ExactConversionsSupport.isFloatToIntExact(value.floatValue());
+ case LONG: return ExactConversionsSupport.isFloatToLongExact(value.floatValue());
+ }
+ break;
+ case LONG:
+ switch (target.getTag()) {
+ case BYTE: return ExactConversionsSupport.isLongToByteExact(value.longValue());
+ case CHAR: return ExactConversionsSupport.isLongToCharExact(value.longValue());
+ case SHORT: return ExactConversionsSupport.isLongToShortExact(value.longValue());
+ case INT: return ExactConversionsSupport.isLongToIntExact(value.longValue());
+ case FLOAT: return ExactConversionsSupport.isLongToFloatExact(value.longValue());
+ case DOUBLE: return ExactConversionsSupport.isLongToDoubleExact(value.longValue());
+ }
+ break;
+ case DOUBLE:
+ switch (target.getTag()) {
+ case BYTE: return ExactConversionsSupport.isDoubleToByteExact(value.doubleValue());
+ case CHAR: return ExactConversionsSupport.isDoubleToCharExact(value.doubleValue());
+ case SHORT: return ExactConversionsSupport.isDoubleToShortExact(value.doubleValue());
+ case INT: return ExactConversionsSupport.isDoubleToIntExact(value.doubleValue());
+ case FLOAT: return ExactConversionsSupport.isDoubleToFloatExact(value.doubleValue());
+ case LONG: return ExactConversionsSupport.isDoubleToLongExact(value.doubleValue());
+ }
+ break;
+ }
+ return true;
}
//
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
index 3d9eff107da52..34b30ab1ebbe3 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java
@@ -167,6 +167,7 @@ protected Check(Context context) {
allowModules = Feature.MODULES.allowedInSource(source);
allowRecords = Feature.RECORDS.allowedInSource(source);
allowSealed = Feature.SEALED_CLASSES.allowedInSource(source);
+ allowPrimitivePatterns = preview.isEnabled() && Feature.PRIMITIVE_PATTERNS.allowedInSource(source);
}
/** Character for synthetic names
@@ -190,6 +191,10 @@ protected Check(Context context) {
*/
private final boolean allowSealed;
+ /** Are primitive patterns allowed
+ */
+ private final boolean allowPrimitivePatterns;
+
/** Whether to force suppression of deprecation and preview warnings.
* This happens when attributing import statements for JDK 9+.
* @see Feature#DEPRECATION_ON_IMPORT
@@ -4734,20 +4739,30 @@ void checkSwitchCaseLabelDominated(JCCaseLabel unconditionalCaseLabel, List {}
+ case int ii -> {} // OK
+ };
+
+ switch (42) {
+ case 42 -> {}
+ case int ii -> {} // OK
+ };
+
+ switch (42) {
+ case (byte) 42 -> {}
+ case int ii -> {} // OK
+ };
+
+ switch (42) {
+ case 42 -> {}
+ default -> {} // OK
+ };
+
+ switch (42) {
+ default -> {} // OK
+ case 42 -> {}
+ };
+ }
+}
diff --git a/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchConstants.out b/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchConstants.out
new file mode 100644
index 0000000000000..9a983a8643772
--- /dev/null
+++ b/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchConstants.out
@@ -0,0 +1,11 @@
+PrimitivePatternsSwitchConstants.java:43:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: int, java.lang.Long)
+PrimitivePatternsSwitchConstants.java:9:9: compiler.err.not.exhaustive.statement
+PrimitivePatternsSwitchConstants.java:13:9: compiler.err.not.exhaustive.statement
+PrimitivePatternsSwitchConstants.java:17:9: compiler.err.not.exhaustive.statement
+PrimitivePatternsSwitchConstants.java:21:9: compiler.err.not.exhaustive.statement
+PrimitivePatternsSwitchConstants.java:25:9: compiler.err.not.exhaustive.statement
+PrimitivePatternsSwitchConstants.java:29:9: compiler.err.not.exhaustive.statement
+PrimitivePatternsSwitchConstants.java:42:9: compiler.err.not.exhaustive.statement
+- compiler.note.preview.filename: PrimitivePatternsSwitchConstants.java, DEFAULT
+- compiler.note.preview.recompile
+8 errors
diff --git a/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.java b/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.java
index 3d47c4ac9bc72..dacd48f441cbd 100644
--- a/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.java
+++ b/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.java
@@ -59,7 +59,7 @@ public static int dominationBetweenBoxedAndPrimitive() {
int i = 42;
return switch (i) {
case Integer ib -> ib;
- case byte ip -> ip; // OK - not dominated!
+ case byte ip -> ip; // Error - dominated!
};
}
@@ -265,4 +265,69 @@ public static char disallowedUnboxingAndWidening(Short test) {
public static boolean wideningReferenceConversionUnboxingAndNarrowingPrimitive(T i) {
return i instanceof byte b; // not allowed as a conversion
}
+
+ public static void dominanceIntFloat() {
+ int ii = 42;
+ switch (ii) {
+ case int i -> {}
+ case float f -> {} // Error - dominated!
+ }
+ }
+
+ public static void noDominanceIntFloat() {
+ int ii = 42;
+ switch (ii) {
+ case float f -> {}
+ case int i -> {} // ok
+ }
+ }
+
+ public static void strengtheningDominance() {
+ byte x = 42;
+ switch (x) {
+ case short s -> {}
+ case 42 -> {} // error: dominated
+ }
+
+ long l = 42l;
+ switch (l) {
+ case short s -> {}
+ case 42l -> {} // error: dominated
+ case long _ -> {}
+ }
+
+ char c = 'a';
+ switch (c) {
+ case short s -> {}
+ case 42 -> {} // error: dominated
+ case char _ -> {}
+ }
+
+ int x2 = 42;
+ switch(x2) {
+ case float f -> {}
+ case 16_777_216 -> {} // error: dominated
+ default -> {}
+ }
+
+ switch(x2) {
+ case float f -> {}
+ case 16_777_217 -> {} // OK
+ default -> {}
+ }
+
+ switch(x2) {
+ case int ii -> {}
+ case float f -> {} // error: dominated
+ }
+ }
+
+ public static void unconditionalFollowedByDefault() {
+ int ii = 42;
+ switch (ii) {
+ case int i -> {}
+ case float f -> {} // Error - dominated!
+ default -> {} // Error - unconditional and default
+ }
+ }
}
diff --git a/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.out b/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.out
index 75fd62016a086..5a0822a9aef31 100644
--- a/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.out
+++ b/test/langtools/tools/javac/patterns/PrimitivePatternsSwitchErrors.out
@@ -1,6 +1,7 @@
PrimitivePatternsSwitchErrors.java:15:18: compiler.err.pattern.dominated
PrimitivePatternsSwitchErrors.java:24:18: compiler.err.pattern.dominated
PrimitivePatternsSwitchErrors.java:31:24: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: int, java.lang.Long)
+PrimitivePatternsSwitchErrors.java:62:18: compiler.err.pattern.dominated
PrimitivePatternsSwitchErrors.java:70:18: compiler.err.pattern.dominated
PrimitivePatternsSwitchErrors.java:78:18: compiler.err.pattern.dominated
PrimitivePatternsSwitchErrors.java:84:18: compiler.err.prob.found.req: (compiler.misc.possible.loss.of.precision: long, byte)
@@ -29,6 +30,14 @@ PrimitivePatternsSwitchErrors.java:248:18: compiler.err.prob.found.req: (compile
PrimitivePatternsSwitchErrors.java:255:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Long, int)
PrimitivePatternsSwitchErrors.java:261:18: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: java.lang.Short, char)
PrimitivePatternsSwitchErrors.java:266:16: compiler.err.prob.found.req: (compiler.misc.inconvertible.types: T, byte)
+PrimitivePatternsSwitchErrors.java:273:18: compiler.err.pattern.dominated
+PrimitivePatternsSwitchErrors.java:289:18: compiler.err.pattern.dominated
+PrimitivePatternsSwitchErrors.java:295:18: compiler.err.pattern.dominated
+PrimitivePatternsSwitchErrors.java:302:18: compiler.err.pattern.dominated
+PrimitivePatternsSwitchErrors.java:309:18: compiler.err.pattern.dominated
+PrimitivePatternsSwitchErrors.java:321:18: compiler.err.pattern.dominated
+PrimitivePatternsSwitchErrors.java:330:13: compiler.err.unconditional.pattern.and.default
+PrimitivePatternsSwitchErrors.java:329:18: compiler.err.pattern.dominated
PrimitivePatternsSwitchErrors.java:30:16: compiler.err.not.exhaustive
PrimitivePatternsSwitchErrors.java:37:16: compiler.err.not.exhaustive
PrimitivePatternsSwitchErrors.java:44:16: compiler.err.not.exhaustive
@@ -43,4 +52,4 @@ PrimitivePatternsSwitchErrors.java:254:16: compiler.err.not.exhaustive
PrimitivePatternsSwitchErrors.java:260:16: compiler.err.not.exhaustive
- compiler.note.preview.filename: PrimitivePatternsSwitchErrors.java, DEFAULT
- compiler.note.preview.recompile
-43 errors
\ No newline at end of file
+52 errors
diff --git a/test/langtools/tools/javac/patterns/PrimitiveUnconditionallyExactInAssignability.java b/test/langtools/tools/javac/patterns/PrimitiveUnconditionallyExactInAssignability.java
new file mode 100644
index 0000000000000..97b96069a6831
--- /dev/null
+++ b/test/langtools/tools/javac/patterns/PrimitiveUnconditionallyExactInAssignability.java
@@ -0,0 +1,185 @@
+/*
+ * Copyright (c) 2025, 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
+ * @summary Check assignability of narrowing p.c. with constant expressions vs exact conversion methods
+ * @library /tools/lib/types
+ * @modules jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.file
+ * jdk.compiler/com.sun.tools.javac.util
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.tree
+ * @build TypeHarness
+ * @compile PrimitiveUnconditionallyExactInAssignability.java
+ * @run main PrimitiveUnconditionallyExactInAssignability
+ */
+
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.TypeTag;
+
+import java.lang.runtime.ExactConversionsSupport;
+
+import static com.sun.tools.javac.code.TypeTag.ERROR;
+import static com.sun.tools.javac.code.TypeTag.INT;
+
+public class PrimitiveUnconditionallyExactInAssignability extends TypeHarness {
+ PrimitiveUnconditionallyExactInAssignability() {
+ }
+
+ void assertAssignmentNarrowingAndUnconditionality() {
+ // byte b = vs ExactConversionsSupport::isIntToByteExact
+ assertAssignable(fac.Constant(Short.MIN_VALUE), predef.byteType, ExactConversionsSupport.isIntToByteExact(Short.MIN_VALUE));
+ assertAssignable(fac.Constant((short) (Byte.MIN_VALUE - 1)), predef.byteType, ExactConversionsSupport.isIntToByteExact((short) (Byte.MIN_VALUE - 1)));
+ assertAssignable(fac.Constant((short) (Byte.MAX_VALUE + 1)), predef.byteType, ExactConversionsSupport.isIntToByteExact((short) (Byte.MAX_VALUE + 1)));
+ assertAssignable(fac.Constant(Short.MAX_VALUE), predef.byteType, ExactConversionsSupport.isIntToByteExact(Short.MAX_VALUE));
+
+ // byte b = vs ExactConversionsSupport::isIntToByteExact
+ assertAssignable(fac.Constant(Character.MIN_VALUE), predef.byteType, ExactConversionsSupport.isIntToByteExact(Character.MIN_VALUE));
+ assertAssignable(fac.Constant((char) (Byte.MAX_VALUE + 1)), predef.byteType, ExactConversionsSupport.isIntToByteExact((char) (Byte.MAX_VALUE + 1)));
+ assertAssignable(fac.Constant(Character.MAX_VALUE), predef.byteType, ExactConversionsSupport.isIntToByteExact(Character.MAX_VALUE));
+
+ // byte b = vs ExactConversionsSupport::isIntToByteExact
+ assertAssignable(fac.Constant(Integer.MIN_VALUE), predef.byteType, ExactConversionsSupport.isIntToByteExact(Integer.MIN_VALUE));
+ assertAssignable(fac.Constant((int) (Byte.MIN_VALUE - 1)), predef.byteType, ExactConversionsSupport.isIntToByteExact((int) (Byte.MIN_VALUE - 1)));
+ assertAssignable(fac.Constant((int) (Byte.MAX_VALUE + 1)), predef.byteType, ExactConversionsSupport.isIntToByteExact((int) (Byte.MAX_VALUE + 1)));
+ assertAssignable(fac.Constant(Integer.MAX_VALUE), predef.byteType, ExactConversionsSupport.isIntToByteExact(Integer.MAX_VALUE));
+
+ // char c = vs ExactConversionsSupport::isIntToCharExact
+ assertAssignable(fac.Constant(Short.MIN_VALUE), predef.charType, ExactConversionsSupport.isIntToCharExact(Short.MIN_VALUE));
+ assertAssignable(fac.Constant((short) (Character.MIN_VALUE - 1)), predef.charType, ExactConversionsSupport.isIntToCharExact((short) (Character.MIN_VALUE - 1)));
+ assertAssignable(fac.Constant((short) (Character.MAX_VALUE + 1)), predef.charType, ExactConversionsSupport.isIntToCharExact((short) (Character.MIN_VALUE + 1)));
+ assertAssignable(fac.Constant(Short.MAX_VALUE), predef.charType, ExactConversionsSupport.isIntToCharExact(Short.MAX_VALUE));
+
+ // char c = vs ExactConversionsSupport::isIntToCharExact
+ assertAssignable(fac.Constant(Integer.MIN_VALUE), predef.charType, ExactConversionsSupport.isIntToCharExact(Integer.MIN_VALUE));
+ assertAssignable(fac.Constant((int) (Character.MIN_VALUE - 1)), predef.charType, ExactConversionsSupport.isIntToCharExact((int) (Character.MIN_VALUE - 1)));
+ assertAssignable(fac.Constant((int) (Character.MAX_VALUE + 1)), predef.charType, ExactConversionsSupport.isIntToCharExact((int) (Character.MAX_VALUE + 1)));
+ assertAssignable(fac.Constant(Integer.MAX_VALUE), predef.charType, ExactConversionsSupport.isIntToCharExact(Integer.MAX_VALUE));
+
+ // short b = vs ExactConversionsSupport::isIntToShortExact
+ assertAssignable(fac.Constant(Character.MIN_VALUE), predef.shortType, ExactConversionsSupport.isIntToShortExact(Character.MIN_VALUE));
+ assertAssignable(fac.Constant((char) (Character.MAX_VALUE + 1)), predef.shortType, ExactConversionsSupport.isIntToShortExact((char) (Character.MAX_VALUE + 1)));
+ assertAssignable(fac.Constant(Character.MAX_VALUE), predef.shortType, ExactConversionsSupport.isIntToShortExact(Character.MAX_VALUE));
+
+ // short b = vs ExactConversionsSupport::isIntToShortExact
+ assertAssignable(fac.Constant(Integer.MIN_VALUE), predef.shortType, ExactConversionsSupport.isIntToShortExact(Integer.MIN_VALUE));
+ assertAssignable(fac.Constant((int) (Short.MIN_VALUE - 1)), predef.shortType, ExactConversionsSupport.isIntToShortExact((int) (Short.MIN_VALUE - 1)));
+ assertAssignable(fac.Constant((int) (Short.MAX_VALUE + 1)), predef.shortType, ExactConversionsSupport.isIntToShortExact((int) (Short.MAX_VALUE + 1)));
+ assertAssignable(fac.Constant(Integer.MAX_VALUE), predef.shortType, ExactConversionsSupport.isIntToShortExact(Integer.MAX_VALUE));
+ }
+ void assertOriginalAssignmentNarrowingAndUnconditionality() {
+ // byte b = vs ExactConversionsSupport::isIntToByteExact
+ assertOriginalAssignable(fac.Constant(Short.MIN_VALUE), predef.byteType, ExactConversionsSupport.isIntToByteExact(Short.MIN_VALUE));
+ assertOriginalAssignable(fac.Constant((short) (Byte.MIN_VALUE - 1)), predef.byteType, ExactConversionsSupport.isIntToByteExact((short) (Byte.MIN_VALUE - 1)));
+ assertOriginalAssignable(fac.Constant((short) (Byte.MAX_VALUE + 1)), predef.byteType, ExactConversionsSupport.isIntToByteExact((short) (Byte.MAX_VALUE + 1)));
+ assertOriginalAssignable(fac.Constant(Short.MAX_VALUE), predef.byteType, ExactConversionsSupport.isIntToByteExact(Short.MAX_VALUE));
+
+ // byte b = vs ExactConversionsSupport::isIntToByteExact
+ assertOriginalAssignable(fac.Constant(Character.MIN_VALUE), predef.byteType, ExactConversionsSupport.isIntToByteExact(Character.MIN_VALUE));
+ assertOriginalAssignable(fac.Constant((char) (Byte.MAX_VALUE + 1)), predef.byteType, ExactConversionsSupport.isIntToByteExact((char) (Byte.MAX_VALUE + 1)));
+ assertOriginalAssignable(fac.Constant(Character.MAX_VALUE), predef.byteType, ExactConversionsSupport.isIntToByteExact(Character.MAX_VALUE));
+
+ // byte b = vs ExactConversionsSupport::isIntToByteExact
+ assertOriginalAssignable(fac.Constant(Integer.MIN_VALUE), predef.byteType, ExactConversionsSupport.isIntToByteExact(Integer.MIN_VALUE));
+ assertOriginalAssignable(fac.Constant((int) (Byte.MIN_VALUE - 1)), predef.byteType, ExactConversionsSupport.isIntToByteExact((int) (Byte.MIN_VALUE - 1)));
+ assertOriginalAssignable(fac.Constant((int) (Byte.MAX_VALUE + 1)), predef.byteType, ExactConversionsSupport.isIntToByteExact((int) (Byte.MAX_VALUE + 1)));
+ assertOriginalAssignable(fac.Constant(Integer.MAX_VALUE), predef.byteType, ExactConversionsSupport.isIntToByteExact(Integer.MAX_VALUE));
+
+ // char c = vs ExactConversionsSupport::isIntToCharExact
+ assertOriginalAssignable(fac.Constant(Short.MIN_VALUE), predef.charType, ExactConversionsSupport.isIntToCharExact(Short.MIN_VALUE));
+ assertOriginalAssignable(fac.Constant((short) (Character.MIN_VALUE - 1)), predef.charType, ExactConversionsSupport.isIntToCharExact((short) (Character.MIN_VALUE - 1)));
+ assertOriginalAssignable(fac.Constant((short) (Character.MAX_VALUE + 1)), predef.charType, ExactConversionsSupport.isIntToCharExact((short) (Character.MIN_VALUE + 1)));
+ assertOriginalAssignable(fac.Constant(Short.MAX_VALUE), predef.charType, ExactConversionsSupport.isIntToCharExact(Short.MAX_VALUE));
+
+ // char c = vs ExactConversionsSupport::isIntToCharExact
+ assertOriginalAssignable(fac.Constant(Integer.MIN_VALUE), predef.charType, ExactConversionsSupport.isIntToCharExact(Integer.MIN_VALUE));
+ assertOriginalAssignable(fac.Constant((int) (Character.MIN_VALUE - 1)), predef.charType, ExactConversionsSupport.isIntToCharExact((int) (Character.MIN_VALUE - 1)));
+ assertOriginalAssignable(fac.Constant((int) (Character.MAX_VALUE + 1)), predef.charType, ExactConversionsSupport.isIntToCharExact((int) (Character.MAX_VALUE + 1)));
+ assertOriginalAssignable(fac.Constant(Integer.MAX_VALUE), predef.charType, ExactConversionsSupport.isIntToCharExact(Integer.MAX_VALUE));
+
+ // short b = vs ExactConversionsSupport::isIntToShortExact
+ assertOriginalAssignable(fac.Constant(Character.MIN_VALUE), predef.shortType, ExactConversionsSupport.isIntToShortExact(Character.MIN_VALUE));
+ assertOriginalAssignable(fac.Constant((char) (Character.MAX_VALUE + 1)), predef.shortType, ExactConversionsSupport.isIntToShortExact((char) (Character.MAX_VALUE + 1)));
+ assertOriginalAssignable(fac.Constant(Character.MAX_VALUE), predef.shortType, ExactConversionsSupport.isIntToShortExact(Character.MAX_VALUE));
+
+ // short b = vs ExactConversionsSupport::isIntToShortExact
+ assertOriginalAssignable(fac.Constant(Integer.MIN_VALUE), predef.shortType, ExactConversionsSupport.isIntToShortExact(Integer.MIN_VALUE));
+ assertOriginalAssignable(fac.Constant((int) (Short.MIN_VALUE - 1)), predef.shortType, ExactConversionsSupport.isIntToShortExact((int) (Short.MIN_VALUE - 1)));
+ assertOriginalAssignable(fac.Constant((int) (Short.MAX_VALUE + 1)), predef.shortType, ExactConversionsSupport.isIntToShortExact((int) (Short.MAX_VALUE + 1)));
+ assertOriginalAssignable(fac.Constant(Integer.MAX_VALUE), predef.shortType, ExactConversionsSupport.isIntToShortExact(Integer.MAX_VALUE));
+ }
+ // where
+ public void assertOriginalAssignable(Type s, Type t, boolean expected) {
+ if (originalIsAssignable(s, t) != expected) {
+ String msg = expected ?
+ " is not assignable to " :
+ " is assignable to ";
+ error(s + msg + t);
+ }
+ }
+ public boolean originalIsAssignable(Type t, Type s) {
+ if (t.hasTag(ERROR))
+ return true;
+ if (t.getTag().isSubRangeOf(INT) && t.constValue() != null) {
+ int value = ((Number)t.constValue()).intValue();
+ switch (s.getTag()) {
+ case BYTE:
+ case CHAR:
+ case SHORT:
+ case INT:
+ if (originalCheckRange(s.getTag(), value))
+ return true;
+ break;
+ }
+ }
+ return types.isConvertible(t, s);
+ }
+ public boolean originalCheckRange(TypeTag that, int value) {
+ switch (that) {
+ case BOOLEAN:
+ return 0 <= value && value <= 1;
+ case BYTE:
+ return Byte.MIN_VALUE <= value && value <= Byte.MAX_VALUE;
+ case CHAR:
+ return Character.MIN_VALUE <= value && value <= Character.MAX_VALUE;
+ case SHORT:
+ return Short.MIN_VALUE <= value && value <= Short.MAX_VALUE;
+ case INT:
+ return true;
+ default:
+ throw new AssertionError();
+ }
+ }
+
+ private void error(String msg) {
+ throw new AssertionError("Unexpected result in original isAssignable: " + msg);
+ }
+
+ public static void main(String[] args) {
+ PrimitiveUnconditionallyExactInAssignability harness = new PrimitiveUnconditionallyExactInAssignability();
+ harness.assertAssignmentNarrowingAndUnconditionality();
+ harness.assertOriginalAssignmentNarrowingAndUnconditionality();
+ }
+}
diff --git a/test/langtools/tools/javac/patterns/PrimitiveUnconditionallyExactInExhaustiveSwitches.java b/test/langtools/tools/javac/patterns/PrimitiveUnconditionallyExactInExhaustiveSwitches.java
new file mode 100644
index 0000000000000..e6a204968dd1d
--- /dev/null
+++ b/test/langtools/tools/javac/patterns/PrimitiveUnconditionallyExactInExhaustiveSwitches.java
@@ -0,0 +1,280 @@
+/*
+ * Copyright (c) 2025, 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
+ * @summary Check the unconditionally exact for constant primitives used in the exhaustiveness check
+ * @library /tools/lib/types
+ * @modules jdk.compiler/com.sun.tools.javac.code
+ * jdk.compiler/com.sun.tools.javac.comp
+ * jdk.compiler/com.sun.tools.javac.file
+ * jdk.compiler/com.sun.tools.javac.util
+ * jdk.compiler/com.sun.tools.javac.main
+ * jdk.compiler/com.sun.tools.javac.tree
+ * @build TypeHarness
+ * @compile PrimitiveUnconditionallyExactInExhaustiveSwitches.java
+ * @run main PrimitiveUnconditionallyExactInExhaustiveSwitches
+ */
+
+public class PrimitiveUnconditionallyExactInExhaustiveSwitches extends TypeHarness {
+
+ PrimitiveUnconditionallyExactInExhaustiveSwitches() {
+ }
+ public void testByte() {
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (Byte.MAX_VALUE))), predef.byteType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (0))),predef.byteType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (Byte.MIN_VALUE))),predef.byteType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (Short.MAX_VALUE))),predef.byteType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (0))),predef.byteType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (Short.MIN_VALUE))),predef.byteType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((char) (Character.MAX_VALUE))),predef.byteType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((char) (Character.MIN_VALUE))),predef.byteType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Integer.MAX_VALUE)),predef.byteType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((0)),predef.byteType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Integer.MIN_VALUE)),predef.byteType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Long.MAX_VALUE)),predef.byteType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((0L)),predef.byteType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Long.MIN_VALUE)),predef.byteType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.MAX_VALUE)),predef.byteType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((float) 0)),predef.byteType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.MIN_VALUE)),predef.byteType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.NaN)),predef.byteType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.POSITIVE_INFINITY)),predef.byteType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.NEGATIVE_INFINITY)),predef.byteType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((-0.0f)),predef.byteType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((+0.0f)),predef.byteType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.MAX_VALUE)),predef.byteType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((double) 0)),predef.byteType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.MIN_VALUE)),predef.byteType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.NaN)),predef.byteType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.POSITIVE_INFINITY)),predef.byteType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.NEGATIVE_INFINITY)),predef.byteType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((-0.0d)),predef.byteType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((+0.0d)),predef.byteType, true);
+ }
+ public void testShort() {
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (Byte.MAX_VALUE))),predef.shortType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (0))),predef.shortType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (Byte.MIN_VALUE))),predef.shortType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (Short.MAX_VALUE))),predef.shortType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (0))),predef.shortType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (Short.MIN_VALUE))),predef.shortType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((char) (Character.MAX_VALUE))),predef.shortType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((char) (Character.MIN_VALUE))),predef.shortType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Integer.MAX_VALUE)),predef.shortType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((0)),predef.shortType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Integer.MIN_VALUE)),predef.shortType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Long.MAX_VALUE)),predef.shortType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((0L)),predef.shortType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Long.MIN_VALUE)),predef.shortType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.MAX_VALUE)),predef.shortType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((float) 0)),predef.shortType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.MIN_VALUE)),predef.shortType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.MIN_VALUE)),predef.shortType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.NaN)),predef.shortType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.POSITIVE_INFINITY)),predef.shortType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.NEGATIVE_INFINITY)),predef.shortType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((-0.0f)),predef.shortType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((+0.0f)),predef.shortType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.MAX_VALUE)),predef.shortType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((double) 0)),predef.shortType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.MIN_VALUE)),predef.shortType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.NaN)),predef.shortType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.POSITIVE_INFINITY)),predef.shortType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.NEGATIVE_INFINITY)),predef.shortType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((-0.0d)),predef.shortType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((+0.0d)),predef.shortType, true);
+ }
+ public void testChar() {
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (Byte.MAX_VALUE))),predef.charType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (0))),predef.charType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (Byte.MIN_VALUE))),predef.charType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (Short.MAX_VALUE))),predef.charType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (0))),predef.charType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (Short.MIN_VALUE))),predef.charType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((char) (Character.MAX_VALUE))),predef.charType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((char) (Character.MIN_VALUE))),predef.charType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Integer.MAX_VALUE)),predef.charType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((0)),predef.charType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Integer.MIN_VALUE)),predef.charType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Long.MAX_VALUE)),predef.charType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((0L)),predef.charType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Long.MIN_VALUE)),predef.charType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.MAX_VALUE)),predef.charType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((float) 0)),predef.charType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.MIN_VALUE)),predef.charType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.NaN)),predef.charType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.POSITIVE_INFINITY)),predef.charType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.NEGATIVE_INFINITY)),predef.charType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((-0.0f)),predef.charType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((+0.0f)),predef.charType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.MAX_VALUE)),predef.charType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((double) 0)),predef.charType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.MIN_VALUE)),predef.charType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.NaN)),predef.charType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.POSITIVE_INFINITY)),predef.charType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.NEGATIVE_INFINITY)),predef.charType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((-0.0d)),predef.charType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((+0.0d)),predef.charType, true);
+ }
+ public void testInt() {
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (Byte.MAX_VALUE))),predef.intType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (0))),predef.intType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (Byte.MIN_VALUE))),predef.intType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (Short.MAX_VALUE))),predef.intType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (0))),predef.intType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (Short.MIN_VALUE))),predef.intType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((char) (Character.MAX_VALUE))),predef.intType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((char) (Character.MIN_VALUE))),predef.intType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Integer.MAX_VALUE)),predef.intType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((0)),predef.intType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Integer.MIN_VALUE)),predef.intType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Long.MAX_VALUE)),predef.intType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((0L)),predef.intType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Long.MIN_VALUE)),predef.intType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.MAX_VALUE)),predef.intType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((float) 0)),predef.intType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.MIN_VALUE)),predef.intType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.NaN)),predef.intType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.POSITIVE_INFINITY)),predef.intType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.NEGATIVE_INFINITY)),predef.intType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((-0.0f)),predef.intType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((+0.0f)),predef.intType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.MAX_VALUE)),predef.intType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((double) 0)),predef.intType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.MIN_VALUE)),predef.intType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.NaN)),predef.intType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.POSITIVE_INFINITY)),predef.intType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.NEGATIVE_INFINITY)),predef.intType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((-0.0d)),predef.intType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((+0.0d)),predef.intType, true);
+ }
+ public void testLong() {
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (Byte.MAX_VALUE))),predef.longType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (0))),predef.longType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (Byte.MIN_VALUE))),predef.longType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (Short.MAX_VALUE))),predef.longType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (0))),predef.longType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (Short.MIN_VALUE))),predef.longType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((char) (Character.MAX_VALUE))),predef.longType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((char) (Character.MIN_VALUE))),predef.longType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Integer.MAX_VALUE)),predef.longType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((0L)),predef.longType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Integer.MIN_VALUE)),predef.longType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Long.MAX_VALUE)),predef.longType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((0)),predef.longType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Long.MIN_VALUE)),predef.longType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.MAX_VALUE)),predef.longType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((float) 0)),predef.longType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.MIN_VALUE)),predef.longType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.NaN)),predef.longType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.POSITIVE_INFINITY)),predef.longType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.NEGATIVE_INFINITY)),predef.longType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((-0.0f)),predef.longType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((+0.0f)),predef.longType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.MAX_VALUE)),predef.longType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((double) 0)),predef.longType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.MIN_VALUE)),predef.longType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.NaN)),predef.longType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.POSITIVE_INFINITY)),predef.longType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.NEGATIVE_INFINITY)),predef.longType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((-0.0d)),predef.longType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((+0.0d)),predef.longType, true);
+ }
+ public void testFloat() {
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (Byte.MAX_VALUE))),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((byte) (0)),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (Byte.MIN_VALUE))),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (Short.MAX_VALUE))),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (0))),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (Short.MIN_VALUE))),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((char) (Character.MAX_VALUE))),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((char) (Character.MIN_VALUE))),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Integer.MAX_VALUE)),predef.floatType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((0)),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Integer.MIN_VALUE)),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Long.MAX_VALUE)),predef.floatType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((0L)),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Long.MIN_VALUE)),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.MAX_VALUE)),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((float) 0)),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.MIN_VALUE)),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.NaN)),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.POSITIVE_INFINITY)),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.NEGATIVE_INFINITY)),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((-0.0f)),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((+0.0f)),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.MAX_VALUE)),predef.floatType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((double) 0)),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.MIN_VALUE)),predef.floatType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.NaN)),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.POSITIVE_INFINITY)),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.NEGATIVE_INFINITY)),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((-0.0d)),predef.floatType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((+0.0d)),predef.floatType, true);
+ }
+ public void testDouble() {
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (Byte.MAX_VALUE))),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (0))),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((byte) (Byte.MIN_VALUE))),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (Short.MAX_VALUE))),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (0))),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((short) (Short.MIN_VALUE))),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((char) (Character.MAX_VALUE))),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((char) (Character.MIN_VALUE))),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Integer.MAX_VALUE)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((0)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Integer.MIN_VALUE)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Long.MAX_VALUE)),predef.doubleType, false);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((0L)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Long.MIN_VALUE)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.MAX_VALUE)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((float) 0)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.MIN_VALUE)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.NaN)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.POSITIVE_INFINITY)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Float.NEGATIVE_INFINITY)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((-0.0f)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((+0.0f)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.MAX_VALUE)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant(((double) 0)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.MIN_VALUE)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.NaN)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.POSITIVE_INFINITY)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((Double.NEGATIVE_INFINITY)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((-0.0d)),predef.doubleType, true);
+ assertIsUnconditionallyExactConstantPrimitives(fac.Constant((+0.0d)),predef.doubleType, true);
+ }
+
+
+ public static void main(String[] args) {
+ PrimitiveUnconditionallyExactInExhaustiveSwitches harness = new PrimitiveUnconditionallyExactInExhaustiveSwitches();
+ harness.testByte();
+ harness.testShort();
+ harness.testChar();
+ harness.testInt();
+ harness.testDouble();
+ harness.testLong();
+ harness.testFloat();
+ }
+}
diff --git a/test/langtools/tools/javac/patterns/T8332463a.java b/test/langtools/tools/javac/patterns/T8332463a.java
index 96aaad86a855b..2501a330af2c7 100644
--- a/test/langtools/tools/javac/patterns/T8332463a.java
+++ b/test/langtools/tools/javac/patterns/T8332463a.java
@@ -25,14 +25,14 @@
* @test
* @bug 8332463
* @summary Byte conditional pattern case element dominates short constant case element
- * @compile --enable-preview --source ${jdk.version} T8332463a.java
+ * @compile/fail/ref=T8332463a.out -XDrawDiagnostics --enable-preview --source ${jdk.version} T8332463a.java
*/
public class T8332463a {
public int test2() {
Byte i = (byte) 42;
return switch (i) {
case Byte ib -> 1;
- case short s -> 2;
+ case short s -> 2; // dominated
};
}
@@ -40,7 +40,7 @@ public int test4() {
int i = 42;
return switch (i) {
case Integer ib -> 1;
- case byte ip -> 2;
+ case byte ip -> 2; // dominated
};
}
@@ -48,7 +48,7 @@ public int test3() {
int i = 42;
return switch (i) {
case Integer ib -> 1;
- case (byte) 0 -> 2;
+ case (byte) 0 -> 2; // dominated
};
}
}
diff --git a/test/langtools/tools/javac/patterns/T8332463a.out b/test/langtools/tools/javac/patterns/T8332463a.out
new file mode 100644
index 0000000000000..5a4eec46d82a5
--- /dev/null
+++ b/test/langtools/tools/javac/patterns/T8332463a.out
@@ -0,0 +1,6 @@
+T8332463a.java:35:18: compiler.err.pattern.dominated
+T8332463a.java:43:18: compiler.err.pattern.dominated
+T8332463a.java:51:18: compiler.err.pattern.dominated
+- compiler.note.preview.filename: T8332463a.java, DEFAULT
+- compiler.note.preview.recompile
+3 errors
diff --git a/test/langtools/tools/javac/patterns/T8332463b.java b/test/langtools/tools/javac/patterns/T8332463b.java
index 7956fd31f9f38..73338b2bd8a04 100644
--- a/test/langtools/tools/javac/patterns/T8332463b.java
+++ b/test/langtools/tools/javac/patterns/T8332463b.java
@@ -26,15 +26,14 @@
* @bug 8332463
* @summary Byte conditional pattern case element dominates short constant case element
* @enablePreview
- * @compile T8332463b.java
- * @compile --enable-preview --source ${jdk.version} T8332463b.java
+ * @compile/fail/ref=T8332463b.out -XDrawDiagnostics --enable-preview --source ${jdk.version} T8332463b.java
*/
public class T8332463b {
public int test1() {
Byte i = (byte) 42;
return switch (i) {
case Byte ib -> 1;
- case (short) 0 -> 2;
+ case (short) 0 -> 2; // dominated
};
}
}
diff --git a/test/langtools/tools/javac/patterns/T8332463b.out b/test/langtools/tools/javac/patterns/T8332463b.out
new file mode 100644
index 0000000000000..f912242a6c65a
--- /dev/null
+++ b/test/langtools/tools/javac/patterns/T8332463b.out
@@ -0,0 +1,2 @@
+T8332463b.java:36:18: compiler.err.pattern.dominated
+1 error
diff --git a/test/langtools/tools/lib/types/TypeHarness.java b/test/langtools/tools/lib/types/TypeHarness.java
index 43bf2f961e9e3..ea1f434214524 100644
--- a/test/langtools/tools/lib/types/TypeHarness.java
+++ b/test/langtools/tools/lib/types/TypeHarness.java
@@ -188,6 +188,21 @@ public void assertAssignable(Type s, Type t, boolean expected) {
}
}
+ /** assert that 's' is unconditionally exact to 't' */
+ public void assertIsUnconditionallyExactConstantPrimitives(Type s, Type t) {
+ assertIsUnconditionallyExactConstantPrimitives(s, t, true);
+ }
+
+ /** assert that 's' is/is not unconditionally exact to 't' */
+ public void assertIsUnconditionallyExactConstantPrimitives(Type s, Type t, boolean expected) {
+ if (types.isUnconditionallyExactConstantPrimitives(s, t) != expected) {
+ String msg = expected ?
+ " is not unconditionally exact to " :
+ " is unconditionally exact to ";
+ error(s + msg + t);
+ }
+ }
+
/** assert that generic type 't' is well-formed */
public void assertValidGenericType(Type t) {
assertValidGenericType(t, true);