Refactor language features, which control effect system
- Introduce new language feature 'ReadDeserializedContracts', which allows to deserialize contracts from metadata. - Introduce new language feature 'AllowContractsForCustomFunctions', which allows reading contracts from sources. - Use new features instead of combination 'CallsInPlaceEffect || ReturnsEffect' - Rename 'CallsInPlaceEffect' -> 'UseCallsInPlaceEffect', 'ReturnsEffect' -> 'UseReturnsEffect'. As names suggest, they control if it is allowed to use corresponding effect in analysis. We have to introduce separate 'ReadDeserializedContracts' to enable contracts only in some modules of the project, because libraries are read with project-wide settings (see KT-20692).
This commit is contained in:
@@ -1048,7 +1048,7 @@ class ControlFlowProcessor(private val trace: BindingTrace) {
|
||||
mark(lambdaExpression)
|
||||
val functionLiteral = lambdaExpression.functionLiteral
|
||||
|
||||
// NB. Behaviour here is implicitly controlled by the LanguageFeature 'CallsInPlaceEffect'
|
||||
// NB. Behaviour here is implicitly controlled by the LanguageFeature 'UseCallsInPlaceEffect'
|
||||
// If this feature is turned off, then slice LAMBDA_INVOCATIONS is never written and invocationKind
|
||||
// in all subsequent calls always 'null', resulting in falling back to old behaviour
|
||||
visitFunction(functionLiteral, trace[BindingContext.LAMBDA_INVOCATIONS, lambdaExpression])
|
||||
|
||||
@@ -38,7 +38,7 @@ class ContractDeserializerImpl(private val configuration: DeserializationConfigu
|
||||
): Pair<FunctionDescriptor.UserDataKey<*>, LazyContractProvider>? {
|
||||
if (!proto.hasContract()) return null
|
||||
|
||||
if (!configuration.returnsEffectAllowed && !configuration.callsInPlaceEffectAllowed) return null
|
||||
if (!configuration.readDeserializedContracts) return null
|
||||
|
||||
val worker = ContractDeserializationWorker(typeTable, typeDeserializer, ownerFunction)
|
||||
val contract = worker.deserializeContract(proto.contract)
|
||||
|
||||
@@ -45,7 +45,7 @@ class EffectSystem(val languageVersionSettings: LanguageVersionSettings) {
|
||||
bindingTrace: BindingTrace,
|
||||
moduleDescriptor: ModuleDescriptor
|
||||
): DataFlowInfo {
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.ReturnsEffect)) return DataFlowInfo.EMPTY
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.UseReturnsEffect)) return DataFlowInfo.EMPTY
|
||||
|
||||
// Prevent launch of effect system machinery on pointless cases (constants/enums/constructors/etc.)
|
||||
val callExpression = resolvedCall.call.callElement as? KtCallExpression ?: return DataFlowInfo.EMPTY
|
||||
@@ -62,7 +62,7 @@ class EffectSystem(val languageVersionSettings: LanguageVersionSettings) {
|
||||
bindingTrace: BindingTrace,
|
||||
moduleDescriptor: ModuleDescriptor
|
||||
): ConditionalDataFlowInfo {
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.ReturnsEffect)) return ConditionalDataFlowInfo.EMPTY
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.UseReturnsEffect)) return ConditionalDataFlowInfo.EMPTY
|
||||
if (leftExpression == null || rightExpression == null) return ConditionalDataFlowInfo.EMPTY
|
||||
|
||||
val leftComputation =
|
||||
@@ -82,7 +82,7 @@ class EffectSystem(val languageVersionSettings: LanguageVersionSettings) {
|
||||
}
|
||||
|
||||
fun recordDefiniteInvocations(resolvedCall: ResolvedCall<*>, bindingTrace: BindingTrace, moduleDescriptor: ModuleDescriptor) {
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.CallsInPlaceEffect)) return
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.UseCallsInPlaceEffect)) return
|
||||
|
||||
// Prevent launch of effect system machinery on pointless cases (constants/enums/constructors/etc.)
|
||||
val callExpression = resolvedCall.call.callElement as? KtCallExpression ?: return
|
||||
@@ -102,7 +102,7 @@ class EffectSystem(val languageVersionSettings: LanguageVersionSettings) {
|
||||
bindingTrace: BindingTrace,
|
||||
moduleDescriptor: ModuleDescriptor
|
||||
): DataFlowInfo {
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.ReturnsEffect)) return DataFlowInfo.EMPTY
|
||||
if (!languageVersionSettings.supportsFeature(LanguageFeature.UseReturnsEffect)) return DataFlowInfo.EMPTY
|
||||
if (condition == null) return DataFlowInfo.EMPTY
|
||||
|
||||
return getContextInfoWhen(ESReturns(value.lift()), condition, bindingTrace, moduleDescriptor)
|
||||
|
||||
+1
-2
@@ -43,8 +43,7 @@ class ContractParsingServices(val languageVersionSettings: LanguageVersionSettin
|
||||
if (!isContractDescriptionCallFastCheck(expression) || ownerDescriptor !is FunctionDescriptor) return
|
||||
val contractProvider = ownerDescriptor.getUserData(ContractProviderKey) ?: return
|
||||
|
||||
val isFeatureTurnedOn = languageVersionSettings.supportsFeature(LanguageFeature.CallsInPlaceEffect) ||
|
||||
languageVersionSettings.supportsFeature(LanguageFeature.ReturnsEffect) ||
|
||||
val isFeatureTurnedOn = languageVersionSettings.supportsFeature(LanguageFeature.AllowContractsForCustomFunctions) ||
|
||||
// This condition is here for technical purposes of compiling 1.2-runtime with contracts
|
||||
languageVersionSettings.getFlag(AnalysisFlag.Flags.allowKotlinPackage)
|
||||
|
||||
|
||||
+1
-3
@@ -31,7 +31,5 @@ class CompilerDeserializationConfiguration(languageVersionSettings: LanguageVers
|
||||
|
||||
override val isJvmPackageNameSupported = languageVersionSettings.supportsFeature(LanguageFeature.JvmPackageName)
|
||||
|
||||
override val returnsEffectAllowed: Boolean = languageVersionSettings.supportsFeature(LanguageFeature.ReturnsEffect)
|
||||
|
||||
override val callsInPlaceEffectAllowed: Boolean = languageVersionSettings.supportsFeature(LanguageFeature.CallsInPlaceEffect)
|
||||
override val readDeserializedContracts: Boolean = languageVersionSettings.supportsFeature(LanguageFeature.ReadDeserializedContracts)
|
||||
}
|
||||
|
||||
@@ -235,8 +235,7 @@ class FunctionDescriptorResolver(
|
||||
}
|
||||
val emptyContract = LazyContractProvider.createInitialized(null)
|
||||
|
||||
val isContractsEnabled = languageVersionSettings.supportsFeature(LanguageFeature.CallsInPlaceEffect) ||
|
||||
languageVersionSettings.supportsFeature(LanguageFeature.ReturnsEffect) ||
|
||||
val isContractsEnabled = languageVersionSettings.supportsFeature(LanguageFeature.AllowContractsForCustomFunctions) ||
|
||||
// We need to enable contracts if we're compiling "kotlin"-package to be able to ship contracts in stdlib in 1.2
|
||||
languageVersionSettings.getFlag(AnalysisFlag.allowKotlinPackage)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user