Report error on bound callable references in compatibility mode
Previously examples were failing with IllegalStateException from JVM back-end because there was an error type without any error reported
This commit is contained in:
+16
-6
@@ -98,9 +98,12 @@ class DoubleColonExpressionResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun checkClassLiteral(c: ExpressionTypingContext, expression: KtClassLiteralExpression, result: DoubleColonLHS) {
|
private fun checkClassLiteral(c: ExpressionTypingContext, expression: KtClassLiteralExpression, result: DoubleColonLHS) {
|
||||||
if (result !is DoubleColonLHS.Type) return
|
if (result is DoubleColonLHS.Expression) {
|
||||||
|
if (!result.isObject) reportUnsupportedIfNeeded(expression, c)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
val type = result.type
|
val type = (result as DoubleColonLHS.Type).type
|
||||||
val reportError: Boolean
|
val reportError: Boolean
|
||||||
if (result.possiblyBareType.isBare) {
|
if (result.possiblyBareType.isBare) {
|
||||||
val descriptor = type.constructor.declarationDescriptor
|
val descriptor = type.constructor.declarationDescriptor
|
||||||
@@ -132,7 +135,7 @@ class DoubleColonExpressionResolver(
|
|||||||
!isWithoutValueArguments
|
!isWithoutValueArguments
|
||||||
is KtDotQualifiedExpression ->
|
is KtDotQualifiedExpression ->
|
||||||
receiverExpression.canBeConsideredProperExpression() &&
|
receiverExpression.canBeConsideredProperExpression() &&
|
||||||
selectorExpression?.let { it.canBeConsideredProperExpression() } ?: false
|
selectorExpression?.canBeConsideredProperExpression() ?: false
|
||||||
else -> true
|
else -> true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -150,9 +153,6 @@ class DoubleColonExpressionResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun shouldTryResolveLHSAsExpression(expression: KtDoubleColonExpression): Boolean {
|
private fun shouldTryResolveLHSAsExpression(expression: KtDoubleColonExpression): Boolean {
|
||||||
// TODO: improve diagnostic when bound callable references are disabled
|
|
||||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.BoundCallableReferences)) return false
|
|
||||||
|
|
||||||
val lhs = expression.receiverExpression ?: return false
|
val lhs = expression.receiverExpression ?: return false
|
||||||
return lhs.canBeConsideredProperExpression() && !expression.hasQuestionMarks /* TODO: test this */
|
return lhs.canBeConsideredProperExpression() && !expression.hasQuestionMarks /* TODO: test this */
|
||||||
}
|
}
|
||||||
@@ -162,6 +162,12 @@ class DoubleColonExpressionResolver(
|
|||||||
return lhs != null && lhs.canBeConsideredProperType()
|
return lhs != null && lhs.canBeConsideredProperType()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun reportUnsupportedIfNeeded(expression: KtDoubleColonExpression, c: ExpressionTypingContext) {
|
||||||
|
if (!languageVersionSettings.supportsFeature(LanguageFeature.BoundCallableReferences)) {
|
||||||
|
c.trace.report(UNSUPPORTED_FEATURE.on(expression.receiverExpression!!, LanguageFeature.BoundCallableReferences))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun resolveDoubleColonLHS(doubleColonExpression: KtDoubleColonExpression, c: ExpressionTypingContext): DoubleColonLHS? {
|
private fun resolveDoubleColonLHS(doubleColonExpression: KtDoubleColonExpression, c: ExpressionTypingContext): DoubleColonLHS? {
|
||||||
val resultForExpr = tryResolveLHS(doubleColonExpression, c, this::shouldTryResolveLHSAsExpression, this::resolveExpressionOnLHS)
|
val resultForExpr = tryResolveLHS(doubleColonExpression, c, this::shouldTryResolveLHSAsExpression, this::resolveExpressionOnLHS)
|
||||||
if (resultForExpr != null) {
|
if (resultForExpr != null) {
|
||||||
@@ -432,6 +438,10 @@ class DoubleColonExpressionResolver(
|
|||||||
if (expression.isEmptyLHS) null
|
if (expression.isEmptyLHS) null
|
||||||
else resolveDoubleColonLHS(expression, context)
|
else resolveDoubleColonLHS(expression, context)
|
||||||
|
|
||||||
|
if (lhsResult is DoubleColonLHS.Expression) {
|
||||||
|
reportUnsupportedIfNeeded(expression, context)
|
||||||
|
}
|
||||||
|
|
||||||
val resolutionResults =
|
val resolutionResults =
|
||||||
resolveCallableReferenceRHS(expression, lhsResult, context, resolveArgumentsMode)
|
resolveCallableReferenceRHS(expression, lhsResult, context, resolveArgumentsMode)
|
||||||
|
|
||||||
|
|||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// !LANGUAGE: -BoundCallableReferences
|
||||||
|
|
||||||
|
class C { companion object }
|
||||||
|
val ok1 = C::hashCode
|
||||||
|
val fail1 = <!UNSUPPORTED_FEATURE!>C.Companion<!>::hashCode
|
||||||
|
|
||||||
|
object O
|
||||||
|
val fail2 = <!UNSUPPORTED_FEATURE!>O<!>::hashCode
|
||||||
|
|
||||||
|
fun hashCode() {}
|
||||||
|
|
||||||
|
val fail3 = <!UNSUPPORTED_FEATURE!>""<!>::hashCode
|
||||||
|
val fail4 = <!UNSUPPORTED_FEATURE!>(C)<!>::hashCode
|
||||||
|
val fail5 = <!UNSUPPORTED_FEATURE!>(C.Companion)<!>::hashCode
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val fail1: kotlin.reflect.KFunction0<kotlin.Int>
|
||||||
|
public val fail2: kotlin.reflect.KFunction0<kotlin.Int>
|
||||||
|
public val fail3: kotlin.reflect.KFunction0<kotlin.Int>
|
||||||
|
public val fail4: kotlin.reflect.KFunction0<kotlin.Int>
|
||||||
|
public val fail5: kotlin.reflect.KFunction0<kotlin.Int>
|
||||||
|
public val ok1: kotlin.reflect.KFunction1<C, kotlin.Int>
|
||||||
|
public fun hashCode(): kotlin.Unit
|
||||||
|
|
||||||
|
public final class C {
|
||||||
|
public constructor C()
|
||||||
|
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 companion object Companion {
|
||||||
|
private constructor Companion()
|
||||||
|
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 object O {
|
||||||
|
private constructor O()
|
||||||
|
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
|
||||||
|
}
|
||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// !LANGUAGE: -BoundCallableReferences
|
||||||
|
|
||||||
|
class C { companion object }
|
||||||
|
val ok1 = C::class
|
||||||
|
val ok2 = C.Companion::class
|
||||||
|
|
||||||
|
object O
|
||||||
|
val ok3 = O::class
|
||||||
|
|
||||||
|
|
||||||
|
val fail1 = <!UNSUPPORTED_FEATURE!>""<!>::class
|
||||||
|
val fail2 = <!CLASS_LITERAL_LHS_NOT_A_CLASS!>String?::class<!>
|
||||||
|
val fail3 = <!UNSUPPORTED_FEATURE!>(C)<!>::class
|
||||||
|
val fail4 = <!UNSUPPORTED_FEATURE!>(C.Companion)<!>::class
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public val fail1: kotlin.reflect.KClass<kotlin.String>
|
||||||
|
public val fail2: kotlin.reflect.KClass<kotlin.String?>
|
||||||
|
public val fail3: kotlin.reflect.KClass<C.Companion>
|
||||||
|
public val fail4: kotlin.reflect.KClass<C.Companion>
|
||||||
|
public val ok1: kotlin.reflect.KClass<C>
|
||||||
|
public val ok2: kotlin.reflect.KClass<C.Companion>
|
||||||
|
public val ok3: kotlin.reflect.KClass<O>
|
||||||
|
|
||||||
|
public final class C {
|
||||||
|
public constructor C()
|
||||||
|
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 companion object Companion {
|
||||||
|
private constructor Companion()
|
||||||
|
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 object O {
|
||||||
|
private constructor O()
|
||||||
|
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
|
||||||
|
}
|
||||||
+1
-1
@@ -7,5 +7,5 @@ val <T : Any> KClass<T>.java: Class<T> get() = null!!
|
|||||||
|
|
||||||
val <T : Any> KClass<T>.javaObjectType: Class<T>
|
val <T : Any> KClass<T>.javaObjectType: Class<T>
|
||||||
get() {
|
get() {
|
||||||
return java.lang.Class::class.java as Class<T>
|
return java.<!UNRESOLVED_REFERENCE!>lang<!>.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>Class<!>::class.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>java<!> <!USELESS_CAST!>as Class<T><!>
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -6,5 +6,5 @@ val <T : Any> KClass<T>.java: Class<T> get() = null!!
|
|||||||
|
|
||||||
val <T : Any> KClass<T>.foo: Any?
|
val <T : Any> KClass<T>.foo: Any?
|
||||||
get() {
|
get() {
|
||||||
return java.lang.Integer::hashCode
|
return <!UNSUPPORTED_FEATURE!>java.<!UNRESOLVED_REFERENCE!>lang<!>.<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>Integer<!><!>::<!OVERLOAD_RESOLUTION_AMBIGUITY!>hashCode<!>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19457,6 +19457,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/sourceCompatibility/noBoundCallableReferences"), Pattern.compile("^(.+)\\.kt$"), true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/sourceCompatibility/noBoundCallableReferences"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("boundCallableReference.kt")
|
||||||
|
public void testBoundCallableReference() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/noBoundCallableReferences/boundCallableReference.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("boundClassLiteral.kt")
|
||||||
|
public void testBoundClassLiteral() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/noBoundCallableReferences/boundClassLiteral.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("qualifiedJavaClassLiteralInKClassExtension.kt")
|
@TestMetadata("qualifiedJavaClassLiteralInKClassExtension.kt")
|
||||||
public void testQualifiedJavaClassLiteralInKClassExtension() throws Exception {
|
public void testQualifiedJavaClassLiteralInKClassExtension() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/noBoundCallableReferences/qualifiedJavaClassLiteralInKClassExtension.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/sourceCompatibility/noBoundCallableReferences/qualifiedJavaClassLiteralInKClassExtension.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user