diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/TailRecursionCodegen.kt b/compiler/backend/src/org/jetbrains/kotlin/codegen/TailRecursionCodegen.kt index 8d44ef0bc1f..3b58f7d230c 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/TailRecursionCodegen.kt +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/TailRecursionCodegen.kt @@ -16,17 +16,14 @@ package org.jetbrains.kotlin.codegen -import com.google.common.collect.Lists -import org.jetbrains.kotlin.cfg.TailRecursionKind import org.jetbrains.kotlin.codegen.context.MethodContext import org.jetbrains.kotlin.codegen.coroutines.* import org.jetbrains.kotlin.codegen.state.GenerationState +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.descriptors.CallableDescriptor import org.jetbrains.kotlin.descriptors.FunctionDescriptor import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor -import org.jetbrains.kotlin.psi.KtExpression import org.jetbrains.kotlin.psi.KtSimpleNameExpression -import org.jetbrains.kotlin.psi.ValueArgument import org.jetbrains.kotlin.resolve.calls.callUtil.* import org.jetbrains.kotlin.resolve.calls.model.* import org.jetbrains.org.objectweb.asm.Type @@ -56,7 +53,7 @@ class TailRecursionCodegen( val arguments = resolvedCall.valueArgumentsByIndex ?: throw IllegalStateException("Failed to arrange value arguments by index: $fd") if (fd.isSuspend) { - AsmUtil.pop(v, callable.getValueParameters()[callable.getValueParameters().size - 1].asmType) + AsmUtil.pop(v, callable.getValueParameters().last().asmType) } assignParameterValues(fd, callable, arguments) @@ -81,6 +78,9 @@ class TailRecursionCodegen( callableMethod: CallableMethod, valueArguments: List ) { + val properDefaultInitialization = + state.languageVersionSettings.supportsFeature(LanguageFeature.ProperComputationOrderOfTailrecDefaultParameters) + val types = callableMethod.valueParameterTypes loop@ for (parameterDescriptor in fd.valueParameters.asReversed()) { val arg = valueArguments[parameterDescriptor.index] @@ -102,7 +102,12 @@ class TailRecursionCodegen( } is DefaultValueArgument -> { AsmUtil.pop(v, type) - DefaultParameterValueLoader.DEFAULT.genValue(parameterDescriptor, codegen).put(type, v) + if (properDefaultInitialization) { + //Initialization in proper order is performed in loop below + continue@loop + } else { + DefaultParameterValueLoader.DEFAULT.genValue(parameterDescriptor, codegen).put(type, v) + } } is VarargValueArgument -> { // assign the parameter below @@ -112,6 +117,18 @@ class TailRecursionCodegen( store(parameterDescriptor, type) } + + if (properDefaultInitialization) { + for (parameterDescriptor in fd.valueParameters) { + val arg = valueArguments[parameterDescriptor.index] + val type = types[parameterDescriptor.index] + + if (arg is DefaultValueArgument) { + DefaultParameterValueLoader.DEFAULT.genValue(parameterDescriptor, codegen).put(type, v) + store(parameterDescriptor, type) + } + } + } } private fun store(parameterDescriptor: ValueParameterDescriptor, type: Type) { diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java index 3cd82f0d78e..becc8bc6904 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java @@ -469,6 +469,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok runTest("compiler/testData/diagnostics/tests/ProjectionsInSupertypes.kt"); } + @TestMetadata("properDefaultInitializationInTailrec.kt") + public void testProperDefaultInitializationInTailrec() throws Exception { + runTest("compiler/testData/diagnostics/tests/properDefaultInitializationInTailrec.kt"); + } + @TestMetadata("Properties.kt") public void testProperties() throws Exception { runTest("compiler/testData/diagnostics/tests/Properties.kt"); @@ -689,6 +694,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok runTest("compiler/testData/diagnostics/tests/UnitValue.kt"); } + @TestMetadata("unproperDefaultInitializationInTailrec.kt") + public void testUnproperDefaultInitializationInTailrec() throws Exception { + runTest("compiler/testData/diagnostics/tests/unproperDefaultInitializationInTailrec.kt"); + } + @TestMetadata("Unresolved.kt") public void testUnresolved() throws Exception { runTest("compiler/testData/diagnostics/tests/Unresolved.kt"); diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/DefaultCheckerInTailrec.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/DefaultCheckerInTailrec.kt new file mode 100644 index 00000000000..270312e8481 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/checkers/DefaultCheckerInTailrec.kt @@ -0,0 +1,55 @@ +/* + * Copyright 2010-2019 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.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.config.LanguageFeature +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.psi.KtConstantExpression +import org.jetbrains.kotlin.psi.KtDeclaration +import org.jetbrains.kotlin.psi.KtNamedFunction +import org.jetbrains.kotlin.psi.KtParameter +import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils +import org.jetbrains.kotlin.resolve.checkers.DeclarationChecker +import org.jetbrains.kotlin.resolve.checkers.DeclarationCheckerContext +import org.jetbrains.kotlin.resolve.constants.evaluate.ConstantExpressionEvaluator +import org.jetbrains.kotlin.resolve.descriptorUtil.module +import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm +import org.jetbrains.kotlin.resolve.jvm.getCompileTimeConstant +import org.jetbrains.kotlin.types.typeUtil.isPrimitiveNumberOrNullableType + +object DefaultCheckerInTailrec : DeclarationChecker { + override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) { + if (declaration !is KtNamedFunction || descriptor !is FunctionDescriptor || !descriptor.isTailrec) return + + if (context.languageVersionSettings.supportsFeature(LanguageFeature.ProperComputationOrderOfTailrecDefaultParameters)) return + + val defaultValues = descriptor.valueParameters.filter { it.declaresDefaultValue() }.filter { + val parameterDeclaration = DescriptorToSourceUtils.descriptorToDeclaration(it) + if (parameterDeclaration is KtParameter) { + parameterDeclaration.defaultValue?.let { + getCompileTimeConstant( + it, + context.trace.bindingContext, + false, + context.languageVersionSettings.supportsFeature(LanguageFeature.InlineConstVals) + )?.let { const -> + val type = const.getType(descriptor.module) + return@filter !(KotlinBuiltIns.isPrimitiveTypeOrNullablePrimitiveType(type) || + KotlinBuiltIns.isStringOrNullableString(type)) + } + } + } + + true + } + + if (defaultValues.size > 1) { + context.trace.report(ErrorsJvm.TAILREC_WITH_DEFAULTS.on(declaration)) + } + } +} \ No newline at end of file diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java index a9d7d220086..f54c322c013 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/DefaultErrorMessagesJvm.java @@ -151,6 +151,7 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension { "See https://youtrack.jetbrains.com/issue/KT-18053 for more details"; MAP.put(CONCURRENT_HASH_MAP_CONTAINS_OPERATOR, MESSAGE_FOR_CONCURRENT_HASH_MAP_CONTAINS); MAP.put(CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR, MESSAGE_FOR_CONCURRENT_HASH_MAP_CONTAINS); + MAP.put(TAILREC_WITH_DEFAULTS, "Computation order of non-constant default arguments in tail-recursive functions will change in 1.4. See KT-31540 for more details"); } @NotNull diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java index 42041273cfb..5896455ba80 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/diagnostics/ErrorsJvm.java @@ -10,10 +10,7 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.diagnostics.*; import org.jetbrains.kotlin.name.FqName; -import org.jetbrains.kotlin.psi.KtAnnotationEntry; -import org.jetbrains.kotlin.psi.KtDeclaration; -import org.jetbrains.kotlin.psi.KtElement; -import org.jetbrains.kotlin.psi.KtExpression; +import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.types.KotlinType; import static org.jetbrains.kotlin.diagnostics.PositioningStrategies.*; @@ -135,6 +132,8 @@ public interface ErrorsJvm { DiagnosticFactory0 CONCURRENT_HASH_MAP_CONTAINS_OPERATOR = DiagnosticFactory0.create(WARNING); DiagnosticFactory0 CONCURRENT_HASH_MAP_CONTAINS_OPERATOR_ERROR = DiagnosticFactory0.create(ERROR); + DiagnosticFactory0 TAILREC_WITH_DEFAULTS = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE); + @SuppressWarnings("UnusedDeclaration") Object _initializer = new Object() { { diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt index df99d7754c1..4f35241021d 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/resolve/jvm/platform/JvmPlatformConfigurator.kt @@ -38,7 +38,8 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase( JvmAnnotationsTargetNonExistentAccessorChecker(), BadInheritedJavaSignaturesChecker, JvmMultifileClassStateChecker, - SynchronizedOnInlineMethodChecker + SynchronizedOnInlineMethodChecker, + DefaultCheckerInTailrec ), additionalCallCheckers = listOf( diff --git a/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffects.kt b/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffects.kt index 15acc41f2ad..54467ceb3a6 100644 --- a/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffects.kt +++ b/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffects.kt @@ -1,5 +1,5 @@ +// !LANGUAGE: +ProperComputationOrderOfTailrecDefaultParameters // DONT_RUN_GENERATED_CODE: JS -// IGNORE_BACKEND: JVM var counter = 0 fun inc() = counter++ diff --git a/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffects2.kt b/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffects2.kt index c8c22b22b82..6d5f4315c10 100644 --- a/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffects2.kt +++ b/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffects2.kt @@ -1,3 +1,5 @@ +// !LANGUAGE: +ProperComputationOrderOfTailrecDefaultParameters +// Flag above doesn't matter cause 1 default value is passed explicitly in tail recursion call // DONT_RUN_GENERATED_CODE: JS var counter = 0 diff --git a/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffectsOld.kt b/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffectsOld.kt new file mode 100644 index 00000000000..d17272d67ca --- /dev/null +++ b/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffectsOld.kt @@ -0,0 +1,17 @@ +// !LANGUAGE: -ProperComputationOrderOfTailrecDefaultParameters +// TARGET_BACKEND: JVM +// IGNORE_BACKEND: JVM_IR + +var counter = 0 +fun calc(counter: Int) = if (counter % 2 == 0) "K" else "O" + +tailrec fun test(x: Int, y: String = calc(counter++), z: String = calc(counter++)): String { + if (x > 0) + return y + z + + return test(x + 1) +} + +fun box(): String { + return test(0) +} \ No newline at end of file diff --git a/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffectsOld.txt b/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffectsOld.txt new file mode 100644 index 00000000000..37dd610fbc9 --- /dev/null +++ b/compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffectsOld.txt @@ -0,0 +1,6 @@ +package + +public var counter: kotlin.Int +public fun box(): kotlin.String +public fun calc(/*0*/ counter: kotlin.Int): kotlin.String +public tailrec fun test(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String = ..., /*2*/ z: kotlin.String = ...): kotlin.String diff --git a/compiler/testData/diagnostics/tests/properDefaultInitializationInTailrec.kt b/compiler/testData/diagnostics/tests/properDefaultInitializationInTailrec.kt new file mode 100644 index 00000000000..62acd1f9aba --- /dev/null +++ b/compiler/testData/diagnostics/tests/properDefaultInitializationInTailrec.kt @@ -0,0 +1,39 @@ +//!LANGUAGE: +ProperComputationOrderOfTailrecDefaultParameters +import kotlin.reflect.KClass + +fun withEffects(): String = "OK" + +const val Z = "123" + +enum class EnumA { + A +} + +tailrec fun foo(i: Int = 1, c: Char = '2', s: String = "1234", b: Boolean = true, d: Double = 1.0, l: Long = 1L, y: String = withEffects()) { + foo(i, c, s, b, d, l, y) +} + + +tailrec fun foo2(x: Int = 1, y: String = withEffects(), z: String = Z) { + foo2(x, y, z) +} + +tailrec fun foo3(y: String = withEffects()) { + foo3(y) +} + +tailrec fun foo4(x: String = withEffects(), y: String = withEffects()) { + foo4(x, y) +} + +tailrec fun foo5(x: String = withEffects(), y: String = withEffects(), z: String = withEffects()) { + foo5(x, y, z) +} + +tailrec fun foo6(x: String = withEffects(), y: EnumA = EnumA.A) { + foo6(x, y) +} + +tailrec fun foo7(x: String = withEffects(), y: KClass = EnumA.A::class) { + foo7(x, y) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/properDefaultInitializationInTailrec.txt b/compiler/testData/diagnostics/tests/properDefaultInitializationInTailrec.txt new file mode 100644 index 00000000000..66f7c1f2d03 --- /dev/null +++ b/compiler/testData/diagnostics/tests/properDefaultInitializationInTailrec.txt @@ -0,0 +1,30 @@ +package + +public const val Z: kotlin.String = "123" +public tailrec fun foo(/*0*/ i: kotlin.Int = ..., /*1*/ c: kotlin.Char = ..., /*2*/ s: kotlin.String = ..., /*3*/ b: kotlin.Boolean = ..., /*4*/ d: kotlin.Double = ..., /*5*/ l: kotlin.Long = ..., /*6*/ y: kotlin.String = ...): kotlin.Unit +public tailrec fun foo2(/*0*/ x: kotlin.Int = ..., /*1*/ y: kotlin.String = ..., /*2*/ z: kotlin.String = ...): kotlin.Unit +public tailrec fun foo3(/*0*/ y: kotlin.String = ...): kotlin.Unit +public tailrec fun foo4(/*0*/ x: kotlin.String = ..., /*1*/ y: kotlin.String = ...): kotlin.Unit +public tailrec fun foo5(/*0*/ x: kotlin.String = ..., /*1*/ y: kotlin.String = ..., /*2*/ z: kotlin.String = ...): kotlin.Unit +public tailrec fun foo6(/*0*/ x: kotlin.String = ..., /*1*/ y: EnumA = ...): kotlin.Unit +public tailrec fun foo7(/*0*/ x: kotlin.String = ..., /*1*/ y: kotlin.reflect.KClass = ...): kotlin.Unit +public fun withEffects(): kotlin.String + +public final enum class EnumA : kotlin.Enum { + enum entry A + + private constructor EnumA() + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: EnumA): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit + public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class! + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): EnumA + public final /*synthesized*/ fun values(): kotlin.Array +} diff --git a/compiler/testData/diagnostics/tests/unproperDefaultInitializationInTailrec.kt b/compiler/testData/diagnostics/tests/unproperDefaultInitializationInTailrec.kt new file mode 100644 index 00000000000..89e056dd919 --- /dev/null +++ b/compiler/testData/diagnostics/tests/unproperDefaultInitializationInTailrec.kt @@ -0,0 +1,39 @@ +//!LANGUAGE: -ProperComputationOrderOfTailrecDefaultParameters + +import kotlin.reflect.KClass + +fun withEffects(): String = "OK" + +const val Z = "123" + +enum class EnumA { + A +} + +tailrec fun foo(i: Int = 1, c: Char = '2', s: String = "1234", b: Boolean = true, d: Double = 1.0, l: Long = 1L, y: String = withEffects()) { + foo(i, c, s, b, d, l, y) +} + +tailrec fun foo2(x: Int = 1, y: String = withEffects(), z: String = Z) { + foo2(x, y, z) +} + +tailrec fun foo3(y: String = withEffects()) { + foo3(y) +} + +tailrec fun foo4(x: String = withEffects(), y: String = withEffects()) { + foo4(x, y) +} + +tailrec fun foo5(x: String = withEffects(), y: String = withEffects(), z: String = withEffects()) { + foo5(x, y, z) +} + +tailrec fun foo6(x: String = withEffects(), y: EnumA = EnumA.A) { + foo6(x, y) +} + +tailrec fun foo7(x: String = withEffects(), y: KClass = EnumA.A::class) { + foo7(x, y) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/unproperDefaultInitializationInTailrec.txt b/compiler/testData/diagnostics/tests/unproperDefaultInitializationInTailrec.txt new file mode 100644 index 00000000000..66f7c1f2d03 --- /dev/null +++ b/compiler/testData/diagnostics/tests/unproperDefaultInitializationInTailrec.txt @@ -0,0 +1,30 @@ +package + +public const val Z: kotlin.String = "123" +public tailrec fun foo(/*0*/ i: kotlin.Int = ..., /*1*/ c: kotlin.Char = ..., /*2*/ s: kotlin.String = ..., /*3*/ b: kotlin.Boolean = ..., /*4*/ d: kotlin.Double = ..., /*5*/ l: kotlin.Long = ..., /*6*/ y: kotlin.String = ...): kotlin.Unit +public tailrec fun foo2(/*0*/ x: kotlin.Int = ..., /*1*/ y: kotlin.String = ..., /*2*/ z: kotlin.String = ...): kotlin.Unit +public tailrec fun foo3(/*0*/ y: kotlin.String = ...): kotlin.Unit +public tailrec fun foo4(/*0*/ x: kotlin.String = ..., /*1*/ y: kotlin.String = ...): kotlin.Unit +public tailrec fun foo5(/*0*/ x: kotlin.String = ..., /*1*/ y: kotlin.String = ..., /*2*/ z: kotlin.String = ...): kotlin.Unit +public tailrec fun foo6(/*0*/ x: kotlin.String = ..., /*1*/ y: EnumA = ...): kotlin.Unit +public tailrec fun foo7(/*0*/ x: kotlin.String = ..., /*1*/ y: kotlin.reflect.KClass = ...): kotlin.Unit +public fun withEffects(): kotlin.String + +public final enum class EnumA : kotlin.Enum { + enum entry A + + private constructor EnumA() + public final override /*1*/ /*fake_override*/ val name: kotlin.String + public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int + protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any + public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: EnumA): kotlin.Int + public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + protected/*protected and package*/ final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun finalize(): kotlin.Unit + public final override /*1*/ /*fake_override*/ /*isHiddenForResolutionEverywhereBesideSupercalls*/ fun getDeclaringClass(): java.lang.Class! + public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String + + // Static members + public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): EnumA + public final /*synthesized*/ fun values(): kotlin.Array +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index dc7edf4d6bd..a7a1fbfb03d 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -471,6 +471,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/ProjectionsInSupertypes.kt"); } + @TestMetadata("properDefaultInitializationInTailrec.kt") + public void testProperDefaultInitializationInTailrec() throws Exception { + runTest("compiler/testData/diagnostics/tests/properDefaultInitializationInTailrec.kt"); + } + @TestMetadata("Properties.kt") public void testProperties() throws Exception { runTest("compiler/testData/diagnostics/tests/Properties.kt"); @@ -691,6 +696,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/UnitValue.kt"); } + @TestMetadata("unproperDefaultInitializationInTailrec.kt") + public void testUnproperDefaultInitializationInTailrec() throws Exception { + runTest("compiler/testData/diagnostics/tests/unproperDefaultInitializationInTailrec.kt"); + } + @TestMetadata("Unresolved.kt") public void testUnresolved() throws Exception { runTest("compiler/testData/diagnostics/tests/Unresolved.kt"); @@ -24125,6 +24135,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffects2.kt"); } + @TestMetadata("defaultArgsWithSideEffectsOld.kt") + public void testDefaultArgsWithSideEffectsOld() throws Exception { + runTest("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffectsOld.kt"); + } + @TestMetadata("extensionTailCall.kt") public void testExtensionTailCall() throws Exception { runTest("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/extensionTailCall.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index e5e916d52bf..b01e901d750 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -471,6 +471,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/ProjectionsInSupertypes.kt"); } + @TestMetadata("properDefaultInitializationInTailrec.kt") + public void testProperDefaultInitializationInTailrec() throws Exception { + runTest("compiler/testData/diagnostics/tests/properDefaultInitializationInTailrec.kt"); + } + @TestMetadata("Properties.kt") public void testProperties() throws Exception { runTest("compiler/testData/diagnostics/tests/Properties.kt"); @@ -691,6 +696,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/UnitValue.kt"); } + @TestMetadata("unproperDefaultInitializationInTailrec.kt") + public void testUnproperDefaultInitializationInTailrec() throws Exception { + runTest("compiler/testData/diagnostics/tests/unproperDefaultInitializationInTailrec.kt"); + } + @TestMetadata("Unresolved.kt") public void testUnresolved() throws Exception { runTest("compiler/testData/diagnostics/tests/Unresolved.kt"); @@ -24045,6 +24055,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffects2.kt"); } + @TestMetadata("defaultArgsWithSideEffectsOld.kt") + public void testDefaultArgsWithSideEffectsOld() throws Exception { + runTest("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffectsOld.kt"); + } + @TestMetadata("extensionTailCall.kt") public void testExtensionTailCall() throws Exception { runTest("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/extensionTailCall.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java index 23cf7a0dbc6..b31abaafc49 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/BlackBoxCodegenTestGenerated.java @@ -10056,6 +10056,11 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest { runTest("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffects2.kt"); } + @TestMetadata("defaultArgsWithSideEffectsOld.kt") + public void testDefaultArgsWithSideEffectsOld() throws Exception { + runTest("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffectsOld.kt"); + } + @TestMetadata("extensionTailCall.kt") public void testExtensionTailCall() throws Exception { runTest("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/extensionTailCall.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java index a3890549ee4..b34ebd0ffb0 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/LightAnalysisModeTestGenerated.java @@ -10023,11 +10023,6 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) public static class TailRecursion extends AbstractLightAnalysisModeTest { - @TestMetadata("defaultArgsWithSideEffects.kt") - public void ignoreDefaultArgsWithSideEffects() throws Exception { - runTest("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffects.kt"); - } - private void runTest(String testDataFilePath) throws Exception { KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath); } @@ -10051,11 +10046,21 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes runTest("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsOverridden.kt"); } + @TestMetadata("defaultArgsWithSideEffects.kt") + public void testDefaultArgsWithSideEffects() throws Exception { + runTest("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffects.kt"); + } + @TestMetadata("defaultArgsWithSideEffects2.kt") public void testDefaultArgsWithSideEffects2() throws Exception { runTest("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffects2.kt"); } + @TestMetadata("defaultArgsWithSideEffectsOld.kt") + public void testDefaultArgsWithSideEffectsOld() throws Exception { + runTest("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffectsOld.kt"); + } + @TestMetadata("extensionTailCall.kt") public void testExtensionTailCall() throws Exception { runTest("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/extensionTailCall.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java index 9095f24482b..eec290e7d07 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/ir/IrBlackBoxCodegenTestGenerated.java @@ -8941,6 +8941,11 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes runTest("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffects2.kt"); } + @TestMetadata("defaultArgsWithSideEffectsOld.kt") + public void testDefaultArgsWithSideEffectsOld() throws Exception { + runTest("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/defaultArgsWithSideEffectsOld.kt"); + } + @TestMetadata("extensionTailCall.kt") public void testExtensionTailCall() throws Exception { runTest("compiler/testData/codegen/box/diagnostics/functions/tailRecursion/extensionTailCall.kt"); diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 8dba573d2d3..aa077c23b02 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -109,6 +109,7 @@ enum class LanguageFeature( AllowBreakAndContinueInsideWhen(KOTLIN_1_4), MixedNamedArgumentsInTheirOwnPosition(KOTLIN_1_4), ProhibitTailrecOnVirtualMember(KOTLIN_1_4, kind = BUG_FIX), + ProperComputationOrderOfTailrecDefaultParameters(KOTLIN_1_4), ProperVisibilityForCompanionObjectInstanceField(sinceVersion = null, kind = BUG_FIX), // Temporarily disabled, see KT-27084/KT-22379