8341408: Implement JEP 488: Primitive Types in Patterns, instanceof, and switch (Second Preview)
Reviewed-by: vromero, jlahoda
This commit is contained in:
parent
72a45ddbad
commit
6811a11e27
@ -199,7 +199,27 @@ public class TransPatterns extends TreeTranslator {
|
||||
|
||||
@Override
|
||||
public void visitTypeTest(JCInstanceOf tree) {
|
||||
if (tree.pattern instanceof JCPattern pattern) {
|
||||
// Translates regular instanceof type operation to instanceof pattern operator when
|
||||
// the expression was originally T but was subsequently erased to Object.
|
||||
//
|
||||
// $expr instanceof $primitiveType
|
||||
// =>
|
||||
// $expr instanceof T $temp && $temp instanceof $primitiveType
|
||||
if (tree.erasedExprOriginalType!=null && !types.isSameType(tree.expr.type, tree.erasedExprOriginalType)) {
|
||||
BindingSymbol temp = new BindingSymbol(Flags.FINAL | Flags.SYNTHETIC,
|
||||
names.fromString("temp" + variableIndex++ + target.syntheticNameChar()),
|
||||
tree.erasedExprOriginalType,
|
||||
currentMethodSym);
|
||||
|
||||
JCVariableDecl tempDecl = make.at(tree.pos()).VarDef(temp, null);
|
||||
|
||||
JCTree resultExpr =
|
||||
makeBinary(Tag.AND,
|
||||
make.TypeTest(tree.expr, make.BindingPattern(tempDecl).setType(tree.erasedExprOriginalType)).setType(syms.booleanType),
|
||||
make.TypeTest(make.Ident(tempDecl), tree.pattern).setType(syms.booleanType));
|
||||
|
||||
result = translate(resultExpr);
|
||||
} else if (tree.pattern instanceof JCPattern pattern) {
|
||||
//first, resolve any record patterns:
|
||||
JCExpression extraConditions = null;
|
||||
if (pattern instanceof JCRecordPattern recordPattern) {
|
||||
|
@ -813,8 +813,7 @@ public class TransTypes extends TreeTranslator {
|
||||
Type selsuper = types.supertype(tree.selector.type);
|
||||
boolean enumSwitch = selsuper != null &&
|
||||
selsuper.tsym == syms.enumSym;
|
||||
Type target = enumSwitch ? erasure(tree.selector.type) : syms.intType;
|
||||
tree.selector = translate(tree.selector, target);
|
||||
tree.selector = translate(tree.selector, erasure(tree.selector.type));
|
||||
tree.cases = translateCases(tree.cases);
|
||||
result = tree;
|
||||
}
|
||||
@ -852,8 +851,7 @@ public class TransTypes extends TreeTranslator {
|
||||
Type selsuper = types.supertype(tree.selector.type);
|
||||
boolean enumSwitch = selsuper != null &&
|
||||
selsuper.tsym == syms.enumSym;
|
||||
Type target = enumSwitch ? erasure(tree.selector.type) : syms.intType;
|
||||
tree.selector = translate(tree.selector, target);
|
||||
tree.selector = translate(tree.selector, erasure(tree.selector.type));
|
||||
tree.cases = translate(tree.cases, tree.type);
|
||||
tree.type = erasure(tree.type);
|
||||
result = retype(tree, tree.type, pt);
|
||||
@ -1067,8 +1065,14 @@ public class TransTypes extends TreeTranslator {
|
||||
}
|
||||
|
||||
public void visitTypeTest(JCInstanceOf tree) {
|
||||
tree.expr = translate(tree.expr, null);
|
||||
tree.pattern = translate(tree.pattern, null);
|
||||
if (tree.pattern.type.isPrimitive()) {
|
||||
tree.erasedExprOriginalType = erasure(tree.expr.type);
|
||||
tree.expr = translate(tree.expr, null);
|
||||
}
|
||||
else {
|
||||
tree.expr = translate(tree.expr, null);
|
||||
}
|
||||
result = tree;
|
||||
}
|
||||
|
||||
|
@ -2272,6 +2272,8 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
||||
/**{@code true} if this instanceof test should have
|
||||
* value {@code true} when the {@code expr} is {@code null}.*/
|
||||
public boolean allowNull;
|
||||
public Type erasedExprOriginalType;
|
||||
|
||||
protected JCInstanceOf(JCExpression expr, JCTree pattern) {
|
||||
this.expr = expr;
|
||||
this.pattern = pattern;
|
||||
|
@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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 8341408
|
||||
* @summary Compiler Implementation for Primitive types in patterns, instanceof, and switch (Second Preview)
|
||||
* @enablePreview
|
||||
*/
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PrimitiveTypesInTestingContextErasure {
|
||||
public static void main(String[] args) {
|
||||
erasureSwitch();
|
||||
erasureInstanceofTypeComparisonOperator();
|
||||
erasureInstanceofPatternMatchingOperator();
|
||||
|
||||
pollutedInstanceofPatternMatchingOperatorReference();
|
||||
pollutedInstanceofPatternMatchingOperator();
|
||||
pollutedInstanceofTypeComparisonOperator();
|
||||
pollutedSwitch();
|
||||
}
|
||||
|
||||
public static void erasureSwitch() {
|
||||
List<Short> ls = List.of((short) 42);
|
||||
Short s = 42;
|
||||
|
||||
assertTrue(switch(ls.get(0)) {
|
||||
case int _ -> true; // Short to int
|
||||
default -> false;
|
||||
});
|
||||
}
|
||||
|
||||
public static void erasureInstanceofTypeComparisonOperator() {
|
||||
List<Short> ls = List.of((short) 42);
|
||||
|
||||
assertTrue(ls.get(0) instanceof int); // Short to int
|
||||
}
|
||||
|
||||
public static void erasureInstanceofPatternMatchingOperator() {
|
||||
List<Short> ls = List.of((short) 42);
|
||||
|
||||
assertTrue(ls.get(0) instanceof int i); // Short to int
|
||||
}
|
||||
|
||||
public static void pollutedInstanceofPatternMatchingOperator() {
|
||||
List<Short> ls = (List) List.of("42");
|
||||
|
||||
assertTrue(!(ls.get(0) instanceof int i));
|
||||
}
|
||||
|
||||
public static void pollutedInstanceofTypeComparisonOperator() {
|
||||
List<Short> ls = (List) List.of("42");
|
||||
|
||||
assertTrue(!(ls.get(0) instanceof int));
|
||||
}
|
||||
|
||||
public static void pollutedInstanceofPatternMatchingOperatorReference() {
|
||||
List<Short> ls = (List) List.of("42");
|
||||
|
||||
assertTrue(!(ls.get(0) instanceof Short));
|
||||
}
|
||||
|
||||
public static void pollutedSwitch() {
|
||||
List<Short> ls = (List) List.of("42");
|
||||
|
||||
try {
|
||||
var res = switch(ls.get(0)) {
|
||||
case int _ -> true;
|
||||
default -> false;
|
||||
};
|
||||
throw new AssertionError("Expected: ClassCastException");
|
||||
} catch (ClassCastException e) {
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
static void assertTrue(boolean actual) {
|
||||
if (!actual) {
|
||||
throw new AssertionError("Expected: true, but got false");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user