Fix #KT-28999. Prohibit type parameters on anonymous objects

This commit is contained in:
Dmitriy Novozhilov
2019-02-07 13:26:29 +03:00
parent 11e5ddf9ae
commit 49a42f9434
9 changed files with 82 additions and 6 deletions
@@ -396,6 +396,7 @@ public interface Errors {
DiagnosticFactory1<KtObjectDeclaration, ClassDescriptor> LOCAL_OBJECT_NOT_ALLOWED = DiagnosticFactory1.create(ERROR, DECLARATION_NAME);
DiagnosticFactory1<KtClass, ClassDescriptor> LOCAL_INTERFACE_NOT_ALLOWED = DiagnosticFactory1.create(ERROR, DECLARATION_NAME);
DiagnosticFactory0<KtTypeParameterList> TYPE_PARAMETERS_IN_OBJECT = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtTypeParameterList> TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT = DiagnosticFactory0.create(WARNING);
// Type parameter declarations
@@ -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");
@@ -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<KtTypeParameterList> 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<KtTypeParameter> typeParameters = typeParameterList.getParameters();
if (typeParameters.isEmpty()) return Collections.emptyList();
@@ -2,23 +2,23 @@
// ISSUE: KT-28999
fun case_1() {
val x = object<T> { } // type of x is <anonymous object><T>
val x = object<!TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT!><T><!> { } // type of x is <anonymous object><T>
}
fun case_2() {
val x = object<T : Number, K: Comparable<K>> { }
val x = object<!TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT!><T : Number, K: Comparable<K>><!> { }
}
fun case_3() {
val x = object<T> <!SYNTAX!>where <!DEBUG_INFO_MISSING_UNRESOLVED!>T<!> : <!DEBUG_INFO_MISSING_UNRESOLVED!>Comparable<!><<!DEBUG_INFO_MISSING_UNRESOLVED!>T<!>><!> { } // ERROR: Where clause is not allowed for objects
val x = object<!TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT!><T><!> <!SYNTAX!>where <!DEBUG_INFO_MISSING_UNRESOLVED!>T<!> : <!DEBUG_INFO_MISSING_UNRESOLVED!>Comparable<!><<!DEBUG_INFO_MISSING_UNRESOLVED!>T<!>><!> { } // ERROR: Where clause is not allowed for objects
}
val x = object<T, K: Comparable<K>> {
val x = object<!TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT!><T, K: Comparable<K>><!> {
fun test() = 10 <!UNCHECKED_CAST!>as T<!> // OK
}
fun case_4() {
val x = object<T> {
val x = object<!TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT!><T><!> {
fun test() = 10 <!UNCHECKED_CAST!>as T<!>
}
@@ -26,7 +26,7 @@ fun case_4() {
}
inline fun <reified T> case_5() {
val x = object<T> {
val x = object<!TYPE_PARAMETERS_IN_ANONYMOUS_OBJECT!><T><!> {
fun test() = 10 <!UNCHECKED_CAST!>as T<!>
}
@@ -0,0 +1,40 @@
// !LANGUAGE: +ProhibitTypeParametersInAnonymousObjects
// !DIAGNOSTICS: -UNUSED_VARIABLE!
// ISSUE: KT-28999
fun case_1() {
val x = object<!TYPE_PARAMETERS_IN_OBJECT!><T><!> { } // type of x is <anonymous object><T>
}
fun case_2() {
val x = object<!TYPE_PARAMETERS_IN_OBJECT!><T : Number, K: Comparable<K>><!> { }
}
fun case_3() {
val x = object<!TYPE_PARAMETERS_IN_OBJECT!><T><!> <!SYNTAX!>where <!DEBUG_INFO_MISSING_UNRESOLVED!>T<!> : <!DEBUG_INFO_MISSING_UNRESOLVED!>Comparable<!><<!DEBUG_INFO_MISSING_UNRESOLVED!>T<!>><!> { } // ERROR: Where clause is not allowed for objects
}
val x = object<!TYPE_PARAMETERS_IN_OBJECT!><T, K: Comparable<K>><!> {
fun test() = 10 <!UNCHECKED_CAST!>as T<!> // OK
}
fun case_4() {
val x = object<!TYPE_PARAMETERS_IN_OBJECT!><T><!> {
fun test() = 10 <!UNCHECKED_CAST!>as T<!>
}
val y = x.test() // type y is T
}
inline fun <reified T> case_5() {
val x = object<!TYPE_PARAMETERS_IN_OBJECT!><T><!> {
fun test() = 10 <!UNCHECKED_CAST!>as T<!>
}
val z = x.test()
if (z is T) {
// z is {T!! & T!!} (smart cast from T)
<!UNRESOLVED_REFERENCE!>println<!>(z)
}
}
@@ -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 </*0*/ reified T> case_5(): kotlin.Unit
@@ -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");
@@ -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");
@@ -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