From 537a59d6ca7cceeaf7ca14728828044b8b9f65f3 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Wed, 22 Apr 2020 04:30:58 +0300 Subject: [PATCH] Introduce basic suspend conversion in FE #KT-15917 In Progress --- ...irOldFrontendDiagnosticsTestGenerated.java | 33 +++++++++++++++ .../tower/KotlinToResolvedCallTransformer.kt | 22 +++++++++- .../calls/components/ResolutionParts.kt | 8 ++-- .../components/suspendConversionUtils.kt | 42 +++++++++++++++++++ .../resolve/calls/model/ResolutionAtoms.kt | 1 + .../calls/model/ResolutionCandidate.kt | 15 +++++++ .../basicSuspendConversion.fir.kt | 23 ++++++++++ .../basicSuspendConversion.kt | 23 ++++++++++ .../basicSuspendConversion.txt | 6 +++ .../basicSuspendConversionGenerics.fir.kt | 30 +++++++++++++ .../basicSuspendConversionGenerics.kt | 30 +++++++++++++ .../basicSuspendConversionGenerics.txt | 14 +++++++ .../severalConversionsInOneCall.fir.kt | 11 +++++ .../severalConversionsInOneCall.kt | 11 +++++ .../severalConversionsInOneCall.txt | 4 ++ .../suspendConversionDisabled.fir.kt | 23 ++++++++++ .../suspendConversionDisabled.kt | 23 ++++++++++ .../suspendConversionDisabled.txt | 6 +++ .../coroutines/lambdaExpectedType.kt | 1 + .../functionVsSuspendFunction.kt | 1 + .../checkers/DiagnosticsTestGenerated.java | 33 +++++++++++++++ .../DiagnosticsUsingJavacTestGenerated.java | 33 +++++++++++++++ .../kotlin/config/LanguageVersionSettings.kt | 1 + 23 files changed, 388 insertions(+), 6 deletions(-) create mode 100644 compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/suspendConversionUtils.kt create mode 100644 compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversion.fir.kt create mode 100644 compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversion.kt create mode 100644 compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversion.txt create mode 100644 compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversionGenerics.fir.kt create mode 100644 compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversionGenerics.kt create mode 100644 compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversionGenerics.txt create mode 100644 compiler/testData/diagnostics/tests/suspendConversion/severalConversionsInOneCall.fir.kt create mode 100644 compiler/testData/diagnostics/tests/suspendConversion/severalConversionsInOneCall.kt create mode 100644 compiler/testData/diagnostics/tests/suspendConversion/severalConversionsInOneCall.txt create mode 100644 compiler/testData/diagnostics/tests/suspendConversion/suspendConversionDisabled.fir.kt create mode 100644 compiler/testData/diagnostics/tests/suspendConversion/suspendConversionDisabled.kt create mode 100644 compiler/testData/diagnostics/tests/suspendConversion/suspendConversionDisabled.txt diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java index cf6cea15859..dc5e1a3e0e9 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirOldFrontendDiagnosticsTestGenerated.java @@ -22994,6 +22994,39 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte } } + @TestMetadata("compiler/testData/diagnostics/tests/suspendConversion") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class SuspendConversion extends AbstractFirOldFrontendDiagnosticsTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInSuspendConversion() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/suspendConversion"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @TestMetadata("basicSuspendConversion.kt") + public void testBasicSuspendConversion() throws Exception { + runTest("compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversion.kt"); + } + + @TestMetadata("basicSuspendConversionGenerics.kt") + public void testBasicSuspendConversionGenerics() throws Exception { + runTest("compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversionGenerics.kt"); + } + + @TestMetadata("severalConversionsInOneCall.kt") + public void testSeveralConversionsInOneCall() throws Exception { + runTest("compiler/testData/diagnostics/tests/suspendConversion/severalConversionsInOneCall.kt"); + } + + @TestMetadata("suspendConversionDisabled.kt") + public void testSuspendConversionDisabled() throws Exception { + runTest("compiler/testData/diagnostics/tests/suspendConversion/suspendConversionDisabled.kt"); + } + } + @TestMetadata("compiler/testData/diagnostics/tests/syntheticExtensions") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt index cfda2f0b472..528b574fdae 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt @@ -290,8 +290,10 @@ class KotlinToResolvedCallTransformer( is ArgumentMatch -> { parameter = argumentMapping.valueParameter - val expectedType = resolvedCall.getExpectedTypeForSamConvertedArgument(valueArgument) - ?: getEffectiveExpectedType(argumentMapping.valueParameter, valueArgument, context) + val expectedType = + resolvedCall.getExpectedTypeForSamConvertedArgument(valueArgument) + ?: resolvedCall.getExpectedTypeForSuspendConvertedArgument(valueArgument) + ?: getEffectiveExpectedType(argumentMapping.valueParameter, valueArgument, context) Pair( expectedType, CallPosition.ValueArgumentPosition(resolvedCall, argumentMapping.valueParameter, valueArgument), @@ -656,6 +658,7 @@ class NewResolvedCallImpl( private var dispatchReceiver = resolvedCallAtom.dispatchReceiverArgument?.receiver?.receiverValue private var smartCastDispatchReceiverType: KotlinType? = null private var expectedTypeForSamConvertedArgumentMap: MutableMap? = null + private var expectedTypeForSuspendConvertedArgumentMap: MutableMap? = null private var argumentTypeForConstantConvertedMap: MutableMap? = null @@ -737,6 +740,7 @@ class NewResolvedCallImpl( } calculateExpectedTypeForSamConvertedArgumentMap(substitutor) + calculateExpectedTypeForSuspendConvertedArgumentMap(substitutor) calculateExpectedTypeForConstantConvertedArgumentMap() } @@ -805,6 +809,9 @@ class NewResolvedCallImpl( fun getExpectedTypeForSamConvertedArgument(valueArgument: ValueArgument): UnwrappedType? = expectedTypeForSamConvertedArgumentMap?.get(valueArgument) + fun getExpectedTypeForSuspendConvertedArgument(valueArgument: ValueArgument): UnwrappedType? = + expectedTypeForSuspendConvertedArgumentMap?.get(valueArgument) + private fun calculateExpectedTypeForConstantConvertedArgumentMap() { if (resolvedCallAtom.argumentsWithConstantConversion.isEmpty()) return @@ -827,6 +834,17 @@ class NewResolvedCallImpl( } } + private fun calculateExpectedTypeForSuspendConvertedArgumentMap(substitutor: NewTypeSubstitutor?) { + if (resolvedCallAtom.argumentsWithSuspendConversion.isEmpty()) return + + expectedTypeForSuspendConvertedArgumentMap = hashMapOf() + for ((argument, convertedType) in resolvedCallAtom.argumentsWithSuspendConversion) { + val typeWithFreshVariables = resolvedCallAtom.freshVariablesSubstitutor.safeSubstitute(convertedType) + val expectedType = substitutor?.safeSubstitute(typeWithFreshVariables) ?: typeWithFreshVariables + expectedTypeForSuspendConvertedArgumentMap!![argument.psiCallArgument.valueArgument] = expectedType + } + } + override fun argumentToParameterMap( resultingDescriptor: CallableDescriptor, valueArguments: Map, diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt index a34d91c6bb8..1580ca1b965 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/ResolutionParts.kt @@ -483,10 +483,10 @@ private fun KotlinResolutionCandidate.prepareExpectedType( argument: KotlinCallArgument, candidateParameter: ParameterDescriptor ): UnwrappedType { - val argumentType = getExpectedTypeWithSAMConversion(argument, candidateParameter) ?: argument.getExpectedType( - candidateParameter, - callComponents.languageVersionSettings - ) + val argumentType = + getExpectedTypeWithSAMConversion(argument, candidateParameter) + ?: getExpectedTypeWithSuspendConversion(argument, candidateParameter) + ?: argument.getExpectedType(candidateParameter, callComponents.languageVersionSettings) val resultType = knownTypeParametersResultingSubstitutor?.substitute(argumentType) ?: argumentType return resolvedCall.freshVariablesSubstitutor.safeSubstitute(resultType) } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/suspendConversionUtils.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/suspendConversionUtils.kt new file mode 100644 index 00000000000..525a953c69a --- /dev/null +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/suspendConversionUtils.kt @@ -0,0 +1,42 @@ +/* + * Copyright 2010-2020 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.calls.components + +import org.jetbrains.kotlin.builtins.* +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.descriptors.ParameterDescriptor +import org.jetbrains.kotlin.resolve.calls.model.* +import org.jetbrains.kotlin.types.UnwrappedType + +fun KotlinResolutionCandidate.getExpectedTypeWithSuspendConversion( + argument: KotlinCallArgument, + candidateParameter: ParameterDescriptor +): UnwrappedType? { + if (!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SuspendConversion)) return null + + if (argument !is SimpleKotlinCallArgument) return null + + val argumentType = argument.receiver.stableType + if (!argumentType.isFunctionType) return null + if (argumentType.isSuspendFunctionType) return null + + val parameterType = candidateParameter.type + if (!parameterType.isSuspendFunctionType) return null + + val nonSuspendParameterType = createFunctionType( + callComponents.builtIns, + parameterType.annotations, + parameterType.getReceiverTypeFromFunctionType(), + parameterType.getValueParameterTypesFromFunctionType().map { it.type }, + parameterNames = null, + parameterType.getReturnTypeFromFunctionType(), + suspendFunction = false + ) + + resolvedCall.registerArgumentWithSuspendConversion(argument, nonSuspendParameterType) + + return nonSuspendParameterType +} \ No newline at end of file diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionAtoms.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionAtoms.kt index b0af7f71892..9fb88d69baa 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionAtoms.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionAtoms.kt @@ -71,6 +71,7 @@ abstract class ResolvedCallAtom : ResolvedAtom() { abstract val freshVariablesSubstitutor: FreshVariableNewTypeSubstitutor abstract val knownParametersSubstitutor: TypeSubstitutor abstract val argumentsWithConversion: Map + abstract val argumentsWithSuspendConversion: Map abstract val argumentsWithConstantConversion: Map } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt index f47bb6a172c..669325aeda3 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/ResolutionCandidate.kt @@ -31,6 +31,7 @@ import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind import org.jetbrains.kotlin.resolve.calls.tower.* import org.jetbrains.kotlin.resolve.constants.IntegerValueTypeConstant import org.jetbrains.kotlin.types.TypeSubstitutor +import org.jetbrains.kotlin.types.UnwrappedType abstract class ResolutionPart { @@ -185,14 +186,21 @@ class MutableResolvedCallAtom( override lateinit var knownParametersSubstitutor: TypeSubstitutor lateinit var argumentToCandidateParameter: Map private var samAdapterMap: HashMap? = null + private var suspendAdapterMap: HashMap? = null private var signedUnsignedConstantConversions: HashMap? = null val hasSamConversion: Boolean get() = samAdapterMap != null + val hasSuspendConversion: Boolean + get() = suspendAdapterMap != null + override val argumentsWithConversion: Map get() = samAdapterMap ?: emptyMap() + override val argumentsWithSuspendConversion: Map + get() = suspendAdapterMap ?: emptyMap() + override val argumentsWithConstantConversion: Map get() = signedUnsignedConstantConversions ?: emptyMap() @@ -203,6 +211,13 @@ class MutableResolvedCallAtom( samAdapterMap!![argument] = samConversionDescription } + fun registerArgumentWithSuspendConversion(argument: KotlinCallArgument, convertedType: UnwrappedType) { + if (suspendAdapterMap == null) + suspendAdapterMap = hashMapOf() + + suspendAdapterMap!![argument] = convertedType + } + fun registerArgumentWithConstantConversion(argument: KotlinCallArgument, convertedConstant: IntegerValueTypeConstant) { if (signedUnsignedConstantConversions == null) signedUnsignedConstantConversions = hashMapOf() diff --git a/compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversion.fir.kt b/compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversion.fir.kt new file mode 100644 index 00000000000..cde39929f37 --- /dev/null +++ b/compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversion.fir.kt @@ -0,0 +1,23 @@ +// !LANGUAGE: +SuspendConversion +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun foo1(f: suspend () -> String) {} +fun foo2(f: suspend (Int) -> String) {} +fun foo3(f: suspend () -> Unit) {} + +fun test( + f0: suspend () -> String, + f1: () -> String, + f2: (Int) -> String, + f3: () -> Unit, +) { + foo1 { "str" } + foo1(f0) + + foo1(f1) + foo2(f2) + foo3(f3) + + foo1(f2) + foo1(f3) +} diff --git a/compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversion.kt b/compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversion.kt new file mode 100644 index 00000000000..daf4e3de0f7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversion.kt @@ -0,0 +1,23 @@ +// !LANGUAGE: +SuspendConversion +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun foo1(f: suspend () -> String) {} +fun foo2(f: suspend (Int) -> String) {} +fun foo3(f: suspend () -> Unit) {} + +fun test( + f0: suspend () -> String, + f1: () -> String, + f2: (Int) -> String, + f3: () -> Unit, +) { + foo1 { "str" } + foo1(f0) + + foo1(f1) + foo2(f2) + foo3(f3) + + foo1(f2) + foo1(f3) +} diff --git a/compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversion.txt b/compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversion.txt new file mode 100644 index 00000000000..7abf5398088 --- /dev/null +++ b/compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversion.txt @@ -0,0 +1,6 @@ +package + +public fun foo1(/*0*/ f: suspend () -> kotlin.String): kotlin.Unit +public fun foo2(/*0*/ f: suspend (kotlin.Int) -> kotlin.String): kotlin.Unit +public fun foo3(/*0*/ f: suspend () -> kotlin.Unit): kotlin.Unit +public fun test(/*0*/ f0: suspend () -> kotlin.String, /*1*/ f1: () -> kotlin.String, /*2*/ f2: (kotlin.Int) -> kotlin.String, /*3*/ f3: () -> kotlin.Unit): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversionGenerics.fir.kt b/compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversionGenerics.fir.kt new file mode 100644 index 00000000000..5a8e1071bfc --- /dev/null +++ b/compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversionGenerics.fir.kt @@ -0,0 +1,30 @@ +// !LANGUAGE: +SuspendConversion +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION + +class Inv2 + +fun foo1(f: suspend (T) -> String): T = TODO() +fun foo2(f: suspend () -> T): T = TODO() +fun foo3(f: suspend (T) -> K): Inv2 = TODO() + +fun id(e: I): I = e + +fun test(f: (Int) -> String, g: () -> String) { + val a0 = foo1(f) + a0 + + val a1 = foo2(g) + a1 + + val a2 = foo3(f) + a2 + + val a3 = foo1(id(f)) + a3 + + val a4 = foo2(id(g)) + a4 + + val a5 = foo3(id(f)) + a5 +} diff --git a/compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversionGenerics.kt b/compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversionGenerics.kt new file mode 100644 index 00000000000..87970894bfc --- /dev/null +++ b/compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversionGenerics.kt @@ -0,0 +1,30 @@ +// !LANGUAGE: +SuspendConversion +// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_EXPRESSION + +class Inv2 + +fun foo1(f: suspend (T) -> String): T = TODO() +fun foo2(f: suspend () -> T): T = TODO() +fun foo3(f: suspend (T) -> K): Inv2 = TODO() + +fun id(e: I): I = e + +fun test(f: (Int) -> String, g: () -> String) { + val a0 = foo1(f) + a0 + + val a1 = foo2(g) + a1 + + val a2 = foo3(f) + ")!>a2 + + val a3 = foo1(id(f)) + a3 + + val a4 = foo2(id(g)) + a4 + + val a5 = foo3(id(f)) + ")!>a5 +} diff --git a/compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversionGenerics.txt b/compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversionGenerics.txt new file mode 100644 index 00000000000..260f7221920 --- /dev/null +++ b/compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversionGenerics.txt @@ -0,0 +1,14 @@ +package + +public fun foo1(/*0*/ f: suspend (T) -> kotlin.String): T +public fun foo2(/*0*/ f: suspend () -> T): T +public fun foo3(/*0*/ f: suspend (T) -> K): Inv2 +public fun id(/*0*/ e: I): I +public fun test(/*0*/ f: (kotlin.Int) -> kotlin.String, /*1*/ g: () -> kotlin.String): kotlin.Unit + +public final class Inv2 { + public constructor Inv2() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/suspendConversion/severalConversionsInOneCall.fir.kt b/compiler/testData/diagnostics/tests/suspendConversion/severalConversionsInOneCall.fir.kt new file mode 100644 index 00000000000..5a08eb3ccb9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/suspendConversion/severalConversionsInOneCall.fir.kt @@ -0,0 +1,11 @@ +// !LANGUAGE: +SuspendConversion +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun foo(f: () -> String, g: suspend () -> String, h: suspend () -> String) {} + +fun test(f: () -> String, g: suspend () -> String) { + foo(f, f, f) + foo(f, { "str" }, f) + foo(f, f, g) + foo(f, g, g) +} diff --git a/compiler/testData/diagnostics/tests/suspendConversion/severalConversionsInOneCall.kt b/compiler/testData/diagnostics/tests/suspendConversion/severalConversionsInOneCall.kt new file mode 100644 index 00000000000..dd2768745b3 --- /dev/null +++ b/compiler/testData/diagnostics/tests/suspendConversion/severalConversionsInOneCall.kt @@ -0,0 +1,11 @@ +// !LANGUAGE: +SuspendConversion +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun foo(f: () -> String, g: suspend () -> String, h: suspend () -> String) {} + +fun test(f: () -> String, g: suspend () -> String) { + foo(f, f, f) + foo(f, { "str" }, f) + foo(f, f, g) + foo(f, g, g) +} diff --git a/compiler/testData/diagnostics/tests/suspendConversion/severalConversionsInOneCall.txt b/compiler/testData/diagnostics/tests/suspendConversion/severalConversionsInOneCall.txt new file mode 100644 index 00000000000..be200b8eadc --- /dev/null +++ b/compiler/testData/diagnostics/tests/suspendConversion/severalConversionsInOneCall.txt @@ -0,0 +1,4 @@ +package + +public fun foo(/*0*/ f: () -> kotlin.String, /*1*/ g: suspend () -> kotlin.String, /*2*/ h: suspend () -> kotlin.String): kotlin.Unit +public fun test(/*0*/ f: () -> kotlin.String, /*1*/ g: suspend () -> kotlin.String): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/suspendConversion/suspendConversionDisabled.fir.kt b/compiler/testData/diagnostics/tests/suspendConversion/suspendConversionDisabled.fir.kt new file mode 100644 index 00000000000..7ad794fd2bc --- /dev/null +++ b/compiler/testData/diagnostics/tests/suspendConversion/suspendConversionDisabled.fir.kt @@ -0,0 +1,23 @@ +// !LANGUAGE: -SuspendConversion +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun foo1(f: suspend () -> String) {} +fun foo2(f: suspend (Int) -> String) {} +fun foo3(f: suspend () -> Unit) {} + +fun test( + f0: suspend () -> String, + f1: () -> String, + f2: (Int) -> String, + f3: () -> Unit, +) { + foo1 { "str" } + foo1(f0) + + foo1(f1) + foo2(f2) + foo3(f3) + + foo1(f2) + foo1(f3) +} diff --git a/compiler/testData/diagnostics/tests/suspendConversion/suspendConversionDisabled.kt b/compiler/testData/diagnostics/tests/suspendConversion/suspendConversionDisabled.kt new file mode 100644 index 00000000000..ccccead0f34 --- /dev/null +++ b/compiler/testData/diagnostics/tests/suspendConversion/suspendConversionDisabled.kt @@ -0,0 +1,23 @@ +// !LANGUAGE: -SuspendConversion +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun foo1(f: suspend () -> String) {} +fun foo2(f: suspend (Int) -> String) {} +fun foo3(f: suspend () -> Unit) {} + +fun test( + f0: suspend () -> String, + f1: () -> String, + f2: (Int) -> String, + f3: () -> Unit, +) { + foo1 { "str" } + foo1(f0) + + foo1(f1) + foo2(f2) + foo3(f3) + + foo1(f2) + foo1(f3) +} diff --git a/compiler/testData/diagnostics/tests/suspendConversion/suspendConversionDisabled.txt b/compiler/testData/diagnostics/tests/suspendConversion/suspendConversionDisabled.txt new file mode 100644 index 00000000000..7abf5398088 --- /dev/null +++ b/compiler/testData/diagnostics/tests/suspendConversion/suspendConversionDisabled.txt @@ -0,0 +1,6 @@ +package + +public fun foo1(/*0*/ f: suspend () -> kotlin.String): kotlin.Unit +public fun foo2(/*0*/ f: suspend (kotlin.Int) -> kotlin.String): kotlin.Unit +public fun foo3(/*0*/ f: suspend () -> kotlin.Unit): kotlin.Unit +public fun test(/*0*/ f0: suspend () -> kotlin.String, /*1*/ f1: () -> kotlin.String, /*2*/ f2: (kotlin.Int) -> kotlin.String, /*3*/ f3: () -> kotlin.Unit): kotlin.Unit diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/lambdaExpectedType.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/lambdaExpectedType.kt index 0466fc0c4cb..9f4dd77d24e 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/lambdaExpectedType.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/lambdaExpectedType.kt @@ -1,3 +1,4 @@ +// !LANGUAGE: -SuspendConversion // !WITH_NEW_INFERENCE // !CHECK_TYPE // !DIAGNOSTICS: -UNUSED_PARAMETER -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE -UNUSED_VALUE -UNUSED_VARIABLE diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendFunctionType/functionVsSuspendFunction.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendFunctionType/functionVsSuspendFunction.kt index 7e979a0c646..370c0e6f882 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendFunctionType/functionVsSuspendFunction.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/suspendFunctionType/functionVsSuspendFunction.kt @@ -1,3 +1,4 @@ +// !LANGUAGE: -SuspendConversion // !DIAGNOSTICS: -UNUSED_PARAMETER fun useSuspendFn(sfn: suspend () -> Unit) = sfn diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 3d157a7c5fb..832f783a7d7 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -23076,6 +23076,39 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTestWithFirVali } } + @TestMetadata("compiler/testData/diagnostics/tests/suspendConversion") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class SuspendConversion extends AbstractDiagnosticsTestWithFirValidation { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInSuspendConversion() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/suspendConversion"), Pattern.compile("^(.*)\\.kts?$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @TestMetadata("basicSuspendConversion.kt") + public void testBasicSuspendConversion() throws Exception { + runTest("compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversion.kt"); + } + + @TestMetadata("basicSuspendConversionGenerics.kt") + public void testBasicSuspendConversionGenerics() throws Exception { + runTest("compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversionGenerics.kt"); + } + + @TestMetadata("severalConversionsInOneCall.kt") + public void testSeveralConversionsInOneCall() throws Exception { + runTest("compiler/testData/diagnostics/tests/suspendConversion/severalConversionsInOneCall.kt"); + } + + @TestMetadata("suspendConversionDisabled.kt") + public void testSuspendConversionDisabled() throws Exception { + runTest("compiler/testData/diagnostics/tests/suspendConversion/suspendConversionDisabled.kt"); + } + } + @TestMetadata("compiler/testData/diagnostics/tests/syntheticExtensions") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index be3d0900cea..3d1d9d1ca5c 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -22996,6 +22996,39 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing } } + @TestMetadata("compiler/testData/diagnostics/tests/suspendConversion") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class SuspendConversion extends AbstractDiagnosticsUsingJavacTest { + private void runTest(String testDataFilePath) throws Exception { + KotlinTestUtils.runTest(this::doTest, this, testDataFilePath); + } + + public void testAllFilesPresentInSuspendConversion() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/tests/suspendConversion"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true); + } + + @TestMetadata("basicSuspendConversion.kt") + public void testBasicSuspendConversion() throws Exception { + runTest("compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversion.kt"); + } + + @TestMetadata("basicSuspendConversionGenerics.kt") + public void testBasicSuspendConversionGenerics() throws Exception { + runTest("compiler/testData/diagnostics/tests/suspendConversion/basicSuspendConversionGenerics.kt"); + } + + @TestMetadata("severalConversionsInOneCall.kt") + public void testSeveralConversionsInOneCall() throws Exception { + runTest("compiler/testData/diagnostics/tests/suspendConversion/severalConversionsInOneCall.kt"); + } + + @TestMetadata("suspendConversionDisabled.kt") + public void testSuspendConversionDisabled() throws Exception { + runTest("compiler/testData/diagnostics/tests/suspendConversion/suspendConversionDisabled.kt"); + } + } + @TestMetadata("compiler/testData/diagnostics/tests/syntheticExtensions") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 8e4885e08fe..796dd82b33f 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -150,6 +150,7 @@ enum class LanguageFeature( SamConversionPerArgument(sinceVersion = KOTLIN_1_4), FunctionReferenceWithDefaultValueAsOtherType(sinceVersion = KOTLIN_1_4), NonStrictOnlyInputTypesChecks(sinceVersion = KOTLIN_1_4), + SuspendConversion(sinceVersion = KOTLIN_1_4), BooleanElvisBoundSmartCasts(sinceVersion = KOTLIN_1_3, defaultState = State.DISABLED), // see KT-26357 for details NewDataFlowForTryExpressions(sinceVersion = KOTLIN_1_4, defaultState = State.DISABLED),