diff --git a/make/CompileInterimLangtools.gmk b/make/CompileInterimLangtools.gmk
index e860169891f..f0312a5e8fa 100644
--- a/make/CompileInterimLangtools.gmk
+++ b/make/CompileInterimLangtools.gmk
@@ -49,7 +49,8 @@ TARGETS += $(patsubst %, $(BUILDTOOLS_OUTPUTDIR)/gensrc/%/module-info.java, \
$(INTERIM_LANGTOOLS_MODULES))
$(eval $(call SetupCopyFiles, COPY_PREVIEW_FEATURES, \
- FILES := $(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java, \
+ FILES := $(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java \
+ $(TOPDIR)/src/java.base/share/classes/jdk/internal/javac/NoPreview.java, \
DEST := $(BUILDTOOLS_OUTPUTDIR)/gensrc/java.base.interim/jdk/internal/javac/, \
))
diff --git a/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java
new file mode 100644
index 00000000000..a396b092d8c
--- /dev/null
+++ b/src/java.base/share/classes/java/lang/runtime/SwitchBootstraps.java
@@ -0,0 +1,170 @@
+/*
+ * Copyright (c) 2017, 2021, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package java.lang.runtime;
+
+import java.lang.invoke.CallSite;
+import java.lang.invoke.ConstantCallSite;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.util.Arrays;
+import java.util.Objects;
+import java.util.stream.Stream;
+
+import jdk.internal.javac.PreviewFeature;
+
+import static java.util.Objects.requireNonNull;
+
+/**
+ * Bootstrap methods for linking {@code invokedynamic} call sites that implement
+ * the selection functionality of the {@code switch} statement. The bootstraps
+ * take additional static arguments corresponding to the {@code case} labels
+ * of the {@code switch}, implicitly numbered sequentially from {@code [0..N)}.
+ *
+ * @since 17
+ */
+@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING)
+public class SwitchBootstraps {
+
+ private SwitchBootstraps() {}
+
+ private static final MethodHandles.Lookup LOOKUP = MethodHandles.lookup();
+
+ private static final MethodHandle DO_SWITCH;
+
+ static {
+ try {
+ DO_SWITCH = LOOKUP.findStatic(SwitchBootstraps.class, "doSwitch",
+ MethodType.methodType(int.class, Object.class, int.class, Object[].class));
+ }
+ catch (ReflectiveOperationException e) {
+ throw new ExceptionInInitializerError(e);
+ }
+ }
+
+ /**
+ * Bootstrap method for linking an {@code invokedynamic} call site that
+ * implements a {@code switch} on a target of a reference type. The static
+ * arguments are an array of case labels which must be non-null and of type
+ * {@code String} or {@code Integer} or {@code Class}.
+ *
+ * The type of the returned {@code CallSite}'s method handle will have
+ * a return type of {@code int}. It has two parameters: the first argument
+ * will be an {@code Object} instance ({@code target}) and the second
+ * will be {@code int} ({@code restart}).
+ *
+ * If the {@code target} is {@code null}, then the method of the call site
+ * returns {@literal -1}.
+ *
+ * If the {@code target} is not {@code null}, then the method of the call site
+ * returns the index of the first element in the {@code labels} array starting from
+ * the {@code restart} index matching one of the following conditions:
+ *
+ *
the element is of type {@code Class} that is assignable
+ * from the target's class; or
+ *
the element is of type {@code String} or {@code Integer} and
+ * equals to the target.
+ *
+ *
+ * If no element in the {@code labels} array matches the target, then
+ * the method of the call site return the length of the {@code labels} array.
+ *
+ * @param lookup Represents a lookup context with the accessibility
+ * privileges of the caller. When used with {@code invokedynamic},
+ * this is stacked automatically by the VM.
+ * @param invocationName unused
+ * @param invocationType The invocation type of the {@code CallSite} with two parameters,
+ * a reference type, an {@code int}, and {@code int} as a return type.
+ * @param labels case labels - {@code String} and {@code Integer} constants
+ * and {@code Class} instances, in any combination
+ * @return a {@code CallSite} returning the first matching element as described above
+ *
+ * @throws NullPointerException if any argument is {@code null}
+ * @throws IllegalArgumentException if any element in the labels array is null, if the
+ * invocation type is not not a method type of first parameter of a reference type,
+ * second parameter of type {@code int} and with {@code int} as its return type,
+ * or if {@code labels} contains an element that is not of type {@code String},
+ * {@code Integer} or {@code Class}.
+ * @throws Throwable if there is any error linking the call site
+ * @jvms 4.4.6 The CONSTANT_NameAndType_info Structure
+ * @jvms 4.4.10 The CONSTANT_Dynamic_info and CONSTANT_InvokeDynamic_info Structures
+ */
+ public static CallSite typeSwitch(MethodHandles.Lookup lookup,
+ String invocationName,
+ MethodType invocationType,
+ Object... labels) throws Throwable {
+ if (invocationType.parameterCount() != 2
+ || (!invocationType.returnType().equals(int.class))
+ || invocationType.parameterType(0).isPrimitive()
+ || !invocationType.parameterType(1).equals(int.class))
+ throw new IllegalArgumentException("Illegal invocation type " + invocationType);
+ requireNonNull(labels);
+
+ labels = labels.clone();
+ Stream.of(labels).forEach(SwitchBootstraps::verifyLabel);
+
+ MethodHandle target = MethodHandles.insertArguments(DO_SWITCH, 2, (Object) labels);
+ return new ConstantCallSite(target);
+ }
+
+ private static void verifyLabel(Object label) {
+ if (label == null) {
+ throw new IllegalArgumentException("null label found");
+ }
+ Class> labelClass = label.getClass();
+ if (labelClass != Class.class &&
+ labelClass != String.class &&
+ labelClass != Integer.class) {
+ throw new IllegalArgumentException("label with illegal type found: " + label.getClass());
+ }
+ }
+
+ private static int doSwitch(Object target, int startIndex, Object[] labels) {
+ if (target == null)
+ return -1;
+
+ // Dumbest possible strategy
+ Class> targetClass = target.getClass();
+ for (int i = startIndex; i < labels.length; i++) {
+ Object label = labels[i];
+ if (label instanceof Class> c) {
+ if (c.isAssignableFrom(targetClass))
+ return i;
+ } else if (label instanceof Integer constant) {
+ if (target instanceof Number input && constant.intValue() == input.intValue()) {
+ return i;
+ } else if (target instanceof Character input && constant.intValue() == input.charValue()) {
+ return i;
+ }
+ } else if (label.equals(target)) {
+ return i;
+ }
+ }
+
+ return labels.length;
+ }
+
+}
diff --git a/src/java.base/share/classes/jdk/internal/javac/NoPreview.java b/src/java.base/share/classes/jdk/internal/javac/NoPreview.java
new file mode 100644
index 00000000000..0337d52752e
--- /dev/null
+++ b/src/java.base/share/classes/jdk/internal/javac/NoPreview.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2021, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package jdk.internal.javac;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * The element annotated with this annotation should not be marked as a preview element.
+ */
+@Target({ElementType.METHOD,
+ ElementType.CONSTRUCTOR,
+ ElementType.FIELD,
+ ElementType.PACKAGE,
+ ElementType.MODULE,
+ ElementType.TYPE})
+@Retention(RetentionPolicy.CLASS)
+public @interface NoPreview {
+}
diff --git a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java
index 6ec5eeae5ca..c11390d3937 100644
--- a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java
+++ b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java
@@ -58,6 +58,7 @@ public @interface PreviewFeature {
* This one can only be removed after JDK 17
*/
SEALED_CLASSES,
+ SWITCH_PATTERN_MATCHING,
/**
* A key for testing.
*/
diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/CaseLabelTree.java b/src/jdk.compiler/share/classes/com/sun/source/tree/CaseLabelTree.java
new file mode 100644
index 00000000000..422e7575c74
--- /dev/null
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/CaseLabelTree.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2021, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package com.sun.source.tree;
+
+import jdk.internal.javac.PreviewFeature;
+
+/**
+ * A marker interface for {@code Tree}s that may be used as {@link CaseTree} labels.
+ *
+ * @since 17
+ */
+@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
+public interface CaseLabelTree extends Tree {}
diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/CaseTree.java b/src/jdk.compiler/share/classes/com/sun/source/tree/CaseTree.java
index d3fbb6b2f30..0a25df0a856 100644
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/CaseTree.java
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/CaseTree.java
@@ -27,6 +27,8 @@ package com.sun.source.tree;
import java.util.List;
+import jdk.internal.javac.PreviewFeature;
+
/**
* A tree node for a {@code case} in a {@code switch} statement or expression.
*
@@ -65,6 +67,16 @@ public interface CaseTree extends Tree {
*/
List extends ExpressionTree> getExpressions();
+ /**
+ * Returns the labels for this case.
+ * For {@code default} case return a list with a single element, {@link DefaultCaseLabelTree}.
+ *
+ * @return labels for this case
+ * @since 17
+ */
+ @PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
+ List extends CaseLabelTree> getLabels();
+
/**
* For case with kind {@linkplain CaseKind#STATEMENT},
* returns the statements labeled by the case.
diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/DefaultCaseLabelTree.java b/src/jdk.compiler/share/classes/com/sun/source/tree/DefaultCaseLabelTree.java
new file mode 100644
index 00000000000..7cbe33b3fa0
--- /dev/null
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/DefaultCaseLabelTree.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2021, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+package com.sun.source.tree;
+
+import jdk.internal.javac.PreviewFeature;
+
+/**
+ * A case label that marks {@code default} in {@code case null, default}.
+ *
+ * @since 17
+ */
+@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
+public interface DefaultCaseLabelTree extends CaseLabelTree {}
diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/ExpressionTree.java b/src/jdk.compiler/share/classes/com/sun/source/tree/ExpressionTree.java
index bd6b17c4e0f..8377e853ffa 100644
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/ExpressionTree.java
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/ExpressionTree.java
@@ -25,6 +25,8 @@
package com.sun.source.tree;
+import jdk.internal.javac.NoPreview;
+
/**
* A tree node used as the base class for the different types of
* expressions.
@@ -35,4 +37,5 @@ package com.sun.source.tree;
* @author Jonathan Gibbons
* @since 1.6
*/
-public interface ExpressionTree extends Tree {}
+@NoPreview
+public interface ExpressionTree extends Tree, CaseLabelTree {}
diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/GuardedPatternTree.java b/src/jdk.compiler/share/classes/com/sun/source/tree/GuardedPatternTree.java
new file mode 100644
index 00000000000..75eba374e84
--- /dev/null
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/GuardedPatternTree.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2017, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package com.sun.source.tree;
+
+import jdk.internal.javac.PreviewFeature;
+
+/**
+ * A guard pattern tree.
+ *
+ * @since 17
+ */
+@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
+public interface GuardedPatternTree extends PatternTree {
+
+ /**
+ * The guarded pattern expression.
+ * @return the guarded pattern
+ */
+ public PatternTree getPattern();
+
+ /**
+ * The guard expression.
+ * @return the guard expression
+ */
+ public ExpressionTree getExpression();
+
+}
diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/ParenthesizedPatternTree.java b/src/jdk.compiler/share/classes/com/sun/source/tree/ParenthesizedPatternTree.java
new file mode 100644
index 00000000000..ff4ebb7a16b
--- /dev/null
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/ParenthesizedPatternTree.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 2005, 2014, 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. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * 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.
+ */
+
+package com.sun.source.tree;
+
+import jdk.internal.javac.PreviewFeature;
+
+/**
+ * A tree node for a parenthesized pattern.
+ *
+ * For example:
+ *
+ * ( pattern )
+ *
+ *
+ * @jls 14.30.1 Kinds of Patterns
+ *
+ * @since 17
+ */
+@PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
+public interface ParenthesizedPatternTree extends PatternTree {
+ /**
+ * Returns the pattern within the parentheses.
+ * @return the pattern
+ */
+ PatternTree getPattern();
+}
diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/PatternTree.java b/src/jdk.compiler/share/classes/com/sun/source/tree/PatternTree.java
index 283fa20e63a..c8c1b7ae9b1 100644
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/PatternTree.java
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/PatternTree.java
@@ -31,4 +31,4 @@ package com.sun.source.tree;
*
* @since 16
*/
-public interface PatternTree extends Tree {}
+public interface PatternTree extends Tree, CaseLabelTree {}
diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java b/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java
index 3a6cb0910c9..9de5bb7443f 100644
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/Tree.java
@@ -25,6 +25,8 @@
package com.sun.source.tree;
+import jdk.internal.javac.PreviewFeature;
+
/**
* Common interface for all nodes in an abstract syntax tree.
*
@@ -226,6 +228,30 @@ public interface Tree {
*/
BINDING_PATTERN(BindingPatternTree.class),
+ /**
+ * Used for instances of {@link GuardedPatternTree}.
+ *
+ * @since 17
+ */
+ @PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
+ GUARDED_PATTERN(GuardedPatternTree.class),
+
+ /**
+ * Used for instances of {@link ParenthesizedPatternTree}.
+ *
+ * @since 17
+ */
+ @PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
+ PARENTHESIZED_PATTERN(ParenthesizedPatternTree.class),
+
+ /**
+ * Used for instances of {@link DefaultCaseLabelTree}.
+ *
+ * @since 17
+ */
+ @PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
+ DEFAULT_CASE_LABEL(DefaultCaseLabelTree.class),
+
/**
* Used for instances of {@link PrimitiveTypeTree}.
*/
diff --git a/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java b/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java
index cbb6f720f20..b38ed112e93 100644
--- a/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java
+++ b/src/jdk.compiler/share/classes/com/sun/source/tree/TreeVisitor.java
@@ -25,6 +25,8 @@
package com.sun.source.tree;
+import jdk.internal.javac.PreviewFeature;
+
/**
* A visitor of trees, in the style of the visitor design pattern.
* Classes implementing this interface are used to operate
@@ -266,6 +268,16 @@ public interface TreeVisitor {
*/
R visitBindingPattern(BindingPatternTree node, P p);
+ /**
+ * Visits a DefaultCaseLabelTree node.
+ * @param node the node being visited
+ * @param p a parameter value
+ * @return a result value
+ * @since 17
+ */
+ @PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
+ R visitDefaultCaseLabel(DefaultCaseLabelTree node, P p);
+
/**
* Visits a MethodTree node.
* @param node the node being visited
@@ -290,6 +302,26 @@ public interface TreeVisitor {
*/
R visitNewArray(NewArrayTree node, P p);
+ /**
+ * Visits a GuardPatternTree node.
+ * @param node the node being visited
+ * @param p a parameter value
+ * @return a result value
+ * @since 17
+ */
+ @PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
+ R visitGuardedPattern(GuardedPatternTree node, P p);
+
+ /**
+ * Visits a ParenthesizedPatternTree node.
+ * @param node the node being visited
+ * @param p a parameter value
+ * @return a result value
+ * @since 17
+ */
+ @PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
+ R visitParenthesizedPattern(ParenthesizedPatternTree node, P p);
+
/**
* Visits a NewClassTree node.
* @param node the node being visited
diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java b/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java
index 03ff696a980..89a1fe2c9fc 100644
--- a/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/SimpleTreeVisitor.java
@@ -26,6 +26,7 @@
package com.sun.source.util;
import com.sun.source.tree.*;
+import jdk.internal.javac.PreviewFeature;
/**
* A simple visitor for tree nodes.
@@ -564,6 +565,20 @@ public class SimpleTreeVisitor implements TreeVisitor {
return defaultAction(node, p);
}
+ /**
+ * {@inheritDoc} This implementation calls {@code defaultAction}.
+ *
+ * @param node {@inheritDoc}
+ * @param p {@inheritDoc}
+ * @return the result of {@code defaultAction}
+ * @since 17
+ */
+ @Override
+ @PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
+ public R visitDefaultCaseLabel(DefaultCaseLabelTree node, P p) {
+ return defaultAction(node, p);
+ }
+
/**
* {@inheritDoc} This implementation calls {@code defaultAction}.
*
@@ -588,6 +603,34 @@ public class SimpleTreeVisitor implements TreeVisitor {
return defaultAction(node, p);
}
+ /**
+ * {@inheritDoc} This implementation calls {@code defaultAction}.
+ *
+ * @param node {@inheritDoc}
+ * @param p {@inheritDoc}
+ * @return the result of {@code defaultAction}
+ * @since 17
+ */
+ @Override
+ @PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
+ public R visitParenthesizedPattern(ParenthesizedPatternTree node, P p) {
+ return defaultAction(node, p);
+ }
+
+ /**
+ * {@inheritDoc} This implementation calls {@code defaultAction}.
+ *
+ * @param node {@inheritDoc}
+ * @param p {@inheritDoc}
+ * @return the result of {@code defaultAction}
+ * @since 17
+ */
+ @Override
+ @PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
+ public R visitGuardedPattern(GuardedPatternTree node, P p) {
+ return defaultAction(node, p);
+ }
+
/**
* {@inheritDoc} This implementation calls {@code defaultAction}.
*
diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java b/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java
index dc4295fb96b..8ffbccb578a 100644
--- a/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/TreeScanner.java
@@ -26,6 +26,7 @@
package com.sun.source.util;
import com.sun.source.tree.*;
+import jdk.internal.javac.PreviewFeature;
/**
* A TreeVisitor that visits all the child tree nodes.
@@ -695,6 +696,20 @@ public class TreeScanner implements TreeVisitor {
return scan(node.getVariable(), p);
}
+ /**
+ * {@inheritDoc} This implementation returns {@code null}.
+ *
+ * @param node {@inheritDoc}
+ * @param p {@inheritDoc}
+ * @return the result of scanning
+ * @since 17
+ */
+ @Override
+ @PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
+ public R visitDefaultCaseLabel(DefaultCaseLabelTree node, P p) {
+ return null;
+ }
+
/**
* {@inheritDoc} This implementation scans the children in left to right order.
*
@@ -721,6 +736,35 @@ public class TreeScanner implements TreeVisitor {
return scan(node.getExpression(), p);
}
+ /**
+ * {@inheritDoc} This implementation scans the children in left to right order.
+ *
+ * @param node {@inheritDoc}
+ * @param p {@inheritDoc}
+ * @return the result of scanning
+ * @since 17
+ */
+ @Override
+ @PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
+ public R visitParenthesizedPattern(ParenthesizedPatternTree node, P p) {
+ return scan(node.getPattern(), p);
+ }
+
+ /**
+ * {@inheritDoc} This implementation scans the children in left to right order.
+ *
+ * @param node {@inheritDoc}
+ * @param p {@inheritDoc}
+ * @return the result of scanning
+ * @since 17
+ */
+ @Override
+ @PreviewFeature(feature=PreviewFeature.Feature.SWITCH_PATTERN_MATCHING, reflective=true)
+ public R visitGuardedPattern(GuardedPatternTree node, P p) {
+ R r = scan(node.getPattern(), p);
+ return scanAndReduce(node.getExpression(), p, r);
+ }
+
/**
* {@inheritDoc} This implementation scans the children in left to right order.
*
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java
index b9efac8113f..1e5052e6da5 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Preview.java
@@ -50,6 +50,7 @@ import static com.sun.tools.javac.code.Flags.RECORD;
import static com.sun.tools.javac.code.Flags.SEALED;
import static com.sun.tools.javac.code.Flags.NON_SEALED;
import static com.sun.tools.javac.main.Option.PREVIEW;
+import com.sun.tools.javac.util.JCDiagnostic;
/**
* Helper class to handle preview language features. This class maps certain language features
@@ -79,6 +80,7 @@ public class Preview {
private final Lint lint;
private final Log log;
+ private final Source source;
private static final Context.Key previewKey = new Context.Key<>();
@@ -96,7 +98,7 @@ public class Preview {
enabled = options.isSet(PREVIEW);
log = Log.instance(context);
lint = Lint.instance(context);
- Source source = Source.instance(context);
+ source = Source.instance(context);
this.previewHandler =
new MandatoryWarningHandler(log, source, lint.isEnabled(LintCategory.PREVIEW), true, "preview", LintCategory.PREVIEW);
forcePreview = options.isSet("forcePreview");
@@ -183,6 +185,9 @@ public class Preview {
*/
public boolean isPreview(Feature feature) {
return switch (feature) {
+ case CASE_NULL -> true;
+ case PATTERN_SWITCH -> true;
+
//Note: this is a backdoor which allows to optionally treat all features as 'preview' (for testing).
//When real preview features will be added, this method can be implemented to return 'true'
//for those selected features, and 'false' for all the others.
@@ -236,4 +241,19 @@ public class Preview {
previewHandler.clear();
}
+ public void checkSourceLevel(DiagnosticPosition pos, Feature feature) {
+ if (isPreview(feature) && !isEnabled()) {
+ //preview feature without --preview flag, error
+ log.error(JCDiagnostic.DiagnosticFlag.SOURCE_LEVEL, pos, disabledError(feature));
+ } else {
+ if (!feature.allowedInSource(source)) {
+ log.error(JCDiagnostic.DiagnosticFlag.SOURCE_LEVEL, pos,
+ feature.error(source.name));
+ }
+ if (isEnabled() && isPreview(feature)) {
+ warnPreview(pos, feature);
+ }
+ }
+ }
+
}
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java
index b39b7bbe358..07969019104 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java
@@ -224,6 +224,8 @@ public enum Source {
REIFIABLE_TYPES_INSTANCEOF(JDK16, Fragments.FeatureReifiableTypesInstanceof, DiagKind.PLURAL),
RECORDS(JDK16, Fragments.FeatureRecords, DiagKind.PLURAL),
SEALED_CLASSES(JDK17, Fragments.FeatureSealedClasses, DiagKind.PLURAL),
+ CASE_NULL(JDK17, Fragments.FeatureCaseNull, DiagKind.NORMAL),
+ PATTERN_SWITCH(JDK17, Fragments.FeaturePatternSwitch, DiagKind.PLURAL),
REDUNDANT_STRICTFP(JDK17),
;
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
index af9f1aeebea..cf68737af40 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symtab.java
@@ -220,6 +220,7 @@ public class Symtab {
public final Type previewFeatureInternalType;
public final Type typeDescriptorType;
public final Type recordType;
+ public final Type switchBootstrapsType;
public final Type valueBasedType;
/** The symbol representing the length field of an array.
@@ -585,6 +586,7 @@ public class Symtab {
previewFeatureInternalType = enterSyntheticAnnotation("jdk.internal.PreviewFeature+Annotation");
typeDescriptorType = enterClass("java.lang.invoke.TypeDescriptor");
recordType = enterClass("java.lang.Record");
+ switchBootstrapsType = enterClass("java.lang.runtime.SwitchBootstraps");
valueBasedType = enterClass("jdk.internal.ValueBased");
synthesizeEmptyInterfaceIfMissing(autoCloseableType);
diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
index 644b6f9ab24..6567e8a6cd2 100644
--- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
+++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java
@@ -1657,15 +1657,28 @@ public class Attr extends JCTree.Visitor {
boolean enumSwitch = (seltype.tsym.flags() & Flags.ENUM) != 0;
boolean stringSwitch = types.isSameType(seltype, syms.stringType);
boolean errorEnumSwitch = TreeInfo.isErrorEnumSwitch(selector, cases);
- if (!enumSwitch && !stringSwitch)
- seltype = chk.checkType(selector.pos(), seltype, syms.intType);
+ boolean patternSwitch;
+ if (!enumSwitch && !stringSwitch && !errorEnumSwitch &&
+ !types.isAssignable(seltype, syms.intType)) {
+ preview.checkSourceLevel(selector.pos(), Feature.PATTERN_SWITCH);
+ patternSwitch = true;
+ } else {
+ patternSwitch = cases.stream()
+ .flatMap(c -> c.labels.stream())
+ .anyMatch(l -> l.isPattern());
+ }
// Attribute all cases and
// check that there are no duplicate case labels or default clauses.
Set