Effects: support parsing of functions contracts
Make a fastcheck for a presence of contract-declaration in function body of FunctionDescriptorResolver. If there's something that looks like contract and we need resolve to make a final decision, then prepare LazyContractProvider key in UserDataMap of function's descriptor. Note that we can't passively wait with contracts resolving until the function body is analyzed, because we may need it earlier. However, we can't force body resolve straight during descriptors resolving, because we can run into recursive problems. That's why we are saving deferred resolving of functions body via LazyContractProvider. Also, we have to pass DataFlowInfo into initializeFunctionDescriptorAndExplicitReturnType, because we save deferred body resolving inside, which needs DataFlowInfo. ========== Effect System introduction: 9/18
This commit is contained in:
@@ -21,6 +21,12 @@ import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType
|
||||
import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType
|
||||
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
|
||||
import org.jetbrains.kotlin.config.AnalysisFlag
|
||||
import org.jetbrains.kotlin.config.LanguageFeature
|
||||
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||
import org.jetbrains.kotlin.contracts.description.ContractProviderKey
|
||||
import org.jetbrains.kotlin.contracts.description.LazyContractProvider
|
||||
import org.jetbrains.kotlin.contracts.parsing.ContractParsingServices
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl
|
||||
@@ -33,8 +39,8 @@ import org.jetbrains.kotlin.diagnostics.Errors.*
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
|
||||
import org.jetbrains.kotlin.psi.psiUtil.hasActualModifier
|
||||
import org.jetbrains.kotlin.psi.psiUtil.hasExpectModifier
|
||||
import org.jetbrains.kotlin.resolve.DescriptorResolver.getDefaultModality
|
||||
import org.jetbrains.kotlin.resolve.DescriptorResolver.getDefaultVisibility
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils.getDispatchReceiverParameterIfNeeded
|
||||
@@ -53,6 +59,7 @@ import org.jetbrains.kotlin.types.ErrorUtils
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.TypeUtils
|
||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionExpression
|
||||
import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.isFunctionLiteral
|
||||
@@ -65,7 +72,10 @@ class FunctionDescriptorResolver(
|
||||
private val annotationResolver: AnnotationResolver,
|
||||
private val builtIns: KotlinBuiltIns,
|
||||
private val modifiersChecker: ModifiersChecker,
|
||||
private val overloadChecker: OverloadChecker
|
||||
private val overloadChecker: OverloadChecker,
|
||||
private val contractParsingServices: ContractParsingServices,
|
||||
private val expressionTypingServices: ExpressionTypingServices,
|
||||
private val languageVersionSettings: LanguageVersionSettings
|
||||
) {
|
||||
fun resolveFunctionDescriptor(
|
||||
containingDescriptor: DeclarationDescriptor,
|
||||
@@ -107,7 +117,7 @@ class FunctionDescriptorResolver(
|
||||
CallableMemberDescriptor.Kind.DECLARATION,
|
||||
function.toSourceElement()
|
||||
)
|
||||
initializeFunctionDescriptorAndExplicitReturnType(containingDescriptor, scope, function, functionDescriptor, trace, expectedFunctionType)
|
||||
initializeFunctionDescriptorAndExplicitReturnType(containingDescriptor, scope, function, functionDescriptor, trace, expectedFunctionType, dataFlowInfo)
|
||||
initializeFunctionReturnTypeBasedOnFunctionBody(scope, function, functionDescriptor, trace, dataFlowInfo)
|
||||
BindingContextUtils.recordFunctionDeclarationToDescriptor(trace, function, functionDescriptor)
|
||||
return functionDescriptor
|
||||
@@ -141,7 +151,8 @@ class FunctionDescriptorResolver(
|
||||
function: KtFunction,
|
||||
functionDescriptor: SimpleFunctionDescriptorImpl,
|
||||
trace: BindingTrace,
|
||||
expectedFunctionType: KotlinType
|
||||
expectedFunctionType: KotlinType,
|
||||
dataFlowInfo: DataFlowInfo
|
||||
) {
|
||||
val headerScope = LexicalWritableScope(scope, functionDescriptor, true,
|
||||
TraceBasedLocalRedeclarationChecker(trace, overloadChecker), LexicalScopeKind.FUNCTION_HEADER)
|
||||
@@ -169,6 +180,8 @@ class FunctionDescriptorResolver(
|
||||
val visibility = resolveVisibilityFromModifiers(function, getDefaultVisibility(function, container))
|
||||
val modality = resolveMemberModalityFromModifiers(function, getDefaultModality(container, visibility, function.hasBody()),
|
||||
trace.bindingContext, container)
|
||||
val contractProvider = getContractProvider(functionDescriptor, trace, scope, dataFlowInfo, function)
|
||||
|
||||
functionDescriptor.initialize(
|
||||
receiverType,
|
||||
getDispatchReceiverParameterIfNeeded(container),
|
||||
@@ -176,7 +189,8 @@ class FunctionDescriptorResolver(
|
||||
valueParameterDescriptors,
|
||||
returnType,
|
||||
modality,
|
||||
visibility
|
||||
visibility,
|
||||
mapOf(ContractProviderKey to contractProvider)
|
||||
)
|
||||
functionDescriptor.isOperator = function.hasModifier(KtTokens.OPERATOR_KEYWORD)
|
||||
functionDescriptor.isInfix = function.hasModifier(KtTokens.INFIX_KEYWORD)
|
||||
@@ -194,6 +208,26 @@ class FunctionDescriptorResolver(
|
||||
}
|
||||
}
|
||||
|
||||
private fun getContractProvider(
|
||||
functionDescriptor: SimpleFunctionDescriptorImpl,
|
||||
trace: BindingTrace,
|
||||
scope: LexicalScope,
|
||||
dataFlowInfo: DataFlowInfo,
|
||||
function: KtFunction
|
||||
): LazyContractProvider {
|
||||
val provideByDeferredForceResolve = LazyContractProvider {
|
||||
expressionTypingServices.getBodyExpressionType(trace, scope, dataFlowInfo, function, functionDescriptor)
|
||||
}
|
||||
val emptyContract = LazyContractProvider.createInitialized(null)
|
||||
|
||||
val isContractsEnabled = languageVersionSettings.supportsFeature(LanguageFeature.CallsInPlaceEffect) ||
|
||||
languageVersionSettings.supportsFeature(LanguageFeature.ReturnsEffect)
|
||||
|
||||
if (!isContractsEnabled || !contractParsingServices.fastCheckIfContractPresent(function)) return emptyContract
|
||||
|
||||
return provideByDeferredForceResolve
|
||||
}
|
||||
|
||||
private fun createValueParameterDescriptors(
|
||||
function: KtFunction,
|
||||
functionDescriptor: SimpleFunctionDescriptorImpl,
|
||||
|
||||
+1
-1
@@ -193,7 +193,7 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
|
||||
)
|
||||
components.functionDescriptorResolver.
|
||||
initializeFunctionDescriptorAndExplicitReturnType(context.scope.ownerDescriptor, context.scope, functionLiteral,
|
||||
functionDescriptor, context.trace, context.expectedType)
|
||||
functionDescriptor, context.trace, context.expectedType, context.dataFlowInfo)
|
||||
for (parameterDescriptor in functionDescriptor.valueParameters) {
|
||||
ForceResolveUtil.forceResolveAllContents(parameterDescriptor.annotations)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user