diff options
| author | Stephan Herrmann | 2014-04-15 11:30:18 +0000 |
|---|---|---|
| committer | Stephan Herrmann | 2014-04-15 11:30:18 +0000 |
| commit | dd4e66116fa81ff4f74deaa928460684d87fc74d (patch) | |
| tree | 7e54eda02edb22f11d7e00d836169fbb1a246da3 | |
| parent | 7365eb3c9bc3c4e2bcff5eac5d972246c40d599d (diff) | |
| download | eclipse.jdt.core-dd4e66116fa81ff4f74deaa928460684d87fc74d.tar.gz eclipse.jdt.core-dd4e66116fa81ff4f74deaa928460684d87fc74d.tar.xz eclipse.jdt.core-dd4e66116fa81ff4f74deaa928460684d87fc74d.zip | |
Bug 432223 - [1.8][null] Java 1.8 null annotations cause 'Contradictory
null annotations' error
2 files changed, 49 insertions, 11 deletions
diff --git a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java index ed7c17fd96..61977d510e 100644 --- a/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java +++ b/org.eclipse.jdt.core.tests.compiler/src/org/eclipse/jdt/core/tests/compiler/regression/NullTypeAnnotationTest.java @@ -2606,8 +2606,10 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest { "----------\n"); } - // conflicting annotations from type variable application and type variable substitution + // conflicting annotations from type variable application and type variable substitution -> exclude null annotations from inference public void testNullTypeInference3() { + Map compilerOptions = getCompilerOptions(); + compilerOptions.put(JavaCore.COMPILER_PB_NULL_UNCHECKED_CONVERSION, JavaCore.ERROR); runNegativeTestWithLibs( new String[] { "Generics.java", @@ -2624,16 +2626,16 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest { " }\n" + "}\n" }, - getCompilerOptions(), + compilerOptions, "----------\n" + "1. ERROR in Generics.java (at line 6)\n" + " @NonNull String s = m(in);\n" + - " ^^\n" + - "Contradictory null annotations: method was inferred as \'@NonNull String m(@NonNull @Nullable String)\', but only one of \'@NonNull\' and \'@Nullable\' can be effective at any location\n" + + " ^^^^^\n" + + "Null type safety (type annotations): The expression of type \'String\' needs unchecked conversion to conform to \'@NonNull String\'\n" + "----------\n"); } - // conflicting annotations from type variable application and type variable substitution + // conflicting annotations from type variable application and type variable substitution -> exclude null annotations from inference public void testNullTypeInference3b() { runNegativeTestWithLibs( new String[] { @@ -2657,12 +2659,12 @@ public class NullTypeAnnotationTest extends AbstractNullAnnotationTest { "1. ERROR in Generics.java (at line 7)\n" + " @NonNull String s1 = m1(in);\n" + " ^^^^^^\n" + - "Contradictory null annotations: method was inferred as \'@NonNull @Nullable String m1(@NonNull @Nullable String)\', but only one of \'@NonNull\' and \'@Nullable\' can be effective at any location\n" + + "Null type mismatch (type annotations): required \'@NonNull String\' but this expression has type \'@Nullable String\'\n" + "----------\n" + "2. ERROR in Generics.java (at line 8)\n" + " @NonNull String s2 = m2(in);\n" + " ^^^^^^\n" + - "Contradictory null annotations: method was inferred as \'@NonNull @Nullable String m2(@NonNull String)\', but only one of \'@NonNull\' and \'@Nullable\' can be effective at any location\n" + + "Null type mismatch (type annotations): required \'@NonNull String\' but this expression has type \'@Nullable String\'\n" + "----------\n"); } @@ -4902,4 +4904,32 @@ public void testBug431269() { "Type mismatch: cannot convert from QField<R,Long> to QField<R,String>\n" + "----------\n"); } +// was inferring null type annotations too aggressively +public void testBug432223() { + runConformTestWithLibs( + new String[] { + "X.java", + "import org.eclipse.jdt.annotation.*;\n" + + "public class X {\n" + + " String val;\n" + + " public static @NonNull <T> T assertNotNull(@Nullable T object) {\n" + + " return assertNotNull(null, object);\n" + + " }\n" + + "\n" + + " public static @NonNull <T> T assertNotNull(@Nullable String message, @Nullable T object) {\n" + + " if (object == null) {\n" + + " throw new NullPointerException(message);\n" + + " }\n" + + " return object;\n" + + " }\n" + + " void test(@Nullable X x) {\n" + + " @NonNull X safe = assertNotNull(x);\n" + + " System.out.println(safe.val);\n" + + " }\n" + + "}\n" + }, + getCompilerOptions(), + ""); +} + } diff --git a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java index 3d56216b49..24f9b2a077 100644 --- a/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java +++ b/org.eclipse.jdt.core/compiler/org/eclipse/jdt/internal/compiler/lookup/BoundSet.java @@ -233,11 +233,17 @@ class BoundSet { * which only happens if null annotations are enabled in the first place. */ private void useNullHints(long nullHints, TypeBinding[] boundTypes, LookupEnvironment environment) { - AnnotationBinding[] annot = environment.nullAnnotationsFromTagBits(nullHints); - if (annot != null) { - // only get here if exactly one of @NonNull or @Nullable was hinted; now apply this hint: + if (nullHints == TagBits.AnnotationNullMASK) { + // on contradiction remove null type annotations for (int i = 0; i < boundTypes.length; i++) - boundTypes[i] = environment.createAnnotatedType(boundTypes[i], annot); + boundTypes[i] = boundTypes[i].unannotated(); + } else { + AnnotationBinding[] annot = environment.nullAnnotationsFromTagBits(nullHints); + if (annot != null) { + // only get here if exactly one of @NonNull or @Nullable was hinted; now apply this hint: + for (int i = 0; i < boundTypes.length; i++) + boundTypes[i] = environment.createAnnotatedType(boundTypes[i], annot); + } } } TypeBinding combineAndUseNullHints(TypeBinding type, long nullHints, LookupEnvironment environment) { @@ -259,6 +265,8 @@ class BoundSet { while(it.hasNext()) nullHints |= it.next().nullHints; } + if (nullHints == TagBits.AnnotationNullMASK) // on contradiction remove null type annotations + return type.unannotated(); AnnotationBinding[] annot = environment.nullAnnotationsFromTagBits(nullHints); if (annot != null) // only get here if exactly one of @NonNull or @Nullable was hinted; now apply this hint: |
