Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Arthanareeswaran2020-05-12 14:11:18 +0000
committerJay Arthanareeswaran2020-05-14 02:28:34 +0000
commit9295bf84c9dbff60af20ec946d9d9cb0c37008df (patch)
tree632a5bf867e6e7daee88e1add569fd1023c44597
parent53022ce4a0390470da9bbf2e286a2f79f50687fe (diff)
downloadeclipse.jdt.core-9295bf84c9dbff60af20ec946d9d9cb0c37008df.tar.gz
eclipse.jdt.core-9295bf84c9dbff60af20ec946d9d9cb0c37008df.tar.xz
eclipse.jdt.core-9295bf84c9dbff60af20ec946d9d9cb0c37008df.zip
Bug 562392 - [14] Type parameters should be allowed in instanceof
expressions from Java 14 Change-Id: Ib9587a26209337d3abf033d1be176b8f4be99da2 Signed-off-by: Jay Arthanareeswaran <jarthana@in.ibm.com>
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java2
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java38
-rw-r--r--org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching14Test.java206
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java4
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java12
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java32
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java28
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java16
-rw-r--r--org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties1
9 files changed, 298 insertions, 41 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
index 8b0005a744..4b629a8470 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/CompilerInvocationTests.java
@@ -1097,6 +1097,7 @@ public void test011_problem_categories() {
expectedProblemAttributes.put("UnqualifiedFieldAccess", new ProblemAttributes(CategorizedProblem.CAT_CODE_STYLE));
expectedProblemAttributes.put("UnreachableCatch", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("UnresolvedVariable", new ProblemAttributes(CategorizedProblem.CAT_MEMBER));
+ expectedProblemAttributes.put("UnsafeCast", new ProblemAttributes(CategorizedProblem.CAT_TYPE));
expectedProblemAttributes.put("UnsafeElementTypeConversion", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
expectedProblemAttributes.put("UnsafeGenericArrayForVarargs", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
expectedProblemAttributes.put("UnsafeGenericCast", new ProblemAttributes(CategorizedProblem.CAT_UNCHECKED_RAW));
@@ -2122,6 +2123,7 @@ public void test012_compiler_problems_tuning() {
expectedProblemAttributes.put("UnqualifiedFieldAccess", new ProblemAttributes(JavaCore.COMPILER_PB_UNQUALIFIED_FIELD_ACCESS));
expectedProblemAttributes.put("UnreachableCatch", SKIP);
expectedProblemAttributes.put("UnresolvedVariable", SKIP);
+ expectedProblemAttributes.put("UnsafeCast", SKIP);
expectedProblemAttributes.put("UnsafeElementTypeConversion", new ProblemAttributes(JavaCore.COMPILER_PB_UNCHECKED_TYPE_OPERATION));
expectedProblemAttributes.put("UnsafeGenericArrayForVarargs", new ProblemAttributes(JavaCore.COMPILER_PB_UNCHECKED_TYPE_OPERATION));
expectedProblemAttributes.put("UnsafeGenericCast", new ProblemAttributes(JavaCore.COMPILER_PB_UNCHECKED_TYPE_OPERATION));
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
index 9e73da19fe..47beae1a92 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/GenericTypeTest.java
@@ -1,5 +1,5 @@
/*******************************************************************************
- * Copyright (c) 2000, 2019 IBM Corporation and others.
+ * Copyright (c) 2000, 2020 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
@@ -5400,10 +5400,12 @@ public class GenericTypeTest extends AbstractComparableTest {
true,
customOptions);
}
- public void _test0178a() {
+ public void test0178a() {
if (this.complianceLevel < ClassFileConstants.JDK14)
return;
Map customOptions = getCompilerOptions();
+ customOptions.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.ENABLED);
+ customOptions.put(CompilerOptions.OPTION_ReportPreviewFeatures, CompilerOptions.WARNING);
this.runNegativeTest(
new String[] {
"X.java",
@@ -5419,7 +5421,7 @@ public class GenericTypeTest extends AbstractComparableTest {
" return t;\n" +
" } else if (t instanceof T) {\n" +
" return t;\n" +
- " } else if (t instanceof X) {\n" +
+ " } else if (t instanceof X) { // this is allowed since Java 14 as preview feature\n" +
" return t;\n" +
" }\n" +
" return null;\n" +
@@ -5429,13 +5431,33 @@ public class GenericTypeTest extends AbstractComparableTest {
"----------\n" +
"1. ERROR in X.java (at line 5)\n" +
" if (t instanceof X<T>) {\n" +
- " ^^^^^^^^^^^^^^\n" +
- "Type mismatch: cannot convert from T to X<T>\n" +
+ " ^\n" +
+ "Type T cannot be safely cast to X<T>\n" +
"----------\n" +
- "2. ERROR in X.java (at line 7)\n" +
+ "2. WARNING in X.java (at line 5)\n" +
+ " if (t instanceof X<T>) {\n" +
+ " ^\n" +
+ "You are using a preview language feature that may or may not be supported in a future release\n" +
+ "----------\n" +
+ "3. ERROR in X.java (at line 7)\n" +
" } else if (t instanceof X<String>) {\n" +
- " ^^^^^^^^^^^^^^\n" +
- "Type mismatch: cannot convert from T to X<String>\n" +
+ " ^\n" +
+ "Type T cannot be safely cast to X<String>\n" +
+ "----------\n" +
+ "4. WARNING in X.java (at line 7)\n" +
+ " } else if (t instanceof X<String>) {\n" +
+ " ^\n" +
+ "You are using a preview language feature that may or may not be supported in a future release\n" +
+ "----------\n" +
+ "5. WARNING in X.java (at line 11)\n" +
+ " } else if (t instanceof T) {\n" +
+ " ^^^^^^^^^^^^^^\n" +
+ "The expression of type T is already an instance of type T\n" +
+ "----------\n" +
+ "6. WARNING in X.java (at line 11)\n" +
+ " } else if (t instanceof T) {\n" +
+ " ^\n" +
+ "You are using a preview language feature that may or may not be supported in a future release\n" +
"----------\n",
null,
true,
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching14Test.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching14Test.java
index 9dc03a4a46..016414f1df 100644
--- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching14Test.java
+++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/PatternMatching14Test.java
@@ -24,7 +24,7 @@ public class PatternMatching14Test extends AbstractRegressionTest {
static {
// TESTS_NUMBERS = new int [] { 40 };
// TESTS_RANGE = new int[] { 1, -1 };
-// TESTS_NAMES = new String[] { "test005" };
+// TESTS_NAMES = new String[] { "testBug562392" };
}
public static Class<?> testClass() {
@@ -2045,7 +2045,7 @@ public class PatternMatching14Test extends AbstractRegressionTest {
compilerOptions);
compilerOptions.put(CompilerOptions.OPTION_PreserveUnusedLocal, old);
}
- public void _testBug562392a() {
+ public void testBug562392a() {
Map<String, String> compilerOptions = getCompilerOptions(true);
runConformTest(
new String[] {
@@ -2067,11 +2067,12 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"true",
compilerOptions);
}
- public void _testBug562392b() {
+ public void testBug562392b() {
Map<String, String> compilerOptions = getCompilerOptions(true);
runNegativeTest(
new String[] {
"X.java",
+ "@SuppressWarnings(\"preview\")\n" +
"public class X<T> {\n" +
" public boolean foo(Object obj) {\n" +
" if (obj instanceof T) {\n" +
@@ -2085,17 +2086,21 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"}\n",
},
"----------\n" +
- "1. ERROR in X.java (at line 3)\n" +
+ "1. ERROR in X.java (at line 4)\n" +
" if (obj instanceof T) {\n" +
- " ^^^^^^^^^^^^^^^^\n" +
- "Type mismatch: cannot convert from Object to T\n" +
+ " ^^^\n" +
+ "Type Object cannot be safely cast to T\n" +
"----------\n",
- "",
+ "X.java:4: error: Object cannot be safely cast to T\n" +
+ " if (obj instanceof T) {\n" +
+ " ^\n" +
+ " where T is a type-variable:\n" +
+ " T extends Object declared in class X",
null,
true,
compilerOptions);
}
- public void _testBug562392c() {
+ public void testBug562392c() {
Map<String, String> compilerOptions = getCompilerOptions(true);
runNegativeTest(
new String[] {
@@ -2116,15 +2121,19 @@ public class PatternMatching14Test extends AbstractRegressionTest {
"----------\n" +
"1. ERROR in X.java (at line 4)\n" +
" if (obj instanceof T t) {\n" +
- " ^^^^^^^^^^^^^^^^^^\n" +
- "Type mismatch: cannot convert from Object to T\n" +
+ " ^^^\n" +
+ "Type Object cannot be safely cast to T\n" +
"----------\n",
- "",
+ "X.java:4: error: Object cannot be safely cast to T\n" +
+ " if (obj instanceof T t) {\n" +
+ " ^\n" +
+ " where T is a type-variable:\n" +
+ " T extends Object declared in class X",
null,
true,
compilerOptions);
}
- public void _testBug562392d() {
+ public void testBug562392d() {
Map<String, String> compilerOptions = getCompilerOptions(true);
runConformTest(
new String[] {
@@ -2144,7 +2153,180 @@ public class PatternMatching14Test extends AbstractRegressionTest {
},
"",
compilerOptions);
+ }
+ public void testBug562392e() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "@SuppressWarnings(\"preview\")\n" +
+ "public class X<T> {\n" +
+ " public boolean foo(X<?> obj) {\n" +
+ " if (obj instanceof X<String> p) {\n" +
+ " return true;\n" +
+ " }\n" +
+ " return false;\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 4)\n" +
+ " if (obj instanceof X<String> p) {\n" +
+ " ^^^\n" +
+ "Type X<capture#1-of ?> cannot be safely cast to X<String>\n" +
+ "----------\n",
+ "",
+ null,
+ true,
+ compilerOptions);
+ }
+ public void testBug562392f() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "class Outer<T> {\n" +
+ " static class Inner<T> {\n" +
+ " }\n" +
+ "}\n" +
+ "@SuppressWarnings({\"preview\", \"rawtypes\"})\n" +
+ "class X<T> {\n" +
+ " public boolean foo(Outer.Inner obj) {\n" +
+ " if (obj instanceof Outer<?> p) {\n" +
+ " return true;\n" +
+ " }\n" +
+ " return false;\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 8)\n" +
+ " if (obj instanceof Outer<?> p) {\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Incompatible conditional operand types Outer.Inner and Outer<?>\n" +
+ "----------\n",
+ "",
+ null,
+ true,
+ compilerOptions);
+ }
+ public void testBug562392g() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runConformTest(
+ new String[] {
+ "X.java",
+ "class Outer<T> {\n" +
+ " static class Inner<T> {\n" +
+ " }\n" +
+ "}\n" +
+ "@SuppressWarnings({\"preview\", \"rawtypes\"})\n" +
+ "class X<T> {\n" +
+ " public boolean foo(Object obj) {\n" +
+ " if (obj instanceof Outer.Inner<?> p) {\n" +
+ " return true;\n" +
+ " }\n" +
+ " return false;\n" +
+ " }\n" +
+ " public static void main(String argv[]) {\n" +
+ " Outer.Inner inn = new Outer.Inner();\n" +
+ " System.out.println(new X<String>().foo(inn));\n" +
+ " }\n" +
+ "}\n",
+ },
+ "true",
+ compilerOptions);
+ }
+ public void testBug562392h() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runNegativeTest(
+ new String[] {
+ "X.java",
+ "@SuppressWarnings({\"preview\", \"rawtypes\"})\n" +
+ "public class X<T> {\n" +
+ " public boolean foo(X[] obj) {\n" +
+ " if (obj instanceof Object[] p) {\n" +
+ " return true;\n" +
+ " }\n" +
+ " return false;\n" +
+ " }\n" +
+ " public static void main(String argv[]) {\n" +
+ " Object[] param = {new X()};\n" +
+ " System.out.println(new X<String>().foo(param));\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in X.java (at line 11)\n" +
+ " System.out.println(new X<String>().foo(param));\n" +
+ " ^^^\n" +
+ "The method foo(X[]) in the type X<String> is not applicable for the arguments (Object[])\n" +
+ "----------\n",
+ "",
+ null,
+ true,
+ compilerOptions);
+ }
+ public void testBug562392i() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ String backup = compilerOptions.get(CompilerOptions.OPTION_EnablePreviews);
+ compilerOptions.put(CompilerOptions.OPTION_EnablePreviews, CompilerOptions.DISABLED);
+ try {
+ runNegativeTest(
+ new String[] {
+ "Test.java",
+ "import java.util.ArrayList;\n" +
+ "import java.util.List;\n" +
+ "import java.util.function.Function;\n" +
+ "import java.util.function.UnaryOperator;\n" +
+ "@SuppressWarnings({\"preview\"})\n" +
+ "public class Test<T> {\n" +
+ " public boolean foo(Function<ArrayList<T>, ArrayList<T>> obj) {\n" +
+ " if (obj instanceof UnaryOperator<? extends List<T>>) {\n" +
+ " return false;\n" +
+ " }\n" +
+ " return true;\n" +
+ " }\n" +
+ "}\n",
+ },
+ "----------\n" +
+ "1. ERROR in Test.java (at line 8)\n" +
+ " if (obj instanceof UnaryOperator<? extends List<T>>) {\n" +
+ " ^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n" +
+ "Cannot perform instanceof check against parameterized type UnaryOperator<? extends List<T>>. Use the form UnaryOperator<?> instead since further generic type information will be erased at runtime\n" +
+ "----------\n",
+ "",
+ null,
+ true,
+ compilerOptions);
+ } finally {
+ compilerOptions.put(CompilerOptions.OPTION_EnablePreviews, backup);
}
+ }
+ public void testBug562392j() {
+ Map<String, String> compilerOptions = getCompilerOptions(true);
+ runConformTest(
+ new String[] {
+ "Test.java",
+ "import java.util.ArrayList;\n" +
+ "import java.util.List;\n" +
+ "import java.util.function.Function;\n" +
+ "import java.util.function.UnaryOperator;\n" +
+ "@SuppressWarnings({\"preview\", \"rawtypes\"})\n" +
+ "public class Test<T> {\n" +
+ " public boolean foo(Function<ArrayList<T>, ArrayList<T>> obj) {\n" +
+ " if (obj instanceof UnaryOperator<? extends List<T>>) {\n" +
+ " return false;\n" +
+ " }\n" +
+ " return true;\n" +
+ " }\n" +
+ " public static void main(String argv[]) {\n" +
+ " System.out.println(\"\");\n" +
+ " }\n" +
+ "}\n",
+ },
+ "",
+ compilerOptions);
+ }
public void test053() {
Map<String, String> compilerOptions = getCompilerOptions(true);
runConformTest(
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
index 393226d08e..e9f48d34db 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/core/compiler/IProblem.java
@@ -702,6 +702,10 @@ void setSourceStart(int sourceStart);
/** @since 3.5 */
int ComparingIdentical = Internal + 211;
+ /** @since 3.22
+ * @noreference preview feature error */
+ int UnsafeCast = TypeRelated + 212;
+
int UnmatchedBracket = Syntax + Internal + 220;
int NoFieldOnBaseType = FieldRelated + 221;
int InvalidExpressionAsStatement = Syntax + Internal + 222;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
index 22cde62aaa..35f1d8a40b 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/ASTNode.java
@@ -99,14 +99,14 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
public final static int Bit4 = 0x8; // return type (operator) | first assignment to local (name ref,local decl) | undocumented empty block (block, type and method decl)
public final static int Bit5 = 0x10; // value for return (expression) | has all method bodies (unit) | supertype ref (type ref) | resolved (field decl)| name ref (yield result value)
public final static int Bit6 = 0x20; // depth (name ref, msg) | ignore need cast check (cast expression) | error in signature (method declaration/ initializer) | is recovered (annotation reference)
- public final static int Bit7 = 0x40; // depth (name ref, msg) | operator (operator) | need runtime checkcast (cast expression) | label used (labelStatement) | needFreeReturn (AbstractMethodDeclaration)
- public final static int Bit8 = 0x80; // depth (name ref, msg) | operator (operator) | unsafe cast (cast expression) | is default constructor (constructor declaration) | isElseStatementUnreachable (if statement)
+ public final static int Bit7 = 0x40; // depth (name ref, msg) | need runtime checkcast (cast expression) | label used (labelStatement) | needFreeReturn (AbstractMethodDeclaration)
+ public final static int Bit8 = 0x80; // depth (name ref, msg) | unsafe cast (cast expression) | is default constructor (constructor declaration) | isElseStatementUnreachable (if statement)
public final static int Bit9 = 0x100; // depth (name ref, msg) | operator (operator) | is local type (type decl) | isThenStatementUnreachable (if statement) | can be static
public final static int Bit10= 0x200; // depth (name ref, msg) | operator (operator) | is anonymous type (type decl) | is implicit constructor (constructor)
public final static int Bit11 = 0x400; // depth (name ref, msg) | operator (operator) | is member type (type decl)
public final static int Bit12 = 0x800; // depth (name ref, msg) | operator (operator) | has abstract methods (type decl)
- public final static int Bit13 = 0x1000; // depth (name ref, msg) | is secondary type (type decl)
- public final static int Bit14 = 0x2000; // strictly assigned (reference lhs) | discard enclosing instance (explicit constr call) | hasBeenGenerated (type decl)
+ public final static int Bit13 = 0x1000; // depth (name ref, msg) | operator (operator) | is secondary type (type decl)
+ public final static int Bit14 = 0x2000; // strictly assigned (reference lhs) | operator (operator) | discard enclosing instance (explicit constr call) | hasBeenGenerated (type decl)
public final static int Bit15 = 0x4000; // is unnecessary cast (expression) | is varargs (type ref) | isSubRoutineEscaping (try statement) | superAccess (javadoc allocation expression/javadoc message send/javadoc return statement)
public final static int Bit16 = 0x8000; // in javadoc comment (name ref, type ref, msg)
public final static int Bit17 = 0x10000; // compound assigned (reference lhs) | unchecked (msg, alloc, explicit constr call)
@@ -164,8 +164,8 @@ public abstract class ASTNode implements TypeConstants, TypeIds {
// for operators
public static final int ReturnTypeIDMASK = Bit1|Bit2|Bit3|Bit4;
- public static final int OperatorSHIFT = 6; // Bit7 -> Bit12
- public static final int OperatorMASK = Bit7|Bit8|Bit9|Bit10|Bit11|Bit12; // 6 bits for operator ID
+ public static final int OperatorSHIFT = 8; // Bit9 -> Bit14
+ public static final int OperatorMASK = Bit9|Bit10|Bit11|Bit12|Bit13|Bit14; // 6 bits for operator ID
// for binary expressions
public static final int IsReturnedValue = Bit5;
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
index aad157f6c1..38fa4fccbe 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/CastExpression.java
@@ -396,10 +396,16 @@ private static boolean preventsUnlikelyTypeWarning(TypeBinding castedType, TypeB
@Override
public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding expressionType, TypeBinding match, boolean isNarrowing) {
+ return CastExpression.checkUnsafeCast(this, scope, castType, expressionType, match, isNarrowing);
+}
+public static boolean checkUnsafeCast(Expression expression, Scope scope, TypeBinding castType, TypeBinding expressionType, TypeBinding match, boolean isNarrowing) {
+ // In case of expression being a InstanceOfExpression, this.resolvedType is null
+ // hence use the type of RHS of the instanceof operator
+ TypeBinding resolvedType = expression.resolvedType != null ? expression.resolvedType : castType;
if (TypeBinding.equalsEquals(match, castType)) {
- if (!isNarrowing && TypeBinding.equalsEquals(match, this.resolvedType.leafComponentType()) // do not tag as unnecessary when recursing through upper bounds
+ if (!isNarrowing && TypeBinding.equalsEquals(match, resolvedType.leafComponentType()) // do not tag as unnecessary when recursing through upper bounds
&& !(expressionType.isParameterizedType() && expressionType.isProvablyDistinct(castType))) {
- tagAsUnnecessaryCast(scope, castType);
+ expression.tagAsUnnecessaryCast(scope, castType);
}
return true;
}
@@ -414,7 +420,7 @@ public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding ex
case Binding.PARAMETERIZED_TYPE :
if (!castType.isReifiable()) {
if (match == null) { // unrelated types
- this.bits |= ASTNode.UnsafeCast;
+ expression.bits |= ASTNode.UnsafeCast;
return true;
}
switch (match.kind()) {
@@ -422,7 +428,7 @@ public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding ex
if (isNarrowing) {
// [JLS 5.5] T <: S
if (expressionType.isRawType() || !expressionType.isEquivalentTo(match)) {
- this.bits |= ASTNode.UnsafeCast;
+ expression.bits |= ASTNode.UnsafeCast;
return true;
}
// [JLS 5.5] S has no subtype X != T, such that |X| == |T|
@@ -433,7 +439,7 @@ public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding ex
TypeBinding[] castArguments = paramCastType.arguments;
int length = castArguments == null ? 0 : castArguments.length;
if (paramMatch.arguments == null || length > paramMatch.arguments.length) {
- this.bits |= ASTNode.UnsafeCast;
+ expression.bits |= ASTNode.UnsafeCast;
} else if ((paramCastType.tagBits & (TagBits.HasDirectWildcard|TagBits.HasTypeVariable)) != 0) {
// verify alternate cast type, substituting different type arguments
nextAlternateArgument: for (int i = 0; i < length; i++) {
@@ -451,7 +457,7 @@ public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding ex
LookupEnvironment environment = scope.environment();
ParameterizedTypeBinding alternateCastType = environment.createParameterizedType((ReferenceBinding)castType.erasure(), alternateArguments, castType.enclosingType());
if (TypeBinding.equalsEquals(alternateCastType.findSuperTypeOriginatingFrom(expressionType), match)) {
- this.bits |= ASTNode.UnsafeCast;
+ expression.bits |= ASTNode.UnsafeCast;
break;
}
}
@@ -460,18 +466,18 @@ public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding ex
} else {
// [JLS 5.5] T >: S
if (!match.isEquivalentTo(castType)) {
- this.bits |= ASTNode.UnsafeCast;
+ expression.bits |= ASTNode.UnsafeCast;
return true;
}
}
break;
case Binding.RAW_TYPE :
- this.bits |= ASTNode.UnsafeCast; // upcast since castType is known to be bound paramType
+ expression.bits |= ASTNode.UnsafeCast; // upcast since castType is known to be bound paramType
return true;
default :
if (isNarrowing){
// match is not parameterized or raw, then any other subtype of match will erase to |T|
- this.bits |= ASTNode.UnsafeCast;
+ expression.bits |= ASTNode.UnsafeCast;
return true;
}
break;
@@ -481,12 +487,12 @@ public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding ex
case Binding.ARRAY_TYPE :
TypeBinding leafType = castType.leafComponentType();
if (isNarrowing && (!leafType.isReifiable() || leafType.isTypeVariable())) {
- this.bits |= ASTNode.UnsafeCast;
+ expression.bits |= ASTNode.UnsafeCast;
return true;
}
break;
case Binding.TYPE_PARAMETER :
- this.bits |= ASTNode.UnsafeCast;
+ expression.bits |= ASTNode.UnsafeCast;
return true;
// (disabled) https://bugs.eclipse.org/bugs/show_bug.cgi?id=240807
// case Binding.TYPE :
@@ -496,8 +502,8 @@ public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding ex
// }
// break;
}
- if (!isNarrowing && TypeBinding.equalsEquals(match, this.resolvedType.leafComponentType())) { // do not tag as unnecessary when recursing through upper bounds
- tagAsUnnecessaryCast(scope, castType);
+ if (!isNarrowing && TypeBinding.equalsEquals(match, resolvedType.leafComponentType())) { // do not tag as unnecessary when recursing through upper bounds
+ expression.tagAsUnnecessaryCast(scope, castType);
}
return true;
}
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
index 3ca65a79e0..4ce3b690b4 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/ast/InstanceOfExpression.java
@@ -26,9 +26,12 @@ package org.eclipse.jdt.internal.compiler.ast;
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.ast.TypeReference.AnnotationPosition;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.codegen.*;
import org.eclipse.jdt.internal.compiler.flow.*;
+import org.eclipse.jdt.internal.compiler.impl.CompilerOptions;
import org.eclipse.jdt.internal.compiler.impl.Constant;
+import org.eclipse.jdt.internal.compiler.impl.IrritantSet;
import org.eclipse.jdt.internal.compiler.lookup.*;
public class InstanceOfExpression extends OperatorExpression {
@@ -176,7 +179,21 @@ public TypeBinding resolveType(BlockScope scope) {
return null;
if (!checkedType.isReifiable()) {
- scope.problemReporter().illegalInstanceOfGenericType(checkedType, this);
+ CompilerOptions options = scope.compilerOptions();
+ // If preview is disabled, report same as before, even at Java 14
+ if (options.complianceLevel < ClassFileConstants.JDK14 || !options.enablePreviewFeatures) {
+ scope.problemReporter().illegalInstanceOfGenericType(checkedType, this);
+ } else {
+ if (options.isAnyEnabled(IrritantSet.PREVIEW)) {
+ scope.problemReporter().previewFeatureUsed(this.type.sourceStart, this.type.sourceEnd);
+ }
+ if (expressionType != TypeBinding.NULL) {
+ boolean isLegal = checkCastTypesCompatibility(scope, checkedType, expressionType, this.expression, true);
+ if (!isLegal || (this.bits & ASTNode.UnsafeCast) != 0) {
+ scope.problemReporter().unsafeCastInInstanceof(this.expression, checkedType, expressionType);
+ }
+ }
+ }
} else if (checkedType.isValidBinding()) {
// if not a valid binding, an error has already been reported for unresolved type
if ((expressionType != TypeBinding.NULL && expressionType.isBaseType()) // disallow autoboxing
@@ -187,10 +204,17 @@ public TypeBinding resolveType(BlockScope scope) {
}
return this.resolvedType = TypeBinding.BOOLEAN;
}
-
+@Override
+public boolean checkUnsafeCast(Scope scope, TypeBinding castType, TypeBinding expressionType, TypeBinding match, boolean isNarrowing) {
+ if (!castType.isReifiable())
+ return CastExpression.checkUnsafeCast(this, scope, castType, expressionType, match, isNarrowing);
+ else
+ return super.checkUnsafeCast(scope, castType, expressionType, match, isNarrowing);
+}
/**
* @see org.eclipse.jdt.internal.compiler.ast.Expression#tagAsUnnecessaryCast(Scope,TypeBinding)
*/
+
@Override
public void tagAsUnnecessaryCast(Scope scope, TypeBinding castType) {
// null is not instanceof Type, recognize direct scenario
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
index 2ea0d3a4ec..dddb9efd6c 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/ProblemReporter.java
@@ -8405,6 +8405,22 @@ public void typeCastError(CastExpression expression, TypeBinding leftType, TypeB
expression.sourceStart,
expression.sourceEnd);
}
+public void unsafeCastInInstanceof(Expression expression, TypeBinding leftType, TypeBinding rightType) {
+ String leftName = new String(leftType.readableName());
+ String rightName = new String(rightType.readableName());
+ String leftShortName = new String(leftType.shortReadableName());
+ String rightShortName = new String(rightType.shortReadableName());
+ if (leftShortName.equals(rightShortName)){
+ leftShortName = leftName;
+ rightShortName = rightName;
+ }
+ this.handle(
+ IProblem.UnsafeCast,
+ new String[] { rightName, leftName },
+ new String[] { rightShortName, leftShortName },
+ expression.sourceStart,
+ expression.sourceEnd);
+}
public void typeCollidesWithEnclosingType(TypeDeclaration typeDecl) {
String[] arguments = new String[] {new String(typeDecl.name)};
this.handle(
diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
index 1518d0abb7..57a5e15a3a 100644
--- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
+++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/problem/messages.properties
@@ -244,6 +244,7 @@
209 = Syntax error on keyword "{0}"; {1} expected
210 = Syntax error on keyword "{0}", no accurate correction available
211 = Comparing identical expressions
+212 = Type {0} cannot be safely cast to {1}
220 = Unmatched bracket
221 = The primitive type {0} of {1} does not have a field {2}

Back to the top