diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java index 06c41156ad4..5dc85d5f2c5 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java @@ -106,7 +106,6 @@ import com.sun.tools.javac.tree.JCTree.LetExpr; import com.sun.tools.javac.tree.TreeInfo; import com.sun.tools.javac.tree.TreeScanner; import com.sun.tools.javac.util.Assert; -import com.sun.tools.javac.util.JCDiagnostic; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; @@ -393,7 +392,7 @@ public class TransPatterns extends TreeTranslator { boolean hasUnconditionalPattern, boolean patternSwitch) { if (patternSwitch) { - Type seltype = selector.type.hasTag(BOT) + Type seltype = selector.type.hasTag(BOT) || target.usesReferenceOnlySelectorTypes() ? syms.objectType : selector.type; @@ -496,14 +495,12 @@ public class TransPatterns extends TreeTranslator { .toArray(s -> new LoadableConstant[s]); boolean enumSelector = seltype.tsym.isEnum(); - boolean primitiveSelector = seltype.isPrimitive(); Name bootstrapName = enumSelector ? names.enumSwitch : names.typeSwitch; MethodSymbol bsm = rs.resolveInternalMethod(tree.pos(), env, syms.switchBootstrapsType, bootstrapName, staticArgTypes, List.nil()); - Type resolvedSelectorType = seltype; MethodType indyType = new MethodType( - List.of(resolvedSelectorType, syms.intType), + List.of(seltype, syms.intType), syms.intType, List.nil(), syms.methodClass diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java index 94b77016d86..35461b031f2 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java @@ -226,4 +226,10 @@ public enum Target { public boolean optimizeOuterThis() { return compareTo(JDK1_18) >= 0; } + + /** Releases prior to JDK 23 expect a less precise SwitchBootstraps.typeSwitch signature on the selectorType + */ + public boolean usesReferenceOnlySelectorTypes() { + return compareTo(Target.JDK1_23) < 0; + } } diff --git a/test/langtools/tools/javac/T8328747.java b/test/langtools/tools/javac/T8328747.java new file mode 100644 index 00000000000..4c384319ac1 --- /dev/null +++ b/test/langtools/tools/javac/T8328747.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2024, 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 8328747 + * @summary WrongMethodTypeException with pattern matching on switch on sealed classes + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.jdeps/com.sun.tools.javap + * @build toolbox.ToolBox toolbox.JavapTask + * @compile T8328747.java + * @run main T8328747 + */ + +import toolbox.*; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +public class T8328747 extends TestRunner { + private ToolBox tb; + + public static void main(String... args) throws Exception { + new T8328747().runTests(); + } + + T8328747() { + super(System.err); + tb = new ToolBox(); + } + + public void runTests() throws Exception { + runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + @Test + public void test(Path base) throws Exception { + Path current = base.resolve("."); + Path src = current.resolve("src"); + Path classes = current.resolve("classes"); + tb.writeJavaFiles(src, + """ + package test; + public class Test { + public static void main(String[] args) { + f(new P()); + f(new O()); + } + + private static void f(I info) { + switch (info) { + case P p -> System.err.println(p); + case O o -> System.err.println(o); + } + } + + static sealed interface I permits P, O {} + private abstract static class A {} + static final class P extends A implements I {} + static final class O extends A implements I {} + } + """); + + Files.createDirectories(classes); + + {//with --release: + new JavacTask(tb) + .options("--release", "21") + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.SUCCESS) + .writeAll(); + + String javapOut = new JavapTask(tb) + .options("-v") + .classpath(classes.toString()) + .classes("test.Test") + .run() + .getOutput(Task.OutputKind.DIRECT); + + if (!javapOut.contains("#25 = InvokeDynamic #0:#26 // #0:typeSwitch:(Ljava/lang/Object;I)I")) + throw new AssertionError("typeSwitch for a version less than 23 should accept a static type of java.lang.Object"); + } + + {//without: + new JavacTask(tb) + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.SUCCESS) + .writeAll(); + + String javapOut = new JavapTask(tb) + .options("-v") + .classpath(classes.toString()) + .classes("test.Test") + .run() + .getOutput(Task.OutputKind.DIRECT); + + if (!javapOut.contains("#25 = InvokeDynamic #0:#26 // #0:typeSwitch:(Ltest/Test$I;I)I")) + throw new AssertionError("typeSwitch from version 23 and beyond should accept a precise selector type"); + } + } +}