[FIR] Fix resolution of calls on super to avoid resolve to interface methods

#KT-38400 Fixed
This commit is contained in:
Dmitriy Novozhilov
2020-09-29 10:09:19 +03:00
parent fb871a55a3
commit 9e4623c52b
5 changed files with 77 additions and 0 deletions
@@ -0,0 +1,17 @@
// ISSUE: KT-38400
interface IWithToString {
override fun toString(): String
fun foo(): String
fun bar(): String
}
open class B {
open fun foo(): String = ""
}
class A : IWithToString, B() {
override fun toString(): String = super.toString() // resolve to Any.toString
override fun foo(): String = super.foo() // resolve to B.foo()
override fun bar(): String = super.<!ABSTRACT_SUPER_CALL!>bar<!>() // should be an error
}
@@ -0,0 +1,37 @@
FILE: abstractSuperCallInPresenseOfNonAbstractMethodInParent.kt
public abstract interface IWithToString : R|kotlin/Any| {
public abstract override fun toString(): R|kotlin/String|
public abstract fun foo(): R|kotlin/String|
public abstract fun bar(): R|kotlin/String|
}
public open class B : R|kotlin/Any| {
public constructor(): R|B| {
super<R|kotlin/Any|>()
}
public open fun foo(): R|kotlin/String| {
^foo String()
}
}
public final class A : R|IWithToString|, R|B| {
public constructor(): R|A| {
super<R|B|>()
}
public final override fun toString(): R|kotlin/String| {
^toString this@R|/A|.super<R|B|>.R|kotlin/Any.toString|()
}
public final override fun foo(): R|kotlin/String| {
^foo this@R|/A|.super<R|B|>.R|/B.foo|()
}
public final override fun bar(): R|kotlin/String| {
^bar this@R|/A|.super<R|IWithToString|>.R|/IWithToString.bar|()
}
}
@@ -937,6 +937,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/abstractSuperCall.kt");
}
@TestMetadata("abstractSuperCallInPresenseOfNonAbstractMethodInParent.kt")
public void testAbstractSuperCallInPresenseOfNonAbstractMethodInParent() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/abstractSuperCallInPresenseOfNonAbstractMethodInParent.kt");
}
public void testAllFilesPresentInDiagnostics() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/diagnostics"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@@ -937,6 +937,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/abstractSuperCall.kt");
}
@TestMetadata("abstractSuperCallInPresenseOfNonAbstractMethodInParent.kt")
public void testAbstractSuperCallInPresenseOfNonAbstractMethodInParent() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/abstractSuperCallInPresenseOfNonAbstractMethodInParent.kt");
}
public void testAllFilesPresentInDiagnostics() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/fir/analysis-tests/testData/resolve/diagnostics"), Pattern.compile("^([^.]+)\\.kt$"), null, true);
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.expressions.FirExpression
@@ -103,6 +104,13 @@ internal sealed class CheckReceivers : ResolutionStage() {
val explicitReceiverExpression = callInfo.explicitReceiver
val explicitReceiverKind = candidate.explicitReceiverKind
if (explicitReceiverExpression.isSuperCall()) {
val status = candidate.symbol.fir as? FirMemberDeclaration
if (status?.modality == Modality.ABSTRACT) {
sink.reportDiagnostic(ResolvedWithLowPriority)
}
}
if (expectedReceiverType != null) {
if (explicitReceiverExpression != null &&
explicitReceiverKind.shouldBeCheckedAgainstExplicit() &&
@@ -136,6 +144,11 @@ internal sealed class CheckReceivers : ResolutionStage() {
}
}
}
private fun FirExpression?.isSuperCall(): Boolean {
if (this !is FirQualifiedAccessExpression) return false
return calleeReference is FirSuperReference
}
}
private fun FirExpression.isSuperReferenceExpression(): Boolean {