From 49a42f943407cfbaf9559ca7274750cbb09f5472 Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Thu, 7 Feb 2019 13:26:29 +0300 Subject: [PATCH] Fix #KT-28999. Prohibit type parameters on anonymous objects --- .../jetbrains/kotlin/diagnostics/Errors.java | 1 + .../rendering/DefaultErrorMessages.java | 1 + .../lazy/descriptors/LazyClassDescriptor.java | 15 +++++++ .../typeParametersInAnnonymousObject.kt | 12 +++--- .../typeParametersInAnnonymousObject_after.kt | 40 +++++++++++++++++++ ...typeParametersInAnnonymousObject_after.txt | 8 ++++ .../checkers/DiagnosticsTestGenerated.java | 5 +++ .../DiagnosticsUsingJavacTestGenerated.java | 5 +++ .../kotlin/config/LanguageVersionSettings.kt | 1 + 9 files changed, 82 insertions(+), 6 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/classObjects/typeParametersInAnnonymousObject_after.kt create mode 100644 compiler/testData/diagnostics/tests/classObjects/typeParametersInAnnonymousObject_after.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 14736e8073f..9485852ea50 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -396,6 +396,7 @@ public interface Errors { DiagnosticFactory1 LOCAL_OBJECT_NOT_ALLOWED = DiagnosticFactory1.create(ERROR, DECLARATION_NAME); DiagnosticFactory1 LOCAL_INTERFACE_NOT_ALLOWED = DiagnosticFactory1.create(ERROR, DECLARATION_NAME); DiagnosticFactory0 TYPE_PARAMETERS_IN_OBJECT = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT = DiagnosticFactory0.create(WARNING); // Type parameter declarations diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index f18392afa6c..9e526610ded 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -381,6 +381,7 @@ public class DefaultErrorMessages { MAP.put(LOCAL_OBJECT_NOT_ALLOWED, "Named object ''{0}'' is a singleton and cannot be local. Try to use anonymous object instead", NAME); MAP.put(LOCAL_INTERFACE_NOT_ALLOWED, "''{0}'' is an interface so it cannot be local. Try to use anonymous object or abstract class instead", NAME); MAP.put(TYPE_PARAMETERS_IN_OBJECT, "Type parameters are not allowed for objects"); + MAP.put(TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT, "Type parameters for anonymous objects are deprecated"); MAP.put(ENUM_CLASS_CONSTRUCTOR_CALL, "Enum types cannot be instantiated"); MAP.put(SEALED_CLASS_CONSTRUCTOR_CALL, "Sealed types cannot be instantiated"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java index efa35ce21d9..f7275a099b6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/lazy/descriptors/LazyClassDescriptor.java @@ -13,10 +13,14 @@ import kotlin.jvm.functions.Function1; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.builtins.KotlinBuiltIns; +import org.jetbrains.kotlin.config.LanguageFeature; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorBase; import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl; +import org.jetbrains.kotlin.diagnostics.DiagnosticFactory; +import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0; +import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.incremental.components.NoLookupLocation; import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.name.Name; @@ -226,12 +230,23 @@ public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDes KtTypeParameterList typeParameterList = classInfo.getTypeParameterList(); if (typeParameterList == null) return Collections.emptyList(); + boolean isAnonymousObject = (classInfo.getClassKind() == ClassKind.CLASS) && (classInfo.getCorrespondingClassOrObject() instanceof KtObjectDeclaration); + if (classInfo.getClassKind() == ClassKind.ENUM_CLASS) { c.getTrace().report(TYPE_PARAMETERS_IN_ENUM.on(typeParameterList)); } if (classInfo.getClassKind() == ClassKind.OBJECT) { c.getTrace().report(TYPE_PARAMETERS_IN_OBJECT.on(typeParameterList)); } + if (isAnonymousObject) { + DiagnosticFactory0 diagnosticFactory; + if (c.getLanguageVersionSettings().supportsFeature(LanguageFeature.ProhibitTypeParametersInAnonymousObjects)) { + diagnosticFactory = TYPE_PARAMETERS_IN_OBJECT; + } else { + diagnosticFactory = TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT; + } + c.getTrace().report(diagnosticFactory.on(typeParameterList)); + } List typeParameters = typeParameterList.getParameters(); if (typeParameters.isEmpty()) return Collections.emptyList(); diff --git a/compiler/testData/diagnostics/tests/classObjects/typeParametersInAnnonymousObject.kt b/compiler/testData/diagnostics/tests/classObjects/typeParametersInAnnonymousObject.kt index 314af0fb29b..b72518722bf 100644 --- a/compiler/testData/diagnostics/tests/classObjects/typeParametersInAnnonymousObject.kt +++ b/compiler/testData/diagnostics/tests/classObjects/typeParametersInAnnonymousObject.kt @@ -2,23 +2,23 @@ // ISSUE: KT-28999 fun case_1() { - val x = object { } // type of x is + val x = object { } // type of x is } fun case_2() { - val x = object> { } + val x = object> { } } fun case_3() { - val x = object where T : Comparable<T> { } // ERROR: Where clause is not allowed for objects + val x = object where T : Comparable<T> { } // ERROR: Where clause is not allowed for objects } -val x = object> { +val x = object> { fun test() = 10 as T // OK } fun case_4() { - val x = object { + val x = object { fun test() = 10 as T } @@ -26,7 +26,7 @@ fun case_4() { } inline fun case_5() { - val x = object { + val x = object { fun test() = 10 as T } diff --git a/compiler/testData/diagnostics/tests/classObjects/typeParametersInAnnonymousObject_after.kt b/compiler/testData/diagnostics/tests/classObjects/typeParametersInAnnonymousObject_after.kt new file mode 100644 index 00000000000..3ebe56c899a --- /dev/null +++ b/compiler/testData/diagnostics/tests/classObjects/typeParametersInAnnonymousObject_after.kt @@ -0,0 +1,40 @@ +// !LANGUAGE: +ProhibitTypeParametersInAnonymousObjects +// !DIAGNOSTICS: -UNUSED_VARIABLE! +// ISSUE: KT-28999 + +fun case_1() { + val x = object { } // type of x is +} + +fun case_2() { + val x = object> { } +} + +fun case_3() { + val x = object where T : Comparable<T> { } // ERROR: Where clause is not allowed for objects +} + +val x = object> { + fun test() = 10 as T // OK +} + +fun case_4() { + val x = object { + fun test() = 10 as T + } + + val y = x.test() // type y is T +} + +inline fun case_5() { + val x = object { + fun test() = 10 as T + } + + val z = x.test() + + if (z is T) { + // z is {T!! & T!!} (smart cast from T) + println(z) + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/classObjects/typeParametersInAnnonymousObject_after.txt b/compiler/testData/diagnostics/tests/classObjects/typeParametersInAnnonymousObject_after.txt new file mode 100644 index 00000000000..b67d9a855e1 --- /dev/null +++ b/compiler/testData/diagnostics/tests/classObjects/typeParametersInAnnonymousObject_after.txt @@ -0,0 +1,8 @@ +package + +public val x: kotlin.Any +public fun case_1(): kotlin.Unit +public fun case_2(): kotlin.Unit +public fun case_3(): kotlin.Unit +public fun case_4(): kotlin.Unit +public inline fun case_5(): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index b4b5e5f88e6..2e36f737cf7 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -3114,6 +3114,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/classObjects/typeParametersInAnnonymousObject.kt"); } + @TestMetadata("typeParametersInAnnonymousObject_after.kt") + public void testTypeParametersInAnnonymousObject_after() throws Exception { + runTest("compiler/testData/diagnostics/tests/classObjects/typeParametersInAnnonymousObject_after.kt"); + } + @TestMetadata("typeParametersInObject.kt") public void testTypeParametersInObject() throws Exception { runTest("compiler/testData/diagnostics/tests/classObjects/typeParametersInObject.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 406f3af861f..13830acfc8b 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -3109,6 +3109,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/classObjects/typeParametersInAnnonymousObject.kt"); } + @TestMetadata("typeParametersInAnnonymousObject_after.kt") + public void testTypeParametersInAnnonymousObject_after() throws Exception { + runTest("compiler/testData/diagnostics/tests/classObjects/typeParametersInAnnonymousObject_after.kt"); + } + @TestMetadata("typeParametersInObject.kt") public void testTypeParametersInObject() throws Exception { runTest("compiler/testData/diagnostics/tests/classObjects/typeParametersInObject.kt"); diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index cc02fa025e7..5e3c257f264 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -96,6 +96,7 @@ enum class LanguageFeature( ProhibitConcurrentHashMapContains(KOTLIN_1_4, kind = BUG_FIX), ProhibitTypeParametersForLocalVariables(KOTLIN_1_4, kind = BUG_FIX), ProhibitJvmOverloadsOnConstructorsOfAnnotationClasses(KOTLIN_1_4, kind = BUG_FIX), + ProhibitTypeParametersInAnonymousObjects(KOTLIN_1_4, kind = BUG_FIX), ProperVisibilityForCompanionObjectInstanceField(sinceVersion = null, kind = BUG_FIX), // Temporarily disabled, see KT-27084/KT-22379