Fix recursion in contract declaration analysis. KT-26386 Fixed
Issue fixed only in old inference
This commit is contained in:
@@ -33,6 +33,7 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
||||
import org.jetbrains.kotlin.psi.KtExpression
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.BindingTrace
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
@@ -127,6 +128,10 @@ class EffectSystem(
|
||||
bindingTrace: BindingTrace,
|
||||
moduleDescriptor: ModuleDescriptor
|
||||
): MutableContextInfo {
|
||||
val isInContractBlock = expression.parentsWithSelf.filterIsInstance<KtExpression>().any {
|
||||
bindingTrace.bindingContext[BindingContext.IS_CONTRACT_DECLARATION_BLOCK, it] == true
|
||||
}
|
||||
if (isInContractBlock) return MutableContextInfo.EMPTY
|
||||
val computation = getNonTrivialComputation(expression, bindingTrace, moduleDescriptor) ?: return MutableContextInfo.EMPTY
|
||||
return InfoCollector(observedEffect, constants).collectFromSchema(computation.effects)
|
||||
}
|
||||
|
||||
@@ -99,6 +99,7 @@ public interface BindingContext {
|
||||
WritableSlice<KtExpression, KotlinType> EXPECTED_EXPRESSION_TYPE = new BasicWritableSlice<>(DO_NOTHING);
|
||||
WritableSlice<KtElement, Computation> EXPRESSION_EFFECTS = Slices.createSimpleSlice();
|
||||
WritableSlice<KtElement, Boolean> CONTRACT_NOT_ALLOWED = Slices.createSimpleSlice();
|
||||
WritableSlice<KtElement, Boolean> IS_CONTRACT_DECLARATION_BLOCK = Slices.createSimpleSlice();
|
||||
WritableSlice<KtFunction, KotlinType> EXPECTED_RETURN_TYPE = new BasicWritableSlice<>(DO_NOTHING);
|
||||
WritableSlice<KtExpression, DataFlowInfo> DATAFLOW_INFO_AFTER_CONDITION = Slices.createSimpleSlice();
|
||||
WritableSlice<VariableDescriptor, DataFlowValue> BOUND_INITIALIZER_VALUE = Slices.createSimpleSlice();
|
||||
|
||||
@@ -9,12 +9,18 @@ import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType
|
||||
import org.jetbrains.kotlin.builtins.getValueParameterTypesFromFunctionType
|
||||
import org.jetbrains.kotlin.builtins.isFunctionOrSuspendFunctionType
|
||||
import org.jetbrains.kotlin.contracts.EffectSystem
|
||||
import org.jetbrains.kotlin.contracts.description.ContractProviderKey
|
||||
import org.jetbrains.kotlin.contracts.description.LazyContractProvider
|
||||
import org.jetbrains.kotlin.contracts.parsing.isContractCallDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isContractDescriptionCallPsiCheck
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isFirstStatement
|
||||
import org.jetbrains.kotlin.resolve.*
|
||||
import org.jetbrains.kotlin.resolve.BindingContext.CONSTRAINT_SYSTEM_COMPLETER
|
||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.ResolveArgumentsMode.RESOLVE_FUNCTION_ARGUMENTS
|
||||
@@ -129,6 +135,20 @@ class CallCompleter(
|
||||
context: BasicCallResolutionContext,
|
||||
tracing: TracingStrategy
|
||||
) {
|
||||
context.call.callElement.safeAs<KtExpression>()?.let { callExpression ->
|
||||
if (callExpression.isFirstStatement() && callExpression.isContractDescriptionCallPsiCheck()) {
|
||||
if (resolvedCall?.resultingDescriptor?.isContractCallDescriptor() != true) {
|
||||
context.scope.ownerDescriptor
|
||||
.safeAs<FunctionDescriptor>()
|
||||
?.getUserData(ContractProviderKey)
|
||||
?.safeAs<LazyContractProvider>()
|
||||
?.setContractDescription(null)
|
||||
} else {
|
||||
context.trace.record(BindingContext.IS_CONTRACT_DECLARATION_BLOCK, callExpression, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (resolvedCall == null || resolvedCall.isCompleted || resolvedCall.constraintSystem == null) {
|
||||
completeArguments(context, results)
|
||||
resolvedCall?.updateResultDataFlowInfoUsingEffects(context.trace)
|
||||
|
||||
+2
-9
@@ -12,9 +12,8 @@ import org.jetbrains.kotlin.descriptors.PackageFragmentDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.PropertyAccessorDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.isOverridable
|
||||
import org.jetbrains.kotlin.diagnostics.Errors
|
||||
import org.jetbrains.kotlin.psi.KtBlockExpression
|
||||
import org.jetbrains.kotlin.psi.KtDotQualifiedExpression
|
||||
import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.psi.psiUtil.isFirstStatement
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
|
||||
@@ -57,13 +56,7 @@ object ContractNotAllowedCallChecker : CallChecker {
|
||||
|
||||
if (functionDescriptor?.isOverridable == true) contractNotAllowed("Contracts are not allowed for open functions")
|
||||
|
||||
var parent = callElement.parent
|
||||
var element = callElement
|
||||
if (parent is KtDotQualifiedExpression) {
|
||||
element = parent
|
||||
parent = parent.parent
|
||||
}
|
||||
if ((parent !is KtBlockExpression || parent.children.first { it is KtElement } != element) && inFunctionBodyBlock) {
|
||||
if (!callElement.isFirstStatement() && inFunctionBodyBlock) {
|
||||
contractNotAllowed("Contract should be the first statement")
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user