[NI] Refactoring. Introduced PostponableCallArgument
Also here argument resolution was divided to two parts: for SimpleCallArguments and for PostponableCallArguments. Call Resolution for SimpleCallArguments also used for CheckReceivers and lambda result arguments checks
This commit is contained in:
committed by
Mikhail Zarechenskiy
parent
1bc68e073d
commit
3450340d7f
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.components
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallArgument
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.checker.intersectWrappedTypes
|
||||
|
||||
|
||||
internal fun unexpectedArgument(argument: KotlinCallArgument): Nothing =
|
||||
error("Unexpected argument type: $argument, ${argument.javaClass.canonicalName}.")
|
||||
|
||||
// if expression is not stable and has smart casts, then we create this type
|
||||
internal val ReceiverValueWithSmartCastInfo.unstableType: UnwrappedType?
|
||||
get() {
|
||||
if (isStable || possibleTypes.isEmpty()) return null
|
||||
return intersectWrappedTypes(possibleTypes + receiverValue.type)
|
||||
}
|
||||
|
||||
// with all smart casts if stable
|
||||
internal val ReceiverValueWithSmartCastInfo.stableType: UnwrappedType
|
||||
get() {
|
||||
if (!isStable || possibleTypes.isEmpty()) return receiverValue.type.unwrap()
|
||||
return intersectWrappedTypes(possibleTypes + receiverValue.type)
|
||||
}
|
||||
|
||||
|
||||
|
||||
internal fun KotlinCallArgument.getExpectedType(parameter: ValueParameterDescriptor) =
|
||||
if (this.isSpread) {
|
||||
parameter.type.unwrap()
|
||||
}
|
||||
else {
|
||||
parameter.varargElementType?.unwrap() ?: parameter.type.unwrap()
|
||||
}
|
||||
-333
@@ -1,333 +0,0 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.components
|
||||
|
||||
import org.jetbrains.kotlin.builtins.*
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ReceiverConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForLambdaReturnType
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValueWithSmartCastInfo
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.checker.captureFromExpression
|
||||
import org.jetbrains.kotlin.types.checker.hasSupertypeWithGivenTypeConstructor
|
||||
import org.jetbrains.kotlin.types.checker.intersectWrappedTypes
|
||||
import org.jetbrains.kotlin.types.lowerIfFlexible
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
||||
import org.jetbrains.kotlin.types.upperIfFlexible
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
internal object CheckArguments : ResolutionPart {
|
||||
override fun SimpleKotlinResolutionCandidate.process(): List<KotlinCallDiagnostic> {
|
||||
val diagnostics = SmartList<KotlinCallDiagnostic>()
|
||||
for (parameterDescriptor in descriptorWithFreshTypes.valueParameters) {
|
||||
// error was reported in ArgumentsToParametersMapper
|
||||
val resolvedCallArgument = argumentMappingByOriginal[parameterDescriptor.original] ?: continue
|
||||
for (argument in resolvedCallArgument.arguments) {
|
||||
|
||||
val diagnostic = checkArgument(callContext, kotlinCall, csBuilder, argument, argument.getExpectedType(parameterDescriptor),
|
||||
postponeCallableReferenceArguments)
|
||||
diagnostics.addIfNotNull(diagnostic)
|
||||
|
||||
if (diagnostic != null && !diagnostic.candidateApplicability.isSuccess) break
|
||||
}
|
||||
}
|
||||
return diagnostics
|
||||
}
|
||||
|
||||
fun checkArgument(
|
||||
callContext: KotlinCallContext,
|
||||
kotlinCall: KotlinCall,
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
argument: KotlinCallArgument,
|
||||
expectedType: UnwrappedType,
|
||||
postponeCallableReferenceArguments: MutableList<PostponeCallableReferenceArgument>? = null
|
||||
): KotlinCallDiagnostic? {
|
||||
return when (argument) {
|
||||
is ExpressionKotlinCallArgument -> checkExpressionArgument(csBuilder, argument, expectedType, isReceiver = false)
|
||||
is SubKotlinCallArgument -> checkSubCallArgument(csBuilder, argument, expectedType, isReceiver = false)
|
||||
is LambdaKotlinCallArgument -> processLambdaArgument(kotlinCall, csBuilder, argument, expectedType)
|
||||
is CallableReferenceKotlinCallArgument -> {
|
||||
if (postponeCallableReferenceArguments == null) {
|
||||
processCallableReferenceArgument(callContext, kotlinCall, csBuilder, argument, expectedType)
|
||||
}
|
||||
else {
|
||||
// callable reference resolution will be run after choosing single descriptor
|
||||
postponeCallableReferenceArguments.add(PostponeCallableReferenceArgument(argument, expectedType))
|
||||
checkCallableExpectedType(csBuilder, argument, expectedType)
|
||||
}
|
||||
}
|
||||
is CollectionLiteralKotlinCallArgument -> processCollectionLiteralArgument(kotlinCall, csBuilder, argument, expectedType)
|
||||
else -> error("Incorrect argument type: $argument, ${argument.javaClass.canonicalName}.")
|
||||
}
|
||||
}
|
||||
|
||||
// if expected type isn't function type, then may be it is Function<R>, Any or just `T`
|
||||
private fun processLambdaArgument(
|
||||
kotlinCall: KotlinCall,
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
argument: LambdaKotlinCallArgument,
|
||||
expectedType: UnwrappedType
|
||||
): KotlinCallDiagnostic? {
|
||||
val builtIns = expectedType.builtIns
|
||||
val isSuspend = expectedType.isSuspendFunctionType
|
||||
|
||||
val receiverType: UnwrappedType? // null means that there is no receiver
|
||||
val parameters: List<UnwrappedType>
|
||||
val returnType: UnwrappedType
|
||||
|
||||
if (expectedType.isBuiltinFunctionalType) {
|
||||
receiverType = if (argument is FunctionExpression) argument.receiverType else expectedType.getReceiverTypeFromFunctionType()?.unwrap()
|
||||
|
||||
val expectedParameters = expectedType.getValueParameterTypesFromFunctionType()
|
||||
if (argument.parametersTypes != null) {
|
||||
parameters = argument.parametersTypes!!.mapIndexed {
|
||||
index, type ->
|
||||
type ?: expectedParameters.getOrNull(index)?.type?.unwrap() ?: builtIns.anyType
|
||||
}
|
||||
}
|
||||
else {
|
||||
// lambda without explicit parameters: { }
|
||||
parameters = expectedParameters.map { it.type.unwrap() }
|
||||
}
|
||||
returnType = (argument as? FunctionExpression)?.returnType ?: expectedType.getReturnTypeFromFunctionType().unwrap()
|
||||
}
|
||||
else {
|
||||
val isFunctionSupertype = KotlinBuiltIns.isNotNullOrNullableFunctionSupertype(expectedType)
|
||||
receiverType = (argument as? FunctionExpression)?.receiverType
|
||||
parameters = argument.parametersTypes?.map { it ?: builtIns.nothingType } ?: emptyList()
|
||||
returnType = (argument as? FunctionExpression)?.returnType ?:
|
||||
expectedType.arguments.singleOrNull()?.type?.unwrap()?.takeIf { isFunctionSupertype } ?:
|
||||
createFreshTypeVariableForLambdaReturnType(csBuilder, argument, builtIns)
|
||||
|
||||
// what about case where expected type is type variable? In old TY such cases was not supported. => do nothing for now. todo design
|
||||
}
|
||||
|
||||
val resolvedArgument = ResolvedLambdaArgument(kotlinCall, argument, isSuspend, receiverType, parameters, returnType)
|
||||
|
||||
csBuilder.addSubtypeConstraint(resolvedArgument.type, expectedType, ArgumentConstraintPosition(argument))
|
||||
csBuilder.addLambdaArgument(resolvedArgument)
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
private fun createFreshTypeVariableForLambdaReturnType(
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
argument: LambdaKotlinCallArgument,
|
||||
builtIns: KotlinBuiltIns
|
||||
): UnwrappedType {
|
||||
val typeVariable = TypeVariableForLambdaReturnType(argument, builtIns, "_L")
|
||||
csBuilder.registerVariable(typeVariable)
|
||||
return typeVariable.defaultType
|
||||
}
|
||||
|
||||
private fun checkCallableExpectedType(
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
argument: CallableReferenceKotlinCallArgument,
|
||||
expectedType: UnwrappedType
|
||||
): KotlinCallDiagnostic? {
|
||||
val notCallableTypeConstructor = csBuilder.getProperSuperTypeConstructors(expectedType).firstOrNull { !ReflectionTypes.isPossibleExpectedCallableType(it) }
|
||||
return notCallableTypeConstructor?.let { NotCallableExpectedType(argument, expectedType, notCallableTypeConstructor) }
|
||||
}
|
||||
|
||||
fun processCallableReferenceArgument(
|
||||
callContext: KotlinCallContext,
|
||||
kotlinCall: KotlinCall,
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
argument: CallableReferenceKotlinCallArgument,
|
||||
expectedType: UnwrappedType
|
||||
): KotlinCallDiagnostic? {
|
||||
val subLHSCall = ((argument.lhsResult as? LHSResult.Expression)?.lshCallArgument as? SubKotlinCallArgument)
|
||||
if (subLHSCall != null) {
|
||||
csBuilder.addInnerCall(subLHSCall.resolvedCall)
|
||||
}
|
||||
val candidates = callContext.callableReferenceResolver.runRLSResolution(callContext, argument, expectedType) { checkCallableReference ->
|
||||
csBuilder.runTransaction { checkCallableReference(this); false }
|
||||
}
|
||||
val chosenCandidate = when (candidates.size) {
|
||||
0 -> return NoneCallableReferenceCandidates(argument)
|
||||
1 -> candidates.single()
|
||||
else -> return CallableReferenceCandidatesAmbiguity(argument, candidates)
|
||||
}
|
||||
val (toFreshSubstitutor, diagnostic) = with(chosenCandidate) {
|
||||
csBuilder.checkCallableReference(argument, dispatchReceiver, extensionReceiver, candidate,
|
||||
reflectionCandidateType, expectedType, callContext.scopeTower.lexicalScope.ownerDescriptor)
|
||||
}
|
||||
|
||||
val resolvedCallableReference = ResolvedCallableReferenceArgument(
|
||||
kotlinCall, argument, toFreshSubstitutor.freshVariables,
|
||||
chosenCandidate, toFreshSubstitutor.safeSubstitute(chosenCandidate.reflectionCandidateType))
|
||||
|
||||
csBuilder.addCallableReferenceArgument(resolvedCallableReference)
|
||||
|
||||
return diagnostic
|
||||
}
|
||||
|
||||
fun processCollectionLiteralArgument(
|
||||
kotlinCall: KotlinCall,
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
collectionLiteralArgument: CollectionLiteralKotlinCallArgument,
|
||||
expectedType: UnwrappedType
|
||||
): KotlinCallDiagnostic? {
|
||||
csBuilder.addCollectionLiteralArgument(ResolvedCollectionLiteralArgument(kotlinCall, collectionLiteralArgument, expectedType))
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
internal fun checkExpressionArgument(
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
expressionArgument: ExpressionKotlinCallArgument,
|
||||
expectedType: UnwrappedType,
|
||||
isReceiver: Boolean
|
||||
): KotlinCallDiagnostic? {
|
||||
// todo run this approximation only once for call
|
||||
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(expressionArgument.receiver.stableType, expectedType)
|
||||
|
||||
fun unstableSmartCastOrSubtypeError(
|
||||
unstableType: UnwrappedType?, expectedType: UnwrappedType, position: ConstraintPosition
|
||||
): KotlinCallDiagnostic? {
|
||||
if (unstableType != null) {
|
||||
if (csBuilder.addSubtypeConstraintIfCompatible(unstableType, expectedType, position)) {
|
||||
return UnstableSmartCast(expressionArgument, unstableType)
|
||||
}
|
||||
}
|
||||
csBuilder.addSubtypeConstraint(argumentType, expectedType, position)
|
||||
return null
|
||||
}
|
||||
|
||||
val expectedNullableType = expectedType.makeNullableAsSpecified(true)
|
||||
val position = if (isReceiver) ReceiverConstraintPosition(expressionArgument) else ArgumentConstraintPosition(expressionArgument)
|
||||
if (expressionArgument.isSafeCall) {
|
||||
if (!csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedNullableType, position)) {
|
||||
return unstableSmartCastOrSubtypeError(expressionArgument.receiver.unstableType, expectedNullableType, position)?.let { return it }
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
if (!csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedType, position)) {
|
||||
if (!isReceiver) {
|
||||
return unstableSmartCastOrSubtypeError(expressionArgument.receiver.unstableType, expectedType, position)?.let { return it }
|
||||
}
|
||||
|
||||
val unstableType = expressionArgument.receiver.unstableType
|
||||
if (unstableType != null && csBuilder.addSubtypeConstraintIfCompatible(unstableType, expectedType, position)) {
|
||||
return UnstableSmartCast(expressionArgument, unstableType)
|
||||
}
|
||||
else if (csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedNullableType, position)) {
|
||||
return UnsafeCallError(expressionArgument)
|
||||
}
|
||||
else {
|
||||
csBuilder.addSubtypeConstraint(argumentType, expectedType, position)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* interface Inv<T>
|
||||
* fun <Y> bar(l: Inv<Y>): Y = ...
|
||||
*
|
||||
* fun <X : Inv<out Int>> foo(x: X) {
|
||||
* val xr = bar(x)
|
||||
* }
|
||||
* Here we try to capture from upper bound from type parameter.
|
||||
* We replace type of `x` to `Inv<out Int>`(we chose supertype which contains supertype with expectedTypeConstructor) and capture from this type.
|
||||
* It is correct, because it is like this code:
|
||||
* fun <X : Inv<out Int>> foo(x: X) {
|
||||
* val inv: Inv<out Int> = x
|
||||
* val xr = bar(inv)
|
||||
* }
|
||||
*
|
||||
*/
|
||||
private fun captureFromTypeParameterUpperBoundIfNeeded(argumentType: UnwrappedType, expectedType: UnwrappedType): UnwrappedType {
|
||||
val expectedTypeConstructor = expectedType.upperIfFlexible().constructor
|
||||
|
||||
if (argumentType.lowerIfFlexible().constructor.declarationDescriptor is TypeParameterDescriptor) {
|
||||
val chosenSupertype = argumentType.lowerIfFlexible().supertypes().singleOrNull {
|
||||
it.constructor.declarationDescriptor is ClassifierDescriptorWithTypeParameters &&
|
||||
it.unwrap().hasSupertypeWithGivenTypeConstructor(expectedTypeConstructor)
|
||||
}
|
||||
if (chosenSupertype != null) {
|
||||
return captureFromExpression(chosenSupertype.unwrap()) ?: argumentType
|
||||
}
|
||||
}
|
||||
|
||||
return argumentType
|
||||
}
|
||||
|
||||
// if expression is not stable and has smart casts, then we create this type
|
||||
private val ReceiverValueWithSmartCastInfo.unstableType: UnwrappedType?
|
||||
get() {
|
||||
if (isStable || possibleTypes.isEmpty()) return null
|
||||
return intersectWrappedTypes(possibleTypes + receiverValue.type)
|
||||
}
|
||||
|
||||
// with all smart casts if stable
|
||||
internal val ReceiverValueWithSmartCastInfo.stableType: UnwrappedType
|
||||
get() {
|
||||
if (!isStable || possibleTypes.isEmpty()) return receiverValue.type.unwrap()
|
||||
return intersectWrappedTypes(possibleTypes + receiverValue.type)
|
||||
}
|
||||
|
||||
|
||||
internal fun checkSubCallArgument(
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
subCallArgument: SubKotlinCallArgument,
|
||||
expectedType: UnwrappedType,
|
||||
isReceiver: Boolean
|
||||
): KotlinCallDiagnostic? {
|
||||
val resolvedCall = subCallArgument.resolvedCall
|
||||
val expectedNullableType = expectedType.makeNullableAsSpecified(true)
|
||||
val position = ArgumentConstraintPosition(subCallArgument)
|
||||
|
||||
csBuilder.addInnerCall(resolvedCall)
|
||||
|
||||
// subArgument cannot has stable smartcast
|
||||
val currentReturnType = subCallArgument.receiver.receiverValue.type.unwrap()
|
||||
if (subCallArgument.isSafeCall) {
|
||||
csBuilder.addSubtypeConstraint(currentReturnType, expectedNullableType, position)
|
||||
return null
|
||||
}
|
||||
|
||||
if (isReceiver && !csBuilder.addSubtypeConstraintIfCompatible(currentReturnType, expectedType, position) &&
|
||||
csBuilder.addSubtypeConstraintIfCompatible(currentReturnType, expectedNullableType, position)
|
||||
) {
|
||||
return UnsafeCallError(subCallArgument)
|
||||
}
|
||||
|
||||
csBuilder.addSubtypeConstraint(currentReturnType, expectedType, position)
|
||||
return null
|
||||
}
|
||||
|
||||
internal fun KotlinCallArgument.getExpectedType(parameter: ValueParameterDescriptor) =
|
||||
if (this.isSpread) {
|
||||
parameter.type.unwrap()
|
||||
}
|
||||
else {
|
||||
parameter.varargElementType?.unwrap() ?: parameter.type.unwrap()
|
||||
}
|
||||
+4
-5
@@ -104,7 +104,7 @@ class KotlinCallCompleter(
|
||||
|
||||
private fun resolveCallableReferenceArguments(candidate: SimpleKotlinResolutionCandidate) {
|
||||
for (callableReferenceArgument in candidate.postponeCallableReferenceArguments) {
|
||||
CheckArguments.processCallableReferenceArgument(candidate.callContext, candidate.kotlinCall, candidate.csBuilder,
|
||||
processCallableReferenceArgument(candidate.callContext, candidate.kotlinCall, candidate.csBuilder,
|
||||
callableReferenceArgument.argument, callableReferenceArgument.expectedType)
|
||||
}
|
||||
candidate.postponeCallableReferenceArguments.clear()
|
||||
@@ -242,7 +242,7 @@ class KotlinCallCompleter(
|
||||
|
||||
val lambda = c.lambdaArguments.find { canWeAnalyzeIt(c, it) }
|
||||
if (lambda != null) {
|
||||
analyzeLambda(c, resolutionCallbacks, callContext, kotlinCall, lambda)
|
||||
analyzeLambda(c, resolutionCallbacks, lambda)
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -262,7 +262,7 @@ class KotlinCallCompleter(
|
||||
return true
|
||||
}
|
||||
|
||||
private fun analyzeLambda(c: Context, resolutionCallbacks: KotlinResolutionCallbacks, topLevelCallContext: KotlinCallContext, topLevelCall: KotlinCall, lambda: ResolvedLambdaArgument) {
|
||||
private fun analyzeLambda(c: Context, resolutionCallbacks: KotlinResolutionCallbacks, lambda: ResolvedLambdaArgument) {
|
||||
val currentSubstitutor = c.buildCurrentSubstitutor()
|
||||
fun substitute(type: UnwrappedType) = currentSubstitutor.safeSubstitute(type)
|
||||
|
||||
@@ -273,8 +273,7 @@ class KotlinCallCompleter(
|
||||
lambda.resultArguments = resolutionCallbacks.analyzeAndGetLambdaResultArguments(lambda.outerCall, lambda.argument, lambda.isSuspend, receiver, parameters, expectedType)
|
||||
|
||||
for (innerCall in lambda.resultArguments) {
|
||||
// todo strange code -- why top-level kotlinCall? may be it isn't right outer call
|
||||
CheckArguments.checkArgument(topLevelCallContext, topLevelCall, c.getBuilder(), innerCall, lambda.returnType.let(::substitute))
|
||||
checkSimpleArgument(c.getBuilder(), innerCall, lambda.returnType.let(::substitute))
|
||||
}
|
||||
|
||||
if (lambda.resultArguments.isEmpty()) {
|
||||
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.components
|
||||
|
||||
import org.jetbrains.kotlin.builtins.*
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableForLambdaReturnType
|
||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
|
||||
fun createPostponedArgumentAndPerformInitialChecks(
|
||||
kotlinCall: KotlinCall,
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
argument: PostponableCallArgument,
|
||||
parameterDescriptor: ValueParameterDescriptor,
|
||||
postponeCallableReferenceArguments: MutableList<PostponeCallableReferenceArgument>
|
||||
): KotlinCallDiagnostic? {
|
||||
val expectedType = argument.getExpectedType(parameterDescriptor)
|
||||
return when (argument) {
|
||||
is LambdaKotlinCallArgument -> processLambdaArgument(kotlinCall, csBuilder, argument, expectedType)
|
||||
is CallableReferenceKotlinCallArgument -> {
|
||||
// callable reference resolution will be run after choosing single descriptor
|
||||
postponeCallableReferenceArguments.add(PostponeCallableReferenceArgument(argument, expectedType))
|
||||
checkCallableExpectedType(csBuilder, argument, expectedType)
|
||||
}
|
||||
is CollectionLiteralKotlinCallArgument -> processCollectionLiteralArgument(kotlinCall, csBuilder, argument, expectedType)
|
||||
else -> unexpectedArgument(argument)
|
||||
}
|
||||
}
|
||||
|
||||
// if expected type isn't function type, then may be it is Function<R>, Any or just `T`
|
||||
private fun processLambdaArgument(
|
||||
kotlinCall: KotlinCall,
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
argument: LambdaKotlinCallArgument,
|
||||
expectedType: UnwrappedType
|
||||
): KotlinCallDiagnostic? {
|
||||
val builtIns = expectedType.builtIns
|
||||
val isSuspend = expectedType.isSuspendFunctionType
|
||||
|
||||
val receiverType: UnwrappedType? // null means that there is no receiver
|
||||
val parameters: List<UnwrappedType>
|
||||
val returnType: UnwrappedType
|
||||
|
||||
if (expectedType.isBuiltinFunctionalType) {
|
||||
receiverType = if (argument is FunctionExpression) argument.receiverType else expectedType.getReceiverTypeFromFunctionType()?.unwrap()
|
||||
|
||||
val expectedParameters = expectedType.getValueParameterTypesFromFunctionType()
|
||||
if (argument.parametersTypes != null) {
|
||||
parameters = argument.parametersTypes!!.mapIndexed {
|
||||
index, type ->
|
||||
type ?: expectedParameters.getOrNull(index)?.type?.unwrap() ?: builtIns.anyType
|
||||
}
|
||||
}
|
||||
else {
|
||||
// lambda without explicit parameters: { }
|
||||
parameters = expectedParameters.map { it.type.unwrap() }
|
||||
}
|
||||
returnType = (argument as? FunctionExpression)?.returnType ?: expectedType.getReturnTypeFromFunctionType().unwrap()
|
||||
}
|
||||
else {
|
||||
val isFunctionSupertype = KotlinBuiltIns.isNotNullOrNullableFunctionSupertype(expectedType)
|
||||
receiverType = (argument as? FunctionExpression)?.receiverType
|
||||
parameters = argument.parametersTypes?.map { it ?: builtIns.nothingType } ?: emptyList()
|
||||
returnType = (argument as? FunctionExpression)?.returnType ?:
|
||||
expectedType.arguments.singleOrNull()?.type?.unwrap()?.takeIf { isFunctionSupertype } ?:
|
||||
createFreshTypeVariableForLambdaReturnType(csBuilder, argument, builtIns)
|
||||
|
||||
// what about case where expected type is type variable? In old TY such cases was not supported. => do nothing for now. todo design
|
||||
}
|
||||
|
||||
val resolvedArgument = ResolvedLambdaArgument(kotlinCall, argument, isSuspend, receiverType, parameters, returnType)
|
||||
|
||||
csBuilder.addSubtypeConstraint(resolvedArgument.type, expectedType, ArgumentConstraintPosition(argument))
|
||||
csBuilder.addLambdaArgument(resolvedArgument)
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
|
||||
private fun createFreshTypeVariableForLambdaReturnType(
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
argument: LambdaKotlinCallArgument,
|
||||
builtIns: KotlinBuiltIns
|
||||
): UnwrappedType {
|
||||
val typeVariable = TypeVariableForLambdaReturnType(argument, builtIns, "_L")
|
||||
csBuilder.registerVariable(typeVariable)
|
||||
return typeVariable.defaultType
|
||||
}
|
||||
|
||||
private fun checkCallableExpectedType(
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
argument: CallableReferenceKotlinCallArgument,
|
||||
expectedType: UnwrappedType
|
||||
): KotlinCallDiagnostic? {
|
||||
val notCallableTypeConstructor = csBuilder.getProperSuperTypeConstructors(expectedType).firstOrNull { !ReflectionTypes.isPossibleExpectedCallableType(it) }
|
||||
return notCallableTypeConstructor?.let { NotCallableExpectedType(argument, expectedType, notCallableTypeConstructor) }
|
||||
}
|
||||
|
||||
fun processCallableReferenceArgument(
|
||||
callContext: KotlinCallContext,
|
||||
kotlinCall: KotlinCall,
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
argument: CallableReferenceKotlinCallArgument,
|
||||
expectedType: UnwrappedType
|
||||
): KotlinCallDiagnostic? {
|
||||
val subLHSCall = ((argument.lhsResult as? LHSResult.Expression)?.lshCallArgument as? SubKotlinCallArgument)
|
||||
if (subLHSCall != null) {
|
||||
csBuilder.addInnerCall(subLHSCall.resolvedCall)
|
||||
}
|
||||
val candidates = callContext.callableReferenceResolver.runRLSResolution(callContext, argument, expectedType) { checkCallableReference ->
|
||||
csBuilder.runTransaction { checkCallableReference(this); false }
|
||||
}
|
||||
val chosenCandidate = when (candidates.size) {
|
||||
0 -> return NoneCallableReferenceCandidates(argument)
|
||||
1 -> candidates.single()
|
||||
else -> return CallableReferenceCandidatesAmbiguity(argument, candidates)
|
||||
}
|
||||
val (toFreshSubstitutor, diagnostic) = with(chosenCandidate) {
|
||||
csBuilder.checkCallableReference(argument, dispatchReceiver, extensionReceiver, candidate,
|
||||
reflectionCandidateType, expectedType, callContext.scopeTower.lexicalScope.ownerDescriptor)
|
||||
}
|
||||
|
||||
val resolvedCallableReference = ResolvedCallableReferenceArgument(
|
||||
kotlinCall, argument, toFreshSubstitutor.freshVariables,
|
||||
chosenCandidate, toFreshSubstitutor.safeSubstitute(chosenCandidate.reflectionCandidateType))
|
||||
|
||||
csBuilder.addCallableReferenceArgument(resolvedCallableReference)
|
||||
|
||||
return diagnostic
|
||||
}
|
||||
|
||||
fun processCollectionLiteralArgument(
|
||||
kotlinCall: KotlinCall,
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
collectionLiteralArgument: CollectionLiteralKotlinCallArgument,
|
||||
expectedType: UnwrappedType
|
||||
): KotlinCallDiagnostic? {
|
||||
csBuilder.addCollectionLiteralArgument(ResolvedCollectionLiteralArgument(kotlinCall, collectionLiteralArgument, expectedType))
|
||||
return null
|
||||
}
|
||||
+24
-30
@@ -32,10 +32,11 @@ import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.INAPPLICABLE
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.ResolutionCandidateApplicability.RUNTIME_ERROR
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.VisibilityError
|
||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||
import org.jetbrains.kotlin.types.TypeConstructor
|
||||
import org.jetbrains.kotlin.types.TypeSubstitutor
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
import org.jetbrains.kotlin.utils.SmartList
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
internal object CheckInstantiationOfAbstractClass : ResolutionPart {
|
||||
override fun SimpleKotlinResolutionCandidate.process(): List<KotlinCallDiagnostic> {
|
||||
@@ -220,27 +221,36 @@ internal object CheckReceivers : ResolutionPart {
|
||||
|
||||
val expectedType = receiverParameter.type.unwrap()
|
||||
|
||||
return when (receiverArgument) {
|
||||
is ExpressionKotlinCallArgument -> checkExpressionArgument(csBuilder, receiverArgument, expectedType, isReceiver = true)
|
||||
is SubKotlinCallArgument -> checkSubCallArgument(csBuilder, receiverArgument, expectedType, isReceiver = true)
|
||||
else -> incorrectReceiver(receiverArgument)
|
||||
}
|
||||
return checkSimpleArgument(csBuilder, receiverArgument, expectedType, isReceiver = true)
|
||||
}
|
||||
|
||||
private fun incorrectReceiver(callReceiver: SimpleKotlinCallArgument): Nothing =
|
||||
error("Incorrect receiver type: $callReceiver. Class name: ${callReceiver.javaClass.canonicalName}")
|
||||
|
||||
override fun SimpleKotlinResolutionCandidate.process() =
|
||||
listOfNotNull(checkReceiver(dispatchReceiverArgument, descriptorWithFreshTypes.dispatchReceiverParameter),
|
||||
checkReceiver(extensionReceiver, descriptorWithFreshTypes.extensionReceiverParameter))
|
||||
}
|
||||
|
||||
internal object CheckArguments : ResolutionPart {
|
||||
override fun SimpleKotlinResolutionCandidate.process(): List<KotlinCallDiagnostic> {
|
||||
val diagnostics = SmartList<KotlinCallDiagnostic>()
|
||||
for (parameterDescriptor in descriptorWithFreshTypes.valueParameters) {
|
||||
// error was reported in ArgumentsToParametersMapper
|
||||
val resolvedCallArgument = argumentMappingByOriginal[parameterDescriptor.original] ?: continue
|
||||
for (argument in resolvedCallArgument.arguments) {
|
||||
|
||||
fun <D : CallableDescriptor> D.safeSubstitute(substitutor: TypeSubstitutor): D =
|
||||
@Suppress("UNCHECKED_CAST") (substitute(substitutor) as D)
|
||||
|
||||
fun UnwrappedType.substitute(substitutor: TypeSubstitutor): UnwrappedType = substitutor.substitute(this, Variance.INVARIANT)!!.unwrap()
|
||||
val diagnostic = when (argument) {
|
||||
is SimpleKotlinCallArgument -> checkSimpleArgument(csBuilder, argument, argument.getExpectedType(parameterDescriptor))
|
||||
is PostponableCallArgument ->
|
||||
createPostponedArgumentAndPerformInitialChecks(kotlinCall, csBuilder, argument, parameterDescriptor, postponeCallableReferenceArguments)
|
||||
else -> unexpectedArgument(argument)
|
||||
}
|
||||
diagnostics.addIfNotNull(diagnostic)
|
||||
|
||||
if (diagnostic != null && !diagnostic.candidateApplicability.isSuccess) break
|
||||
}
|
||||
}
|
||||
return diagnostics
|
||||
}
|
||||
}
|
||||
|
||||
object InstantiationOfAbstractClass : KotlinCallDiagnostic(RUNTIME_ERROR) {
|
||||
override fun report(reporter: DiagnosticReporter) = reporter.onCall(this)
|
||||
@@ -255,22 +265,6 @@ class UnsafeCallError(val receiver: SimpleKotlinCallArgument) : KotlinCallDiagno
|
||||
override fun report(reporter: DiagnosticReporter) = reporter.onCallReceiver(receiver, this)
|
||||
}
|
||||
|
||||
class ExpectedLambdaParametersCountMismatch(
|
||||
val lambdaArgument: LambdaKotlinCallArgument,
|
||||
val expected: Int,
|
||||
val actual: Int
|
||||
) : KotlinCallDiagnostic(INAPPLICABLE) {
|
||||
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(lambdaArgument, this)
|
||||
}
|
||||
|
||||
class UnexpectedReceiver(val functionExpression: FunctionExpression) : KotlinCallDiagnostic(INAPPLICABLE) {
|
||||
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(functionExpression, this)
|
||||
}
|
||||
|
||||
class MissingReceiver(val functionExpression: FunctionExpression) : KotlinCallDiagnostic(INAPPLICABLE) {
|
||||
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(functionExpression, this)
|
||||
}
|
||||
|
||||
class NoneCallableReferenceCandidates(val argument: CallableReferenceKotlinCallArgument) : KotlinCallDiagnostic(INAPPLICABLE) {
|
||||
override fun report(reporter: DiagnosticReporter) = reporter.onCallArgument(argument, this)
|
||||
}
|
||||
|
||||
+162
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.resolve.calls.components
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.ClassifierDescriptorWithTypeParameters
|
||||
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ArgumentConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.inference.model.ReceiverConstraintPosition
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ExpressionKotlinCallArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic
|
||||
import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument
|
||||
import org.jetbrains.kotlin.resolve.calls.model.SubKotlinCallArgument
|
||||
import org.jetbrains.kotlin.types.UnwrappedType
|
||||
import org.jetbrains.kotlin.types.checker.captureFromExpression
|
||||
import org.jetbrains.kotlin.types.checker.hasSupertypeWithGivenTypeConstructor
|
||||
import org.jetbrains.kotlin.types.lowerIfFlexible
|
||||
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
||||
import org.jetbrains.kotlin.types.upperIfFlexible
|
||||
|
||||
|
||||
fun checkSimpleArgument(
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
argument: SimpleKotlinCallArgument,
|
||||
expectedType: UnwrappedType,
|
||||
isReceiver: Boolean = false
|
||||
): KotlinCallDiagnostic? {
|
||||
return when (argument) {
|
||||
is ExpressionKotlinCallArgument -> checkExpressionArgument(csBuilder, argument, expectedType, isReceiver)
|
||||
is SubKotlinCallArgument -> checkSubCallArgument(csBuilder, argument, expectedType, isReceiver)
|
||||
else -> unexpectedArgument(argument)
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkExpressionArgument(
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
expressionArgument: ExpressionKotlinCallArgument,
|
||||
expectedType: UnwrappedType,
|
||||
isReceiver: Boolean
|
||||
): KotlinCallDiagnostic? {
|
||||
// todo run this approximation only once for call
|
||||
val argumentType = captureFromTypeParameterUpperBoundIfNeeded(expressionArgument.receiver.stableType, expectedType)
|
||||
|
||||
fun unstableSmartCastOrSubtypeError(
|
||||
unstableType: UnwrappedType?, actualExpectedType: UnwrappedType, position: ConstraintPosition
|
||||
): KotlinCallDiagnostic? {
|
||||
if (unstableType != null) {
|
||||
if (csBuilder.addSubtypeConstraintIfCompatible(unstableType, actualExpectedType, position)) {
|
||||
return UnstableSmartCast(expressionArgument, unstableType)
|
||||
}
|
||||
}
|
||||
csBuilder.addSubtypeConstraint(argumentType, actualExpectedType, position)
|
||||
return null
|
||||
}
|
||||
|
||||
val expectedNullableType = expectedType.makeNullableAsSpecified(true)
|
||||
val position = if (isReceiver) ReceiverConstraintPosition(expressionArgument) else ArgumentConstraintPosition(expressionArgument)
|
||||
if (expressionArgument.isSafeCall) {
|
||||
if (!csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedNullableType, position)) {
|
||||
return unstableSmartCastOrSubtypeError(expressionArgument.receiver.unstableType, expectedNullableType, position)?.let { return it }
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
if (!csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedType, position)) {
|
||||
if (!isReceiver) {
|
||||
return unstableSmartCastOrSubtypeError(expressionArgument.receiver.unstableType, expectedType, position)?.let { return it }
|
||||
}
|
||||
|
||||
val unstableType = expressionArgument.receiver.unstableType
|
||||
if (unstableType != null && csBuilder.addSubtypeConstraintIfCompatible(unstableType, expectedType, position)) {
|
||||
return UnstableSmartCast(expressionArgument, unstableType)
|
||||
}
|
||||
else if (csBuilder.addSubtypeConstraintIfCompatible(argumentType, expectedNullableType, position)) {
|
||||
return UnsafeCallError(expressionArgument)
|
||||
}
|
||||
else {
|
||||
csBuilder.addSubtypeConstraint(argumentType, expectedType, position)
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* interface Inv<T>
|
||||
* fun <Y> bar(l: Inv<Y>): Y = ...
|
||||
*
|
||||
* fun <X : Inv<out Int>> foo(x: X) {
|
||||
* val xr = bar(x)
|
||||
* }
|
||||
* Here we try to capture from upper bound from type parameter.
|
||||
* We replace type of `x` to `Inv<out Int>`(we chose supertype which contains supertype with expectedTypeConstructor) and capture from this type.
|
||||
* It is correct, because it is like this code:
|
||||
* fun <X : Inv<out Int>> foo(x: X) {
|
||||
* val inv: Inv<out Int> = x
|
||||
* val xr = bar(inv)
|
||||
* }
|
||||
*
|
||||
*/
|
||||
private fun captureFromTypeParameterUpperBoundIfNeeded(argumentType: UnwrappedType, expectedType: UnwrappedType): UnwrappedType {
|
||||
val expectedTypeConstructor = expectedType.upperIfFlexible().constructor
|
||||
|
||||
if (argumentType.lowerIfFlexible().constructor.declarationDescriptor is TypeParameterDescriptor) {
|
||||
val chosenSupertype = argumentType.lowerIfFlexible().supertypes().singleOrNull {
|
||||
it.constructor.declarationDescriptor is ClassifierDescriptorWithTypeParameters &&
|
||||
it.unwrap().hasSupertypeWithGivenTypeConstructor(expectedTypeConstructor)
|
||||
}
|
||||
if (chosenSupertype != null) {
|
||||
return captureFromExpression(chosenSupertype.unwrap()) ?: argumentType
|
||||
}
|
||||
}
|
||||
|
||||
return argumentType
|
||||
}
|
||||
|
||||
private fun checkSubCallArgument(
|
||||
csBuilder: ConstraintSystemBuilder,
|
||||
subCallArgument: SubKotlinCallArgument,
|
||||
expectedType: UnwrappedType,
|
||||
isReceiver: Boolean
|
||||
): KotlinCallDiagnostic? {
|
||||
val resolvedCall = subCallArgument.resolvedCall
|
||||
val expectedNullableType = expectedType.makeNullableAsSpecified(true)
|
||||
val position = ArgumentConstraintPosition(subCallArgument)
|
||||
|
||||
csBuilder.addInnerCall(resolvedCall)
|
||||
|
||||
// subArgument cannot has stable smartcast
|
||||
val currentReturnType = subCallArgument.receiver.receiverValue.type.unwrap()
|
||||
if (subCallArgument.isSafeCall) {
|
||||
csBuilder.addSubtypeConstraint(currentReturnType, expectedNullableType, position)
|
||||
return null
|
||||
}
|
||||
|
||||
if (isReceiver && !csBuilder.addSubtypeConstraintIfCompatible(currentReturnType, expectedType, position) &&
|
||||
csBuilder.addSubtypeConstraintIfCompatible(currentReturnType, expectedNullableType, position)
|
||||
) {
|
||||
return UnsafeCallError(subCallArgument)
|
||||
}
|
||||
|
||||
csBuilder.addSubtypeConstraint(currentReturnType, expectedType, position)
|
||||
return null
|
||||
}
|
||||
|
||||
+5
-3
@@ -39,6 +39,8 @@ interface KotlinCallArgument {
|
||||
val argumentName: Name?
|
||||
}
|
||||
|
||||
interface PostponableCallArgument : KotlinCallArgument
|
||||
|
||||
interface SimpleKotlinCallArgument : KotlinCallArgument, ReceiverKotlinCallArgument {
|
||||
override val receiver: ReceiverValueWithSmartCastInfo
|
||||
|
||||
@@ -51,7 +53,7 @@ interface SubKotlinCallArgument : SimpleKotlinCallArgument {
|
||||
val resolvedCall: ResolvedKotlinCall.OnlyResolvedKotlinCall
|
||||
}
|
||||
|
||||
interface LambdaKotlinCallArgument : KotlinCallArgument {
|
||||
interface LambdaKotlinCallArgument : PostponableCallArgument {
|
||||
override val isSpread: Boolean
|
||||
get() = false
|
||||
|
||||
@@ -110,7 +112,7 @@ sealed class LHSResult {
|
||||
object Empty: LHSResult()
|
||||
}
|
||||
|
||||
interface CallableReferenceKotlinCallArgument : KotlinCallArgument {
|
||||
interface CallableReferenceKotlinCallArgument : PostponableCallArgument {
|
||||
override val isSpread: Boolean
|
||||
get() = false
|
||||
|
||||
@@ -119,7 +121,7 @@ interface CallableReferenceKotlinCallArgument : KotlinCallArgument {
|
||||
val rhsName: Name
|
||||
}
|
||||
|
||||
interface CollectionLiteralKotlinCallArgument : KotlinCallArgument
|
||||
interface CollectionLiteralKotlinCallArgument : PostponableCallArgument
|
||||
|
||||
interface TypeArgument
|
||||
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ class ResolvedLambdaArgument(
|
||||
override val inputTypes: Collection<UnwrappedType> get() = receiver?.let { parameters + it } ?: parameters
|
||||
override val outputType: UnwrappedType get() = returnType
|
||||
|
||||
lateinit var resultArguments: List<KotlinCallArgument>
|
||||
lateinit var resultArguments: List<SimpleKotlinCallArgument>
|
||||
lateinit var finalReturnType: UnwrappedType
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user