[FIR] Fix binding overrides with flexible types in arguments

This commit is contained in:
Dmitriy Novozhilov
2019-11-14 15:49:03 +03:00
parent 3a7251a90b
commit d9fe70f97c
5 changed files with 67 additions and 3 deletions
@@ -34,10 +34,11 @@ class CandidateFactory(
implicitExtensionReceiverValue: ImplicitReceiverValue<*>?,
explicitReceiverKind: ExplicitReceiverKind
): Candidate {
return Candidate(
val candidate = Candidate(
symbol, dispatchReceiverValue, implicitExtensionReceiverValue,
explicitReceiverKind, bodyResolveComponents, baseSystem, callInfo
)
return candidate
}
}
@@ -16,13 +16,38 @@ import org.jetbrains.kotlin.fir.types.ConeTypeContext
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker.strictEqualTypes
import org.jetbrains.kotlin.types.AbstractTypeChecker
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
class FirStandardOverrideChecker(session: FirSession) : FirAbstractOverrideChecker() {
private val context: ConeTypeContext = session.typeContext
private fun isEqualTypes(candidateType: ConeKotlinType, baseType: ConeKotlinType, substitutor: ConeSubstitutor) =
strictEqualTypes(context, substitutor.substituteOrSelf(candidateType), substitutor.substituteOrSelf(baseType))
private fun isEqualTypes(candidateType: ConeKotlinType, baseType: ConeKotlinType, substitutor: ConeSubstitutor): Boolean{
val substitutedCandidateType = substitutor.substituteOrSelf(candidateType)
val substitutedBaseType = substitutor.substituteOrSelf(baseType)
return with(context) {
val baseIsFlexible = substitutedBaseType.isFlexible()
val candidateIsFlexible = substitutedCandidateType.isFlexible()
if (baseIsFlexible == candidateIsFlexible) {
return strictEqualTypes(context, substitutedCandidateType, substitutedBaseType)
}
val lowerBound: SimpleTypeMarker
val upperBound: SimpleTypeMarker
val type: KotlinTypeMarker
if (baseIsFlexible) {
lowerBound = substitutedBaseType.lowerBoundIfFlexible()
upperBound = substitutedBaseType.upperBoundIfFlexible()
type = substitutedCandidateType
} else {
lowerBound = substitutedCandidateType.lowerBoundIfFlexible()
upperBound = substitutedCandidateType.upperBoundIfFlexible()
type = substitutedBaseType
}
AbstractTypeChecker.isSubtypeOf(context, lowerBound, type) && AbstractTypeChecker.isSubtypeOf(context, type, upperBound)
}
}
override fun isEqualTypes(candidateTypeRef: FirTypeRef, baseTypeRef: FirTypeRef, substitutor: ConeSubstitutor) =
isEqualTypes((candidateTypeRef as FirResolvedTypeRef).type, (baseTypeRef as FirResolvedTypeRef).type, substitutor)
@@ -0,0 +1,19 @@
// FILE: A.java
public class A {
Object foo(String s) {
return null;
};
}
// FILE: main.kt
class B : A() {
override fun foo(s: String): Any? {
return null
}
}
fun test(b: B) {
b.foo("")
}
@@ -0,0 +1,14 @@
FILE: main.kt
public final class B : R|A| {
public constructor(): R|B| {
super<R|A|>()
}
public final override fun foo(s: R|kotlin/String|): R|kotlin/Any?| {
^foo Null(null)
}
}
public final fun test(b: R|B|): R|kotlin/Unit| {
R|<local>/b|.R|/B.foo|(String())
}
@@ -230,6 +230,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/fir/resolve/testData/resolve/arguments"), Pattern.compile("^([^.]+)\\.kt$"), true);
}
@TestMetadata("ambiguityOnJavaOverride.kt")
public void testAmbiguityOnJavaOverride() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arguments/ambiguityOnJavaOverride.kt");
}
@TestMetadata("default.kt")
public void testDefault() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arguments/default.kt");