diff --git a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10CallResolver.kt b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10CallResolver.kt index 8812364385e..faa9e1c764b 100644 --- a/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10CallResolver.kt +++ b/analysis/analysis-api-fe10/src/org/jetbrains/kotlin/analysis/api/descriptors/components/KtFe10CallResolver.kt @@ -120,6 +120,7 @@ internal class KtFe10CallResolver( Errors.RESOLUTION_TO_PRIVATE_CONSTRUCTOR_OF_SEALED_CLASS, Errors.UNRESOLVED_REFERENCE, *Errors.TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM.factories, + *Errors.TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_IN_AUGMENTED_ASSIGNMENT.factories, ) private val syntaxErrors = setOf( diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index b56537bda43..42c74353186 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -830,6 +830,8 @@ public interface Errors { DiagnosticFactoryForDeprecation0 TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM = DiagnosticFactoryForDeprecation0.create(LanguageFeature.ForbidRecursiveDelegateExpressions); + DiagnosticFactoryForDeprecation0 TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_IN_AUGMENTED_ASSIGNMENT = + DiagnosticFactoryForDeprecation0.create(LanguageFeature.ReportErrorsOnRecursiveTypeInsidePlusAssignment); // Checking call arguments diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java index 7a8a23f2448..ce190e5e0a6 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -227,7 +227,9 @@ public class DefaultErrorMessages { MAP.put(REDUNDANT_MODIFIER_IN_GETTER, "Visibility modifiers are redundant in getter"); MAP.put(TYPE_PARAMETERS_IN_ENUM, "Enum class cannot have type parameters"); MAP.put(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM, - "Type checking has run into a recursive problem. Easiest workaround: specify types of your declarations explicitly"); // TODO: message + "Type checking has run into a recursive problem. Easiest workaround: specify types of your declarations explicitly"); + MAP.put(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_IN_AUGMENTED_ASSIGNMENT, + "Type checking has run into a recursive problem. Easiest workaround: specify types of your declarations explicitly"); MAP.put(RETURN_NOT_ALLOWED, "'return' is not allowed here"); MAP.put(PROJECTION_IN_IMMEDIATE_ARGUMENT_TO_SUPERTYPE, "Projections are not allowed for immediate arguments of a supertype"); MAP.put(LABEL_NAME_CLASH, "There is more than one label with such a name in this scope"); 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 ef93e25d28e..23a5911e8c1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt @@ -16,10 +16,12 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticFactory2 import org.jetbrains.kotlin.diagnostics.Errors.* import org.jetbrains.kotlin.diagnostics.Errors.BadNamedArgumentsTarget.* import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnce +import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.isNull import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis +import org.jetbrains.kotlin.psi.psiUtil.parents import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceExpectedTypeConstraintPosition @@ -78,9 +80,18 @@ class DiagnosticReporterByTrackingStrategy( is VisibilityError -> tracingStrategy.invisibleMember(trace, diagnostic.invisibleMember) is NoValueForParameter -> tracingStrategy.noValueForParameter(trace, diagnostic.parameterDescriptor) is TypeCheckerHasRanIntoRecursion -> { - val shouldReportErrorsOnRecursiveTypeInsidePlusAssignment = - context.languageVersionSettings.supportsFeature(LanguageFeature.ReportErrorsOnRecursiveTypeInsidePlusAssignment) - tracingStrategy.recursiveType(trace, shouldReportErrorsOnRecursiveTypeInsidePlusAssignment) + // Note: we have two similar diagnostics here + // - TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM (error starting from 1.7) + // - TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_IN_AUGMENTED_ASSIGNMENT (error starting from 1.9) + // however they have different deprecation cycle, and thus it's better to distinguish them. + // This 'insideAugmentedAssignment' is just a heuristics (approximate) to do it. + // It cannot turn red code to green or green to red; the worst thing we can get here + // is replacing red code with yellow, if e.g. LV is set to 1.8 explicitly, + // and we have chosen the second diagnostics instead of the first one. + val insideAugmentedAssignment = call.callElement.parents.any { + it is KtBinaryExpression && it.operationToken in KtTokens.AUGMENTED_ASSIGNMENTS + } + tracingStrategy.recursiveType(trace, context.languageVersionSettings, insideAugmentedAssignment) } is InstantiationOfAbstractClass -> tracingStrategy.instantiationOfAbstractClass(trace) is AbstractSuperCall -> { 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 e7b88966210..3f1fcae2308 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 @@ -20,6 +20,7 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.kotlin.config.LanguageVersionSettings; import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.diagnostics.Diagnostic; import org.jetbrains.kotlin.diagnostics.DiagnosticFactory0; @@ -139,16 +140,14 @@ public abstract class AbstractTracingStrategy implements TracingStrategy { } @Override - public void recursiveType(@NotNull BindingTrace trace, boolean shouldReportErrorsOnRecursiveTypeInsidePlusAssignment) { + public void recursiveType(@NotNull BindingTrace trace, @NotNull LanguageVersionSettings languageVersionSettings, boolean insideAugmentedAssignment) { KtExpression expression = call.getCalleeExpression(); if (expression == null) return; - DiagnosticFactory0 factory; - if (shouldReportErrorsOnRecursiveTypeInsidePlusAssignment) { - factory = TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM.getErrorFactory(); + if (insideAugmentedAssignment) { + trace.report(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_IN_AUGMENTED_ASSIGNMENT.on(languageVersionSettings, expression)); } else { - factory = TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM.getWarningFactory(); + trace.report(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM.on(languageVersionSettings, expression)); } - 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 8f3d1831743..71ad0377ae5 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 @@ -83,7 +83,7 @@ public interface TracingStrategy { ) {} @Override - public void recursiveType(@NotNull BindingTrace trace, boolean shouldReportErrorsOnRecursiveTypeInsidePlusAssignment) {} + public void recursiveType(@NotNull BindingTrace trace, @NotNull LanguageVersionSettings languageVersionSettings, boolean insideAugmentedAssignment) {} @Override public void instantiationOfAbstractClass(@NotNull BindingTrace trace) {} @@ -148,7 +148,7 @@ public interface TracingStrategy { @NotNull Collection> descriptors ); - void recursiveType(@NotNull BindingTrace trace, boolean shouldReportErrorsOnRecursiveTypeInsidePlusAssignment); + void recursiveType(@NotNull BindingTrace trace, @NotNull LanguageVersionSettings languageVersionSettings, boolean insideAugmentedAssignment); 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 66f772d665f..e5cf4bc5f70 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ControlStructureTypingUtils.java @@ -599,7 +599,7 @@ public class ControlStructureTypingUtils { } @Override - public void recursiveType(@NotNull BindingTrace trace, boolean shouldReportErrorsOnRecursiveTypeInsidePlusAssignment) { + public void recursiveType(@NotNull BindingTrace trace, @NotNull LanguageVersionSettings languageVersionSettings, boolean insideAugmentedAssignment) { logError(); } diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.fir.kt b/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.fir.kt index 81e341b1d4f..bb26b7947c2 100644 --- a/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.fir.kt +++ b/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.fir.kt @@ -1,3 +1,4 @@ +// !LANGUAGE: -ReportErrorsOnRecursiveTypeInsidePlusAssignment // WITH_STDLIB // FIR: KT-51648 diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.kt b/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.kt index d1be6993125..ebe0a307d4c 100644 --- a/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.kt +++ b/compiler/testData/diagnostics/tests/delegatedProperty/kt48546.kt @@ -1,10 +1,11 @@ +// !LANGUAGE: -ReportErrorsOnRecursiveTypeInsidePlusAssignment // WITH_STDLIB // FIR: KT-51648 object DelegateTest { var result = "" val f by lazy { - result += f.toString() // Compiler crash + result += f.toString() // Compiler crash "hello" } } @@ -12,7 +13,7 @@ object DelegateTest { object DelegateTest2 { var result = "" val f by lazy { - result += f + result += f "hello" } } diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/kt48546Strict.kt b/compiler/testData/diagnostics/tests/delegatedProperty/kt48546Strict.kt index 43407df6e6d..00d2fbddc34 100644 --- a/compiler/testData/diagnostics/tests/delegatedProperty/kt48546Strict.kt +++ b/compiler/testData/diagnostics/tests/delegatedProperty/kt48546Strict.kt @@ -5,7 +5,7 @@ object DelegateTest { var result = "" val f by lazy { - result += f.toString() // Compiler crash + result += f.toString() // Compiler crash "hello" } } @@ -13,29 +13,29 @@ object DelegateTest { object DelegateTest2 { var result = "" val f by lazy { - result += f + result += f "hello" } var intResult = 0 val i1 by lazy { - intResult += i1 + intResult += i1 0 } val i2 by lazy { - intResult -= i2 + intResult -= i2 0 } val i3 by lazy { - intResult *= i3 + intResult *= i3 0 } val i4 by lazy { - intResult /= i4 + intResult /= i4 0 } val i5 by lazy { - intResult %= i5 + intResult %= i5 0 } } diff --git a/compiler/testData/diagnostics/tests/delegation/kt48546.kt b/compiler/testData/diagnostics/tests/delegation/kt48546.kt index cf86b758374..363606657e1 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" } }