Check for backend when checking for suspend in fun interfaces

This commit is contained in:
Ilmir Usmanov
2021-03-16 01:23:28 +01:00
parent bf2942b5cc
commit a90a5f6dd4
22 changed files with 85 additions and 92 deletions
@@ -489,6 +489,7 @@ default: `indy-with-constants` for JVM target 9 or greater, `inline` otherwise""
result[JvmAnalysisFlags.enableJvmPreview] = enableJvmPreview
result[AnalysisFlags.allowUnstableDependencies] = allowUnstableDependencies || useFir
result[JvmAnalysisFlags.disableUltraLightClasses] = disableUltraLightClasses
result[JvmAnalysisFlags.useIR] = useIR
return result
}
@@ -33,6 +33,9 @@ object JvmAnalysisFlags {
@JvmStatic
val enableJvmPreview by AnalysisFlag.Delegates.Boolean
@JvmStatic
val useIR by AnalysisFlag.Delegates.Boolean
private object Delegates {
object JavaTypeEnhancementStateWarnByDefault {
operator fun provideDelegate(instance: Any?, property: KProperty<*>): AnalysisFlag.Delegate<JavaTypeEnhancementState> =
@@ -10078,28 +10078,6 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/functionLiterals/return/unresolvedReferenceInReturnBlock.kt");
}
}
@Nested
@TestMetadata("compiler/testData/diagnostics/tests/functionLiterals/suspend")
@TestDataPath("$PROJECT_ROOT")
public class Suspend {
@Test
public void testAllFilesPresentInSuspend() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/functionLiterals/suspend"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("disabled.kt")
public void testDisabled() throws Exception {
runTest("compiler/testData/diagnostics/tests/functionLiterals/suspend/disabled.kt");
}
@Test
@TestMetadata("enabled.kt")
public void testEnabled() throws Exception {
runTest("compiler/testData/diagnostics/tests/functionLiterals/suspend/enabled.kt");
}
}
}
@Nested
@@ -0,0 +1,40 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.resolve.jvm.checkers
import org.jetbrains.kotlin.config.JvmAnalysisFlags
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtClass
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker
import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext
import org.jetbrains.kotlin.resolve.sam.getSingleAbstractMethodOrNull
import org.jetbrains.kotlin.resolve.source.getPsi
class SuspendInFunInterfaceChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (declaration !is KtClass) return
if (descriptor !is ClassDescriptor || !descriptor.isFun) return
val funKeyword = declaration.getFunKeyword() ?: return
val abstractMember = getSingleAbstractMethodOrNull(descriptor) ?: return
if (!abstractMember.isSuspend) return
if (context.languageVersionSettings.supportsFeature(LanguageFeature.SuspendFunctionsInFunInterfaces) &&
context.languageVersionSettings.getFlag(JvmAnalysisFlags.useIR)
) return
val ktFunction = abstractMember.source.getPsi() as? KtNamedFunction
val reportOn = ktFunction?.modifierList?.getModifier(KtTokens.SUSPEND_KEYWORD) ?: funKeyword
context.trace.report(Errors.FUN_INTERFACE_WITH_SUSPEND_FUNCTION.on(reportOn))
}
}
@@ -36,6 +36,7 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase(
JvmInlineApplicabilityChecker(),
StrictfpApplicabilityChecker(),
JvmAnnotationsTargetNonExistentAccessorChecker(),
SuspendInFunInterfaceChecker(),
BadInheritedJavaSignaturesChecker,
JvmMultifileClassStateChecker,
SynchronizedOnInlineMethodChecker,
@@ -61,15 +61,6 @@ class FunInterfaceDeclarationChecker : DeclarationChecker {
) {
val ktFunction = abstractMember.source.getPsi() as? KtNamedFunction
if (abstractMember.isSuspend &&
!(context.languageVersionSettings.supportsFeature(LanguageFeature.SuspendFunctionsInFunInterfaces) &&
context.languageVersionSettings.supportsFeature(LanguageFeature.JvmIrEnabledByDefault))
) {
val reportOn = ktFunction?.modifierList?.getModifier(KtTokens.SUSPEND_KEYWORD) ?: funInterfaceKeyword
context.trace.report(Errors.FUN_INTERFACE_WITH_SUSPEND_FUNCTION.on(reportOn))
return
}
if (abstractMember.typeParameters.isNotEmpty()) {
val reportOn = ktFunction?.typeParameterList ?: ktFunction?.funKeyword ?: funInterfaceKeyword
context.trace.report(Errors.FUN_INTERFACE_ABSTRACT_METHOD_WITH_TYPE_PARAMETERS.on(reportOn))
@@ -6,6 +6,7 @@
package org.jetbrains.kotlin.test.builders
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.test.TargetBackend
import org.jetbrains.kotlin.test.directives.LanguageSettingsDirectives
import org.jetbrains.kotlin.test.directives.model.RegisteredDirectives
import org.jetbrains.kotlin.test.directives.model.singleOrZeroValue
@@ -49,7 +50,11 @@ class LanguageVersionSettingsBuilder {
analysisFlags[flag] = value
}
fun configureUsingDirectives(directives: RegisteredDirectives, environmentConfigurators: List<EnvironmentConfigurator>) {
fun configureUsingDirectives(
directives: RegisteredDirectives,
environmentConfigurators: List<EnvironmentConfigurator>,
targetBackend: TargetBackend?
) {
val apiVersion = directives.singleOrZeroValue(LanguageSettingsDirectives.API_VERSION)
if (apiVersion != null) {
this.apiVersion = apiVersion
@@ -69,6 +74,7 @@ class LanguageVersionSettingsBuilder {
analysisFlag(JvmAnalysisFlags.inheritMultifileParts, trueOrNull(LanguageSettingsDirectives.INHERIT_MULTIFILE_PARTS in directives)),
analysisFlag(JvmAnalysisFlags.sanitizeParentheses, trueOrNull(LanguageSettingsDirectives.SANITIZE_PARENTHESES in directives)),
analysisFlag(JvmAnalysisFlags.enableJvmPreview, trueOrNull(LanguageSettingsDirectives.ENABLE_JVM_PREVIEW in directives)),
analysisFlag(JvmAnalysisFlags.useIR, targetBackend == TargetBackend.JVM_IR || targetBackend == null),
analysisFlag(AnalysisFlags.explicitApiVersion, trueOrNull(apiVersion != null)),
)
@@ -0,0 +1,4 @@
$TESTDATA_DIR$/suspendInFunInterfaceIrDisabled.kt
-d
$TEMP_DIR$
-Xuse-old-backend
@@ -0,0 +1,3 @@
fun interface FIC {
suspend fun foo()
}
@@ -0,0 +1,4 @@
compiler/testData/cli/jvm/suspendInFunInterfaceIrDisabled.kt:2:5: error: 'suspend' modifier is not allowed on a single abstract member
suspend fun foo()
^
COMPILATION_ERROR
@@ -0,0 +1,4 @@
$TESTDATA_DIR$/suspendInFunInterfaceIrEnabled.kt
-d
$TEMP_DIR$
-Xuse-ir
@@ -0,0 +1,3 @@
fun interface FIC {
suspend fun foo()
}
@@ -0,0 +1 @@
OK
@@ -1,5 +0,0 @@
// LANGUAGE: -SuspendFunctionsInFunInterfaces, +JvmIrEnabledByDefault
fun interface I {
suspend fun foo()
}
@@ -1,5 +0,0 @@
// LANGUAGE: -SuspendFunctionsInFunInterfaces, +JvmIrEnabledByDefault
fun interface I {
<!FUN_INTERFACE_WITH_SUSPEND_FUNCTION!>suspend<!> fun foo()
}
@@ -1,8 +0,0 @@
package
public fun interface I {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract suspend fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -1,6 +0,0 @@
// FIR_IDENTICAL
// LANGUAGE: +SuspendFunctionsInFunInterfaces, +JvmIrEnabledByDefault
fun interface I {
suspend fun foo()
}
@@ -1,8 +0,0 @@
package
public fun interface I {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public abstract suspend fun foo(): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -10084,28 +10084,6 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/functionLiterals/return/unresolvedReferenceInReturnBlock.kt");
}
}
@Nested
@TestMetadata("compiler/testData/diagnostics/tests/functionLiterals/suspend")
@TestDataPath("$PROJECT_ROOT")
public class Suspend {
@Test
public void testAllFilesPresentInSuspend() throws Exception {
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/functionLiterals/suspend"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@Test
@TestMetadata("disabled.kt")
public void testDisabled() throws Exception {
runTest("compiler/testData/diagnostics/tests/functionLiterals/suspend/disabled.kt");
}
@Test
@TestMetadata("enabled.kt")
public void testEnabled() throws Exception {
runTest("compiler/testData/diagnostics/tests/functionLiterals/suspend/enabled.kt");
}
}
}
@Nested
@@ -11,10 +11,7 @@ import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoot
import org.jetbrains.kotlin.cli.jvm.config.addJvmClasspathRoots
import org.jetbrains.kotlin.cli.jvm.config.jvmClasspathRoots
import org.jetbrains.kotlin.codegen.forTestCompile.ForTestCompileRuntime
import org.jetbrains.kotlin.config.CompilerConfiguration
import org.jetbrains.kotlin.config.CompilerConfigurationKey
import org.jetbrains.kotlin.config.JVMConfigurationKeys
import org.jetbrains.kotlin.config.JvmTarget
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.platform.jvm.JvmPlatforms
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.TestJdkKind
@@ -284,13 +284,14 @@ class ModuleStructureExtractorImpl(
val moduleDirectives = moduleDirectivesBuilder.build() + testServices.defaultDirectives + globalDirectives
moduleDirectives.forEach { it.checkDirectiveApplicability(contextIsGlobal = isImplicitModule, contextIsModule = true) }
currentModuleLanguageVersionSettingsBuilder.configureUsingDirectives(moduleDirectives, environmentConfigurators)
val targetBackend = currentModuleTargetBackend ?: defaultsProvider.defaultTargetBackend
currentModuleLanguageVersionSettingsBuilder.configureUsingDirectives(moduleDirectives, environmentConfigurators, targetBackend)
val moduleName = currentModuleName ?: defaultModuleName
val targetPlatform = currentModuleTargetPlatform ?: parseModulePlatformByName(moduleName) ?: defaultsProvider.defaultPlatform
val testModule = TestModule(
name = moduleName,
targetPlatform = targetPlatform,
targetBackend = currentModuleTargetBackend ?: defaultsProvider.defaultTargetBackend,
targetBackend = targetBackend,
frontendKind = currentModuleFrontendKind ?: defaultsProvider.defaultFrontend,
binaryKind = defaultsProvider.defaultArtifactKind ?: targetPlatform.toArtifactKind(),
files = filesOfCurrentModule,
@@ -766,6 +766,16 @@ public class CliTestGenerated extends AbstractCliTest {
runTest("compiler/testData/cli/jvm/suppressAllWarningsJvm.args");
}
@TestMetadata("suspendInFunInterfaceIrDisabled.args")
public void testSuspendInFunInterfaceIrDisabled() throws Exception {
runTest("compiler/testData/cli/jvm/suspendInFunInterfaceIrDisabled.args");
}
@TestMetadata("suspendInFunInterfaceIrEnabled.args")
public void testSuspendInFunInterfaceIrEnabled() throws Exception {
runTest("compiler/testData/cli/jvm/suspendInFunInterfaceIrEnabled.args");
}
@TestMetadata("suspensionPointInMonitor.args")
public void testSuspensionPointInMonitor() throws Exception {
runTest("compiler/testData/cli/jvm/suspensionPointInMonitor.args");