[FE 1.0] Eliminate resolution ambiguity on inherited SAM-interfaces
^KT-17765 Fixed
This commit is contained in:
committed by
teamcityserver
parent
a5c6d370dd
commit
a6fd14d4e6
+6
@@ -25379,6 +25379,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/tests/samConversions/javaMemberAgainstExtension.kt");
|
runTest("compiler/testData/diagnostics/tests/samConversions/javaMemberAgainstExtension.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt17765.kt")
|
||||||
|
public void testKt17765() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/samConversions/kt17765.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("OverloadPriority.kt")
|
@TestMetadata("OverloadPriority.kt")
|
||||||
public void testOverloadPriority() throws Exception {
|
public void testOverloadPriority() throws Exception {
|
||||||
|
|||||||
+6
@@ -25379,6 +25379,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
runTest("compiler/testData/diagnostics/tests/samConversions/javaMemberAgainstExtension.kt");
|
runTest("compiler/testData/diagnostics/tests/samConversions/javaMemberAgainstExtension.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt17765.kt")
|
||||||
|
public void testKt17765() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/samConversions/kt17765.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("OverloadPriority.kt")
|
@TestMetadata("OverloadPriority.kt")
|
||||||
public void testOverloadPriority() throws Exception {
|
public void testOverloadPriority() throws Exception {
|
||||||
|
|||||||
+6
@@ -40596,6 +40596,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
runTest("compiler/testData/codegen/box/sam/kt17091_4.kt");
|
runTest("compiler/testData/codegen/box/sam/kt17091_4.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt17765.kt")
|
||||||
|
public void testKt17765() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/kt17765.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("kt19910.kt")
|
@TestMetadata("kt19910.kt")
|
||||||
public void testKt19910() throws Exception {
|
public void testKt19910() throws Exception {
|
||||||
|
|||||||
+1
-1
@@ -166,7 +166,7 @@ abstract class AbstractConeCallConflictResolver(
|
|||||||
return FlatSignature(
|
return FlatSignature(
|
||||||
call,
|
call,
|
||||||
(klass as? FirTypeParameterRefsOwner)?.typeParameters?.map { it.symbol.toLookupTag() }.orEmpty(),
|
(klass as? FirTypeParameterRefsOwner)?.typeParameters?.map { it.symbol.toLookupTag() }.orEmpty(),
|
||||||
valueParameterTypes = emptyList(),
|
emptyList(),
|
||||||
hasExtensionReceiver = false,
|
hasExtensionReceiver = false,
|
||||||
hasVarargs = false,
|
hasVarargs = false,
|
||||||
numDefaults = 0,
|
numDefaults = 0,
|
||||||
|
|||||||
+47
-8
@@ -12,18 +12,34 @@ interface SpecificityComparisonCallbacks {
|
|||||||
fun isNonSubtypeNotLessSpecific(specific: KotlinTypeMarker, general: KotlinTypeMarker): Boolean
|
fun isNonSubtypeNotLessSpecific(specific: KotlinTypeMarker, general: KotlinTypeMarker): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TypeWithConversion(val resultType: KotlinTypeMarker?, val originalTypeIfWasConverted: KotlinTypeMarker? = null)
|
||||||
|
|
||||||
class FlatSignature<out T> constructor(
|
class FlatSignature<out T> constructor(
|
||||||
val origin: T,
|
val origin: T,
|
||||||
val typeParameters: Collection<TypeParameterMarker>,
|
val typeParameters: Collection<TypeParameterMarker>,
|
||||||
val valueParameterTypes: List<KotlinTypeMarker?>,
|
|
||||||
val hasExtensionReceiver: Boolean,
|
val hasExtensionReceiver: Boolean,
|
||||||
val hasVarargs: Boolean,
|
val hasVarargs: Boolean,
|
||||||
val numDefaults: Int,
|
val numDefaults: Int,
|
||||||
val isExpect: Boolean,
|
val isExpect: Boolean,
|
||||||
val isSyntheticMember: Boolean
|
val isSyntheticMember: Boolean,
|
||||||
|
val valueParameterTypes: List<TypeWithConversion?>,
|
||||||
) {
|
) {
|
||||||
val isGeneric = typeParameters.isNotEmpty()
|
val isGeneric = typeParameters.isNotEmpty()
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
origin: T,
|
||||||
|
typeParameters: Collection<TypeParameterMarker>,
|
||||||
|
valueParameterTypes: List<KotlinTypeMarker?>,
|
||||||
|
hasExtensionReceiver: Boolean,
|
||||||
|
hasVarargs: Boolean,
|
||||||
|
numDefaults: Int,
|
||||||
|
isExpect: Boolean,
|
||||||
|
isSyntheticMember: Boolean,
|
||||||
|
) : this(
|
||||||
|
origin, typeParameters, hasExtensionReceiver, hasVarargs, numDefaults, isExpect,
|
||||||
|
isSyntheticMember, valueParameterTypes.map(::TypeWithConversion)
|
||||||
|
)
|
||||||
|
|
||||||
companion object
|
companion object
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,19 +55,18 @@ interface SimpleConstraintSystem {
|
|||||||
val context: TypeSystemInferenceExtensionContext
|
val context: TypeSystemInferenceExtensionContext
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <T> SimpleConstraintSystem.isSignatureNotLessSpecific(
|
private fun <T> SimpleConstraintSystem.isValueParameterTypeNotLessSpecific(
|
||||||
specific: FlatSignature<T>,
|
specific: FlatSignature<T>,
|
||||||
general: FlatSignature<T>,
|
general: FlatSignature<T>,
|
||||||
callbacks: SpecificityComparisonCallbacks,
|
callbacks: SpecificityComparisonCallbacks,
|
||||||
specificityComparator: TypeSpecificityComparator
|
specificityComparator: TypeSpecificityComparator,
|
||||||
|
typeKindSelector: (TypeWithConversion?) -> KotlinTypeMarker?
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (specific.hasExtensionReceiver != general.hasExtensionReceiver) return false
|
|
||||||
if (specific.valueParameterTypes.size != general.valueParameterTypes.size) return false
|
|
||||||
|
|
||||||
val typeParameters = general.typeParameters
|
val typeParameters = general.typeParameters
|
||||||
val typeSubstitutor = registerTypeVariables(typeParameters)
|
val typeSubstitutor = registerTypeVariables(typeParameters)
|
||||||
|
val valueParameterTypes = specific.valueParameterTypes.map(typeKindSelector).zip(general.valueParameterTypes.map(typeKindSelector))
|
||||||
|
|
||||||
for ((specificType, generalType) in specific.valueParameterTypes.zip(general.valueParameterTypes)) {
|
for ((specificType, generalType) in valueParameterTypes) {
|
||||||
if (specificType == null || generalType == null) continue
|
if (specificType == null || generalType == null) continue
|
||||||
|
|
||||||
if (specificityComparator.isDefinitelyLessSpecific(specificType, generalType)) {
|
if (specificityComparator.isDefinitelyLessSpecific(specificType, generalType)) {
|
||||||
@@ -80,6 +95,30 @@ fun <T> SimpleConstraintSystem.isSignatureNotLessSpecific(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> SimpleConstraintSystem.isSignatureNotLessSpecific(
|
||||||
|
specific: FlatSignature<T>,
|
||||||
|
general: FlatSignature<T>,
|
||||||
|
callbacks: SpecificityComparisonCallbacks,
|
||||||
|
specificityComparator: TypeSpecificityComparator,
|
||||||
|
useOriginalSamTypes: Boolean = false
|
||||||
|
): Boolean {
|
||||||
|
if (specific.hasExtensionReceiver != general.hasExtensionReceiver) return false
|
||||||
|
if (specific.valueParameterTypes.size != general.valueParameterTypes.size) return false
|
||||||
|
|
||||||
|
if (!isValueParameterTypeNotLessSpecific(specific, general, callbacks, specificityComparator) { it?.resultType }) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (useOriginalSamTypes && !isValueParameterTypeNotLessSpecific(
|
||||||
|
specific, general, callbacks, specificityComparator
|
||||||
|
) { it?.originalTypeIfWasConverted }
|
||||||
|
) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
return !hasContradiction()
|
return !hasContradiction()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+16
-10
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument
|
|||||||
import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate
|
import org.jetbrains.kotlin.resolve.calls.components.candidate.ResolutionCandidate
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallArgument
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallArgument
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.*
|
import org.jetbrains.kotlin.resolve.calls.results.*
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
|
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
|
||||||
import org.jetbrains.kotlin.util.CancellationChecker
|
import org.jetbrains.kotlin.util.CancellationChecker
|
||||||
import java.util.*
|
import java.util.*
|
||||||
@@ -61,6 +60,8 @@ class NewOverloadingConflictResolver(
|
|||||||
val resolvedCall = candidate.resolvedCall
|
val resolvedCall = candidate.resolvedCall
|
||||||
val isEliminationAmbiguitiesWithExternalTypeParametersEnabled =
|
val isEliminationAmbiguitiesWithExternalTypeParametersEnabled =
|
||||||
candidate.callComponents.languageVersionSettings.supportsFeature(LanguageFeature.EliminateAmbiguitiesWithExternalTypeParameters)
|
candidate.callComponents.languageVersionSettings.supportsFeature(LanguageFeature.EliminateAmbiguitiesWithExternalTypeParameters)
|
||||||
|
val isEliminationAmbiguitiesOnInheritedSamInterfacesEnabled =
|
||||||
|
candidate.callComponents.languageVersionSettings.supportsFeature(LanguageFeature.EliminateAmbiguitiesOnInheritedSamInterfaces)
|
||||||
val descriptor = if (isEliminationAmbiguitiesWithExternalTypeParametersEnabled) {
|
val descriptor = if (isEliminationAmbiguitiesWithExternalTypeParametersEnabled) {
|
||||||
resolvedCall.candidateDescriptor
|
resolvedCall.candidateDescriptor
|
||||||
} else {
|
} else {
|
||||||
@@ -69,25 +70,30 @@ class NewOverloadingConflictResolver(
|
|||||||
val valueParameters = descriptor.valueParameters
|
val valueParameters = descriptor.valueParameters
|
||||||
|
|
||||||
var numDefaults = 0
|
var numDefaults = 0
|
||||||
val valueArgumentToParameterType = HashMap<KotlinCallArgument, KotlinType>()
|
val valueArgumentToParameterType = HashMap<KotlinCallArgument, TypeWithConversion>()
|
||||||
for ((valueParameter, resolvedValueArgument) in resolvedCall.argumentMappingByOriginal) {
|
for ((valueParameter, resolvedValueArgument) in resolvedCall.argumentMappingByOriginal) {
|
||||||
if (resolvedValueArgument is ResolvedCallArgument.DefaultArgument) {
|
if (resolvedValueArgument is ResolvedCallArgument.DefaultArgument) {
|
||||||
numDefaults++
|
numDefaults++
|
||||||
} else {
|
} else {
|
||||||
val originalValueParameter = valueParameters[valueParameter.index]
|
val originalValueParameter = valueParameters[valueParameter.index]
|
||||||
for (valueArgument in resolvedValueArgument.arguments) {
|
for (valueArgument in resolvedValueArgument.arguments) {
|
||||||
valueArgumentToParameterType[valueArgument] =
|
val originalType = candidate.resolvedCall.argumentsWithConversion[valueArgument]?.originalParameterType
|
||||||
candidate.resolvedCall.argumentsWithConversion[valueArgument]?.convertedTypeByOriginParameter
|
val resultType = candidate.resolvedCall.argumentsWithConversion[valueArgument]?.convertedTypeByOriginParameter
|
||||||
?: valueArgument.getExpectedType(originalValueParameter, candidate.callComponents.languageVersionSettings)
|
?: valueArgument.getExpectedType(originalValueParameter, candidate.callComponents.languageVersionSettings)
|
||||||
|
valueArgumentToParameterType[valueArgument] = TypeWithConversion(
|
||||||
|
resultType,
|
||||||
|
if (isEliminationAmbiguitiesOnInheritedSamInterfacesEnabled) originalType else null
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return FlatSignature.create(candidate,
|
return FlatSignature.create(
|
||||||
descriptor,
|
candidate,
|
||||||
numDefaults,
|
descriptor,
|
||||||
resolvedCall.atom.argumentsInParenthesis.map { valueArgumentToParameterType[it] } +
|
numDefaults,
|
||||||
listOfNotNull(resolvedCall.atom.externalArgument?.let { valueArgumentToParameterType[it] })
|
parameterTypes = resolvedCall.atom.argumentsInParenthesis.map { valueArgumentToParameterType[it] } +
|
||||||
|
listOfNotNull(resolvedCall.atom.externalArgument?.let { valueArgumentToParameterType[it] })
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -104,7 +104,7 @@ object SamTypeConversions : ParameterTypeConversion {
|
|||||||
|
|
||||||
candidate.resolvedCall.registerArgumentWithSamConversion(
|
candidate.resolvedCall.registerArgumentWithSamConversion(
|
||||||
argument,
|
argument,
|
||||||
SamConversionDescription(convertedTypeByOriginal!!, convertedTypeByCandidate)
|
SamConversionDescription(convertedTypeByOriginal!!, convertedTypeByCandidate, expectedParameterType)
|
||||||
)
|
)
|
||||||
|
|
||||||
if (needCompatibilityResolveForSAM(candidate, expectedParameterType)) {
|
if (needCompatibilityResolveForSAM(candidate, expectedParameterType)) {
|
||||||
|
|||||||
@@ -89,7 +89,8 @@ abstract class ResolvedCallAtom : ResolvedAtom() {
|
|||||||
|
|
||||||
class SamConversionDescription(
|
class SamConversionDescription(
|
||||||
val convertedTypeByOriginParameter: UnwrappedType,
|
val convertedTypeByOriginParameter: UnwrappedType,
|
||||||
val convertedTypeByCandidateParameter: UnwrappedType // expected type for corresponding argument
|
val convertedTypeByCandidateParameter: UnwrappedType, // expected type for corresponding argument
|
||||||
|
val originalParameterType: UnwrappedType // need to overload resolution on inherited SAM interfaces
|
||||||
)
|
)
|
||||||
|
|
||||||
class ResolvedExpressionAtom(override val atom: ExpressionKotlinCallArgument) : ResolvedAtom() {
|
class ResolvedExpressionAtom(override val atom: ExpressionKotlinCallArgument) : ResolvedAtom() {
|
||||||
|
|||||||
+35
-6
@@ -43,6 +43,28 @@ fun <T> FlatSignature.Companion.createFromReflectionType(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@JvmName("createWithConvertedTypes")
|
||||||
|
fun <T> FlatSignature.Companion.create(
|
||||||
|
origin: T,
|
||||||
|
descriptor: CallableDescriptor,
|
||||||
|
numDefaults: Int,
|
||||||
|
parameterTypes: List<TypeWithConversion?>,
|
||||||
|
): FlatSignature<T> {
|
||||||
|
val extensionReceiverType = descriptor.extensionReceiverParameter?.type
|
||||||
|
|
||||||
|
return FlatSignature(
|
||||||
|
origin,
|
||||||
|
descriptor.typeParameters,
|
||||||
|
valueParameterTypes = extensionReceiverType?.let { listOf(TypeWithConversion(it)) }.orEmpty() + parameterTypes,
|
||||||
|
hasExtensionReceiver = extensionReceiverType != null,
|
||||||
|
hasVarargs = descriptor.valueParameters.any { it.varargElementType != null },
|
||||||
|
numDefaults = numDefaults,
|
||||||
|
isExpect = descriptor is MemberDescriptor && descriptor.isExpect,
|
||||||
|
isSyntheticMember = descriptor is SyntheticMemberDescriptor<*>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fun <T> FlatSignature.Companion.create(
|
fun <T> FlatSignature.Companion.create(
|
||||||
origin: T,
|
origin: T,
|
||||||
descriptor: CallableDescriptor,
|
descriptor: CallableDescriptor,
|
||||||
@@ -54,8 +76,7 @@ fun <T> FlatSignature.Companion.create(
|
|||||||
return FlatSignature(
|
return FlatSignature(
|
||||||
origin,
|
origin,
|
||||||
descriptor.typeParameters,
|
descriptor.typeParameters,
|
||||||
valueParameterTypes =
|
valueParameterTypes = listOfNotNull(extensionReceiverType) + parameterTypes,
|
||||||
listOfNotNull(extensionReceiverType) + parameterTypes,
|
|
||||||
hasExtensionReceiver = extensionReceiverType != null,
|
hasExtensionReceiver = extensionReceiverType != null,
|
||||||
hasVarargs = descriptor.valueParameters.any { it.varargElementType != null },
|
hasVarargs = descriptor.valueParameters.any { it.varargElementType != null },
|
||||||
numDefaults = numDefaults,
|
numDefaults = numDefaults,
|
||||||
@@ -64,10 +85,18 @@ fun <T> FlatSignature.Companion.create(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <D : CallableDescriptor> FlatSignature.Companion.createFromCallableDescriptor(
|
fun <D : CallableDescriptor> FlatSignature.Companion.createFromCallableDescriptor(descriptor: D): FlatSignature<D> =
|
||||||
descriptor: D
|
FlatSignature(
|
||||||
): FlatSignature<D> =
|
descriptor,
|
||||||
create(descriptor, descriptor, numDefaults = 0, parameterTypes = descriptor.valueParameters.map { it.argumentValueType })
|
descriptor.typeParameters,
|
||||||
|
valueParameterTypes = listOfNotNull(descriptor.extensionReceiverParameter?.type)
|
||||||
|
+ descriptor.valueParameters.map { it.argumentValueType },
|
||||||
|
hasExtensionReceiver = descriptor.extensionReceiverParameter?.type != null,
|
||||||
|
hasVarargs = descriptor.valueParameters.any { it.varargElementType != null },
|
||||||
|
numDefaults = 0,
|
||||||
|
isExpect = descriptor is MemberDescriptor && descriptor.isExpect,
|
||||||
|
isSyntheticMember = descriptor is SyntheticMemberDescriptor<*>
|
||||||
|
)
|
||||||
|
|
||||||
fun <D : CallableDescriptor> FlatSignature.Companion.createForPossiblyShadowedExtension(descriptor: D): FlatSignature<D> =
|
fun <D : CallableDescriptor> FlatSignature.Companion.createForPossiblyShadowedExtension(descriptor: D): FlatSignature<D> =
|
||||||
FlatSignature(
|
FlatSignature(
|
||||||
|
|||||||
+25
-7
@@ -26,7 +26,9 @@ import org.jetbrains.kotlin.descriptors.synthetic.SyntheticMemberDescriptor
|
|||||||
import org.jetbrains.kotlin.resolve.DescriptorEquivalenceForOverrides
|
import org.jetbrains.kotlin.resolve.DescriptorEquivalenceForOverrides
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
import org.jetbrains.kotlin.resolve.calls.context.CheckArgumentTypesMode
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.getKotlinTypeRefiner
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isTypeRefinementEnabled
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isTypeRefinementEnabled
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.module
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.varargParameterPosition
|
import org.jetbrains.kotlin.resolve.descriptorUtil.varargParameterPosition
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
@@ -176,18 +178,30 @@ open class OverloadingConflictResolver<C : Any>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS ->
|
CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS ->
|
||||||
|
// Attempt 1: general disambiguation
|
||||||
findMaximallySpecificCall(candidates, discriminateGenerics)
|
findMaximallySpecificCall(candidates, discriminateGenerics)
|
||||||
|
|
||||||
|
// Attempt 2: disambiguation excluding SAM converted candidates
|
||||||
?: hasSAMConversion?.let { hasConversion ->
|
?: hasSAMConversion?.let { hasConversion ->
|
||||||
findMaximallySpecificCall(
|
findMaximallySpecificCall(
|
||||||
candidates.filterNotTo(mutableSetOf()) { hasConversion(it) },
|
candidates.filterNotTo(mutableSetOf(), hasConversion),
|
||||||
discriminateGenerics
|
discriminateGenerics
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attempt 3: disambiguation excluding synthetic candidates
|
||||||
?: findMaximallySpecificCall(
|
?: findMaximallySpecificCall(
|
||||||
candidates.filterNotTo(mutableSetOf()) { createFlatSignature(it).isSyntheticMember },
|
candidates.filterNotTo(mutableSetOf()) { createFlatSignature(it).isSyntheticMember },
|
||||||
discriminateGenerics
|
discriminateGenerics
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Attempt 4: disambiguation on original SAM-types
|
||||||
|
?: hasSAMConversion?.let { hasConversion ->
|
||||||
|
findMaximallySpecificCall(
|
||||||
|
candidates.filterTo(mutableSetOf(), hasConversion),
|
||||||
|
discriminateGenerics, useOriginalSamTypes = true
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// null means ambiguity between variables
|
// null means ambiguity between variables
|
||||||
@@ -207,7 +221,7 @@ open class OverloadingConflictResolver<C : Any>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findMaximallySpecificCall(candidates: Set<C>, discriminateGenerics: Boolean): C? {
|
private fun findMaximallySpecificCall(candidates: Set<C>, discriminateGenerics: Boolean, useOriginalSamTypes: Boolean = false): C? {
|
||||||
val filteredCandidates = uniquifyCandidatesSet(candidates)
|
val filteredCandidates = uniquifyCandidatesSet(candidates)
|
||||||
|
|
||||||
if (filteredCandidates.size <= 1) return filteredCandidates.singleOrNull()
|
if (filteredCandidates.size <= 1) return filteredCandidates.singleOrNull()
|
||||||
@@ -219,7 +233,7 @@ open class OverloadingConflictResolver<C : Any>(
|
|||||||
val bestCandidatesByParameterTypes = conflictingCandidates.filter { candidate ->
|
val bestCandidatesByParameterTypes = conflictingCandidates.filter { candidate ->
|
||||||
cancellationChecker.check()
|
cancellationChecker.check()
|
||||||
isMostSpecific(candidate, conflictingCandidates) { call1, call2 ->
|
isMostSpecific(candidate, conflictingCandidates) { call1, call2 ->
|
||||||
isNotLessSpecificCallWithArgumentMapping(call1, call2, discriminateGenerics)
|
isNotLessSpecificCallWithArgumentMapping(call1, call2, discriminateGenerics, useOriginalSamTypes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,12 +276,14 @@ open class OverloadingConflictResolver<C : Any>(
|
|||||||
private fun isNotLessSpecificCallWithArgumentMapping(
|
private fun isNotLessSpecificCallWithArgumentMapping(
|
||||||
call1: FlatSignature<C>,
|
call1: FlatSignature<C>,
|
||||||
call2: FlatSignature<C>,
|
call2: FlatSignature<C>,
|
||||||
discriminateGenerics: Boolean
|
discriminateGenerics: Boolean,
|
||||||
|
useOriginalSamTypes: Boolean
|
||||||
): Boolean {
|
): Boolean {
|
||||||
return tryCompareDescriptorsFromScripts(call1.candidateDescriptor(), call2.candidateDescriptor()) ?: compareCallsByUsedArguments(
|
return tryCompareDescriptorsFromScripts(call1.candidateDescriptor(), call2.candidateDescriptor()) ?: compareCallsByUsedArguments(
|
||||||
call1,
|
call1,
|
||||||
call2,
|
call2,
|
||||||
discriminateGenerics
|
discriminateGenerics,
|
||||||
|
useOriginalSamTypes
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -278,7 +294,8 @@ open class OverloadingConflictResolver<C : Any>(
|
|||||||
private fun compareCallsByUsedArguments(
|
private fun compareCallsByUsedArguments(
|
||||||
call1: FlatSignature<C>,
|
call1: FlatSignature<C>,
|
||||||
call2: FlatSignature<C>,
|
call2: FlatSignature<C>,
|
||||||
discriminateGenerics: Boolean
|
discriminateGenerics: Boolean,
|
||||||
|
useOriginalSamTypes: Boolean
|
||||||
): Boolean {
|
): Boolean {
|
||||||
if (discriminateGenerics) {
|
if (discriminateGenerics) {
|
||||||
val isGeneric1 = call1.isGeneric
|
val isGeneric1 = call1.isGeneric
|
||||||
@@ -297,7 +314,8 @@ open class OverloadingConflictResolver<C : Any>(
|
|||||||
call1,
|
call1,
|
||||||
call2,
|
call2,
|
||||||
SpecificityComparisonWithNumerics,
|
SpecificityComparisonWithNumerics,
|
||||||
specificityComparator
|
specificityComparator,
|
||||||
|
useOriginalSamTypes
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
// IGNORE_BACKEND: JS, NATIVE, WASM, JS_IR, JS_IR_ES6
|
||||||
|
// !LANGUAGE: +EliminateAmbiguitiesOnInheritedSamInterfaces
|
||||||
|
|
||||||
|
// FILE: Test.java
|
||||||
|
public class Test {
|
||||||
|
interface MyRunnable extends Runnable {}
|
||||||
|
|
||||||
|
public static void foo(MyRunnable r) {}
|
||||||
|
public static void foo(Runnable r) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 1.kt
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
Test.foo { }
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
main(arrayOf("", ""))
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
// !LANGUAGE: +NewInference
|
// !LANGUAGE: +EliminateAmbiguitiesOnInheritedSamInterfaces
|
||||||
// !CHECK_TYPE
|
// !CHECK_TYPE
|
||||||
// FILE: Fn.java
|
// FILE: Fn.java
|
||||||
public interface Fn<T, R> {
|
public interface Fn<T, R> {
|
||||||
@@ -26,6 +26,5 @@ fun test(j: J) {
|
|||||||
|
|
||||||
j.<!OVERLOAD_RESOLUTION_AMBIGUITY!>bas<!>({ <!UNRESOLVED_REFERENCE!>it<!> checkType { _<Any>() }; "" }, "") <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>checkType<!> { _<Int>() }
|
j.<!OVERLOAD_RESOLUTION_AMBIGUITY!>bas<!>({ <!UNRESOLVED_REFERENCE!>it<!> checkType { _<Any>() }; "" }, "") <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>checkType<!> { _<Int>() }
|
||||||
|
|
||||||
// NI: TODO
|
j.bar { it checkType { _<String>() }; "" } checkType { _<Int>() }
|
||||||
j.bar { it checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><Any>() }; "" } checkType { _<Int>() }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// !LANGUAGE: +NewInference
|
// !LANGUAGE: +EliminateAmbiguitiesOnInheritedSamInterfaces
|
||||||
// !CHECK_TYPE
|
// !CHECK_TYPE
|
||||||
// FILE: Fn.java
|
// FILE: Fn.java
|
||||||
public interface Fn<T, R> {
|
public interface Fn<T, R> {
|
||||||
@@ -26,6 +26,5 @@ fun test(j: J) {
|
|||||||
|
|
||||||
j.bas({ it checkType { _<Any>() }; "" }, "") checkType { _<Int>() }
|
j.bas({ it checkType { _<Any>() }; "" }, "") checkType { _<Int>() }
|
||||||
|
|
||||||
// NI: TODO
|
j.bar { it checkType { _<String>() }; "" } checkType { _<Int>() }
|
||||||
j.<!OVERLOAD_RESOLUTION_AMBIGUITY!>bar<!> { <!UNRESOLVED_REFERENCE!>it<!> <!DEBUG_INFO_MISSING_UNRESOLVED!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Any>() }; "" } <!DEBUG_INFO_MISSING_UNRESOLVED!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Int>() }
|
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -1,4 +1,4 @@
|
|||||||
// !LANGUAGE: +NewInference +SamConversionForKotlinFunctions +SamConversionPerArgument
|
// !LANGUAGE: +EliminateAmbiguitiesOnInheritedSamInterfaces +SamConversionForKotlinFunctions +SamConversionPerArgument
|
||||||
// !CHECK_TYPE
|
// !CHECK_TYPE
|
||||||
// FILE: Fn.java
|
// FILE: Fn.java
|
||||||
public interface Fn<T, R> {
|
public interface Fn<T, R> {
|
||||||
@@ -25,6 +25,5 @@ fun test(k: K) {
|
|||||||
|
|
||||||
k.<!OVERLOAD_RESOLUTION_AMBIGUITY!>bas<!> { <!UNRESOLVED_REFERENCE!>it<!> checkType { _<Any?>() }; "" } <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>checkType<!> { _<Int>() }
|
k.<!OVERLOAD_RESOLUTION_AMBIGUITY!>bas<!> { <!UNRESOLVED_REFERENCE!>it<!> checkType { _<Any?>() }; "" } <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>checkType<!> { _<Int>() }
|
||||||
|
|
||||||
// NI: TODO
|
k.bar { it checkType { _<String>() }; "" } checkType { _<Int>() }
|
||||||
k.bar { it checkType { <!UNRESOLVED_REFERENCE_WRONG_RECEIVER!>_<!><Any>() }; "" } checkType { _<Int>() }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
// !LANGUAGE: +NewInference +SamConversionForKotlinFunctions +SamConversionPerArgument
|
// !LANGUAGE: +EliminateAmbiguitiesOnInheritedSamInterfaces +SamConversionForKotlinFunctions +SamConversionPerArgument
|
||||||
// !CHECK_TYPE
|
// !CHECK_TYPE
|
||||||
// FILE: Fn.java
|
// FILE: Fn.java
|
||||||
public interface Fn<T, R> {
|
public interface Fn<T, R> {
|
||||||
@@ -25,6 +25,5 @@ fun test(k: K) {
|
|||||||
|
|
||||||
k.bas { it checkType { _<Any?>() }; "" } checkType { _<Int>() }
|
k.bas { it checkType { _<Any?>() }; "" } checkType { _<Int>() }
|
||||||
|
|
||||||
// NI: TODO
|
k.bar { it checkType { _<String>() }; "" } checkType { _<Int>() }
|
||||||
k.<!OVERLOAD_RESOLUTION_AMBIGUITY!>bar<!> { <!UNRESOLVED_REFERENCE!>it<!> <!DEBUG_INFO_MISSING_UNRESOLVED!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Any>() }; "" } <!DEBUG_INFO_MISSING_UNRESOLVED!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Int>() }
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// FILE: Test.java
|
||||||
|
public class Test {
|
||||||
|
interface MyRunnable extends Runnable {}
|
||||||
|
|
||||||
|
public static void foo(MyRunnable r) {}
|
||||||
|
public static void foo(Runnable r) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 1.kt
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
Test.foo { }
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
// FILE: Test.java
|
||||||
|
public class Test {
|
||||||
|
interface MyRunnable extends Runnable {}
|
||||||
|
|
||||||
|
public static void foo(MyRunnable r) {}
|
||||||
|
public static void foo(Runnable r) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 1.kt
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
Test.<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!> { }
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun main(/*0*/ args: kotlin.Array<kotlin.String>): kotlin.Unit
|
||||||
|
|
||||||
|
public open class Test {
|
||||||
|
public constructor Test()
|
||||||
|
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/*package*/ interface MyRunnable : java.lang.Runnable {
|
||||||
|
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 override /*1*/ /*fake_override*/ fun run(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
// Static members
|
||||||
|
public open fun foo(/*0*/ r: Test.MyRunnable!): kotlin.Unit
|
||||||
|
public open fun foo(/*0*/ r: java.lang.Runnable!): kotlin.Unit
|
||||||
|
}
|
||||||
Generated
+6
@@ -25391,6 +25391,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/samConversions/javaMemberAgainstExtension.kt");
|
runTest("compiler/testData/diagnostics/tests/samConversions/javaMemberAgainstExtension.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt17765.kt")
|
||||||
|
public void testKt17765() throws Exception {
|
||||||
|
runTest("compiler/testData/diagnostics/tests/samConversions/kt17765.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("OverloadPriority.kt")
|
@TestMetadata("OverloadPriority.kt")
|
||||||
public void testOverloadPriority() throws Exception {
|
public void testOverloadPriority() throws Exception {
|
||||||
|
|||||||
+6
@@ -40404,6 +40404,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
runTest("compiler/testData/codegen/box/sam/kt17091_4.kt");
|
runTest("compiler/testData/codegen/box/sam/kt17091_4.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt17765.kt")
|
||||||
|
public void testKt17765() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/kt17765.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("kt19910.kt")
|
@TestMetadata("kt19910.kt")
|
||||||
public void testKt19910() throws Exception {
|
public void testKt19910() throws Exception {
|
||||||
|
|||||||
+6
@@ -40596,6 +40596,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
runTest("compiler/testData/codegen/box/sam/kt17091_4.kt");
|
runTest("compiler/testData/codegen/box/sam/kt17091_4.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt17765.kt")
|
||||||
|
public void testKt17765() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/kt17765.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("kt19910.kt")
|
@TestMetadata("kt19910.kt")
|
||||||
public void testKt19910() throws Exception {
|
public void testKt19910() throws Exception {
|
||||||
|
|||||||
+5
@@ -32385,6 +32385,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
runTest("compiler/testData/codegen/box/sam/kt17091_4.kt");
|
runTest("compiler/testData/codegen/box/sam/kt17091_4.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt17765.kt")
|
||||||
|
public void testKt17765() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/kt17765.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt19910.kt")
|
@TestMetadata("kt19910.kt")
|
||||||
public void testKt19910() throws Exception {
|
public void testKt19910() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/sam/kt19910.kt");
|
runTest("compiler/testData/codegen/box/sam/kt19910.kt");
|
||||||
|
|||||||
@@ -240,6 +240,7 @@ enum class LanguageFeature(
|
|||||||
ProhibitAccessToEnumCompanionMembersInEnumConstructorCall(KOTLIN_1_7, kind = BUG_FIX),
|
ProhibitAccessToEnumCompanionMembersInEnumConstructorCall(KOTLIN_1_7, kind = BUG_FIX),
|
||||||
PartiallySpecifiedTypeArguments(KOTLIN_1_7),
|
PartiallySpecifiedTypeArguments(KOTLIN_1_7),
|
||||||
EliminateAmbiguitiesWithExternalTypeParameters(KOTLIN_1_7),
|
EliminateAmbiguitiesWithExternalTypeParameters(KOTLIN_1_7),
|
||||||
|
EliminateAmbiguitiesOnInheritedSamInterfaces(KOTLIN_1_7),
|
||||||
|
|
||||||
// 1.8
|
// 1.8
|
||||||
|
|
||||||
|
|||||||
+6
@@ -32008,6 +32008,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/vararg/evaluationOrder.kt");
|
runTest("compiler/testData/codegen/box/vararg/evaluationOrder.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt10926.kt")
|
||||||
|
public void testKt10926() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/vararg/kt10926.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("kt1978.kt")
|
@TestMetadata("kt1978.kt")
|
||||||
public void testKt1978() throws Exception {
|
public void testKt1978() throws Exception {
|
||||||
|
|||||||
+6
@@ -32110,6 +32110,12 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/vararg/evaluationOrder.kt");
|
runTest("compiler/testData/codegen/box/vararg/evaluationOrder.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt10926.kt")
|
||||||
|
public void testKt10926() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/vararg/kt10926.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("kt1978.kt")
|
@TestMetadata("kt1978.kt")
|
||||||
public void testKt1978() throws Exception {
|
public void testKt1978() throws Exception {
|
||||||
|
|||||||
+5
@@ -26791,6 +26791,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
|||||||
runTest("compiler/testData/codegen/box/vararg/evaluationOrder.kt");
|
runTest("compiler/testData/codegen/box/vararg/evaluationOrder.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt10926.kt")
|
||||||
|
public void testKt10926() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/vararg/kt10926.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt1978.kt")
|
@TestMetadata("kt1978.kt")
|
||||||
public void testKt1978() throws Exception {
|
public void testKt1978() throws Exception {
|
||||||
runTest("compiler/testData/codegen/box/vararg/kt1978.kt");
|
runTest("compiler/testData/codegen/box/vararg/kt1978.kt");
|
||||||
|
|||||||
+12
@@ -41203,6 +41203,12 @@ public class NativeExtBlackBoxTestGenerated extends AbstractNativeBlackBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/sam/kt17091_4.kt");
|
runTest("compiler/testData/codegen/box/sam/kt17091_4.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt17765.kt")
|
||||||
|
public void testKt17765() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/kt17765.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("kt19910.kt")
|
@TestMetadata("kt19910.kt")
|
||||||
public void testKt19910() throws Exception {
|
public void testKt19910() throws Exception {
|
||||||
@@ -44945,6 +44951,12 @@ public class NativeExtBlackBoxTestGenerated extends AbstractNativeBlackBoxTest {
|
|||||||
runTest("compiler/testData/codegen/box/vararg/evaluationOrder.kt");
|
runTest("compiler/testData/codegen/box/vararg/evaluationOrder.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("kt10926.kt")
|
||||||
|
public void testKt10926() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/vararg/kt10926.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@TestMetadata("kt1978.kt")
|
@TestMetadata("kt1978.kt")
|
||||||
public void testKt1978() throws Exception {
|
public void testKt1978() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user