diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index 3b407a850bc..925eb8c2a1d 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -8086,6 +8086,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/delegatedProperty/kt48546.kt"); } + @Test + @TestMetadata("kt48546Strict.kt") + public void testKt48546Strict() throws Exception { + runTest("compiler/testData/diagnostics/tests/delegatedProperty/kt48546Strict.kt"); + } + @Test @TestMetadata("localVariable.kt") public void testLocalVariable() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index 883afd29e9d..3c58cd2b4c7 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -8086,6 +8086,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/delegatedProperty/kt48546.kt"); } + @Test + @TestMetadata("kt48546Strict.kt") + public void testKt48546Strict() throws Exception { + runTest("compiler/testData/diagnostics/tests/delegatedProperty/kt48546Strict.kt"); + } + @Test @TestMetadata("localVariable.kt") public void testLocalVariable() throws Exception { diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index f752b4c4e35..b6b52436d2f 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -796,7 +796,8 @@ public interface Errors { DiagnosticFactory1 NAME_SHADOWING = DiagnosticFactory1.create(WARNING, PositioningStrategies.FOR_REDECLARATION); DiagnosticFactory0 ACCESSOR_PARAMETER_NAME_SHADOWING = DiagnosticFactory0.create(WARNING); - DiagnosticFactoryForDeprecation0 TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM = DiagnosticFactoryForDeprecation0.create(LanguageFeature.ForbidRecursiveDelegateExpressions); + DiagnosticFactoryForDeprecation0 TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM = + DiagnosticFactoryForDeprecation0.create(LanguageFeature.ForbidRecursiveDelegateExpressions); // Checking call arguments diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt index da6f595c216..f7c253f2eff 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt @@ -75,7 +75,11 @@ class DiagnosticReporterByTrackingStrategy( trace, (diagnostic as NoValueForParameter).parameterDescriptor ) - TypeCheckerHasRanIntoRecursion::class.java -> tracingStrategy.recursiveType(trace) + TypeCheckerHasRanIntoRecursion::class.java -> { + val shouldReportErrorsOnRecursiveTypeInsidePlusAssignment = + context.languageVersionSettings.supportsFeature(LanguageFeature.ReportErrorsOnRecursiveTypeInsidePlusAssignment) + tracingStrategy.recursiveType(trace, shouldReportErrorsOnRecursiveTypeInsidePlusAssignment) + } InstantiationOfAbstractClass::class.java -> tracingStrategy.instantiationOfAbstractClass(trace) AbstractSuperCall::class.java -> { val superExpression = (diagnostic as AbstractSuperCall).receiver.psiExpression as? KtSuperExpression diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/AbstractTracingStrategy.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/AbstractTracingStrategy.java index 50a4eda4334..e7b88966210 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/AbstractTracingStrategy.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/AbstractTracingStrategy.java @@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.diagnostics.Diagnostic; +import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0; import org.jetbrains.kotlin.diagnostics.DiagnosticUtilsKt; import org.jetbrains.kotlin.lexer.KtToken; import org.jetbrains.kotlin.lexer.KtTokens; @@ -138,10 +139,16 @@ public abstract class AbstractTracingStrategy implements TracingStrategy { } @Override - public void recursiveType(@NotNull BindingTrace trace) { + public void recursiveType(@NotNull BindingTrace trace, boolean shouldReportErrorsOnRecursiveTypeInsidePlusAssignment) { KtExpression expression = call.getCalleeExpression(); if (expression == null) return; - trace.report(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM.getErrorFactory().on(expression)); + DiagnosticFactory0 factory; + if (shouldReportErrorsOnRecursiveTypeInsidePlusAssignment) { + factory = TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM.getErrorFactory(); + } else { + factory = TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM.getWarningFactory(); + } + trace.report(factory.on(expression)); } @Override diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/TracingStrategy.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/TracingStrategy.java index 2c0fdb98590..8f3d1831743 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/TracingStrategy.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tasks/TracingStrategy.java @@ -17,6 +17,7 @@ package org.jetbrains.kotlin.resolve.calls.tasks; import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.config.LanguageVersionSettings; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.psi.Call; import org.jetbrains.kotlin.resolve.BindingTrace; @@ -82,7 +83,7 @@ public interface TracingStrategy { ) {} @Override - public void recursiveType(@NotNull BindingTrace trace) {} + public void recursiveType(@NotNull BindingTrace trace, boolean shouldReportErrorsOnRecursiveTypeInsidePlusAssignment) {} @Override public void instantiationOfAbstractClass(@NotNull BindingTrace trace) {} @@ -147,7 +148,7 @@ public interface TracingStrategy { @NotNull Collection> descriptors ); - void recursiveType(@NotNull BindingTrace trace); + void recursiveType(@NotNull BindingTrace trace, boolean shouldReportErrorsOnRecursiveTypeInsidePlusAssignment); void instantiationOfAbstractClass(@NotNull BindingTrace trace); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingUtils.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingUtils.java index fb554bd9a9b..fbcd862b535 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingUtils.java @@ -585,7 +585,7 @@ public class ControlStructureTypingUtils { } @Override - public void recursiveType(@NotNull BindingTrace trace) { + public void recursiveType(@NotNull BindingTrace trace, boolean shouldReportErrorsOnRecursiveTypeInsidePlusAssignment) { logError(); } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt index 24980f9d24e..139e7d82a74 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/components/KotlinCallCompleter.kt @@ -273,7 +273,7 @@ class KotlinCallCompleter( constraintSystem.errors.forEach(diagnosticsHolder::addError) if (returnType is ErrorType && returnType.kind == ErrorTypeKind.RECURSIVE_TYPE) { - diagnosticsHolder.addDiagnostic(TypeCheckerHasRanIntoRecursion(resolvedCallAtom)) + diagnosticsHolder.addDiagnostic(TypeCheckerHasRanIntoRecursion) } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallDiagnostics.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallDiagnostics.kt index 3b7405c28fe..38f93dfaa47 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallDiagnostics.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/model/KotlinCallDiagnostics.kt @@ -116,7 +116,7 @@ class WrongCountOfTypeArguments( override fun report(reporter: DiagnosticReporter) = reporter.onTypeArguments(this) } -class TypeCheckerHasRanIntoRecursion : KotlinCallDiagnostic(INAPPLICABLE) { +object TypeCheckerHasRanIntoRecursion : KotlinCallDiagnostic(INAPPLICABLE) { override fun report(reporter: DiagnosticReporter) = reporter.onCall(this) } diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.fir.kt b/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.fir.kt index 80c0827bf9e..961ba715421 100644 --- a/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.fir.kt +++ b/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.fir.kt @@ -1,9 +1,10 @@ // WITH_STDLIB +// FIR: KT-51648 object DelegateTest { var result = "" val f by lazy { - result += f.toString() // Compiler crash + result += f.toString() // Compiler crash "hello" } } @@ -11,7 +12,7 @@ object DelegateTest { object DelegateTest2 { var result = "" val f by lazy { - result += f + result += f "hello" } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.kt b/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.kt index 0b92c03151f..83ca2c5c8e9 100644 --- a/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.kt +++ b/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.kt @@ -1,9 +1,10 @@ // WITH_STDLIB +// FIR: KT-51648 object DelegateTest { var result = "" val f by lazy { - result += f.toString() // Compiler crash + result += f.toString() // Compiler crash "hello" } } @@ -11,7 +12,7 @@ object DelegateTest { object DelegateTest2 { var result = "" val f by lazy { - result += f + result += f "hello" } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.txt b/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.txt index 62ba3e9515a..28dbec02abd 100644 --- a/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.txt +++ b/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.txt @@ -8,3 +8,13 @@ public object DelegateTest { public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String } + +public object DelegateTest2 { + private constructor DelegateTest2() + public final val f: kotlin.String + public final var result: kotlin.String + 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/delegatedProperty/kt48546Strict.fir.kt b/compiler/testData/diagnostics/tests/delegatedProperty/kt48546Strict.fir.kt new file mode 100644 index 00000000000..d574538fe7b --- /dev/null +++ b/compiler/testData/diagnostics/tests/delegatedProperty/kt48546Strict.fir.kt @@ -0,0 +1,19 @@ +// !LANGUAGE: +ReportErrorsOnRecursiveTypeInsidePlusAssignment +// WITH_STDLIB +// FIR: KT-51648 + +object DelegateTest { + var result = "" + val f by lazy { + result += f.toString() // Compiler crash + "hello" + } +} + +object DelegateTest2 { + var result = "" + val f by lazy { + result += f + "hello" + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/kt48546Strict.kt b/compiler/testData/diagnostics/tests/delegatedProperty/kt48546Strict.kt new file mode 100644 index 00000000000..032141357b0 --- /dev/null +++ b/compiler/testData/diagnostics/tests/delegatedProperty/kt48546Strict.kt @@ -0,0 +1,19 @@ +// !LANGUAGE: +ReportErrorsOnRecursiveTypeInsidePlusAssignment +// WITH_STDLIB +// FIR: KT-51648 + +object DelegateTest { + var result = "" + val f by lazy { + result += f.toString() // Compiler crash + "hello" + } +} + +object DelegateTest2 { + var result = "" + val f by lazy { + result += f + "hello" + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/kt48546Strict.txt b/compiler/testData/diagnostics/tests/delegatedProperty/kt48546Strict.txt new file mode 100644 index 00000000000..8d6438c3bb7 --- /dev/null +++ b/compiler/testData/diagnostics/tests/delegatedProperty/kt48546Strict.txt @@ -0,0 +1,19 @@ +package + +public object DelegateTest { + private constructor DelegateTest() + public final val f: kotlin.String + public final var result: kotlin.String + 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 +} + +public object DelegateTest2 { + private constructor DelegateTest2() + public final val f: kotlin.String + public final var result: kotlin.String + 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/delegatedProperty/recursiveType.kt b/compiler/testData/diagnostics/tests/delegatedProperty/recursiveType.kt index 4d7671d7e83..9e28c4bfa10 100644 --- a/compiler/testData/diagnostics/tests/delegatedProperty/recursiveType.kt +++ b/compiler/testData/diagnostics/tests/delegatedProperty/recursiveType.kt @@ -3,12 +3,12 @@ import kotlin.reflect.KProperty -val a by a +val a by a val b by Delegate(b) val c by d -val d by c +val d by c class Delegate(i: Int) { operator fun getValue(t: Any?, p: KProperty<*>): Int { diff --git a/compiler/testData/diagnostics/tests/delegation/kt48546.kt b/compiler/testData/diagnostics/tests/delegation/kt48546.kt index 6e266489d06..caf4554a7b5 100644 --- a/compiler/testData/diagnostics/tests/delegation/kt48546.kt +++ b/compiler/testData/diagnostics/tests/delegation/kt48546.kt @@ -3,7 +3,7 @@ object DelegateTest { var result = "" val f by lazy { - result += f.toString() // Compiler crash + result += f.toString() // Compiler crash "hello" } } \ No newline at end of file diff --git a/compiler/testData/diagnostics/testsWithStdLib/coroutines/kt18292.kt b/compiler/testData/diagnostics/testsWithStdLib/coroutines/kt18292.kt index a236d190ec6..9dd6e3cd967 100644 --- a/compiler/testData/diagnostics/testsWithStdLib/coroutines/kt18292.kt +++ b/compiler/testData/diagnostics/testsWithStdLib/coroutines/kt18292.kt @@ -13,6 +13,6 @@ suspend fun fib(n: Long) = async { when { n < 2 -> n - else -> fib(n - 1).await() + fib(n - 2).await() + else -> fib(n - 1).await() + fib(n - 2).await() } } diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index 07f387c03b0..b11ae933097 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -8092,6 +8092,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/delegatedProperty/kt48546.kt"); } + @Test + @TestMetadata("kt48546Strict.kt") + public void testKt48546Strict() throws Exception { + runTest("compiler/testData/diagnostics/tests/delegatedProperty/kt48546Strict.kt"); + } + @Test @TestMetadata("localVariable.kt") public void testLocalVariable() throws Exception { diff --git a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt index 64aa1de6837..163f7d2c5de 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -270,6 +270,7 @@ enum class LanguageFeature( ProhibitEnumDeclaringClass(KOTLIN_1_9, kind = BUG_FIX), // KT-49653 StopPropagatingDeprecationThroughOverrides(KOTLIN_1_9, kind = BUG_FIX), // KT-47902 ReportTypeVarianceConflictOnQualifierArguments(KOTLIN_1_9, kind = BUG_FIX), // KT-50947 + ReportErrorsOnRecursiveTypeInsidePlusAssignment(KOTLIN_1_9, kind = BUG_FIX), // KT-48546 // Disabled for indefinite time. See KT-48535 and related discussion ApproximateIntegerLiteralTypesInReceiverPosition(sinceVersion = null),