[NI] Prototype for SAM-conversion.
Supported: - conversion in resolution parts. Also sam-with-receiver is supported automatically - separate flag for kotlin function with java SAM as parameters TODO: - fix overload conflict error when function type is the same byte origin types is ordered - consider case when parameter type is T, T <:> Runnable - support vararg of Runnable [NI] Turn off synthetic scope with SAM adapter functions if NI enabled
This commit is contained in:
+11
@@ -49,4 +49,15 @@ interface KotlinResolutionCallbacks {
|
||||
fun isCompileTimeConstant(resolvedAtom: ResolvedCallAtom, expectedType: UnwrappedType): Boolean
|
||||
|
||||
val inferenceSession: InferenceSession
|
||||
}
|
||||
|
||||
interface SamConversionTransformer {
|
||||
fun getFunctionTypeForPossibleSamType(possibleSamType: UnwrappedType): UnwrappedType?
|
||||
|
||||
fun shouldRunSamConversionForFunction(candidate: CallableDescriptor): Boolean
|
||||
|
||||
object Empty : SamConversionTransformer {
|
||||
override fun getFunctionTypeForPossibleSamType(possibleSamType: UnwrappedType): UnwrappedType? = null
|
||||
override fun shouldRunSamConversionForFunction(candidate: CallableDescriptor): Boolean = false
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -61,7 +61,7 @@ class NewOverloadingConflictResolver(
|
||||
} else {
|
||||
val originalValueParameter = originalValueParameters[valueParameter.index]
|
||||
for (valueArgument in resolvedValueArgument.arguments) {
|
||||
valueArgumentToParameterType[valueArgument] =
|
||||
valueArgumentToParameterType[valueArgument] = candidate.resolvedCall.argumentsWithConversion[valueArgument]?.convertedTypeByOriginParameter ?:
|
||||
valueArgument.getExpectedType(originalValueParameter, candidate.callComponents.languageVersionSettings)
|
||||
}
|
||||
}
|
||||
|
||||
+43
-2
@@ -6,6 +6,8 @@
|
||||
package org.jetbrains.kotlin.resolve.calls.components
|
||||
|
||||
import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType
|
||||
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
|
||||
import org.jetbrains.kotlin.builtins.getFunctionalClassKind
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.resolve.calls.components.TypeArgumentsToParametersMapper.TypeArgumentsMapping.NoExplicitArguments
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemOperation
|
||||
@@ -21,6 +23,7 @@ import org.jetbrains.kotlin.resolve.calls.tower.VisibilityError
|
||||
import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.typeUtil.contains
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.checker.anySuperTypeConstructor
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||
|
||||
internal object CheckInstantiationOfAbstractClass : ResolutionPart() {
|
||||
@@ -28,7 +31,8 @@ internal object CheckInstantiationOfAbstractClass : ResolutionPart() {
|
||||
val candidateDescriptor = resolvedCall.candidateDescriptor
|
||||
|
||||
if (candidateDescriptor is ConstructorDescriptor &&
|
||||
!callComponents.statelessCallbacks.isSuperOrDelegatingConstructorCall(resolvedCall.atom)) {
|
||||
!callComponents.statelessCallbacks.isSuperOrDelegatingConstructorCall(resolvedCall.atom)
|
||||
) {
|
||||
if (candidateDescriptor.constructedClass.modality == Modality.ABSTRACT) {
|
||||
addDiagnostic(InstantiationOfAbstractClass)
|
||||
}
|
||||
@@ -244,11 +248,48 @@ private fun KotlinResolutionCandidate.prepareExpectedType(
|
||||
argument: KotlinCallArgument,
|
||||
candidateParameter: ParameterDescriptor
|
||||
): UnwrappedType {
|
||||
val argumentType = argument.getExpectedType(candidateParameter, callComponents.languageVersionSettings)
|
||||
val argumentType = getExpectedTypeWithSAMConversion(argument, candidateParameter) ?: argument.getExpectedType(
|
||||
candidateParameter,
|
||||
callComponents.languageVersionSettings
|
||||
)
|
||||
val resultType = knownTypeParametersResultingSubstitutor?.substitute(argumentType) ?: argumentType
|
||||
return resolvedCall.substitutor.substituteKeepAnnotations(resultType)
|
||||
}
|
||||
|
||||
private fun KotlinResolutionCandidate.getExpectedTypeWithSAMConversion(
|
||||
argument: KotlinCallArgument,
|
||||
candidateParameter: ParameterDescriptor
|
||||
): UnwrappedType? {
|
||||
if (!callComponents.samConversionTransformer.shouldRunSamConversionForFunction(resolvedCall.candidateDescriptor)) return null
|
||||
|
||||
val argumentIsFunctional = when (argument) {
|
||||
is SimpleKotlinCallArgument -> argument.receiver.stableType.isSubtypeOfFunctionType()
|
||||
is LambdaKotlinCallArgument, is CallableReferenceKotlinCallArgument -> true
|
||||
else -> false
|
||||
}
|
||||
if (!argumentIsFunctional) return null
|
||||
|
||||
val originalExpectedType = argument.getExpectedType(candidateParameter.original, callComponents.languageVersionSettings)
|
||||
val convertedTypeByOriginal = callComponents.samConversionTransformer.getFunctionTypeForPossibleSamType(originalExpectedType) ?: return null
|
||||
|
||||
val candidateExpectedType = argument.getExpectedType(candidateParameter, callComponents.languageVersionSettings)
|
||||
val convertedTypeByCandidate = callComponents.samConversionTransformer.getFunctionTypeForPossibleSamType(candidateExpectedType)
|
||||
|
||||
assert(candidateExpectedType.constructor == originalExpectedType.constructor && convertedTypeByCandidate != null) {
|
||||
"If original type is SAM type, then candidate should have same type constructor and corresponding function type\n" +
|
||||
"originalExpectType: $originalExpectedType, candidateExpectType: $candidateExpectedType\n" +
|
||||
"functionTypeByOriginal: $convertedTypeByOriginal, functionTypeByCandidate: $convertedTypeByCandidate"
|
||||
}
|
||||
|
||||
resolvedCall.registerArgumentWithSamConversion(argument, SamConversionDescription(convertedTypeByOriginal, convertedTypeByCandidate!!))
|
||||
|
||||
return convertedTypeByCandidate
|
||||
}
|
||||
|
||||
private fun UnwrappedType.isSubtypeOfFunctionType() = anySuperTypeConstructor {
|
||||
it.declarationDescriptor?.getFunctionalClassKind() == FunctionClassDescriptor.Kind.Function
|
||||
}
|
||||
|
||||
internal object CheckReceivers : ResolutionPart() {
|
||||
private fun KotlinResolutionCandidate.checkReceiver(
|
||||
receiverArgument: SimpleKotlinCallArgument?,
|
||||
|
||||
+2
-1
@@ -42,7 +42,8 @@ class KotlinCallComponents(
|
||||
val constraintInjector: ConstraintInjector,
|
||||
val reflectionTypes: ReflectionTypes,
|
||||
val builtIns: KotlinBuiltIns,
|
||||
val languageVersionSettings: LanguageVersionSettings
|
||||
val languageVersionSettings: LanguageVersionSettings,
|
||||
val samConversionTransformer: SamConversionTransformer
|
||||
)
|
||||
|
||||
class SimpleCandidateFactory(
|
||||
|
||||
@@ -61,8 +61,15 @@ abstract class ResolvedCallAtom : ResolvedAtom() {
|
||||
abstract val typeArgumentMappingByOriginal: TypeArgumentsToParametersMapper.TypeArgumentsMapping
|
||||
abstract val argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
|
||||
abstract val substitutor: FreshVariableNewTypeSubstitutor
|
||||
|
||||
abstract val argumentsWithConversion: Map<KotlinCallArgument, SamConversionDescription>
|
||||
}
|
||||
|
||||
class SamConversionDescription(
|
||||
val convertedTypeByOriginParameter: UnwrappedType,
|
||||
val convertedTypeByCandidateParameter: UnwrappedType // expected type for corresponding argument
|
||||
)
|
||||
|
||||
class ResolvedExpressionAtom(override val atom: ExpressionKotlinCallArgument) : ResolvedAtom() {
|
||||
init {
|
||||
setAnalyzedResults(listOf())
|
||||
|
||||
+12
-1
@@ -24,10 +24,10 @@ import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.components.FreshVariableNewTypeSubstitutor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableFromCallableDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.*
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
|
||||
|
||||
abstract class ResolutionPart {
|
||||
@@ -176,6 +176,17 @@ class MutableResolvedCallAtom(
|
||||
override lateinit var argumentMappingByOriginal: Map<ValueParameterDescriptor, ResolvedCallArgument>
|
||||
override lateinit var substitutor: FreshVariableNewTypeSubstitutor
|
||||
lateinit var argumentToCandidateParameter: Map<KotlinCallArgument, ValueParameterDescriptor>
|
||||
private var samAdapterMap: HashMap<KotlinCallArgument, SamConversionDescription>? = null
|
||||
|
||||
override val argumentsWithConversion: Map<KotlinCallArgument, SamConversionDescription>
|
||||
get() = samAdapterMap ?: emptyMap()
|
||||
|
||||
fun registerArgumentWithSamConversion(argument: KotlinCallArgument, samConversionDescription: SamConversionDescription) {
|
||||
if (samAdapterMap == null)
|
||||
samAdapterMap = hashMapOf()
|
||||
|
||||
samAdapterMap!![argument] = samConversionDescription
|
||||
}
|
||||
|
||||
override public fun setAnalyzedResults(subResolvedAtoms: List<ResolvedAtom>) {
|
||||
super.setAnalyzedResults(subResolvedAtoms)
|
||||
|
||||
Reference in New Issue
Block a user