8339296: Record deconstruction pattern in switch fails to compile
Reviewed-by: vromero, mcimadamore
This commit is contained in:
parent
e96b4cf0a8
commit
f0b130e54f
@ -51,7 +51,6 @@ import com.sun.tools.javac.code.Type.ErrorType;
|
||||
import com.sun.tools.javac.code.Type.JCPrimitiveType;
|
||||
import com.sun.tools.javac.code.Type.JCVoidType;
|
||||
import com.sun.tools.javac.code.Type.MethodType;
|
||||
import com.sun.tools.javac.code.Type.UnknownType;
|
||||
import com.sun.tools.javac.code.Types.UniqueType;
|
||||
import com.sun.tools.javac.comp.Modules;
|
||||
import com.sun.tools.javac.jvm.Target;
|
||||
@ -408,9 +407,6 @@ public class Symtab {
|
||||
|
||||
names = Names.instance(context);
|
||||
|
||||
// Create the unknown type
|
||||
unknownType = new UnknownType();
|
||||
|
||||
messages = JavacMessages.instance(context);
|
||||
|
||||
MissingInfoHandler missingInfoHandler = MissingInfoHandler.instance(context);
|
||||
@ -483,8 +479,8 @@ public class Symtab {
|
||||
errType = new ErrorType(errSymbol, Type.noType);
|
||||
|
||||
unknownSymbol = new ClassSymbol(PUBLIC|STATIC|ACYCLIC, names.fromString("<any?>"), null, rootPackage);
|
||||
unknownSymbol.members_field = new Scope.ErrorScope(unknownSymbol);
|
||||
unknownSymbol.type = unknownType;
|
||||
// Create the unknown type
|
||||
unknownType = new ErrorType(unknownSymbol, Type.noType);
|
||||
|
||||
// initialize builtin types
|
||||
initType(byteType, "byte", "Byte");
|
||||
|
@ -2408,30 +2408,6 @@ public abstract class Type extends AnnoConstruct implements TypeMirror, PoolCons
|
||||
}
|
||||
}
|
||||
|
||||
public static class UnknownType extends Type {
|
||||
|
||||
public UnknownType() {
|
||||
// Unknown is a synthesized internal type, so it cannot be
|
||||
// annotated.
|
||||
super(null, List.nil());
|
||||
}
|
||||
|
||||
@Override
|
||||
public TypeTag getTag() {
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
@Override @DefinedBy(Api.LANGUAGE_MODEL)
|
||||
public <R, P> R accept(TypeVisitor<R, P> v, P p) {
|
||||
return v.visitUnknown(this, p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPartial() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A visitor for types. A visitor is used to implement operations
|
||||
* (or relations) on types. Most common operations on types are
|
||||
|
@ -121,10 +121,6 @@ public enum TypeTag {
|
||||
*/
|
||||
ERROR,
|
||||
|
||||
/** The tag of an unknown type
|
||||
*/
|
||||
UNKNOWN,
|
||||
|
||||
/** The tag of all instantiatable type variables.
|
||||
*/
|
||||
UNDETVAR,
|
||||
|
@ -1216,7 +1216,7 @@ public class Types {
|
||||
@Override
|
||||
public Boolean visitUndetVar(UndetVar t, Type s) {
|
||||
//todo: test against origin needed? or replace with substitution?
|
||||
if (t == s || t.qtype == s || s.hasTag(ERROR) || s.hasTag(UNKNOWN)) {
|
||||
if (t == s || t.qtype == s || s.hasTag(ERROR)) {
|
||||
return true;
|
||||
} else if (s.hasTag(BOT)) {
|
||||
//if 's' is 'null' there's no instantiated type U for which
|
||||
@ -1466,7 +1466,7 @@ public class Types {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (t == s || t.qtype == s || s.hasTag(ERROR) || s.hasTag(UNKNOWN)) {
|
||||
if (t == s || t.qtype == s || s.hasTag(ERROR)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2422,7 +2422,7 @@ public class Types {
|
||||
ARRAY, MODULE, TYPEVAR, WILDCARD, BOT:
|
||||
return s.dropMetadata(Annotations.class);
|
||||
case VOID, METHOD, PACKAGE, FORALL, DEFERRED,
|
||||
NONE, ERROR, UNKNOWN, UNDETVAR, UNINITIALIZED_THIS,
|
||||
NONE, ERROR, UNDETVAR, UNINITIALIZED_THIS,
|
||||
UNINITIALIZED_OBJECT:
|
||||
return s;
|
||||
default:
|
||||
|
@ -28,7 +28,7 @@ import java.util.function.Function;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8262891 8268333 8268896 8269802 8269808 8270151 8269113 8277864 8290709
|
||||
* @bug 8262891 8268333 8268896 8269802 8269808 8270151 8269113 8277864 8290709 8339296
|
||||
* @summary Check behavior of pattern switches.
|
||||
*/
|
||||
public class Switches {
|
||||
@ -117,6 +117,9 @@ public class Switches {
|
||||
assertEquals(0, constantAndPatternGuardEnum(E.B, true));
|
||||
assertEquals(1, constantAndPatternGuardEnum(E.B, false));
|
||||
assertEquals(2, constantAndPatternGuardEnum(E.A, false));
|
||||
assertEquals(0, nestedSwitchesInArgumentPosition(1));
|
||||
assertEquals(1, nestedSwitchesInArgumentPosition(new R(1)));
|
||||
assertEquals(5, nestedSwitchesInArgumentPosition(new R(new R("hello"))));
|
||||
}
|
||||
|
||||
void run(Function<Object, Integer> mapper) {
|
||||
@ -749,6 +752,24 @@ public class Switches {
|
||||
};
|
||||
}
|
||||
|
||||
int nestedSwitchesInArgumentPosition(Object o1) {
|
||||
return id(switch (o1) {
|
||||
case R(var o2) -> switch (o2) {
|
||||
case R(String s) -> s;
|
||||
default -> "n";
|
||||
};
|
||||
default -> "";
|
||||
});
|
||||
}
|
||||
|
||||
int id(String s) {
|
||||
return s.length();
|
||||
}
|
||||
|
||||
int id(int i) {
|
||||
return i;
|
||||
}
|
||||
|
||||
//verify that for cases like:
|
||||
//case ConstantClassClash ->
|
||||
//ConstantClassClash is interpreted as a field, not as a class
|
||||
|
129
test/langtools/tools/javac/types/UnknownTypeTest.java
Normal file
129
test/langtools/tools/javac/types/UnknownTypeTest.java
Normal file
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* 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 8339296
|
||||
* @summary Verify that the UnknownType behaves as an erroneous type
|
||||
* @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
|
||||
* @run main UnknownTypeTest
|
||||
*/
|
||||
|
||||
import com.sun.tools.javac.code.Type;
|
||||
import com.sun.tools.javac.code.Symtab;
|
||||
import com.sun.tools.javac.code.Type.TypeVar;
|
||||
import com.sun.tools.javac.code.Type.UnionClassType;
|
||||
import com.sun.tools.javac.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
public class UnknownTypeTest extends TypeHarness {
|
||||
|
||||
private final Type error;
|
||||
private final Type unknown;
|
||||
private final Type[] testTypes;
|
||||
private final Operation[] testOperations;
|
||||
|
||||
UnknownTypeTest() {
|
||||
Symtab syms = Symtab.instance(context);
|
||||
error = syms.errType;
|
||||
unknown = syms.unknownType;
|
||||
testTypes = new Type[] {
|
||||
syms.objectType,
|
||||
syms.errType,
|
||||
syms.unknownType,
|
||||
new TypeVar(syms.unknownSymbol, syms.objectType, syms.objectType),
|
||||
types.makeIntersectionType(List.of(syms.annotationType, syms.stringType)),
|
||||
new UnionClassType((Type.ClassType) syms.annotationType, List.of(syms.stringType)),
|
||||
syms.intType,
|
||||
types.makeArrayType(syms.stringType)
|
||||
};
|
||||
testOperations = new Operation[] {
|
||||
types::containedBy,
|
||||
types::containsType,
|
||||
types::isAssignable,
|
||||
types::isCastable,
|
||||
types::isConvertible,
|
||||
types::isSameType,
|
||||
types::isSubtype,
|
||||
types::isSuperType,
|
||||
types::isUnconditionallyExact,
|
||||
(t1, _) -> types.isArray(t1),
|
||||
(t1, _) -> types.isDerivedRaw(t1),
|
||||
(t1, _) -> types.isReifiable(t1),
|
||||
(t1, _) -> types.isUnbounded(t1),
|
||||
(t1, _) -> types.boxedTypeOrType(t1),
|
||||
(t1, _) -> types.unboxedType(t1),
|
||||
(t1, _) -> types.unboxedTypeOrType(t1),
|
||||
};
|
||||
}
|
||||
|
||||
void test(Type[] testTypes, Operation[] testOperations) {
|
||||
for (int typeIndex = 0; typeIndex < testTypes.length ; typeIndex++) {
|
||||
for (int operationIndex = 0; operationIndex < testOperations.length ; operationIndex++) {
|
||||
Object expected;
|
||||
Object actual;
|
||||
expected = testOperations[operationIndex].run(error, testTypes[typeIndex]);
|
||||
actual = testOperations[operationIndex].run(unknown, testTypes[typeIndex]);
|
||||
checkEquals("Type index: " + typeIndex + ", operationIndex: " + operationIndex + ", unknown in the first position", expected, actual);
|
||||
expected = testOperations[operationIndex].run(testTypes[typeIndex], error);
|
||||
actual = testOperations[operationIndex].run(testTypes[typeIndex], unknown);
|
||||
checkEquals("Type index: " + typeIndex + ", operationIndex: " + operationIndex + ", unknown in the second position", expected, actual);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void checkEquals(String message, Object expected, Object actual) {
|
||||
boolean matches;
|
||||
|
||||
if (expected instanceof Type t1 && actual instanceof Type t2) {
|
||||
matches = types.isSameType(t1, t2);
|
||||
} else {
|
||||
matches = Objects.equals(expected, actual);
|
||||
}
|
||||
|
||||
if (!matches) {
|
||||
throw new AssertionError("Unexpected outcome: " + actual +
|
||||
", expected: " + expected +
|
||||
", for test: " + message);
|
||||
}
|
||||
}
|
||||
|
||||
void runTests() {
|
||||
test(testTypes, testOperations);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
new UnknownTypeTest().runTests();
|
||||
}
|
||||
|
||||
interface Operation {
|
||||
public Object run(Type t1, Type t2);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user