diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index e4ec364f1d5..a2c6930aae3 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -631,6 +631,7 @@ public interface Errors { DiagnosticFactory0 CLASS_LITERAL_LHS_NOT_A_CLASS = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 ARRAY_CLASS_LITERAL_REQUIRES_ARGUMENT = DiagnosticFactory0.create(ERROR); DiagnosticFactory0 NULLABLE_TYPE_IN_CLASS_LITERAL_LHS = DiagnosticFactory0.create(ERROR); + DiagnosticFactory1 EXPRESSION_OF_NULLABLE_TYPE_IN_CLASS_LITERAL_LHS = DiagnosticFactory1.create(ERROR); // Destructuring-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 4f87d7cb439..abbcdb9aa1a 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -880,6 +880,7 @@ public class DefaultErrorMessages { MAP.put(CLASS_LITERAL_LHS_NOT_A_CLASS, "Only classes are allowed on the left hand side of a class literal"); MAP.put(ARRAY_CLASS_LITERAL_REQUIRES_ARGUMENT, "Array class literal requires a type argument, please specify one in angle brackets"); MAP.put(NULLABLE_TYPE_IN_CLASS_LITERAL_LHS, "Type in a class literal must not be nullable"); + MAP.put(EXPRESSION_OF_NULLABLE_TYPE_IN_CLASS_LITERAL_LHS, "Expression in a class literal has a nullable type ''{0}'', use !! to make the type non-nullable", RENDER_TYPE); //Inline MAP.put(NON_PUBLIC_CALL_FROM_PUBLIC_INLINE, "Public-API inline function cannot access non-public-API ''{0}''", SHORT_NAMES_IN_TYPES, SHORT_NAMES_IN_TYPES); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionFromAnnotatedTemplate.kt b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionFromAnnotatedTemplate.kt index 839afb60c76..e496c29f266 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionFromAnnotatedTemplate.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/script/KotlinScriptDefinitionFromAnnotatedTemplate.kt @@ -66,12 +66,10 @@ open class KotlinScriptDefinitionFromAnnotatedTemplate( private val acceptedAnnotations: List> by lazy { val resolveMethod = ScriptDependenciesResolver::resolve val resolverMethodAnnotations = - resolver::class.memberFunctions.find { - it.name == resolveMethod.name && - sameSignature(it, resolveMethod) - } - ?.annotations - ?.filterIsInstance() + resolver?.let { it::class }?.memberFunctions?.find { function -> + function.name == resolveMethod.name && + sameSignature(function, resolveMethod) + }?.annotations?.filterIsInstance() resolverMethodAnnotations?.flatMap { val v = it.supportedAnnotationClasses v.toList() // TODO: inline after KT-9453 is resolved (now it fails with "java.lang.Class cannot be cast to kotlin.reflect.KClass") diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt index aae10391db8..07f4e91d604 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DoubleColonExpressionResolver.kt @@ -50,6 +50,8 @@ import org.jetbrains.kotlin.resolve.source.toSourceElement import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE import org.jetbrains.kotlin.types.expressions.typeInfoFactory.createTypeInfo +import org.jetbrains.kotlin.types.typeUtil.builtIns +import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf import org.jetbrains.kotlin.types.typeUtil.makeNullable import org.jetbrains.kotlin.utils.addToStdlib.safeAs import java.lang.UnsupportedOperationException @@ -105,12 +107,19 @@ class DoubleColonExpressionResolver( } private fun checkClassLiteral(c: ExpressionTypingContext, expression: KtClassLiteralExpression, result: DoubleColonLHS) { + val type = result.type + if (result is DoubleColonLHS.Expression) { - if (!result.isObject) reportUnsupportedIfNeeded(expression, c) + if (!result.isObject) { + if (!type.isSubtypeOf(type.builtIns.anyType)) { + c.trace.report(EXPRESSION_OF_NULLABLE_TYPE_IN_CLASS_LITERAL_LHS.on(expression.receiverExpression!!, type)) + } + reportUnsupportedIfNeeded(expression, c) + } return } - val type = (result as DoubleColonLHS.Type).type + result as DoubleColonLHS.Type val descriptor = type.constructor.declarationDescriptor if (result.possiblyBareType.isBare) { if (descriptor is ClassDescriptor && KotlinBuiltIns.isNonPrimitiveArray(descriptor)) { diff --git a/compiler/testData/diagnostics/tests/callableReference/bound/expressionWithNullableType.kt b/compiler/testData/diagnostics/tests/callableReference/bound/expressionWithNullableType.kt new file mode 100644 index 00000000000..5b2122695fb --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/bound/expressionWithNullableType.kt @@ -0,0 +1,15 @@ +// FILE: J.java + +public interface J { + String platformString(); +} + +// FILE: test.kt + +fun f1(x: Int?): Any = x::hashCode +fun f2(t: T): Any = t::hashCode +fun f3(s: S): Any = s::hashCode +fun f4(u: U?): Any = u::hashCode +fun f5(c: List<*>): Any = c[0]::hashCode + +fun f6(j: J): Any = j.platformString()::hashCode diff --git a/compiler/testData/diagnostics/tests/callableReference/bound/expressionWithNullableType.txt b/compiler/testData/diagnostics/tests/callableReference/bound/expressionWithNullableType.txt new file mode 100644 index 00000000000..7798c8e4bcb --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/bound/expressionWithNullableType.txt @@ -0,0 +1,16 @@ +package + +public /*synthesized*/ fun J(/*0*/ function: () -> kotlin.String!): J +public fun f1(/*0*/ x: kotlin.Int?): kotlin.Any +public fun f2(/*0*/ t: T): kotlin.Any +public fun f3(/*0*/ s: S): kotlin.Any +public fun f4(/*0*/ u: U?): kotlin.Any +public fun f5(/*0*/ c: kotlin.collections.List<*>): kotlin.Any +public fun f6(/*0*/ j: J): kotlin.Any + +public interface J { + 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 abstract fun platformString(): kotlin.String! + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/callableReference/bound/reservedExpressionSyntax.kt b/compiler/testData/diagnostics/tests/callableReference/bound/reservedExpressionSyntax.kt index 9e7cbaf7ce7..98cc6674839 100644 --- a/compiler/testData/diagnostics/tests/callableReference/bound/reservedExpressionSyntax.kt +++ b/compiler/testData/diagnostics/tests/callableReference/bound/reservedExpressionSyntax.kt @@ -23,8 +23,8 @@ class Test { fun List.testCallable4(): () -> Unit = b?::foo fun List.testClassLiteral1() = a::class - fun List.testClassLiteral2() = b?::class - fun List.testClassLiteral3() = b::class + fun List.testClassLiteral2() = b?::class + fun List.testClassLiteral3() = b::class fun List.testUnresolved1() = unresolved::foo fun List.testUnresolved2() = a<unresolved>::foo diff --git a/compiler/testData/diagnostics/tests/classLiteral/expressionWithNullableType.kt b/compiler/testData/diagnostics/tests/classLiteral/expressionWithNullableType.kt new file mode 100644 index 00000000000..683a0c84d48 --- /dev/null +++ b/compiler/testData/diagnostics/tests/classLiteral/expressionWithNullableType.kt @@ -0,0 +1,15 @@ +// FILE: J.java + +public interface J { + String platformString(); +} + +// FILE: test.kt + +fun f1(x: Int?): Any = x::class +fun f2(t: T): Any = t::class +fun f3(s: S): Any = s::class +fun f4(u: U?): Any = u::class +fun f5(c: List<*>): Any = c[0]::class + +fun f6(j: J): Any = j.platformString()::class diff --git a/compiler/testData/diagnostics/tests/classLiteral/expressionWithNullableType.txt b/compiler/testData/diagnostics/tests/classLiteral/expressionWithNullableType.txt new file mode 100644 index 00000000000..7798c8e4bcb --- /dev/null +++ b/compiler/testData/diagnostics/tests/classLiteral/expressionWithNullableType.txt @@ -0,0 +1,16 @@ +package + +public /*synthesized*/ fun J(/*0*/ function: () -> kotlin.String!): J +public fun f1(/*0*/ x: kotlin.Int?): kotlin.Any +public fun f2(/*0*/ t: T): kotlin.Any +public fun f3(/*0*/ s: S): kotlin.Any +public fun f4(/*0*/ u: U?): kotlin.Any +public fun f5(/*0*/ c: kotlin.collections.List<*>): kotlin.Any +public fun f6(/*0*/ j: J): kotlin.Any + +public interface J { + 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 abstract fun platformString(): kotlin.String! + 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 4ccea137691..3fa42cca494 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -1818,6 +1818,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("expressionWithNullableType.kt") + public void testExpressionWithNullableType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/bound/expressionWithNullableType.kt"); + doTest(fileName); + } + @TestMetadata("functionCallWithoutArguments.kt") public void testFunctionCallWithoutArguments() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/callableReference/bound/functionCallWithoutArguments.kt"); @@ -3022,6 +3028,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("expressionWithNullableType.kt") + public void testExpressionWithNullableType() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/classLiteral/expressionWithNullableType.kt"); + doTest(fileName); + } + @TestMetadata("genericArrays.kt") public void testGenericArrays() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/classLiteral/genericArrays.kt");