[NI] Fixes after review

This commit is contained in:
Stanislav Erokhin
2017-08-05 04:52:35 +03:00
parent 2b01b91315
commit cdaa98fb63
18 changed files with 96 additions and 73 deletions
@@ -120,6 +120,7 @@ class KotlinResolutionCallbacksImpl(
val lastExpressionArgument = getLastDeparentesizedExpression(psiCallArgument)?.let { lastExpression -> val lastExpressionArgument = getLastDeparentesizedExpression(psiCallArgument)?.let { lastExpression ->
if (expectedReturnType?.isUnit() == true) return@let null // coercion to Unit if (expectedReturnType?.isUnit() == true) return@let null // coercion to Unit
// todo lastExpression can be if without else
val lastExpressionType = trace.getType(lastExpression) val lastExpressionType = trace.getType(lastExpression)
val lastExpressionTypeInfo = KotlinTypeInfo(lastExpressionType, lambdaInfo.dataFlowInfoAfter ?: functionTypeInfo.dataFlowInfo) val lastExpressionTypeInfo = KotlinTypeInfo(lastExpressionType, lambdaInfo.dataFlowInfoAfter ?: functionTypeInfo.dataFlowInfo)
createCallArgument(lastExpression, lastExpressionTypeInfo) createCallArgument(lastExpression, lastExpressionTypeInfo)
@@ -70,6 +70,7 @@ class KotlinToResolvedCallTransformer(
allResolvedCalls.add(result) allResolvedCalls.add(result)
if (trace != null) { if (trace != null) {
// todo: check checkers order
val callCheckerContext = CallCheckerContext(context.replaceBindingTrace(trace), languageFeatureSettings) val callCheckerContext = CallCheckerContext(context.replaceBindingTrace(trace), languageFeatureSettings)
for (resolvedCall in allResolvedCalls) { for (resolvedCall in allResolvedCalls) {
runCallCheckers(resolvedCall, callCheckerContext) runCallCheckers(resolvedCall, callCheckerContext)
@@ -221,7 +221,7 @@ internal fun createSimplePSICallArgument(
// we should use DFI after this argument, because there can be some useful smartcast. Popular case: if branches. // we should use DFI after this argument, because there can be some useful smartcast. Popular case: if branches.
val receiverToCast = transformToReceiverWithSmartCastInfo( val receiverToCast = transformToReceiverWithSmartCastInfo(
ownerDescriptor, bindingContext, ownerDescriptor, bindingContext,
typeInfoForArgument.dataFlowInfo, typeInfoForArgument.dataFlowInfo, // dataFlowInfoBeforeThisArgument cannot be used here, because of if() { if (x != null) return; x }
ExpressionReceiver.create(ktExpression, baseType, bindingContext) ExpressionReceiver.create(ktExpression, baseType, bindingContext)
).prepareReceiverRegardingCaptureTypes() ).prepareReceiverRegardingCaptureTypes()
@@ -108,7 +108,7 @@ class NewResolutionOldInference(
): ScopeTowerProcessor<MyCandidate> { ): ScopeTowerProcessor<MyCandidate> {
val functionFactory = outer.CandidateFactoryImpl(name, context, tracing) val functionFactory = outer.CandidateFactoryImpl(name, context, tracing)
val variableFactory = outer.CandidateFactoryImpl(name, context, tracing) val variableFactory = outer.CandidateFactoryImpl(name, context, tracing)
return CompositeScopeTowerProcessor( return PrioritizedCompositeScopeTowerProcessor(
createSimpleFunctionProcessor(scopeTower, name, functionFactory, explicitReceiver, classValueReceiver = false), createSimpleFunctionProcessor(scopeTower, name, functionFactory, explicitReceiver, classValueReceiver = false),
createVariableProcessor(scopeTower, name, variableFactory, explicitReceiver, classValueReceiver = false) createVariableProcessor(scopeTower, name, variableFactory, explicitReceiver, classValueReceiver = false)
) )
@@ -531,14 +531,14 @@ class PSICallResolver(
LHSResult.Object(ClassQualifier(calleeExpression, classifier)) LHSResult.Object(ClassQualifier(calleeExpression, classifier))
} }
else { else {
LHSResult.Empty // this is error case actually LHSResult.Error
} }
} }
else { else {
val fakeArgument = FakeValueArgumentForLeftCallableReference(ktExpression) val fakeArgument = FakeValueArgumentForLeftCallableReference(ktExpression)
val kotlinCallArgument = createSimplePSICallArgument(context, fakeArgument, lhsResult.typeInfo) val kotlinCallArgument = createSimplePSICallArgument(context, fakeArgument, lhsResult.typeInfo)
kotlinCallArgument?.let { LHSResult.Expression(it as SimpleKotlinCallArgument) } ?: LHSResult.Empty kotlinCallArgument?.let { LHSResult.Expression(it as SimpleKotlinCallArgument) } ?: LHSResult.Error
} }
} }
is DoubleColonLHS.Type -> { is DoubleColonLHS.Type -> {
@@ -547,7 +547,7 @@ class PSICallResolver(
LHSResult.Type(qualifier, lhsResult.type.unwrap()) LHSResult.Type(qualifier, lhsResult.type.unwrap())
} }
else { else {
LHSResult.Empty // this is error case actually LHSResult.Error
} }
} }
} }
@@ -318,7 +318,6 @@ public class ExpressionTypingServices {
ContextDependency dependency = context.contextDependency; ContextDependency dependency = context.contextDependency;
if (KotlinResolutionConfigurationKt.getUSE_NEW_INFERENCE()) { if (KotlinResolutionConfigurationKt.getUSE_NEW_INFERENCE()) {
dependency = ContextDependency.INDEPENDENT; dependency = ContextDependency.INDEPENDENT;
} }
return blockLevelVisitor.getTypeInfo(statementExpression, context.replaceExpectedType(expectedType).replaceContextDependency(dependency), true); return blockLevelVisitor.getTypeInfo(statementExpression, context.replaceExpectedType(expectedType).replaceContextDependency(dependency), true);
@@ -35,13 +35,10 @@ import org.jetbrains.kotlin.resolve.scopes.receivers.DetailedReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.QualifierReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.expressions.CoercionStrategy import org.jetbrains.kotlin.types.expressions.CoercionStrategy
import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes
import org.jetbrains.kotlin.types.typeUtil.isUnit import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.types.upperIfFlexible
import org.jetbrains.kotlin.utils.SmartList import org.jetbrains.kotlin.utils.SmartList
import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addIfNotNull
@@ -87,7 +84,7 @@ class CallableReferenceCandidate(
fun createCallableReferenceProcessor(factory: CallableReferencesCandidateFactory): ScopeTowerProcessor<CallableReferenceCandidate> { fun createCallableReferenceProcessor(factory: CallableReferencesCandidateFactory): ScopeTowerProcessor<CallableReferenceCandidate> {
val lhsResult = factory.argument.lhsResult val lhsResult = factory.argument.lhsResult
when (lhsResult) { when (lhsResult) {
LHSResult.Empty, is LHSResult.Expression -> { LHSResult.Empty, LHSResult.Error, is LHSResult.Expression -> {
val explicitReceiver = (lhsResult as? LHSResult.Expression)?.lshCallArgument?.receiver val explicitReceiver = (lhsResult as? LHSResult.Expression)?.lshCallArgument?.receiver
return factory.createCallableProcessor(explicitReceiver) return factory.createCallableProcessor(explicitReceiver)
} }
@@ -95,18 +92,18 @@ fun createCallableReferenceProcessor(factory: CallableReferencesCandidateFactory
val static = factory.createCallableProcessor(lhsResult.qualifier) val static = factory.createCallableProcessor(lhsResult.qualifier)
val unbound = factory.createCallableProcessor(lhsResult.unboundDetailedReceiver) val unbound = factory.createCallableProcessor(lhsResult.unboundDetailedReceiver)
// note that if we use CompositeScopeTowerProcessor then static will win over unbound members // note that if we use PrioritizedCompositeScopeTowerProcessor then static will win over unbound members
val staticOrUnbound = CompositeSimpleScopeTowerProcessor(static, unbound) val staticOrUnbound = SamePriorityCompositeScopeTowerProcessor(static, unbound)
val asValue = lhsResult.qualifier.classValueReceiverWithSmartCastInfo ?: return staticOrUnbound val asValue = lhsResult.qualifier.classValueReceiverWithSmartCastInfo ?: return staticOrUnbound
return CompositeScopeTowerProcessor(staticOrUnbound, factory.createCallableProcessor(asValue)) return PrioritizedCompositeScopeTowerProcessor(staticOrUnbound, factory.createCallableProcessor(asValue))
} }
is LHSResult.Object -> { is LHSResult.Object -> {
// callable reference to nested class constructor // callable reference to nested class constructor
val static = factory.createCallableProcessor(lhsResult.qualifier) val static = factory.createCallableProcessor(lhsResult.qualifier)
val boundObjectReference = factory.createCallableProcessor(lhsResult.objectValueReceiver) val boundObjectReference = factory.createCallableProcessor(lhsResult.objectValueReceiver)
return CompositeSimpleScopeTowerProcessor(static, boundObjectReference) return SamePriorityCompositeScopeTowerProcessor(static, boundObjectReference)
} }
} }
} }
@@ -120,33 +117,37 @@ fun ConstraintSystemOperation.checkCallableReference(
expectedType: UnwrappedType?, expectedType: UnwrappedType?,
ownerDescriptor: DeclarationDescriptor ownerDescriptor: DeclarationDescriptor
): Pair<FreshVariableNewTypeSubstitutor, KotlinCallDiagnostic?> { ): Pair<FreshVariableNewTypeSubstitutor, KotlinCallDiagnostic?> {
val invisibleMember = Visibilities.findInvisibleMember(dispatchReceiver?.asReceiverValueForVisibilityChecks,
candidateDescriptor, ownerDescriptor)
val position = ArgumentConstraintPosition(argument) val position = ArgumentConstraintPosition(argument)
val toFreshSubstitutor = createToFreshVariableSubstitutorAndAddInitialConstraints(candidateDescriptor, this, kotlinCall = null) val toFreshSubstitutor = createToFreshVariableSubstitutorAndAddInitialConstraints(candidateDescriptor, this)
val reflectionType = toFreshSubstitutor.safeSubstitute(reflectionCandidateType)
if (expectedType != null) { if (expectedType != null) {
addSubtypeConstraint(reflectionType, expectedType, position) addSubtypeConstraint(toFreshSubstitutor.safeSubstitute(reflectionCandidateType), expectedType, position)
} }
addReceiverConstraint(toFreshSubstitutor, dispatchReceiver, candidateDescriptor.dispatchReceiverParameter, position) addReceiverConstraint(toFreshSubstitutor, dispatchReceiver, candidateDescriptor.dispatchReceiverParameter, position)
addReceiverConstraint(toFreshSubstitutor, extensionReceiver, candidateDescriptor.extensionReceiverParameter, position) addReceiverConstraint(toFreshSubstitutor, extensionReceiver, candidateDescriptor.extensionReceiverParameter, position)
val invisibleMember = Visibilities.findInvisibleMember(dispatchReceiver?.asReceiverValueForVisibilityChecks,
candidateDescriptor, ownerDescriptor)
return toFreshSubstitutor to invisibleMember?.let(::VisibilityError) return toFreshSubstitutor to invisibleMember?.let(::VisibilityError)
} }
private fun ConstraintSystemOperation.addReceiverConstraint( private fun ConstraintSystemOperation.addReceiverConstraint(
toFreshSubstitutor: FreshVariableNewTypeSubstitutor, toFreshSubstitutor: FreshVariableNewTypeSubstitutor,
receiver: CallableReceiver?, receiverArgument: CallableReceiver?,
candidateReceiver: ReceiverParameterDescriptor?, receiverParameter: ReceiverParameterDescriptor?,
position: ArgumentConstraintPosition position: ArgumentConstraintPosition
) { ) {
val expectedType = toFreshSubstitutor.safeSubstitute(candidateReceiver?.value?.type?.unwrap() ?: return) if (receiverArgument == null || receiverParameter == null) {
val receiverType = receiver?.receiver?.stableType ?: return assert(receiverArgument == null) { "Receiver argument should be null if parameter is: $receiverArgument" }
assert(receiverParameter == null) { "Receiver parameter should be null if argument is: $receiverParameter" }
return
}
val expectedType = toFreshSubstitutor.safeSubstitute(receiverParameter.value.type.unwrap())
val receiverType = receiverArgument.receiver.stableType
addSubtypeConstraint(receiverType, expectedType, position) addSubtypeConstraint(receiverType, expectedType, position)
} }
@@ -170,11 +171,17 @@ class CallableReferencesCandidateFactory(
val dispatchCallableReceiver = towerCandidate.dispatchReceiver?.let { toCallableReceiver(it, explicitReceiverKind == DISPATCH_RECEIVER) } val dispatchCallableReceiver = towerCandidate.dispatchReceiver?.let { toCallableReceiver(it, explicitReceiverKind == DISPATCH_RECEIVER) }
val extensionCallableReceiver = extensionReceiver?.let { toCallableReceiver(it, explicitReceiverKind == EXTENSION_RECEIVER) } val extensionCallableReceiver = extensionReceiver?.let { toCallableReceiver(it, explicitReceiverKind == EXTENSION_RECEIVER) }
val candidateDescriptor = towerCandidate.descriptor val candidateDescriptor = towerCandidate.descriptor
val diagnostics = SmartList<KotlinCallDiagnostic>()
val (reflectionCandidateType, defaults) = buildReflectionType(candidateDescriptor, val (reflectionCandidateType, defaults) = buildReflectionType(
dispatchCallableReceiver, candidateDescriptor,
extensionCallableReceiver, dispatchCallableReceiver,
expectedType) extensionCallableReceiver,
expectedType)
if (defaults != 0) {
diagnostics.add(CallableReferencesDefaultArgumentUsed(argument, candidateDescriptor, defaults))
}
if (candidateDescriptor !is CallableMemberDescriptor) { if (candidateDescriptor !is CallableMemberDescriptor) {
val status = ResolutionCandidateStatus(listOf(NotCallableMemberReference(argument, candidateDescriptor))) val status = ResolutionCandidateStatus(listOf(NotCallableMemberReference(argument, candidateDescriptor)))
@@ -182,15 +189,15 @@ class CallableReferencesCandidateFactory(
explicitReceiverKind, reflectionCandidateType, defaults, status) explicitReceiverKind, reflectionCandidateType, defaults, status)
} }
val diagnostics = SmartList<KotlinCallDiagnostic>()
diagnostics.addAll(towerCandidate.diagnostics) diagnostics.addAll(towerCandidate.diagnostics)
// todo smartcast on receiver diagnostic and CheckInstantiationOfAbstractClass // todo smartcast on receiver diagnostic and CheckInstantiationOfAbstractClass
compatibilityChecker { compatibilityChecker {
if (it.hasContradiction) return@compatibilityChecker if (it.hasContradiction) return@compatibilityChecker
val (_, visibilityError) = it.checkCallableReference(argument, dispatchCallableReceiver, extensionCallableReceiver, candidateDescriptor, val (_, visibilityError) = it.checkCallableReference(
reflectionCandidateType, expectedType, scopeTower.lexicalScope.ownerDescriptor) argument, dispatchCallableReceiver, extensionCallableReceiver, candidateDescriptor,
reflectionCandidateType, expectedType, scopeTower.lexicalScope.ownerDescriptor)
diagnostics.addIfNotNull(visibilityError) diagnostics.addIfNotNull(visibilityError)
@@ -244,8 +251,10 @@ class CallableReferencesCandidateFactory(
} }
if (mappedArguments.any { it == null }) return null if (mappedArguments.any { it == null }) return null
val unitExpectedType = functionType.let(KotlinType::getReturnTypeFromFunctionType).takeIf { it.upperIfFlexible().isUnit() } // lower(Unit!) = Unit
val coercion = if (unitExpectedType != null) CoercionStrategy.COERCION_TO_UNIT else CoercionStrategy.NO_COERCION val returnExpectedType = functionType.getReturnTypeFromFunctionType().lowerIfFlexible()
val coercion = if (returnExpectedType.isUnit()) CoercionStrategy.COERCION_TO_UNIT else CoercionStrategy.NO_COERCION
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
return Triple(mappedArguments as Array<KotlinType>, coercion, defaults) return Triple(mappedArguments as Array<KotlinType>, coercion, defaults)
@@ -30,6 +30,7 @@ import org.jetbrains.kotlin.resolve.calls.results.TypeSpecificityComparator
import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower
import org.jetbrains.kotlin.resolve.calls.tower.TowerResolver import org.jetbrains.kotlin.resolve.calls.tower.TowerResolver
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class CallableReferenceOverloadConflictResolver( class CallableReferenceOverloadConflictResolver(
@@ -68,11 +69,11 @@ class CallableReferenceResolver(
val argument = postponedArgument.argument val argument = postponedArgument.argument
val expectedType = postponedArgument.expectedType val expectedType = postponedArgument.expectedType
val subLHSCall = ((argument.lhsResult as? LHSResult.Expression)?.lshCallArgument as? SubKotlinCallArgument) val subLHSCall = argument.lhsResult.safeAs<LHSResult.Expression>()?.lshCallArgument.safeAs<SubKotlinCallArgument>()
if (subLHSCall != null) { if (subLHSCall != null) {
csBuilder.addInnerCall(subLHSCall.resolvedCall) csBuilder.addInnerCall(subLHSCall.resolvedCall)
} }
val candidates = runRLSResolution(scopeTower, argument, expectedType) { checkCallableReference -> val candidates = runRHSResolution(scopeTower, argument, expectedType) { checkCallableReference ->
csBuilder.runTransaction { checkCallableReference(this); false } csBuilder.runTransaction { checkCallableReference(this); false }
} }
val chosenCandidate = when (candidates.size) { val chosenCandidate = when (candidates.size) {
@@ -93,18 +94,20 @@ class CallableReferenceResolver(
} }
private fun runRLSResolution( private fun runRHSResolution(
scopeTower: ImplicitScopeTower, scopeTower: ImplicitScopeTower,
callableReference: CallableReferenceKotlinCallArgument, callableReference: CallableReferenceKotlinCallArgument,
expectedType: UnwrappedType?, // this type can have not fixed type variable inside expectedType: UnwrappedType?, // this type can have not fixed type variable inside
compatibilityChecker: ((ConstraintSystemOperation) -> Unit) -> Unit // you can run anything throw this operation and all this operation will be roll backed compatibilityChecker: ((ConstraintSystemOperation) -> Unit) -> Unit // you can run anything throw this operation and all this operation will be rolled back
): Set<CallableReferenceCandidate> { ): Set<CallableReferenceCandidate> {
val factory = CallableReferencesCandidateFactory(callableReference, callComponents, scopeTower, compatibilityChecker, expectedType) val factory = CallableReferencesCandidateFactory(callableReference, callComponents, scopeTower, compatibilityChecker, expectedType)
val processor = createCallableReferenceProcessor(factory) val processor = createCallableReferenceProcessor(factory)
val candidates = towerResolver.runResolve(scopeTower, processor, useOrder = true) val candidates = towerResolver.runResolve(scopeTower, processor, useOrder = true)
return callableReferenceOverloadConflictResolver.chooseMaximallySpecificCandidates(candidates, CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS, return callableReferenceOverloadConflictResolver.chooseMaximallySpecificCandidates(
discriminateGenerics = false, candidates,
isDebuggerContext = scopeTower.isDebuggerContext) CheckArgumentTypesMode.CHECK_VALUE_ARGUMENTS,
discriminateGenerics = false, // we can't specify generics explicitly for callable references
isDebuggerContext = scopeTower.isDebuggerContext)
} }
} }
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForLambdaR
import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.kotlin.resolve.calls.model.*
import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.UnwrappedType
import org.jetbrains.kotlin.types.typeUtil.builtIns import org.jetbrains.kotlin.types.typeUtil.builtIns
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
fun createPostponedArgumentAndPerformInitialChecks( fun createPostponedArgumentAndPerformInitialChecks(
csBuilder: ConstraintSystemBuilder, csBuilder: ConstraintSystemBuilder,
@@ -60,20 +61,20 @@ private fun preprocessLambdaArgument(
if (argument.parametersTypes != null) { if (argument.parametersTypes != null) {
parameters = argument.parametersTypes!!.mapIndexed { parameters = argument.parametersTypes!!.mapIndexed {
index, type -> index, type ->
type ?: expectedParameters.getOrNull(index)?.type?.unwrap() ?: builtIns.anyType type ?: expectedParameters.getOrNull(index)?.type?.unwrap() ?: builtIns.nullableAnyType
} }
} }
else { else {
// lambda without explicit parameters: { } // lambda without explicit parameters: { }
parameters = expectedParameters.map { it.type.unwrap() } parameters = expectedParameters.map { it.type.unwrap() }
} }
returnType = (argument as? FunctionExpression)?.returnType ?: expectedType.getReturnTypeFromFunctionType().unwrap() returnType = argument.safeAs<FunctionExpression>()?.returnType ?: expectedType.getReturnTypeFromFunctionType().unwrap()
} }
else { else {
val isFunctionSupertype = KotlinBuiltIns.isNotNullOrNullableFunctionSupertype(expectedType) val isFunctionSupertype = KotlinBuiltIns.isNotNullOrNullableFunctionSupertype(expectedType)
receiverType = (argument as? FunctionExpression)?.receiverType receiverType = argument.safeAs<FunctionExpression>()?.receiverType
parameters = argument.parametersTypes?.map { it ?: builtIns.nothingType } ?: emptyList() parameters = argument.parametersTypes?.map { it ?: builtIns.nothingType } ?: emptyList()
returnType = (argument as? FunctionExpression)?.returnType ?: returnType = argument.safeAs<FunctionExpression>()?.returnType ?:
expectedType.arguments.singleOrNull()?.type?.unwrap()?.takeIf { isFunctionSupertype } ?: expectedType.arguments.singleOrNull()?.type?.unwrap()?.takeIf { isFunctionSupertype } ?:
createFreshTypeVariableForLambdaReturnType(csBuilder, argument, builtIns) createFreshTypeVariableForLambdaReturnType(csBuilder, argument, builtIns)
@@ -109,7 +109,7 @@ internal object CreateDescriptorWithFreshTypeVariables : ResolutionPart {
descriptorWithFreshTypes = candidateDescriptor descriptorWithFreshTypes = candidateDescriptor
return emptyList() return emptyList()
} }
val toFreshVariables = createToFreshVariableSubstitutorAndAddInitialConstraints(candidateDescriptor, csBuilder, kotlinCall) val toFreshVariables = createToFreshVariableSubstitutorAndAddInitialConstraints(candidateDescriptor, csBuilder)
typeVariablesForFreshTypeParameters = toFreshVariables.freshVariables typeVariablesForFreshTypeParameters = toFreshVariables.freshVariables
// bad function -- error on declaration side // bad function -- error on declaration side
@@ -164,12 +164,11 @@ internal object CreateDescriptorWithFreshTypeVariables : ResolutionPart {
fun createToFreshVariableSubstitutorAndAddInitialConstraints( fun createToFreshVariableSubstitutorAndAddInitialConstraints(
candidateDescriptor: CallableDescriptor, candidateDescriptor: CallableDescriptor,
csBuilder: ConstraintSystemOperation, csBuilder: ConstraintSystemOperation
kotlinCall: KotlinCall?
): FreshVariableNewTypeSubstitutor { ): FreshVariableNewTypeSubstitutor {
val typeParameters = candidateDescriptor.typeParameters val typeParameters = candidateDescriptor.typeParameters
val freshTypeVariables = typeParameters.map { TypeVariableFromCallableDescriptor(it, kotlinCall) } val freshTypeVariables = typeParameters.map { TypeVariableFromCallableDescriptor(it) }
val toFreshVariables = FreshVariableNewTypeSubstitutor(freshTypeVariables) val toFreshVariables = FreshVariableNewTypeSubstitutor(freshTypeVariables)
@@ -20,11 +20,12 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.resolve.calls.model.KotlinCall
import org.jetbrains.kotlin.resolve.calls.model.LambdaKotlinCallArgument import org.jetbrains.kotlin.resolve.calls.model.LambdaKotlinCallArgument
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.scopes.MemberScope import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.* import org.jetbrains.kotlin.types.KotlinTypeFactory
import org.jetbrains.kotlin.types.SimpleType
import org.jetbrains.kotlin.types.TypeConstructor
import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor import org.jetbrains.kotlin.types.checker.NewTypeVariableConstructor
@@ -53,8 +54,7 @@ sealed class NewTypeVariable(builtIns: KotlinBuiltIns, name: String) {
} }
class TypeVariableFromCallableDescriptor( class TypeVariableFromCallableDescriptor(
val originalTypeParameter: TypeParameterDescriptor, val originalTypeParameter: TypeParameterDescriptor
val call: KotlinCall? = null
) : NewTypeVariable(originalTypeParameter.builtIns, originalTypeParameter.name.identifier) ) : NewTypeVariable(originalTypeParameter.builtIns, originalTypeParameter.name.identifier)
class TypeVariableForLambdaReturnType( class TypeVariableForLambdaReturnType(
@@ -110,6 +110,8 @@ sealed class LHSResult {
// todo this case is forbid for now // todo this case is forbid for now
object Empty: LHSResult() object Empty: LHSResult()
object Error: LHSResult()
} }
interface CallableReferenceKotlinCallArgument : PostponableKotlinCallArgument { interface CallableReferenceKotlinCallArgument : PostponableKotlinCallArgument {
@@ -98,6 +98,15 @@ class CallableReferenceNotCompatible(
val callableReverenceType: UnwrappedType val callableReverenceType: UnwrappedType
) : InapplicableArgumentDiagnostic() ) : InapplicableArgumentDiagnostic()
// supported by FE but not supported by BE now
class CallableReferencesDefaultArgumentUsed(
val argument: CallableReferenceKotlinCallArgument,
val candidate: CallableDescriptor,
val defaultsCount: Int
) : KotlinCallDiagnostic(IMPOSSIBLE_TO_GENERATE) {
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(argument, this)
}
class NotCallableMemberReference( class NotCallableMemberReference(
override val argument: CallableReferenceKotlinCallArgument, override val argument: CallableReferenceKotlinCallArgument,
val candidate: CallableDescriptor val candidate: CallableDescriptor
@@ -38,7 +38,7 @@ open class OverloadingConflictResolver<C : Any>(
private val getResultingDescriptor: (C) -> CallableDescriptor, private val getResultingDescriptor: (C) -> CallableDescriptor,
private val createEmptyConstraintSystem: () -> SimpleConstraintSystem, private val createEmptyConstraintSystem: () -> SimpleConstraintSystem,
private val createFlatSignature: (C) -> FlatSignature<C>, private val createFlatSignature: (C) -> FlatSignature<C>,
private val getVariableCandidates: (C) -> C?, // vor variable WithInvoke private val getVariableCandidates: (C) -> C?, // for variable WithInvoke
private val isFromSources: (CallableDescriptor) -> Boolean private val isFromSources: (CallableDescriptor) -> Boolean
) { ) {
@@ -17,8 +17,6 @@
package org.jetbrains.kotlin.resolve.calls.tower package org.jetbrains.kotlin.resolve.calls.tower
import org.jetbrains.kotlin.builtins.isBuiltinExtensionFunctionalType import org.jetbrains.kotlin.builtins.isBuiltinExtensionFunctionalType
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.resolve.calls.tasks.createSynthesizedInvokes import org.jetbrains.kotlin.resolve.calls.tasks.createSynthesizedInvokes
@@ -182,7 +180,7 @@ fun <C : Candidate> createCallTowerProcessorForExplicitInvoke(
usualInvoke usualInvoke
} }
else { else {
CompositeScopeTowerProcessor( PrioritizedCompositeScopeTowerProcessor(
usualInvoke, usualInvoke,
InvokeExtensionScopeTowerProcessor(functionContext, invokeExtensionDescriptor, explicitReceiver = null) InvokeExtensionScopeTowerProcessor(functionContext, invokeExtensionDescriptor, explicitReceiver = null)
) )
@@ -32,14 +32,14 @@ class KnownResultProcessor<out C>(
} }
// use this if processors priority is important // use this if processors priority is important
class CompositeScopeTowerProcessor<out C>( class PrioritizedCompositeScopeTowerProcessor<out C>(
vararg val processors: ScopeTowerProcessor<C> vararg val processors: ScopeTowerProcessor<C>
) : ScopeTowerProcessor<C> { ) : ScopeTowerProcessor<C> {
override fun process(data: TowerData): List<Collection<C>> = processors.flatMap { it.process(data) } override fun process(data: TowerData): List<Collection<C>> = processors.flatMap { it.process(data) }
} }
// use this if all processors has same priority // use this if all processors has same priority
class CompositeSimpleScopeTowerProcessor<C : Candidate>( class SamePriorityCompositeScopeTowerProcessor<out C>(
private vararg val processors: SimpleScopeTowerProcessor<C> private vararg val processors: SimpleScopeTowerProcessor<C>
): SimpleScopeTowerProcessor<C> { ): SimpleScopeTowerProcessor<C> {
override fun simpleProcess(data: TowerData): Collection<C> = processors.flatMap { it.simpleProcess(data) } override fun simpleProcess(data: TowerData): Collection<C> = processors.flatMap { it.simpleProcess(data) }
@@ -192,7 +192,7 @@ private fun <C : Candidate> createSimpleProcessor(
if (classValueReceiver && explicitReceiver is QualifierReceiver) { if (classValueReceiver && explicitReceiver is QualifierReceiver) {
val classValue = explicitReceiver.classValueReceiverWithSmartCastInfo ?: return withoutClassValueProcessor val classValue = explicitReceiver.classValueReceiverWithSmartCastInfo ?: return withoutClassValueProcessor
return CompositeScopeTowerProcessor( return PrioritizedCompositeScopeTowerProcessor(
withoutClassValueProcessor, withoutClassValueProcessor,
ExplicitReceiverScopeTowerProcessor(scopeTower, context, classValue, collectCandidates) ExplicitReceiverScopeTowerProcessor(scopeTower, context, classValue, collectCandidates)
) )
@@ -200,11 +200,14 @@ private fun <C : Candidate> createSimpleProcessor(
return withoutClassValueProcessor return withoutClassValueProcessor
} }
fun <C : Candidate> createCallableReferenceProcessor(scopeTower: ImplicitScopeTower, name: Name, context: CandidateFactory<C>, fun <C : Candidate> createCallableReferenceProcessor(
explicitReceiver: DetailedReceiver?): SimpleScopeTowerProcessor<C> { scopeTower: ImplicitScopeTower,
name: Name, context: CandidateFactory<C>,
explicitReceiver: DetailedReceiver?
): SimpleScopeTowerProcessor<C> {
val variable = createSimpleProcessorWithoutClassValueReceiver(scopeTower, context, explicitReceiver) { getVariables(name, it) } val variable = createSimpleProcessorWithoutClassValueReceiver(scopeTower, context, explicitReceiver) { getVariables(name, it) }
val function = createSimpleProcessorWithoutClassValueReceiver(scopeTower, context, explicitReceiver) { getFunctions(name, it) } val function = createSimpleProcessorWithoutClassValueReceiver(scopeTower, context, explicitReceiver) { getFunctions(name, it) }
return CompositeSimpleScopeTowerProcessor(variable, function) return SamePriorityCompositeScopeTowerProcessor(variable, function)
} }
fun <C : Candidate> createVariableProcessor(scopeTower: ImplicitScopeTower, name: Name, fun <C : Candidate> createVariableProcessor(scopeTower: ImplicitScopeTower, name: Name,
@@ -213,7 +216,7 @@ fun <C : Candidate> createVariableProcessor(scopeTower: ImplicitScopeTower, name
fun <C : Candidate> createVariableAndObjectProcessor(scopeTower: ImplicitScopeTower, name: Name, fun <C : Candidate> createVariableAndObjectProcessor(scopeTower: ImplicitScopeTower, name: Name,
context: CandidateFactory<C>, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true context: CandidateFactory<C>, explicitReceiver: DetailedReceiver?, classValueReceiver: Boolean = true
) = CompositeScopeTowerProcessor( ) = PrioritizedCompositeScopeTowerProcessor(
createVariableProcessor(scopeTower, name, context, explicitReceiver), createVariableProcessor(scopeTower, name, context, explicitReceiver),
createSimpleProcessor(scopeTower, context, explicitReceiver, classValueReceiver) { getObjects(name, it) } createSimpleProcessor(scopeTower, context, explicitReceiver, classValueReceiver) { getObjects(name, it) }
) )
@@ -229,7 +232,7 @@ fun <С: Candidate> createFunctionProcessor(
simpleContext: CandidateFactory<С>, simpleContext: CandidateFactory<С>,
factoryProviderForInvoke: CandidateFactoryProviderForInvoke<С>, factoryProviderForInvoke: CandidateFactoryProviderForInvoke<С>,
explicitReceiver: DetailedReceiver? explicitReceiver: DetailedReceiver?
): CompositeScopeTowerProcessor<С> { ): PrioritizedCompositeScopeTowerProcessor<С> {
// a.foo() -- simple function call // a.foo() -- simple function call
val simpleFunction = createSimpleFunctionProcessor(scopeTower, name, simpleContext, explicitReceiver) val simpleFunction = createSimpleFunctionProcessor(scopeTower, name, simpleContext, explicitReceiver)
@@ -242,7 +245,7 @@ fun <С: Candidate> createFunctionProcessor(
InvokeExtensionTowerProcessor(scopeTower, name, factoryProviderForInvoke, it) InvokeExtensionTowerProcessor(scopeTower, name, factoryProviderForInvoke, it)
} }
return CompositeScopeTowerProcessor(simpleFunction, invokeProcessor, invokeExtensionProcessor) return PrioritizedCompositeScopeTowerProcessor(simpleFunction, invokeProcessor, invokeExtensionProcessor)
} }
@@ -132,9 +132,9 @@ class TypeApproximator {
if (conf.flexible) { if (conf.flexible) {
/** /**
* Let inputTypes = L_1..U_1; resultType = L_2..U_2 * Let inputType = L_1..U_1; resultType = L_2..U_2
* We should create resultType such as inputTypes <: resultType. * We should create resultType such as inputType <: resultType.
* It means that if A <: inputTypes, then A <: U_1. And, because inputTypes <: resultType, * It means that if A <: inputType, then A <: U_1. And, because inputType <: resultType,
* A <: resultType => A <: U_2. I.e. for every type A such A <: U_1, A <: U_2 => U_1 <: U_2. * A <: resultType => A <: U_2. I.e. for every type A such A <: U_1, A <: U_2 => U_1 <: U_2.
* *
* Similar for L_1 <: L_2: Let B : resultType <: B. L_2 <: B and L_1 <: B. * Similar for L_1 <: L_2: Let B : resultType <: B. L_2 <: B and L_1 <: B.
@@ -147,7 +147,7 @@ class TypeApproximator {
/** /**
* If C <: L..U then C <: L. * If C <: L..U then C <: L.
* inputTypes.lower <: lowerResult => inputTypes.lower <: lowerResult?.lowerIfFlexible() * inputType.lower <: lowerResult => inputType.lower <: lowerResult?.lowerIfFlexible()
* i.e. this type is correct. We use this type, because this type more flexible. * i.e. this type is correct. We use this type, because this type more flexible.
* *
* If U_1 <: U_2.lower .. U_2.upper, then we know only that U_1 <: U_2.upper. * If U_1 <: U_2.lower .. U_2.upper, then we know only that U_1 <: U_2.upper.
@@ -277,8 +277,6 @@ public abstract class KotlinBuiltIns {
public final FqNameUnsafe functionSupertype = fqNameUnsafe("Function"); public final FqNameUnsafe functionSupertype = fqNameUnsafe("Function");
public final FqName throwable = fqName("Throwable"); public final FqName throwable = fqName("Throwable");
public final FqName comparable = fqName("Comparable"); public final FqName comparable = fqName("Comparable");