Add compatibility resolve when SAM conversion was applied partially
#KT-40646 Fixed
This commit is contained in:
+5
@@ -19831,6 +19831,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
|||||||
runTest("compiler/testData/diagnostics/tests/samConversions/GenericSubstitutionKT.kt");
|
runTest("compiler/testData/diagnostics/tests/samConversions/GenericSubstitutionKT.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("javaMemberAgainstExtension.kt")
|
||||||
|
public void testJavaMemberAgainstExtension() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/samConversions/javaMemberAgainstExtension.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("OverloadPriority.kt")
|
@TestMetadata("OverloadPriority.kt")
|
||||||
public void testOverloadPriority() throws Exception {
|
public void testOverloadPriority() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/samConversions/OverloadPriority.kt");
|
runTest("compiler/testData/diagnostics/tests/samConversions/OverloadPriority.kt");
|
||||||
|
|||||||
+22
@@ -273,6 +273,28 @@ internal object CompatibilityOfTypeVariableAsIntersectionTypePart : ResolutionPa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal object CompatibilityOfPartiallyApplicableSamConversion : ResolutionPart() {
|
||||||
|
override fun KotlinResolutionCandidate.process(workIndex: Int) {
|
||||||
|
if (resolvedCall.argumentsWithConversion.isEmpty()) return
|
||||||
|
if (resolvedCall.argumentsWithConversion.size == candidateDescriptor.valueParameters.size) return
|
||||||
|
|
||||||
|
for (argument in kotlinCall.argumentsInParenthesis) {
|
||||||
|
if (resolvedCall.argumentsWithConversion[argument] != null) continue
|
||||||
|
|
||||||
|
val expectedParameterType = argument.getExpectedType(
|
||||||
|
resolvedCall.argumentToCandidateParameter[argument] ?: continue,
|
||||||
|
callComponents.languageVersionSettings
|
||||||
|
)
|
||||||
|
|
||||||
|
// argument for the parameter doesn't have a conversion but parameter can be converted => we need a compatibility resolve
|
||||||
|
if (SamTypeConversions.isJavaParameterCanBeConverted(this, expectedParameterType)) {
|
||||||
|
markCandidateForCompatibilityResolve()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal object CheckExplicitReceiverKindConsistency : ResolutionPart() {
|
internal object CheckExplicitReceiverKindConsistency : ResolutionPart() {
|
||||||
private fun KotlinResolutionCandidate.hasError(): Nothing =
|
private fun KotlinResolutionCandidate.hasError(): Nothing =
|
||||||
error(
|
error(
|
||||||
|
|||||||
+21
-1
@@ -11,7 +11,6 @@ import org.jetbrains.kotlin.config.LanguageFeature
|
|||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ParameterDescriptor
|
||||||
import org.jetbrains.kotlin.incremental.record
|
import org.jetbrains.kotlin.incremental.record
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.LowerPriorityToPreserveCompatibility
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||||
import org.jetbrains.kotlin.resolve.sam.SAM_LOOKUP_NAME
|
import org.jetbrains.kotlin.resolve.sam.SAM_LOOKUP_NAME
|
||||||
import org.jetbrains.kotlin.resolve.sam.getFunctionTypeForPossibleSamType
|
import org.jetbrains.kotlin.resolve.sam.getFunctionTypeForPossibleSamType
|
||||||
@@ -127,4 +126,25 @@ object SamTypeConversions : ParameterTypeConversion {
|
|||||||
// now conversions for Kotlin candidates are possible, so we have to perform compatibility resolve
|
// now conversions for Kotlin candidates are possible, so we have to perform compatibility resolve
|
||||||
return !candidate.callComponents.samConversionOracle.isJavaApplicableCandidate(candidate.resolvedCall.candidateDescriptor)
|
return !candidate.callComponents.samConversionOracle.isJavaApplicableCandidate(candidate.resolvedCall.candidateDescriptor)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun isJavaParameterCanBeConverted(
|
||||||
|
candidate: KotlinResolutionCandidate,
|
||||||
|
expectedParameterType: UnwrappedType
|
||||||
|
): Boolean {
|
||||||
|
val callComponents = candidate.callComponents
|
||||||
|
|
||||||
|
val samConversionOracle = callComponents.samConversionOracle
|
||||||
|
if (!samConversionOracle.isJavaApplicableCandidate(candidate.resolvedCall.candidateDescriptor)) return false
|
||||||
|
|
||||||
|
val declarationDescriptor = expectedParameterType.constructor.declarationDescriptor
|
||||||
|
if (declarationDescriptor is ClassDescriptor && declarationDescriptor.isDefinitelyNotSamInterface) return false
|
||||||
|
|
||||||
|
val convertedType =
|
||||||
|
callComponents.samConversionResolver.getFunctionTypeForPossibleSamType(
|
||||||
|
expectedParameterType,
|
||||||
|
callComponents.samConversionOracle
|
||||||
|
)
|
||||||
|
|
||||||
|
return convertedType != null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
@@ -229,6 +229,7 @@ enum class KotlinCallKind(vararg resolutionPart: ResolutionPart) {
|
|||||||
CheckExternalArgument,
|
CheckExternalArgument,
|
||||||
EagerResolveOfCallableReferences,
|
EagerResolveOfCallableReferences,
|
||||||
CompatibilityOfTypeVariableAsIntersectionTypePart,
|
CompatibilityOfTypeVariableAsIntersectionTypePart,
|
||||||
|
CompatibilityOfPartiallyApplicableSamConversion,
|
||||||
PostponedVariablesInitializerResolutionPart
|
PostponedVariablesInitializerResolutionPart
|
||||||
),
|
),
|
||||||
INVOKE(*FUNCTION.resolutionSequence.toTypedArray()),
|
INVOKE(*FUNCTION.resolutionSequence.toTypedArray()),
|
||||||
|
|||||||
+31
@@ -0,0 +1,31 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION
|
||||||
|
|
||||||
|
// FILE: Observer.java
|
||||||
|
public interface Observer<K> {
|
||||||
|
void onChanged(K k);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: LiveData.java
|
||||||
|
public class LiveData<T> {
|
||||||
|
public void observe(java.lang.Runnable r, Observer<? super T> o) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: extension.kt
|
||||||
|
fun <T> LiveData<T>.observe(a: Any, observer: (T) -> Unit): Observer<T> {
|
||||||
|
return Observer { observer(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: test.kt
|
||||||
|
fun <T> test1(r: Runnable, l: LiveData<T>): Observer<T> = l.observe(r) { } // partial conversion
|
||||||
|
|
||||||
|
fun <T> test2(r: Runnable, o: Observer<T>, l: LiveData<T>) {
|
||||||
|
val a = l.observe(r, o) // no conversion
|
||||||
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!>a<!>
|
||||||
|
|
||||||
|
val b = l.observe({}, {}) // conversion for all arguments
|
||||||
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!>b<!>
|
||||||
|
|
||||||
|
val c = l.observe({}) {} // conversion for all arguments
|
||||||
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!>c<!>
|
||||||
|
}
|
||||||
|
|
||||||
+30
@@ -0,0 +1,30 @@
|
|||||||
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION
|
||||||
|
|
||||||
|
// FILE: Observer.java
|
||||||
|
public interface Observer<K> {
|
||||||
|
void onChanged(K k);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: LiveData.java
|
||||||
|
public class LiveData<T> {
|
||||||
|
public void observe(java.lang.Runnable r, Observer<? super T> o) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: extension.kt
|
||||||
|
fun <T> LiveData<T>.observe(a: Any, observer: (T) -> Unit): Observer<T> {
|
||||||
|
return Observer { observer(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: test.kt
|
||||||
|
fun <T> test1(r: Runnable, l: LiveData<T>): Observer<T> = l.<!COMPATIBILITY_WARNING!>observe<!>(r) { } // partial conversion
|
||||||
|
|
||||||
|
fun <T> test2(r: Runnable, o: Observer<T>, l: LiveData<T>) {
|
||||||
|
val a = l.observe(r, o) // no conversion
|
||||||
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!>a<!>
|
||||||
|
|
||||||
|
val b = l.observe({}, {}) // conversion for all arguments
|
||||||
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!>b<!>
|
||||||
|
|
||||||
|
val c = l.observe({}) {} // conversion for all arguments
|
||||||
|
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Unit")!>c<!>
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun </*0*/ T> test1(/*0*/ r: java.lang.Runnable, /*1*/ l: LiveData<T>): Observer<T>
|
||||||
|
public fun </*0*/ T> test2(/*0*/ r: java.lang.Runnable, /*1*/ o: Observer<T>, /*2*/ l: LiveData<T>): kotlin.Unit
|
||||||
|
public fun </*0*/ T> LiveData<T>.observe(/*0*/ a: kotlin.Any, /*1*/ observer: (T) -> kotlin.Unit): Observer<T>
|
||||||
|
|
||||||
|
public open class LiveData</*0*/ T : kotlin.Any!> {
|
||||||
|
public constructor LiveData</*0*/ T : kotlin.Any!>()
|
||||||
|
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 fun observe(/*0*/ r: java.lang.Runnable!, /*1*/ o: Observer<in T!>!): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface Observer</*0*/ K : kotlin.Any!> {
|
||||||
|
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 onChanged(/*0*/ k: K!): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -19843,6 +19843,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali
|
|||||||
runTest("compiler/testData/diagnostics/tests/samConversions/GenericSubstitutionKT.kt");
|
runTest("compiler/testData/diagnostics/tests/samConversions/GenericSubstitutionKT.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("javaMemberAgainstExtension.kt")
|
||||||
|
public void testJavaMemberAgainstExtension() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/samConversions/javaMemberAgainstExtension.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("OverloadPriority.kt")
|
@TestMetadata("OverloadPriority.kt")
|
||||||
public void testOverloadPriority() throws Exception {
|
public void testOverloadPriority() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/samConversions/OverloadPriority.kt");
|
runTest("compiler/testData/diagnostics/tests/samConversions/OverloadPriority.kt");
|
||||||
|
|||||||
Generated
+5
@@ -19833,6 +19833,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
|||||||
runTest("compiler/testData/diagnostics/tests/samConversions/GenericSubstitutionKT.kt");
|
runTest("compiler/testData/diagnostics/tests/samConversions/GenericSubstitutionKT.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("javaMemberAgainstExtension.kt")
|
||||||
|
public void testJavaMemberAgainstExtension() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/samConversions/javaMemberAgainstExtension.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("OverloadPriority.kt")
|
@TestMetadata("OverloadPriority.kt")
|
||||||
public void testOverloadPriority() throws Exception {
|
public void testOverloadPriority() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/samConversions/OverloadPriority.kt");
|
runTest("compiler/testData/diagnostics/tests/samConversions/OverloadPriority.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user