K1: add separate TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_IN_AUGMENTED_ASSIGNMENT

This is made to have a correct error message for a problem
described in KT-48546
#KT-48546 Fixed
This commit is contained in:
Mikhail Glukhikh
2023-04-26 16:57:07 +02:00
committed by Space Team
parent c5fe4b53cf
commit bbee881b5b
11 changed files with 40 additions and 23 deletions
@@ -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(
@@ -830,6 +830,8 @@ public interface Errors {
DiagnosticFactoryForDeprecation0<KtExpression> TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM =
DiagnosticFactoryForDeprecation0.create(LanguageFeature.ForbidRecursiveDelegateExpressions);
DiagnosticFactoryForDeprecation0<KtExpression> TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_IN_AUGMENTED_ASSIGNMENT =
DiagnosticFactoryForDeprecation0.create(LanguageFeature.ReportErrorsOnRecursiveTypeInsidePlusAssignment);
// Checking call arguments
@@ -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");
@@ -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 -> {
@@ -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<KtExpression> 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
@@ -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<? extends ResolvedCall<D>> descriptors
);
void recursiveType(@NotNull BindingTrace trace, boolean shouldReportErrorsOnRecursiveTypeInsidePlusAssignment);
void recursiveType(@NotNull BindingTrace trace, @NotNull LanguageVersionSettings languageVersionSettings, boolean insideAugmentedAssignment);
void instantiationOfAbstractClass(@NotNull BindingTrace trace);
@@ -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();
}
@@ -1,3 +1,4 @@
// !LANGUAGE: -ReportErrorsOnRecursiveTypeInsidePlusAssignment
// WITH_STDLIB
// FIR: KT-51648
@@ -1,10 +1,11 @@
// !LANGUAGE: -ReportErrorsOnRecursiveTypeInsidePlusAssignment
// WITH_STDLIB
// FIR: KT-51648
object DelegateTest {
var result = ""
val f by lazy {
result += <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_ERROR!>f<!>.<!DEBUG_INFO_MISSING_UNRESOLVED!>toString<!>() // Compiler crash
result += <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_IN_AUGMENTED_ASSIGNMENT_WARNING!>f<!>.<!DEBUG_INFO_MISSING_UNRESOLVED!>toString<!>() // Compiler crash
"hello"
}
}
@@ -12,7 +13,7 @@ object DelegateTest {
object DelegateTest2 {
var result = ""
val f by lazy {
result += <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_ERROR!>f<!>
result += <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_IN_AUGMENTED_ASSIGNMENT_WARNING!>f<!>
"hello"
}
}
@@ -5,7 +5,7 @@
object DelegateTest {
var result = ""
val f by lazy {
result += <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_ERROR!>f<!>.<!DEBUG_INFO_MISSING_UNRESOLVED!>toString<!>() // Compiler crash
result += <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_IN_AUGMENTED_ASSIGNMENT_ERROR!>f<!>.<!DEBUG_INFO_MISSING_UNRESOLVED!>toString<!>() // Compiler crash
"hello"
}
}
@@ -13,29 +13,29 @@ object DelegateTest {
object DelegateTest2 {
var result = ""
val f by lazy {
result += <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_ERROR!>f<!>
result += <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_IN_AUGMENTED_ASSIGNMENT_ERROR!>f<!>
"hello"
}
var intResult = 0
val i1 by lazy {
intResult <!OVERLOAD_RESOLUTION_AMBIGUITY!>+=<!> <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_ERROR!>i1<!>
intResult <!OVERLOAD_RESOLUTION_AMBIGUITY!>+=<!> <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_IN_AUGMENTED_ASSIGNMENT_ERROR!>i1<!>
0
}
val i2 by lazy {
intResult <!OVERLOAD_RESOLUTION_AMBIGUITY!>-=<!> <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_ERROR!>i2<!>
intResult <!OVERLOAD_RESOLUTION_AMBIGUITY!>-=<!> <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_IN_AUGMENTED_ASSIGNMENT_ERROR!>i2<!>
0
}
val i3 by lazy {
intResult <!OVERLOAD_RESOLUTION_AMBIGUITY!>*=<!> <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_ERROR!>i3<!>
intResult <!OVERLOAD_RESOLUTION_AMBIGUITY!>*=<!> <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_IN_AUGMENTED_ASSIGNMENT_ERROR!>i3<!>
0
}
val i4 by lazy {
intResult <!OVERLOAD_RESOLUTION_AMBIGUITY!>/=<!> <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_ERROR!>i4<!>
intResult <!OVERLOAD_RESOLUTION_AMBIGUITY!>/=<!> <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_IN_AUGMENTED_ASSIGNMENT_ERROR!>i4<!>
0
}
val i5 by lazy {
intResult <!OVERLOAD_RESOLUTION_AMBIGUITY!>%=<!> <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_ERROR!>i5<!>
intResult <!OVERLOAD_RESOLUTION_AMBIGUITY!>%=<!> <!TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_IN_AUGMENTED_ASSIGNMENT_ERROR!>i5<!>
0
}
}
+1 -1
View File
@@ -3,7 +3,7 @@
object DelegateTest {
var result = ""
val f by lazy {
result += <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_ERROR!>f<!>.<!DEBUG_INFO_MISSING_UNRESOLVED!>toString<!>() // Compiler crash
result += <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE, TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM_IN_AUGMENTED_ASSIGNMENT_ERROR!>f<!>.<!DEBUG_INFO_MISSING_UNRESOLVED!>toString<!>() // Compiler crash
"hello"
}
}