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
|
@Override
|
||||||
public void visitTypeTest(JCInstanceOf tree) {
|
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:
|
//first, resolve any record patterns:
|
||||||
JCExpression extraConditions = null;
|
JCExpression extraConditions = null;
|
||||||
if (pattern instanceof JCRecordPattern recordPattern) {
|
if (pattern instanceof JCRecordPattern recordPattern) {
|
||||||
|
@ -813,8 +813,7 @@ public class TransTypes extends TreeTranslator {
|
|||||||
Type selsuper = types.supertype(tree.selector.type);
|
Type selsuper = types.supertype(tree.selector.type);
|
||||||
boolean enumSwitch = selsuper != null &&
|
boolean enumSwitch = selsuper != null &&
|
||||||
selsuper.tsym == syms.enumSym;
|
selsuper.tsym == syms.enumSym;
|
||||||
Type target = enumSwitch ? erasure(tree.selector.type) : syms.intType;
|
tree.selector = translate(tree.selector, erasure(tree.selector.type));
|
||||||
tree.selector = translate(tree.selector, target);
|
|
||||||
tree.cases = translateCases(tree.cases);
|
tree.cases = translateCases(tree.cases);
|
||||||
result = tree;
|
result = tree;
|
||||||
}
|
}
|
||||||
@ -852,8 +851,7 @@ public class TransTypes extends TreeTranslator {
|
|||||||
Type selsuper = types.supertype(tree.selector.type);
|
Type selsuper = types.supertype(tree.selector.type);
|
||||||
boolean enumSwitch = selsuper != null &&
|
boolean enumSwitch = selsuper != null &&
|
||||||
selsuper.tsym == syms.enumSym;
|
selsuper.tsym == syms.enumSym;
|
||||||
Type target = enumSwitch ? erasure(tree.selector.type) : syms.intType;
|
tree.selector = translate(tree.selector, erasure(tree.selector.type));
|
||||||
tree.selector = translate(tree.selector, target);
|
|
||||||
tree.cases = translate(tree.cases, tree.type);
|
tree.cases = translate(tree.cases, tree.type);
|
||||||
tree.type = erasure(tree.type);
|
tree.type = erasure(tree.type);
|
||||||
result = retype(tree, tree.type, pt);
|
result = retype(tree, tree.type, pt);
|
||||||
@ -1067,8 +1065,14 @@ public class TransTypes extends TreeTranslator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void visitTypeTest(JCInstanceOf tree) {
|
public void visitTypeTest(JCInstanceOf tree) {
|
||||||
tree.expr = translate(tree.expr, null);
|
|
||||||
tree.pattern = translate(tree.pattern, 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;
|
result = tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2272,6 +2272,8 @@ public abstract class JCTree implements Tree, Cloneable, DiagnosticPosition {
|
|||||||
/**{@code true} if this instanceof test should have
|
/**{@code true} if this instanceof test should have
|
||||||
* value {@code true} when the {@code expr} is {@code null}.*/
|
* value {@code true} when the {@code expr} is {@code null}.*/
|
||||||
public boolean allowNull;
|
public boolean allowNull;
|
||||||
|
public Type erasedExprOriginalType;
|
||||||
|
|
||||||
protected JCInstanceOf(JCExpression expr, JCTree pattern) {
|
protected JCInstanceOf(JCExpression expr, JCTree pattern) {
|
||||||
this.expr = expr;
|
this.expr = expr;
|
||||||
this.pattern = pattern;
|
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