From c318a13e6c2f00a26e19885f686b5be12b3de276 Mon Sep 17 00:00:00 2001 From: Michael Nedzelsky Date: Wed, 28 Oct 2015 18:46:09 +0300 Subject: [PATCH] Error on using extension function type as an upper bound --- .../jetbrains/kotlin/diagnostics/Errors.java | 1 + .../rendering/DefaultErrorMessages.java | 1 + .../kotlin/resolve/DescriptorResolver.java | 3 +++ .../generics/nullability/functionalBound.kt | 8 ++++---- .../generics/nullability/functionalBound.txt | 2 +- .../extFunctionTypeAsUpperBound.kt | 7 +++++++ .../extFunctionTypeAsUpperBound.txt | 17 +++++++++++++++++ .../typeParameters/functionTypeAsUpperBound.kt | 7 +++++++ .../typeParameters/functionTypeAsUpperBound.txt | 17 +++++++++++++++++ .../checkers/DiagnosticsTestGenerated.java | 12 ++++++++++++ 10 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/typeParameters/extFunctionTypeAsUpperBound.kt create mode 100644 compiler/testData/diagnostics/tests/typeParameters/extFunctionTypeAsUpperBound.txt create mode 100644 compiler/testData/diagnostics/tests/typeParameters/functionTypeAsUpperBound.kt create mode 100644 compiler/testData/diagnostics/tests/typeParameters/functionTypeAsUpperBound.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index a7970d92f0a..8b1edda73d9 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -259,6 +259,7 @@ public interface Errors { DiagnosticFactory1 FINAL_UPPER_BOUND = DiagnosticFactory1.create(WARNING); DiagnosticFactory0 DYNAMIC_UPPER_BOUND = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE = DiagnosticFactory0.create(ERROR); DiagnosticFactory1 CONFLICTING_UPPER_BOUNDS = DiagnosticFactory1.create(ERROR, DECLARATION_NAME); 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 23f1f17f249..c2913af74b2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -391,6 +391,7 @@ public class DefaultErrorMessages { MAP.put(UPPER_BOUND_VIOLATED, "Type argument is not within its bounds: should be subtype of ''{0}''", RENDER_TYPE, RENDER_TYPE); MAP.put(FINAL_UPPER_BOUND, "''{0}'' is a final type, and thus a value of the type parameter is predetermined", RENDER_TYPE); + MAP.put(UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE, "Extension function type can not be used as an upper bound"); MAP.put(DYNAMIC_UPPER_BOUND, "Dynamic type can not be used as an upper bound"); MAP.put(USELESS_ELVIS, "Elvis operator (?:) always returns the left operand of non-nullable type {0}", RENDER_TYPE); MAP.put(USELESS_ELVIS_ON_FUNCTION_LITERAL, "Left operand of elvis operator (?:) is function literal"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java index 739e3a5507b..536f17eefbe 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/DescriptorResolver.java @@ -589,6 +589,9 @@ public class DescriptorResolver { if (DynamicTypesKt.isDynamic(upperBoundType)) { trace.report(DYNAMIC_UPPER_BOUND.on(upperBound)); } + if (KotlinBuiltIns.isExactExtensionFunctionType(upperBoundType)) { + trace.report(UPPER_BOUND_IS_EXTENSION_FUNCTION_TYPE.on(upperBound)); + } } @NotNull diff --git a/compiler/testData/diagnostics/tests/generics/nullability/functionalBound.kt b/compiler/testData/diagnostics/tests/generics/nullability/functionalBound.kt index bb3b9ae4e84..d689d5518a0 100644 --- a/compiler/testData/diagnostics/tests/generics/nullability/functionalBound.kt +++ b/compiler/testData/diagnostics/tests/generics/nullability/functionalBound.kt @@ -1,13 +1,13 @@ -fun Unit)?> foo(x: E, y: T) { +fun Unit)?> foo(x: E, y: T) { if (x != null) { - x.y() + y(x) } if (y != null) { - x.y() + y(x) } if (x != null && y != null) { - x.y() + y(x) } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/generics/nullability/functionalBound.txt b/compiler/testData/diagnostics/tests/generics/nullability/functionalBound.txt index 06d52ea2165..45dbec4f9ab 100644 --- a/compiler/testData/diagnostics/tests/generics/nullability/functionalBound.txt +++ b/compiler/testData/diagnostics/tests/generics/nullability/functionalBound.txt @@ -1,3 +1,3 @@ package -public fun kotlin.Unit)?> foo(/*0*/ x: E, /*1*/ y: T): kotlin.Unit +public fun kotlin.Unit)?> foo(/*0*/ x: E, /*1*/ y: T): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/typeParameters/extFunctionTypeAsUpperBound.kt b/compiler/testData/diagnostics/tests/typeParameters/extFunctionTypeAsUpperBound.kt new file mode 100644 index 00000000000..2f21553c3df --- /dev/null +++ b/compiler/testData/diagnostics/tests/typeParameters/extFunctionTypeAsUpperBound.kt @@ -0,0 +1,7 @@ +fun Int.() -> String> foo() {} + +val <T: Int.() -> String> bar = fun (x: Int): String { return x.toString() } + +class A where T : Double.(Int) -> Unit + +interface BT.() -> Unit> \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/typeParameters/extFunctionTypeAsUpperBound.txt b/compiler/testData/diagnostics/tests/typeParameters/extFunctionTypeAsUpperBound.txt new file mode 100644 index 00000000000..126d6bad704 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typeParameters/extFunctionTypeAsUpperBound.txt @@ -0,0 +1,17 @@ +package + +public val kotlin.String> bar: (kotlin.Int) -> kotlin.String +public fun kotlin.String> foo(): kotlin.Unit + +public final class A kotlin.Unit> { + public constructor A kotlin.Unit>() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface B kotlin.Unit> { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + 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/typeParameters/functionTypeAsUpperBound.kt b/compiler/testData/diagnostics/tests/typeParameters/functionTypeAsUpperBound.kt new file mode 100644 index 00000000000..cab01fc0082 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typeParameters/functionTypeAsUpperBound.kt @@ -0,0 +1,7 @@ +fun String> foo() {} + +val <T: (kotlin.Int) -> kotlin.String> bar = fun (x: Int): String { return x.toString() } + +class A where T : () -> Unit, U : (Int) -> Double, V : (T, U) -> U + +interface B Unit> \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/typeParameters/functionTypeAsUpperBound.txt b/compiler/testData/diagnostics/tests/typeParameters/functionTypeAsUpperBound.txt new file mode 100644 index 00000000000..7245929a337 --- /dev/null +++ b/compiler/testData/diagnostics/tests/typeParameters/functionTypeAsUpperBound.txt @@ -0,0 +1,17 @@ +package + +public val kotlin.String> bar: (kotlin.Int) -> kotlin.String +public fun kotlin.String> foo(): kotlin.Unit + +public final class A kotlin.Unit, /*1*/ U : (kotlin.Int) -> kotlin.Double, /*2*/ V : (T, U) -> U> { + public constructor A kotlin.Unit, /*1*/ U : (kotlin.Int) -> kotlin.Double, /*2*/ V : (T, U) -> U>() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +public interface B kotlin.Unit> { + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index a71b1809d96..ff624d68dd4 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -16563,6 +16563,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("extFunctionTypeAsUpperBound.kt") + public void testExtFunctionTypeAsUpperBound() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typeParameters/extFunctionTypeAsUpperBound.kt"); + doTest(fileName); + } + + @TestMetadata("functionTypeAsUpperBound.kt") + public void testFunctionTypeAsUpperBound() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typeParameters/functionTypeAsUpperBound.kt"); + doTest(fileName); + } + @TestMetadata("misplacedConstraints.kt") public void testMisplacedConstraints() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/typeParameters/misplacedConstraints.kt");