diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index 0daa6285114..0f6bb6582b5 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -249,6 +249,8 @@ public interface Errors { DiagnosticFactory0 TYPE_PARAMETERS_NOT_ALLOWED = DiagnosticFactory0.create(ERROR, TYPE_PARAMETERS_OR_DECLARATION_SIGNATURE); + DiagnosticFactory0 CYCLIC_GENERIC_UPPER_BOUND = DiagnosticFactory0.create(ERROR); + // Members DiagnosticFactory0 PACKAGE_MEMBER_CANNOT_BE_PROTECTED = 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 4272678d51f..69c0bd405ff 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -421,6 +421,7 @@ public class DefaultErrorMessages { MAP.put(TYPE_MISMATCH_IN_RANGE, "Type mismatch: incompatible types of range and element checked in it"); MAP.put(CYCLIC_INHERITANCE_HIERARCHY, "There's a cycle in the inheritance hierarchy for this type"); + MAP.put(CYCLIC_GENERIC_UPPER_BOUND, "Type parameter has itself as an upper bound"); MAP.put(MANY_CLASSES_IN_SUPERTYPE_LIST, "Only one class may appear in a supertype list"); MAP.put(SUPERTYPE_NOT_A_CLASS_OR_TRAIT, "Only classes and interfaces may serve as supertypes"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java index 5e23f7bef6c..6bbac29d8f4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java @@ -28,6 +28,7 @@ import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.annotations.Annotations; import org.jetbrains.kotlin.descriptors.impl.*; import org.jetbrains.kotlin.diagnostics.DiagnosticFactory1; +import org.jetbrains.kotlin.diagnostics.Errors; import org.jetbrains.kotlin.lexer.JetKeywordToken; import org.jetbrains.kotlin.lexer.JetModifierKeywordToken; import org.jetbrains.kotlin.lexer.JetTokens; @@ -476,6 +477,10 @@ public class DescriptorResolver { JetTypeReference extendsBound = jetTypeParameter.getExtendsBound(); if (extendsBound != null) { JetType type = typeResolver.resolveType(scope, extendsBound, trace, false); + if (type.getConstructor().equals(typeParameterDescriptor.getTypeConstructor())) { + trace.report(Errors.CYCLIC_GENERIC_UPPER_BOUND.on(extendsBound)); + type = ErrorUtils.createErrorType("Cyclic upper bound: " + type); + } typeParameterDescriptor.addUpperBound(type); deferredUpperBoundCheckerTasks.add(new UpperBoundCheckerTask(extendsBound, type)); } diff --git a/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBound.kt b/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBound.kt new file mode 100644 index 00000000000..7bc7846fc26 --- /dev/null +++ b/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBound.kt @@ -0,0 +1,3 @@ +// !DIAGNOSTICS: -MUST_BE_INITIALIZED +fun T?> foo() {} +val T?> prop diff --git a/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBound.txt b/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBound.txt new file mode 100644 index 00000000000..e9d759332ac --- /dev/null +++ b/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBound.txt @@ -0,0 +1,4 @@ +package + +internal val prop: [ERROR : No type, no body] +internal fun foo(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundLocal.kt b/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundLocal.kt new file mode 100644 index 00000000000..353988510c3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundLocal.kt @@ -0,0 +1,4 @@ +fun bar() { + fun T?> foo() {} + foo() +} diff --git a/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundLocal.txt b/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundLocal.txt new file mode 100644 index 00000000000..b015afc1ae0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundLocal.txt @@ -0,0 +1,3 @@ +package + +internal fun bar(): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundMember.kt b/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundMember.kt new file mode 100644 index 00000000000..91cc9ac8fc2 --- /dev/null +++ b/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundMember.kt @@ -0,0 +1,5 @@ +// !DIAGNOSTICS: -MUST_BE_INITIALIZED_OR_BE_ABSTRACT +class My { + fun T?> foo() {} + val T?> prop: T +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundMember.txt b/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundMember.txt new file mode 100644 index 00000000000..213f4fddd64 --- /dev/null +++ b/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundMember.txt @@ -0,0 +1,10 @@ +package + +internal final class My { + public constructor My() + internal final val prop: [ERROR : ?] + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + internal final fun foo(): kotlin.Unit + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundNotNull.kt b/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundNotNull.kt new file mode 100644 index 00000000000..3700e3f4236 --- /dev/null +++ b/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundNotNull.kt @@ -0,0 +1,3 @@ +// !DIAGNOSTICS: -MUST_BE_INITIALIZED +fun T> foo() {} +val T?> prop: T diff --git a/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundNotNull.txt b/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundNotNull.txt new file mode 100644 index 00000000000..78109cf3027 --- /dev/null +++ b/compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundNotNull.txt @@ -0,0 +1,4 @@ +package + +internal val prop: [ERROR : ?] +internal fun foo(): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 3d746285e04..c3fba608824 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -10224,6 +10224,30 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("itselfAsUpperBound.kt") + public void testItselfAsUpperBound() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/regressions/itselfAsUpperBound.kt"); + doTest(fileName); + } + + @TestMetadata("itselfAsUpperBoundLocal.kt") + public void testItselfAsUpperBoundLocal() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundLocal.kt"); + doTest(fileName); + } + + @TestMetadata("itselfAsUpperBoundMember.kt") + public void testItselfAsUpperBoundMember() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundMember.kt"); + doTest(fileName); + } + + @TestMetadata("itselfAsUpperBoundNotNull.kt") + public void testItselfAsUpperBoundNotNull() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/regressions/itselfAsUpperBoundNotNull.kt"); + doTest(fileName); + } + @TestMetadata("Jet11.kt") public void testJet11() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/regressions/Jet11.kt");