Create SimpleFunctionDescriptorImpl under nonCancelableSection

SimpleFunctionDescriptorImpl initialization consists of two phases:
ctor + initialize.
When SimpleFunctionDescriptorImpl is created wrapped descriptor
(e.g. ValueParameterDescriptorImpl) is leaked through bindingTrace
with not fully initialized `containingDeclaration` (that is
SimpleFunctionDescriptorImpl).
If PCE happens after this unsafe publication prior to `initialize` then
it will be case with NPE on fully initialized instance reading.

#KT-56364 Fixed
This commit is contained in:
Vladimir Dolzhenko
2023-02-02 17:15:12 +01:00
committed by Space Team
parent 9be4aa2e02
commit a049fda75b
2 changed files with 210 additions and 175 deletions
@@ -17,6 +17,8 @@
package org.jetbrains.kotlin.resolve package org.jetbrains.kotlin.resolve
import com.google.common.collect.HashMultimap import com.google.common.collect.HashMultimap
import com.intellij.openapi.diagnostic.ControlFlowException
import com.intellij.openapi.progress.ProgressManager
import com.intellij.openapi.util.ThrowableComputable import com.intellij.openapi.util.ThrowableComputable
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.util.AstLoadingFilter import com.intellij.util.AstLoadingFilter
@@ -71,6 +73,7 @@ import org.jetbrains.kotlin.types.isError
import org.jetbrains.kotlin.types.typeUtil.replaceAnnotations import org.jetbrains.kotlin.types.typeUtil.replaceAnnotations
import java.util.* import java.util.*
class FunctionDescriptorResolver( class FunctionDescriptorResolver(
private val typeResolver: TypeResolver, private val typeResolver: TypeResolver,
private val descriptorResolver: DescriptorResolver, private val descriptorResolver: DescriptorResolver,
@@ -129,19 +132,21 @@ class FunctionDescriptorResolver(
CallableMemberDescriptor.Kind.DECLARATION, CallableMemberDescriptor.Kind.DECLARATION,
function.toSourceElement() function.toSourceElement()
) )
initializeFunctionDescriptorAndExplicitReturnType( return computeInNonCancelableSection {
containingDescriptor, initializeFunctionDescriptorAndExplicitReturnType(
scope, containingDescriptor,
function, scope,
functionDescriptor, function,
trace, functionDescriptor,
expectedFunctionType, trace,
dataFlowInfo, expectedFunctionType,
inferenceSession dataFlowInfo,
) inferenceSession
initializeFunctionReturnTypeBasedOnFunctionBody(scope, function, functionDescriptor, trace, dataFlowInfo, inferenceSession) )
BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, function, functionDescriptor) initializeFunctionReturnTypeBasedOnFunctionBody(scope, function, functionDescriptor, trace, dataFlowInfo, inferenceSession)
return functionDescriptor BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, function, functionDescriptor)
functionDescriptor
}
} }
private fun initializeFunctionReturnTypeBasedOnFunctionBody( private fun initializeFunctionReturnTypeBasedOnFunctionBody(
@@ -182,117 +187,124 @@ class FunctionDescriptorResolver(
dataFlowInfo: DataFlowInfo, dataFlowInfo: DataFlowInfo,
inferenceSession: InferenceSession? inferenceSession: InferenceSession?
) { ) {
val headerScope = LexicalWritableScope( try {
scope, functionDescriptor, true, val headerScope = LexicalWritableScope(
TraceBasedLocalRedeclarationChecker(trace, overloadChecker), LexicalScopeKind.FUNCTION_HEADER scope, functionDescriptor, true,
) TraceBasedLocalRedeclarationChecker(trace, overloadChecker), LexicalScopeKind.FUNCTION_HEADER
)
val typeParameterDescriptors = val typeParameterDescriptors =
descriptorResolver.resolveTypeParametersForDescriptor(functionDescriptor, headerScope, scope, function.typeParameters, trace) descriptorResolver.resolveTypeParametersForDescriptor(functionDescriptor, headerScope, scope, function.typeParameters, trace)
descriptorResolver.resolveGenericBounds(function, functionDescriptor, headerScope, typeParameterDescriptors, trace) descriptorResolver.resolveGenericBounds(function, functionDescriptor, headerScope, typeParameterDescriptors, trace)
val receiverTypeRef = function.receiverTypeReference val receiverTypeRef = function.receiverTypeReference
val receiverType = val receiverType =
if (receiverTypeRef != null) { if (receiverTypeRef != null) {
typeResolver.resolveType(headerScope, receiverTypeRef, trace, true) typeResolver.resolveType(headerScope, receiverTypeRef, trace, true)
} else { } else {
if (function is KtFunctionLiteral) expectedFunctionType.getReceiverType() else null if (function is KtFunctionLiteral) expectedFunctionType.getReceiverType() else null
}
val contextReceivers = function.contextReceivers
val contextReceiverTypes =
if (function is KtFunctionLiteral) expectedFunctionType.getContextReceiversTypes()
else contextReceivers
.mapNotNull {
val typeReference = it.typeReference() ?: return@mapNotNull null
val type = typeResolver.resolveType(headerScope, typeReference, trace, true)
ContextReceiverTypeWithLabel(type, it.labelNameAsName())
} }
val contextReceivers = function.contextReceivers
val contextReceiverTypes =
if (function is KtFunctionLiteral) expectedFunctionType.getContextReceiversTypes()
else contextReceivers
.mapNotNull {
val typeReference = it.typeReference() ?: return@mapNotNull null
val type = typeResolver.resolveType(headerScope, typeReference, trace, true)
ContextReceiverTypeWithLabel(type, it.labelNameAsName())
}
val valueParameterDescriptors =
createValueParameterDescriptors(function, functionDescriptor, headerScope, trace, expectedFunctionType, inferenceSession)
headerScope.freeze() val valueParameterDescriptors =
createValueParameterDescriptors(function, functionDescriptor, headerScope, trace, expectedFunctionType, inferenceSession)
val returnType = function.typeReference?.let { typeResolver.resolveType(headerScope, it, trace, true) } headerScope.freeze()
val visibility = resolveVisibilityFromModifiers(function, getDefaultVisibility(function, container)) val returnType = function.typeReference?.let { typeResolver.resolveType(headerScope, it, trace, true) }
val modality = resolveMemberModalityFromModifiers(
function, getDefaultModality(container, visibility, function.hasBody()),
trace.bindingContext, container
)
val contractProvider = getContractProvider(functionDescriptor, trace, scope, dataFlowInfo, function, inferenceSession) val visibility = resolveVisibilityFromModifiers(function, getDefaultVisibility(function, container))
val userData = mutableMapOf<CallableDescriptor.UserDataKey<*>, Any>().apply { val modality = resolveMemberModalityFromModifiers(
if (contractProvider != null) { function, getDefaultModality(container, visibility, function.hasBody()),
put(ContractProviderKey, contractProvider) trace.bindingContext, container
}
if (receiverType != null && expectedFunctionType.functionTypeExpected() && !expectedFunctionType.annotations.isEmpty()) {
put(DslMarkerUtils.FunctionTypeAnnotationsKey, expectedFunctionType.annotations)
}
}
val extensionReceiver = receiverType?.let {
val splitter = AnnotationSplitter(storageManager, it.annotations, EnumSet.of(AnnotationUseSiteTarget.RECEIVER))
DescriptorFactory.createExtensionReceiverParameterForCallable(
functionDescriptor, it, splitter.getAnnotationsForTarget(AnnotationUseSiteTarget.RECEIVER)
) )
}
val contextReceiverDescriptors = contextReceiverTypes.mapIndexedNotNull { index, contextReceiver ->
val splitter = AnnotationSplitter(storageManager, contextReceiver.type.annotations, EnumSet.of(AnnotationUseSiteTarget.RECEIVER))
DescriptorFactory.createContextReceiverParameterForCallable(
functionDescriptor,
contextReceiver.type,
contextReceiver.label,
splitter.getAnnotationsForTarget(AnnotationUseSiteTarget.RECEIVER),
index
)
}
if (languageVersionSettings.supportsFeature(LanguageFeature.ContextReceivers)) { val contractProvider = getContractProvider(functionDescriptor, trace, scope, dataFlowInfo, function, inferenceSession)
val labelNameToReceiverMap = HashMultimap.create<String, ReceiverParameterDescriptor>() val userData = mutableMapOf<CallableDescriptor.UserDataKey<*>, Any>().apply {
if (receiverTypeRef != null && extensionReceiver != null) { if (contractProvider != null) {
receiverTypeRef.nameForReceiverLabel()?.let { put(ContractProviderKey, contractProvider)
labelNameToReceiverMap.put(it, extensionReceiver) }
if (receiverType != null && expectedFunctionType.functionTypeExpected() && !expectedFunctionType.annotations.isEmpty()) {
put(DslMarkerUtils.FunctionTypeAnnotationsKey, expectedFunctionType.annotations)
} }
} }
contextReceiverDescriptors.zip(0 until contextReceivers.size).reversed()
.forEach { (contextReceiverDescriptor, i) -> val extensionReceiver = receiverType?.let {
contextReceivers[i].name()?.let { val splitter = AnnotationSplitter(storageManager, it.annotations, EnumSet.of(AnnotationUseSiteTarget.RECEIVER))
labelNameToReceiverMap.put(it, contextReceiverDescriptor) DescriptorFactory.createExtensionReceiverParameterForCallable(
functionDescriptor, it, splitter.getAnnotationsForTarget(AnnotationUseSiteTarget.RECEIVER)
)
}
val contextReceiverDescriptors = contextReceiverTypes.mapIndexedNotNull { index, contextReceiver ->
val splitter = AnnotationSplitter(storageManager, contextReceiver.type.annotations, EnumSet.of(AnnotationUseSiteTarget.RECEIVER))
DescriptorFactory.createContextReceiverParameterForCallable(
functionDescriptor,
contextReceiver.type,
contextReceiver.label,
splitter.getAnnotationsForTarget(AnnotationUseSiteTarget.RECEIVER),
index
)
}
if (languageVersionSettings.supportsFeature(LanguageFeature.ContextReceivers)) {
val labelNameToReceiverMap = HashMultimap.create<String, ReceiverParameterDescriptor>()
if (receiverTypeRef != null && extensionReceiver != null) {
receiverTypeRef.nameForReceiverLabel()?.let {
labelNameToReceiverMap.put(it, extensionReceiver)
} }
} }
contextReceiverDescriptors.zip(0 until contextReceivers.size).reversed()
.forEach { (contextReceiverDescriptor, i) ->
contextReceivers[i].name()?.let {
labelNameToReceiverMap.put(it, contextReceiverDescriptor)
}
}
trace.record(BindingContext.DESCRIPTOR_TO_CONTEXT_RECEIVER_MAP, functionDescriptor, labelNameToReceiverMap) trace.record(BindingContext.DESCRIPTOR_TO_CONTEXT_RECEIVER_MAP, functionDescriptor, labelNameToReceiverMap)
} }
functionDescriptor.initialize( functionDescriptor.initialize(
extensionReceiver, extensionReceiver,
getDispatchReceiverParameterIfNeeded(container), getDispatchReceiverParameterIfNeeded(container),
contextReceiverDescriptors, contextReceiverDescriptors,
typeParameterDescriptors, typeParameterDescriptors,
valueParameterDescriptors, valueParameterDescriptors,
returnType, returnType,
modality, modality,
visibility, visibility,
userData.takeIf { it.isNotEmpty() } userData.takeIf { it.isNotEmpty() }
) )
functionDescriptor.isOperator = function.hasModifier(KtTokens.OPERATOR_KEYWORD) functionDescriptor.isOperator = function.hasModifier(KtTokens.OPERATOR_KEYWORD)
functionDescriptor.isInfix = function.hasModifier(KtTokens.INFIX_KEYWORD) functionDescriptor.isInfix = function.hasModifier(KtTokens.INFIX_KEYWORD)
functionDescriptor.isExternal = function.hasModifier(KtTokens.EXTERNAL_KEYWORD) functionDescriptor.isExternal = function.hasModifier(KtTokens.EXTERNAL_KEYWORD)
functionDescriptor.isInline = function.hasModifier(KtTokens.INLINE_KEYWORD) functionDescriptor.isInline = function.hasModifier(KtTokens.INLINE_KEYWORD)
functionDescriptor.isTailrec = function.hasModifier(KtTokens.TAILREC_KEYWORD) functionDescriptor.isTailrec = function.hasModifier(KtTokens.TAILREC_KEYWORD)
functionDescriptor.isSuspend = function.hasModifier(KtTokens.SUSPEND_KEYWORD) functionDescriptor.isSuspend = function.hasModifier(KtTokens.SUSPEND_KEYWORD)
functionDescriptor.isExpect = container is PackageFragmentDescriptor && function.hasExpectModifier() || functionDescriptor.isExpect = container is PackageFragmentDescriptor && function.hasExpectModifier() ||
container is ClassDescriptor && container.isExpect container is ClassDescriptor && container.isExpect
functionDescriptor.isActual = function.hasActualModifier() functionDescriptor.isActual = function.hasActualModifier()
receiverType?.let { ForceResolveUtil.forceResolveAllContents(it.annotations) } receiverType?.let { ForceResolveUtil.forceResolveAllContents(it.annotations) }
for (valueParameterDescriptor in valueParameterDescriptors) { for (valueParameterDescriptor in valueParameterDescriptors) {
ForceResolveUtil.forceResolveAllContents(valueParameterDescriptor.type.annotations) ForceResolveUtil.forceResolveAllContents(valueParameterDescriptor.type.annotations)
}
} catch (e: Exception) {
if (e is ControlFlowException) {
throw IllegalStateException("Method should be run under nonCancelableSection", e)
}
throw e
} }
} }
@@ -444,8 +456,6 @@ class FunctionDescriptorResolver(
constructorDescriptor.isActual = modifierList?.hasActualModifier() == true || constructorDescriptor.isActual = modifierList?.hasActualModifier() == true ||
// We don't require 'actual' for constructors of actual annotations // We don't require 'actual' for constructors of actual annotations
classDescriptor.kind == ClassKind.ANNOTATION_CLASS && classDescriptor.isActual classDescriptor.kind == ClassKind.ANNOTATION_CLASS && classDescriptor.isActual
if (declarationToTrace is PsiElement)
trace.record(BindingContext.CONSTRUCTOR, declarationToTrace, constructorDescriptor)
val parameterScope = LexicalWritableScope( val parameterScope = LexicalWritableScope(
scope, scope,
constructorDescriptor, constructorDescriptor,
@@ -453,20 +463,27 @@ class FunctionDescriptorResolver(
TraceBasedLocalRedeclarationChecker(trace, overloadChecker), TraceBasedLocalRedeclarationChecker(trace, overloadChecker),
LexicalScopeKind.CONSTRUCTOR_HEADER LexicalScopeKind.CONSTRUCTOR_HEADER
) )
val constructor = constructorDescriptor.initialize( return computeInNonCancelableSection {
resolveValueParameters( if (declarationToTrace is PsiElement)
constructorDescriptor, parameterScope, valueParameters, trace, null, inferenceSession trace.record(BindingContext.CONSTRUCTOR, declarationToTrace, constructorDescriptor)
), val constructor = constructorDescriptor.initialize(
resolveVisibilityFromModifiers( resolveValueParameters(
modifierList, constructorDescriptor, parameterScope, valueParameters, trace, null, inferenceSession
DescriptorUtils.getDefaultConstructorVisibility(classDescriptor, languageVersionSettings.supportsFeature(LanguageFeature.AllowSealedInheritorsInDifferentFilesOfSamePackage)) ),
resolveVisibilityFromModifiers(
modifierList,
DescriptorUtils.getDefaultConstructorVisibility(
classDescriptor,
languageVersionSettings.supportsFeature(LanguageFeature.AllowSealedInheritorsInDifferentFilesOfSamePackage)
)
)
) )
) constructor.returnType = classDescriptor.defaultType
constructor.returnType = classDescriptor.defaultType if (DescriptorUtils.isAnnotationClass(classDescriptor)) {
if (DescriptorUtils.isAnnotationClass(classDescriptor)) { CompileTimeConstantUtils.checkConstructorParametersType(valueParameters, trace)
CompileTimeConstantUtils.checkConstructorParametersType(valueParameters, trace) }
constructor
} }
return constructor
} }
private fun resolveValueParameters( private fun resolveValueParameters(
@@ -477,57 +494,67 @@ class FunctionDescriptorResolver(
expectedParameterTypes: List<KotlinType>?, expectedParameterTypes: List<KotlinType>?,
inferenceSession: InferenceSession? inferenceSession: InferenceSession?
): List<ValueParameterDescriptor> { ): List<ValueParameterDescriptor> {
val result = ArrayList<ValueParameterDescriptor>() try {
val result = ArrayList<ValueParameterDescriptor>()
for (i in valueParameters.indices) { for (i in valueParameters.indices) {
val valueParameter = valueParameters[i] val valueParameter = valueParameters[i]
val typeReference = valueParameter.typeReference val typeReference = valueParameter.typeReference
val expectedType = expectedParameterTypes?.let { if (i < it.size) it[i] else null }?.takeUnless { TypeUtils.noExpectedType(it) } val expectedType = expectedParameterTypes?.let { if (i < it.size) it[i] else null }?.takeUnless { TypeUtils.noExpectedType(it) }
val type: KotlinType val type: KotlinType
if (typeReference != null) { if (typeReference != null) {
type = typeResolver.resolveType(parameterScope, typeReference, trace, true) type = typeResolver.resolveType(parameterScope, typeReference, trace, true)
if (expectedType != null) { if (expectedType != null) {
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(expectedType, type)) { if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(expectedType, type)) {
trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(valueParameter, expectedType)) trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(valueParameter, expectedType))
}
} }
}
} else {
type = if (isFunctionLiteral(functionDescriptor) || isFunctionExpression(functionDescriptor)) {
val containsErrorType = TypeUtils.contains(expectedType) { it.isError }
if (expectedType == null || containsErrorType) {
trace.report(CANNOT_INFER_PARAMETER_TYPE.on(valueParameter))
}
expectedType ?: TypeUtils.CANNOT_INFER_FUNCTION_PARAM_TYPE
} else { } else {
trace.report(VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION.on(valueParameter)) type = if (isFunctionLiteral(functionDescriptor) || isFunctionExpression(functionDescriptor)) {
ErrorUtils.createErrorType(ErrorTypeKind.MISSED_TYPE_FOR_PARAMETER, valueParameter.nameAsSafeName.toString()) val containsErrorType = TypeUtils.contains(expectedType) { it.isError }
if (expectedType == null || containsErrorType) {
trace.report(CANNOT_INFER_PARAMETER_TYPE.on(valueParameter))
}
expectedType ?: TypeUtils.CANNOT_INFER_FUNCTION_PARAM_TYPE
} else {
trace.report(VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION.on(valueParameter))
ErrorUtils.createErrorType(ErrorTypeKind.MISSED_TYPE_FOR_PARAMETER, valueParameter.nameAsSafeName.toString())
}
} }
}
if (functionDescriptor !is ConstructorDescriptor || !functionDescriptor.isPrimary) { if (functionDescriptor !is ConstructorDescriptor || !functionDescriptor.isPrimary) {
val isConstructor = functionDescriptor is ConstructorDescriptor val isConstructor = functionDescriptor is ConstructorDescriptor
with(modifiersChecker.withTrace(trace)) { with(modifiersChecker.withTrace(trace)) {
checkParameterHasNoValOrVar( checkParameterHasNoValOrVar(
valueParameter, valueParameter,
if (isConstructor) VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER else VAL_OR_VAR_ON_FUN_PARAMETER if (isConstructor) VAL_OR_VAR_ON_SECONDARY_CONSTRUCTOR_PARAMETER else VAL_OR_VAR_ON_FUN_PARAMETER
) )
}
} }
val valueParameterDescriptor = descriptorResolver.resolveValueParameterDescriptor(
parameterScope, functionDescriptor, valueParameter, i, type, trace, Annotations.EMPTY, inferenceSession
)
// Do not report NAME_SHADOWING for lambda destructured parameters as they may be not fully resolved at this time
ExpressionTypingUtils.checkVariableShadowing(parameterScope, trace, valueParameterDescriptor)
parameterScope.addVariableDescriptor(valueParameterDescriptor)
result.add(valueParameterDescriptor)
} }
return result
val valueParameterDescriptor = descriptorResolver.resolveValueParameterDescriptor( } catch (e: Exception) {
parameterScope, functionDescriptor, valueParameter, i, type, trace, Annotations.EMPTY, inferenceSession if (e is ControlFlowException) {
) throw IllegalStateException("Method should be run under nonCancelableSection", e)
}
// Do not report NAME_SHADOWING for lambda destructured parameters as they may be not fully resolved at this time throw e
ExpressionTypingUtils.checkVariableShadowing(parameterScope, trace, valueParameterDescriptor)
parameterScope.addVariableDescriptor(valueParameterDescriptor)
result.add(valueParameterDescriptor)
} }
return result
} }
private data class ContextReceiverTypeWithLabel(val type: KotlinType, val label: Name?) private data class ContextReceiverTypeWithLabel(val type: KotlinType, val label: Name?)
} }
private fun <T> computeInNonCancelableSection(action: () -> T): T =
ProgressManager.getInstance().computeInNonCancelableSection<T, Exception>(action)
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.types.expressions package org.jetbrains.kotlin.types.expressions
import com.google.common.collect.Lists import com.google.common.collect.Lists
import com.intellij.openapi.progress.ProgressManager
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.* import org.jetbrains.kotlin.builtins.*
import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.config.LanguageFeature
@@ -209,23 +210,30 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
context: ExpressionTypingContext context: ExpressionTypingContext
): AnonymousFunctionDescriptor { ): AnonymousFunctionDescriptor {
val functionLiteral = expression.functionLiteral val functionLiteral = expression.functionLiteral
val functionDescriptor = AnonymousFunctionDescriptor( val annotations = components.annotationResolver.resolveAnnotationsWithArguments(
context.scope.ownerDescriptor, context.scope,
components.annotationResolver.resolveAnnotationsWithArguments(context.scope, expression.getAnnotationEntries(), context.trace), expression.getAnnotationEntries(),
CallableMemberDescriptor.Kind.DECLARATION, functionLiteral.toSourceElement(), context.trace
context.expectedType.isSuspendFunctionType()
).let {
facade.components.typeResolutionInterceptor.interceptFunctionLiteralDescriptor(expression, context, it)
}
components.functionDescriptorResolver.initializeFunctionDescriptorAndExplicitReturnType(
context.scope.ownerDescriptor, context.scope, functionLiteral,
functionDescriptor, context.trace, context.expectedType, context.dataFlowInfo, context.inferenceSession
) )
for (parameterDescriptor in functionDescriptor.valueParameters) { return ProgressManager.getInstance().computeInNonCancelableSection<AnonymousFunctionDescriptor, Exception> {
ForceResolveUtil.forceResolveAllContents(parameterDescriptor.annotations) val functionDescriptor = AnonymousFunctionDescriptor(
context.scope.ownerDescriptor,
annotations,
CallableMemberDescriptor.Kind.DECLARATION, functionLiteral.toSourceElement(),
context.expectedType.isSuspendFunctionType()
).let {
facade.components.typeResolutionInterceptor.interceptFunctionLiteralDescriptor(expression, context, it)
}
components.functionDescriptorResolver.initializeFunctionDescriptorAndExplicitReturnType(
context.scope.ownerDescriptor, context.scope, functionLiteral,
functionDescriptor, context.trace, context.expectedType, context.dataFlowInfo, context.inferenceSession
)
for (parameterDescriptor in functionDescriptor.valueParameters) {
ForceResolveUtil.forceResolveAllContents(parameterDescriptor.annotations)
}
BindingContextUtils.recordFunctionDeclarationToDescriptor(context.trace, functionLiteral, functionDescriptor)
functionDescriptor
} }
BindingContextUtils.recordFunctionDeclarationToDescriptor(context.trace, functionLiteral, functionDescriptor)
return functionDescriptor
} }
private fun KotlinType.isBuiltinFunctionalType() = private fun KotlinType.isBuiltinFunctionalType() =