[FE 1.0] Get rid of the old builder inference support
This commit is contained in:
committed by
teamcity
parent
bd665dc5d9
commit
1c91e3a606
@@ -54,7 +54,6 @@ val SPECIAL_FUNCTION_NAMES = ResolveConstruct.values().map { it.specialFunctionN
|
|||||||
|
|
||||||
class GenericCandidateResolver(
|
class GenericCandidateResolver(
|
||||||
private val argumentTypeResolver: ArgumentTypeResolver,
|
private val argumentTypeResolver: ArgumentTypeResolver,
|
||||||
private val builderInferenceSupport: BuilderInferenceSupport,
|
|
||||||
private val languageVersionSettings: LanguageVersionSettings,
|
private val languageVersionSettings: LanguageVersionSettings,
|
||||||
private val dataFlowValueFactory: DataFlowValueFactory
|
private val dataFlowValueFactory: DataFlowValueFactory
|
||||||
) {
|
) {
|
||||||
@@ -384,10 +383,6 @@ class GenericCandidateResolver(
|
|||||||
|
|
||||||
val effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument, context)
|
val effectiveExpectedType = getEffectiveExpectedType(valueParameterDescriptor, valueArgument, context)
|
||||||
|
|
||||||
if (isBuilderInferenceCall(valueParameterDescriptor, valueArgument, languageVersionSettings)) {
|
|
||||||
builderInferenceSupport.analyzeBuilderInferenceCall(functionLiteral, valueArgument, constraintSystem, context, effectiveExpectedType)
|
|
||||||
}
|
|
||||||
|
|
||||||
val currentSubstitutor = constraintSystem.build().currentSubstitutor
|
val currentSubstitutor = constraintSystem.build().currentSubstitutor
|
||||||
val newSubstitution = object : DelegatedTypeSubstitution(currentSubstitutor.substitution) {
|
val newSubstitution = object : DelegatedTypeSubstitution(currentSubstitutor.substitution) {
|
||||||
override fun approximateContravariantCapturedTypes() = true
|
override fun approximateContravariantCapturedTypes() = true
|
||||||
|
|||||||
+4
-324
@@ -9,331 +9,27 @@ import org.jetbrains.kotlin.builtins.*
|
|||||||
import org.jetbrains.kotlin.config.LanguageFeature
|
import org.jetbrains.kotlin.config.LanguageFeature
|
||||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.coroutines.hasFunctionOrSuspendFunctionType
|
import org.jetbrains.kotlin.coroutines.hasFunctionOrSuspendFunctionType
|
||||||
import org.jetbrains.kotlin.coroutines.hasSuspendFunctionType
|
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRendererOptions
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver.getCallableReferenceExpressionIfAny
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver.getFunctionLiteralArgumentIfAny
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.CallCompleter
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.util.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.util.getEffectiveExpectedType
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.util.hasUnknownFunctionParameter
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.*
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.constraintPosition.ConstraintPositionKind
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ArgumentMatch
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.isReallySuccess
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.TracingStrategy
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.hasBuilderInferenceAnnotation
|
import org.jetbrains.kotlin.resolve.descriptorUtil.hasBuilderInferenceAnnotation
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
|
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE
|
|
||||||
import org.jetbrains.kotlin.types.checker.ClassicTypeCheckerState
|
|
||||||
import org.jetbrains.kotlin.types.checker.ClassicTypeCheckerStateInternals
|
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
|
|
||||||
import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker
|
|
||||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
|
|
||||||
import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo
|
|
||||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
|
||||||
import org.jetbrains.kotlin.types.typeUtil.*
|
import org.jetbrains.kotlin.types.typeUtil.*
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class TypeTemplate(
|
|
||||||
val typeVariable: TypeVariable,
|
|
||||||
val builderInferenceData: BuilderInferenceData,
|
|
||||||
nullable: Boolean = true
|
|
||||||
) : FlexibleType(
|
|
||||||
typeVariable.originalTypeParameter.builtIns.nothingType,
|
|
||||||
typeVariable.originalTypeParameter.builtIns.anyType.makeNullableAsSpecified(nullable)
|
|
||||||
) {
|
|
||||||
override fun replaceAttributes(newAttributes: TypeAttributes) = this
|
|
||||||
|
|
||||||
override fun makeNullableAsSpecified(newNullability: Boolean) = TypeTemplate(typeVariable, builderInferenceData, newNullability)
|
|
||||||
|
|
||||||
override val delegate: SimpleType
|
|
||||||
get() = upperBound
|
|
||||||
|
|
||||||
override fun render(renderer: DescriptorRenderer, options: DescriptorRendererOptions) =
|
|
||||||
"~${renderer.renderType(typeVariable.type)}"
|
|
||||||
|
|
||||||
@TypeRefinement
|
|
||||||
override fun refine(kotlinTypeRefiner: KotlinTypeRefiner) = this
|
|
||||||
}
|
|
||||||
|
|
||||||
class BuilderInferenceData {
|
|
||||||
private val csBuilder = ConstraintSystemBuilderImpl()
|
|
||||||
private val typeTemplates = HashMap<TypeVariable, TypeTemplate>()
|
|
||||||
private var hereIsBadCall = false
|
|
||||||
|
|
||||||
fun getTypeTemplate(typeVariable: TypeVariable) =
|
|
||||||
typeTemplates.getOrPut(typeVariable) {
|
|
||||||
TypeTemplate(typeVariable, this)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun initSystem() {
|
|
||||||
csBuilder.registerTypeVariables(CallHandle.NONE, typeTemplates.keys.map { it.freshTypeParameter })
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toNewVariableType(type: KotlinType): KotlinType {
|
|
||||||
return (type.unwrap() as? TypeTemplate)?.typeVariable?.freshTypeParameter?.let { typeVariable ->
|
|
||||||
csBuilder.typeVariableSubstitutors[CallHandle.NONE]?.substitution?.get(typeVariable.defaultType)?.type
|
|
||||||
} ?: type
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun addConstraint(subType: KotlinType, superType: KotlinType, allowOnlyTrivialConstraints: Boolean) {
|
|
||||||
val newSubType = toNewVariableType(subType)
|
|
||||||
val newSuperType = toNewVariableType(superType)
|
|
||||||
|
|
||||||
if (allowOnlyTrivialConstraints) {
|
|
||||||
if (isTrivialConstraint(subType, superType)) {
|
|
||||||
// It's important to avoid adding even trivial constraints from extensions,
|
|
||||||
// because we allow only calls that don't matter at all and here we can get
|
|
||||||
// into a situation when type is inferred from only trivial constraints to Any?, for example.
|
|
||||||
|
|
||||||
// Actually, this is a more general problem about inferring type without constraints (KT-5464)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
badCallHappened()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
csBuilder.addSubtypeConstraint(newSubType, newSuperType, ConstraintPositionKind.SPECIAL.position())
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isTrivialConstraint(subType: KotlinType, superType: KotlinType): Boolean {
|
|
||||||
return subType is SimpleType && subType.isNothing() || superType is SimpleType && superType.isNullableAny()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun reportInferenceResult(externalCSBuilder: ConstraintSystem.Builder) {
|
|
||||||
if (hereIsBadCall) return
|
|
||||||
|
|
||||||
val resultingSubstitution = csBuilder.build().resultingSubstitutor.substitution
|
|
||||||
for ((originalTypeVariable) in typeTemplates) {
|
|
||||||
resultingSubstitution[originalTypeVariable.type]?.type.let {
|
|
||||||
externalCSBuilder.addSubtypeConstraint(originalTypeVariable.type, it, ConstraintPositionKind.FROM_COMPLETER.position())
|
|
||||||
externalCSBuilder.addSubtypeConstraint(it, originalTypeVariable.type, ConstraintPositionKind.FROM_COMPLETER.position())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun badCallHappened() {
|
|
||||||
hereIsBadCall = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class BuilderInferenceSupport(
|
|
||||||
val argumentTypeResolver: ArgumentTypeResolver,
|
|
||||||
val expressionTypingServices: ExpressionTypingServices
|
|
||||||
) {
|
|
||||||
@set:Inject
|
|
||||||
lateinit var callCompleter: CallCompleter
|
|
||||||
|
|
||||||
private val languageVersionSettings get() = expressionTypingServices.languageVersionSettings
|
|
||||||
|
|
||||||
fun analyzeBuilderInferenceCall(
|
|
||||||
functionLiteral: KtFunction,
|
|
||||||
valueArgument: ValueArgument,
|
|
||||||
csBuilder: ConstraintSystem.Builder,
|
|
||||||
context: CallCandidateResolutionContext<*>,
|
|
||||||
lambdaExpectedType: KotlinType
|
|
||||||
) {
|
|
||||||
val argumentExpression = valueArgument.getArgumentExpression() ?: return
|
|
||||||
if (!checkExpectedTypeForArgument(lambdaExpectedType)) return
|
|
||||||
|
|
||||||
val lambdaReceiverType = lambdaExpectedType.getReceiverTypeFromFunctionType() ?: return
|
|
||||||
|
|
||||||
val inferenceData = BuilderInferenceData()
|
|
||||||
|
|
||||||
val constraintSystem = csBuilder.build()
|
|
||||||
val newSubstitution = object : DelegatedTypeSubstitution(constraintSystem.currentSubstitutor.substitution) {
|
|
||||||
override fun get(key: KotlinType): TypeProjection? {
|
|
||||||
val substitutedType = super.get(key)
|
|
||||||
if (substitutedType?.type != TypeUtils.DONT_CARE) return substitutedType
|
|
||||||
|
|
||||||
// todo: what about nullable type?
|
|
||||||
val typeVariable = constraintSystem.typeVariables.firstOrNull {
|
|
||||||
it.originalTypeParameter.defaultType == key
|
|
||||||
} ?: return substitutedType
|
|
||||||
|
|
||||||
return inferenceData.getTypeTemplate(typeVariable).asTypeProjection()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun approximateContravariantCapturedTypes() = true
|
|
||||||
}
|
|
||||||
val newReceiverType = newSubstitution.buildSubstitutor().substitute(lambdaReceiverType, Variance.INVARIANT) ?: return
|
|
||||||
|
|
||||||
val approximationSubstitutor = object : DelegatedTypeSubstitution(constraintSystem.currentSubstitutor.substitution) {
|
|
||||||
override fun approximateContravariantCapturedTypes() = true
|
|
||||||
}
|
|
||||||
val approximatedLambdaType =
|
|
||||||
approximationSubstitutor.buildSubstitutor().substitute(lambdaExpectedType, Variance.IN_VARIANCE) ?: return
|
|
||||||
|
|
||||||
val newExpectedType = createFunctionType(
|
|
||||||
newReceiverType.builtIns, approximatedLambdaType.annotations, newReceiverType, emptyList(), // TODO: Context receivers?
|
|
||||||
approximatedLambdaType.getValueParameterTypesFromFunctionType().map(TypeProjection::getType),
|
|
||||||
parameterNames = null, // TODO: parameterNames
|
|
||||||
returnType = approximatedLambdaType.getReturnTypeFromFunctionType(),
|
|
||||||
suspendFunction = true
|
|
||||||
)
|
|
||||||
|
|
||||||
if (hasUnknownFunctionParameter(newExpectedType)) return
|
|
||||||
|
|
||||||
inferenceData.initSystem()
|
|
||||||
|
|
||||||
// this trace shouldn't be committed
|
|
||||||
val temporaryForBuilderInference = TemporaryTraceAndCache.create(
|
|
||||||
context, "trace to infer a type argument using the builder inference", functionLiteral
|
|
||||||
)
|
|
||||||
|
|
||||||
val newContext = context.replaceExpectedType(newExpectedType)
|
|
||||||
.replaceDataFlowInfo(context.candidateCall.dataFlowInfoForArguments.getInfo(valueArgument))
|
|
||||||
.replaceContextDependency(ContextDependency.INDEPENDENT).replaceTraceAndCache(temporaryForBuilderInference)
|
|
||||||
argumentTypeResolver.getFunctionLiteralTypeInfo(argumentExpression, functionLiteral, newContext, RESOLVE_FUNCTION_ARGUMENTS, true)
|
|
||||||
|
|
||||||
inferenceData.reportInferenceResult(csBuilder)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkExpectedTypeForArgument(expectedType: KotlinType): Boolean {
|
|
||||||
return if (languageVersionSettings.supportsFeature(LanguageFeature.ExperimentalBuilderInference))
|
|
||||||
expectedType.isFunctionOrSuspendFunctionType
|
|
||||||
else
|
|
||||||
expectedType.isSuspendFunctionType
|
|
||||||
}
|
|
||||||
|
|
||||||
fun checkBuilderInferenceCalls(
|
|
||||||
context: BasicCallResolutionContext,
|
|
||||||
tracingStrategy: TracingStrategy,
|
|
||||||
overloadResults: OverloadResolutionResultsImpl<*>
|
|
||||||
) {
|
|
||||||
val inferenceData = overloadResults.getBuilderInferenceData() ?: return
|
|
||||||
|
|
||||||
val resultingCall = overloadResults.resultingCall
|
|
||||||
|
|
||||||
forceInferenceForArguments(context) { _: ValueArgument, _: KotlinType -> /* do nothing */ }
|
|
||||||
|
|
||||||
callCompleter.completeCall(context, overloadResults, tracingStrategy)
|
|
||||||
if (!resultingCall.isReallySuccess()) return
|
|
||||||
|
|
||||||
val resultingDescriptor = resultingCall.resultingDescriptor
|
|
||||||
if (!isApplicableCallForBuilderInference(resultingDescriptor, languageVersionSettings)) {
|
|
||||||
inferenceData.badCallHappened()
|
|
||||||
}
|
|
||||||
|
|
||||||
forceInferenceForArguments(context) { valueArgument: ValueArgument, kotlinType: KotlinType ->
|
|
||||||
val argumentMatch = resultingCall.getArgumentMapping(valueArgument) as? ArgumentMatch ?: return@forceInferenceForArguments
|
|
||||||
|
|
||||||
with(NewKotlinTypeChecker.Default) {
|
|
||||||
val parameterType = getEffectiveExpectedType(argumentMatch.valueParameter, valueArgument, context)
|
|
||||||
BuilderInferenceTypeCheckerState(allowOnlyTrivialConstraints = false).isSubtypeOf(kotlinType.unwrap(), parameterType.unwrap())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val extensionReceiver = resultingDescriptor.extensionReceiverParameter ?: return
|
|
||||||
val allowOnlyTrivialConstraintsForReceiver =
|
|
||||||
if (languageVersionSettings.supportsFeature(LanguageFeature.ExperimentalBuilderInference))
|
|
||||||
!resultingDescriptor.hasBuilderInferenceAnnotation()
|
|
||||||
else
|
|
||||||
false
|
|
||||||
|
|
||||||
resultingCall.extensionReceiver?.let { actualReceiver ->
|
|
||||||
with(NewKotlinTypeChecker.Default) {
|
|
||||||
BuilderInferenceTypeCheckerState(allowOnlyTrivialConstraints = allowOnlyTrivialConstraintsForReceiver).isSubtypeOf(
|
|
||||||
actualReceiver.type.unwrap(), extensionReceiver.value.type.unwrap()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@OptIn(ClassicTypeCheckerStateInternals::class)
|
|
||||||
private class BuilderInferenceTypeCheckerState(
|
|
||||||
private val allowOnlyTrivialConstraints: Boolean
|
|
||||||
) : ClassicTypeCheckerState(isErrorTypeEqualsToAnything = true) {
|
|
||||||
override fun addSubtypeConstraint(subType: KotlinTypeMarker, superType: KotlinTypeMarker, isFromNullabilityConstraint: Boolean): Boolean? {
|
|
||||||
require(subType is UnwrappedType)
|
|
||||||
require(superType is UnwrappedType)
|
|
||||||
val typeTemplate = subType as? TypeTemplate ?: superType as? TypeTemplate
|
|
||||||
typeTemplate?.builderInferenceData?.addConstraint(subType, superType, allowOnlyTrivialConstraints)
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun forceInferenceForArguments(
|
|
||||||
context: CallResolutionContext<*>,
|
|
||||||
callback: (argument: ValueArgument, argumentType: KotlinType) -> Unit
|
|
||||||
) {
|
|
||||||
val infoForArguments = context.dataFlowInfoForArguments
|
|
||||||
val call = context.call
|
|
||||||
val baseContext = context.replaceContextDependency(ContextDependency.INDEPENDENT).replaceExpectedType(NO_EXPECTED_TYPE)
|
|
||||||
|
|
||||||
for (argument in call.valueArguments) {
|
|
||||||
val expression = argument.getArgumentExpression() ?: continue
|
|
||||||
val typeInfoForCall = getArgumentTypeInfo(expression, baseContext.replaceDataFlowInfo(infoForArguments.getInfo(argument)))
|
|
||||||
typeInfoForCall.type?.let { callback(argument, it) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getArgumentTypeInfo(
|
|
||||||
expression: KtExpression,
|
|
||||||
context: CallResolutionContext<*>
|
|
||||||
): KotlinTypeInfo {
|
|
||||||
getFunctionLiteralArgumentIfAny(expression, context)?.let {
|
|
||||||
return argumentTypeResolver.getFunctionLiteralTypeInfo(expression, it, context, RESOLVE_FUNCTION_ARGUMENTS, false)
|
|
||||||
}
|
|
||||||
|
|
||||||
getCallableReferenceExpressionIfAny(expression, context)?.let {
|
|
||||||
return argumentTypeResolver.getCallableReferenceTypeInfo(expression, it, context, RESOLVE_FUNCTION_ARGUMENTS)
|
|
||||||
}
|
|
||||||
|
|
||||||
return expressionTypingServices.getTypeInfo(expression, context)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun KotlinType.containsTypeTemplate() = contains { it is TypeTemplate || it is StubTypeForBuilderInference }
|
|
||||||
|
|
||||||
fun isApplicableCallForBuilderInference(descriptor: CallableDescriptor, languageVersionSettings: LanguageVersionSettings): Boolean {
|
fun isApplicableCallForBuilderInference(descriptor: CallableDescriptor, languageVersionSettings: LanguageVersionSettings): Boolean {
|
||||||
if (languageVersionSettings.supportsFeature(LanguageFeature.UnrestrictedBuilderInference)) return true
|
if (languageVersionSettings.supportsFeature(LanguageFeature.UnrestrictedBuilderInference)) return true
|
||||||
|
|
||||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.ExperimentalBuilderInference)) {
|
|
||||||
return isGoodCallForOldBuilderInference(descriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (descriptor.isExtension && !descriptor.hasBuilderInferenceAnnotation()) {
|
if (descriptor.isExtension && !descriptor.hasBuilderInferenceAnnotation()) {
|
||||||
return descriptor.extensionReceiverParameter?.type?.containsTypeTemplate() == false
|
return descriptor.extensionReceiverParameter?.type?.contains { it is StubTypeForBuilderInference } == false
|
||||||
}
|
}
|
||||||
|
|
||||||
val returnType = descriptor.returnType ?: return false
|
val returnType = descriptor.returnType ?: return false
|
||||||
return !returnType.containsTypeTemplate()
|
return !returnType.contains { it is StubTypeForBuilderInference }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun isGoodCallForOldBuilderInference(resultingDescriptor: CallableDescriptor): Boolean {
|
fun isBuilderInferenceCall(parameterDescriptor: ValueParameterDescriptor, argument: ValueArgument): Boolean {
|
||||||
val returnType = resultingDescriptor.returnType ?: return false
|
val parameterHasOptIn = parameterDescriptor.hasBuilderInferenceAnnotation() && parameterDescriptor.hasFunctionOrSuspendFunctionType
|
||||||
if (returnType.containsTypeTemplate()) return false
|
|
||||||
|
|
||||||
if (resultingDescriptor !is FunctionDescriptor || resultingDescriptor.isSuspend) return true
|
|
||||||
|
|
||||||
if (resultingDescriptor.valueParameters.any { it.type.containsTypeTemplate() }) return false
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isBuilderInferenceCall(
|
|
||||||
parameterDescriptor: ValueParameterDescriptor,
|
|
||||||
argument: ValueArgument,
|
|
||||||
languageVersionSettings: LanguageVersionSettings
|
|
||||||
): Boolean {
|
|
||||||
val parameterHasOptIn = if (languageVersionSettings.supportsFeature(LanguageFeature.ExperimentalBuilderInference))
|
|
||||||
parameterDescriptor.hasBuilderInferenceAnnotation() && parameterDescriptor.hasFunctionOrSuspendFunctionType
|
|
||||||
else
|
|
||||||
parameterDescriptor.hasSuspendFunctionType
|
|
||||||
|
|
||||||
val pureExpression = argument.getArgumentExpression()
|
val pureExpression = argument.getArgumentExpression()
|
||||||
val baseExpression = if (pureExpression is KtLabeledExpression) pureExpression.baseExpression else pureExpression
|
val baseExpression = if (pureExpression is KtLabeledExpression) pureExpression.baseExpression else pureExpression
|
||||||
|
|
||||||
@@ -341,19 +37,3 @@ fun isBuilderInferenceCall(
|
|||||||
baseExpression is KtLambdaExpression &&
|
baseExpression is KtLambdaExpression &&
|
||||||
parameterDescriptor.type.let { it.isBuiltinFunctionalType && it.getReceiverTypeFromFunctionType() != null }
|
parameterDescriptor.type.let { it.isBuiltinFunctionalType && it.getReceiverTypeFromFunctionType() != null }
|
||||||
}
|
}
|
||||||
|
|
||||||
fun OverloadResolutionResultsImpl<*>.isResultWithBuilderInference() = getBuilderInferenceData() != null
|
|
||||||
|
|
||||||
private fun OverloadResolutionResultsImpl<*>.getBuilderInferenceData(): BuilderInferenceData? {
|
|
||||||
if (!isSingleResult) return null
|
|
||||||
|
|
||||||
fun getData(receiverValue: ReceiverValue?): BuilderInferenceData? {
|
|
||||||
var builderInferenceData: BuilderInferenceData? = null
|
|
||||||
receiverValue?.type?.contains {
|
|
||||||
(it as? TypeTemplate)?.builderInferenceData?.let { builderInferenceData = it }
|
|
||||||
false
|
|
||||||
}
|
|
||||||
return builderInferenceData
|
|
||||||
}
|
|
||||||
return getData(resultingCall.dispatchReceiver) ?: getData(resultingCall.extensionReceiver)
|
|
||||||
}
|
|
||||||
|
|||||||
+1
-2
@@ -40,7 +40,6 @@ import org.jetbrains.kotlin.resolve.calls.model.SimpleKotlinCallArgument
|
|||||||
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem
|
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem
|
||||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
|
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.KotlinTypeRefinerImpl
|
|
||||||
import org.jetbrains.kotlin.types.TypeIntersector
|
import org.jetbrains.kotlin.types.TypeIntersector
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
|
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
@@ -96,7 +95,7 @@ class KotlinResolutionStatelessCallbacksImpl(
|
|||||||
functionCall.safeAs<PSIKotlinCallForInvoke>()?.variableCall
|
functionCall.safeAs<PSIKotlinCallForInvoke>()?.variableCall
|
||||||
|
|
||||||
override fun isBuilderInferenceCall(argument: KotlinCallArgument, parameter: ValueParameterDescriptor): Boolean =
|
override fun isBuilderInferenceCall(argument: KotlinCallArgument, parameter: ValueParameterDescriptor): Boolean =
|
||||||
isBuilderInferenceCall(parameter, argument.psiCallArgument.valueArgument, languageVersionSettings)
|
isBuilderInferenceCall(parameter, argument.psiCallArgument.valueArgument)
|
||||||
|
|
||||||
override fun isApplicableCallForBuilderInference(
|
override fun isApplicableCallForBuilderInference(
|
||||||
descriptor: CallableDescriptor,
|
descriptor: CallableDescriptor,
|
||||||
|
|||||||
-3
@@ -34,7 +34,6 @@ import org.jetbrains.kotlin.resolve.calls.CallResolver
|
|||||||
import org.jetbrains.kotlin.resolve.calls.CallTransformer
|
import org.jetbrains.kotlin.resolve.calls.CallTransformer
|
||||||
import org.jetbrains.kotlin.resolve.calls.CandidateResolver
|
import org.jetbrains.kotlin.resolve.calls.CandidateResolver
|
||||||
import org.jetbrains.kotlin.resolve.calls.context.*
|
import org.jetbrains.kotlin.resolve.calls.context.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSupport
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl
|
import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResultsImpl
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.ResolutionResultsHandler
|
import org.jetbrains.kotlin.resolve.calls.results.ResolutionResultsHandler
|
||||||
@@ -65,7 +64,6 @@ class NewResolutionOldInference(
|
|||||||
private val dynamicCallableDescriptors: DynamicCallableDescriptors,
|
private val dynamicCallableDescriptors: DynamicCallableDescriptors,
|
||||||
private val syntheticScopes: SyntheticScopes,
|
private val syntheticScopes: SyntheticScopes,
|
||||||
private val languageVersionSettings: LanguageVersionSettings,
|
private val languageVersionSettings: LanguageVersionSettings,
|
||||||
private val builderInferenceSupport: BuilderInferenceSupport,
|
|
||||||
private val deprecationResolver: DeprecationResolver,
|
private val deprecationResolver: DeprecationResolver,
|
||||||
private val typeApproximator: TypeApproximator,
|
private val typeApproximator: TypeApproximator,
|
||||||
private val implicitsResolutionFilter: ImplicitsExtensionsResolutionFilter,
|
private val implicitsResolutionFilter: ImplicitsExtensionsResolutionFilter,
|
||||||
@@ -212,7 +210,6 @@ class NewResolutionOldInference(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val overloadResults = convertToOverloadResults<D>(candidates, tracing, context)
|
val overloadResults = convertToOverloadResults<D>(candidates, tracing, context)
|
||||||
builderInferenceSupport.checkBuilderInferenceCalls(context, tracing, overloadResults)
|
|
||||||
return overloadResults
|
return overloadResults
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user