[NI] Fix checking for inline lambdas without candidate

#KT-34506
This commit is contained in:
Dmitriy Novozhilov
2020-06-01 13:55:26 +03:00
parent 30037682f8
commit 069adebf01
11 changed files with 160 additions and 13 deletions
@@ -274,6 +274,7 @@ public interface BindingContext {
WritableSlice<KtExpression, PrimitiveNumericComparisonInfo> PRIMITIVE_NUMERIC_COMPARISON_INFO = Slices.createSimpleSlice();
WritableSlice<KtExpression, Ref<VariableDescriptor>> NEW_INFERENCE_CATCH_EXCEPTION_PARAMETER = Slices.createSimpleSlice();
WritableSlice<PsiElement, Boolean> NEW_INFERENCE_IS_LAMBDA_FOR_OVERLOAD_RESOLUTION_INLINE = Slices.createSimpleSlice();
@SuppressWarnings("UnusedDeclaration")
@Deprecated // This field is needed only for the side effects of its initializer
@@ -8,19 +8,14 @@ package org.jetbrains.kotlin.resolve.calls.tower
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isPrimitiveTypeOrNullablePrimitiveType
import org.jetbrains.kotlin.builtins.KotlinBuiltIns.isUnderKotlinPackage
import org.jetbrains.kotlin.builtins.UnsignedTypes
import org.jetbrains.kotlin.builtins.createFunctionType
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.psi.KtReturnExpression
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.getBinaryWithTypeParent
import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis
import org.jetbrains.kotlin.resolve.*
@@ -40,6 +35,7 @@ import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant
import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.expressions.DoubleColonExpressionResolver
@@ -48,7 +44,6 @@ import org.jetbrains.kotlin.types.expressions.KotlinTypeInfo
import org.jetbrains.kotlin.types.refinement.TypeRefinement
import org.jetbrains.kotlin.types.typeUtil.isUnit
import org.jetbrains.kotlin.types.typeUtil.makeNullable
import org.jetbrains.kotlin.utils.addIfNotNull
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
data class LambdaContextInfo(
@@ -317,6 +312,17 @@ class KotlinResolutionCallbacksImpl(
return convertSignedConstantToUnsigned(argumentExpression)
}
override fun recordInlinabilityOfLambda(lambdas: Set<Map.Entry<KotlinResolutionCandidate, ResolvedLambdaAtom>>) {
val call = lambdas.first().value.atom.psiCallArgument.valueArgument as? KtLambdaArgument ?: return
val literal = call.getLambdaExpression()?.functionLiteral ?: return
val isLambdaInline = lambdas.all { (candidate, atom) ->
if (!InlineUtil.isInline(candidate.resolvedCall.candidateDescriptor)) return
val valueParameterDescriptor = candidate.resolvedCall.argumentToCandidateParameter[atom.atom] ?: return
InlineUtil.isInlineParameter(valueParameterDescriptor)
}.takeIf { it }
trace.record(BindingContext.NEW_INFERENCE_IS_LAMBDA_FOR_OVERLOAD_RESOLUTION_INLINE, literal, isLambdaInline)
}
private fun convertSignedConstantToUnsigned(expression: KtExpression): IntegerValueTypeConstant? {
val constant = trace[BindingContext.COMPILE_TIME_VALUE, expression]
if (constant !is IntegerValueTypeConstant || !constantCanBeConvertedToUnsigned(constant)) return null
@@ -99,6 +99,11 @@ public class InlineUtil {
if (containingFunctionDescriptor == null) return false;
while (canBeInlineArgument(containingFunction) && fromFunction != containingFunctionDescriptor) {
Boolean isLambdaDefinitelyInline = bindingContext.get(BindingContext.NEW_INFERENCE_IS_LAMBDA_FOR_OVERLOAD_RESOLUTION_INLINE, containingFunction);
if (isLambdaDefinitelyInline != null) {
return isLambdaDefinitelyInline;
}
if (!isInlinedArgument((KtFunction) containingFunction, bindingContext, true)) {
return false;
}