diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index 7873b2ec537..0464c54a7c2 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -14011,6 +14011,18 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/inference/builderInference/changingResolveIfDontUseBuilderInference.kt"); } + @Test + @TestMetadata("equalityChecksOnIntegerTypes.kt") + public void testEqualityChecksOnIntegerTypes() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypes.kt"); + } + + @Test + @TestMetadata("equalityChecksOnIntegerTypesProgressive.kt") + public void testEqualityChecksOnIntegerTypesProgressive() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypesProgressive.kt"); + } + @Test @TestMetadata("kt47744.kt") public void testKt47744() throws Exception { 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 3055c46dc72..be683b08eb9 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 @@ -14011,6 +14011,18 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/inference/builderInference/changingResolveIfDontUseBuilderInference.kt"); } + @Test + @TestMetadata("equalityChecksOnIntegerTypes.kt") + public void testEqualityChecksOnIntegerTypes() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypes.kt"); + } + + @Test + @TestMetadata("equalityChecksOnIntegerTypesProgressive.kt") + public void testEqualityChecksOnIntegerTypesProgressive() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypesProgressive.kt"); + } + @Test @TestMetadata("kt47744.kt") public void testKt47744() 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 f7dbefedf24..318b49db4e2 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 @@ -14011,6 +14011,18 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/inference/builderInference/changingResolveIfDontUseBuilderInference.kt"); } + @Test + @TestMetadata("equalityChecksOnIntegerTypes.kt") + public void testEqualityChecksOnIntegerTypes() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypes.kt"); + } + + @Test + @TestMetadata("equalityChecksOnIntegerTypesProgressive.kt") + public void testEqualityChecksOnIntegerTypesProgressive() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypesProgressive.kt"); + } + @Test @TestMetadata("kt47744.kt") public void testKt47744() 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 2cd96cc9761..b5206aa39b1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -964,6 +964,8 @@ public interface Errors { DiagnosticFactory0 EQUALS_MISSING = DiagnosticFactory0.create(ERROR); DiagnosticFactory3 EQUALITY_NOT_APPLICABLE = DiagnosticFactory3.create(ERROR); + DiagnosticFactory3 EQUALITY_NOT_APPLICABLE_WARNING = + DiagnosticFactory3.create(WARNING); DiagnosticFactory2 INCOMPATIBLE_ENUM_COMPARISON = DiagnosticFactory2.create(WARNING); 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 f942d3ccbd4..91d6b61df8d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -840,10 +840,8 @@ public class DefaultErrorMessages { MAP.put(INCONSISTENT_TYPE_PARAMETER_VALUES, "Type parameter {0} of ''{1}'' has inconsistent values: {2}", NAME, NAME, RENDER_COLLECTION_OF_TYPES); MAP.put(INCONSISTENT_TYPE_PARAMETER_BOUNDS, "Type parameter {0} of ''{1}'' has inconsistent bounds: {2}", NAME, NAME, RENDER_COLLECTION_OF_TYPES); - MAP.put(EQUALITY_NOT_APPLICABLE, "Operator ''{0}'' cannot be applied to ''{1}'' and ''{2}''", (nameExpression, context) -> { - //noinspection ConstantConditions - return nameExpression.getReferencedName(); - }, RENDER_TYPE, RENDER_TYPE); + MAP.put(EQUALITY_NOT_APPLICABLE, "Operator ''{0}'' cannot be applied to ''{1}'' and ''{2}''", (nameExpression, context) -> nameExpression.getReferencedName(), RENDER_TYPE, RENDER_TYPE); + MAP.put(EQUALITY_NOT_APPLICABLE_WARNING, "Operator ''{0}'' cannot be applied to ''{1}'' and ''{2}''. It will became an error in future releases.", (nameExpression, context) -> nameExpression.getReferencedName(), RENDER_TYPE, RENDER_TYPE); MAP.put(INCOMPATIBLE_ENUM_COMPARISON, "Comparison of incompatible enums ''{0}'' and ''{1}'' is always unsuccessful", RENDER_TYPE, RENDER_TYPE); MAP.put(INCOMPATIBLE_ENUM_COMPARISON_ERROR, "Comparison of incompatible enums ''{0}'' and ''{1}'' is always unsuccessful", RENDER_TYPE, RENDER_TYPE); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java index 4c0d0c901c3..f36fe128742 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/BindingContext.java @@ -176,6 +176,8 @@ public interface BindingContext { WritableSlice, Boolean> SUSPEND_LAMBDA_PARAMETER_USED = Slices.createSimpleSlice(); + WritableSlice MARKED_EQUALIY_CALL_PROPER_IN_BUILDER_INFERENCE = Slices.createSimpleSlice(); + /** * Has type of current expression has been already resolved */ diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/EqualityCallChecker.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/EqualityCallChecker.kt index 8dc125b1000..d0a26f88264 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/EqualityCallChecker.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/checkers/EqualityCallChecker.kt @@ -7,9 +7,12 @@ package org.jetbrains.kotlin.resolve.calls.checkers import com.intellij.psi.PsiElement import org.jetbrains.kotlin.builtins.KotlinBuiltIns +import org.jetbrains.kotlin.config.LanguageFeature import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.psi.KtBinaryExpression +import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext +import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.isInlineClassType import org.jetbrains.kotlin.types.KotlinType @@ -88,7 +91,14 @@ object EqualityCallChecker : CallChecker { val rightType = context.trace.getType(right) ?: return if (TypeIntersector.isIntersectionEmpty(leftType, rightType)) { - context.trace.report(Errors.EQUALITY_NOT_APPLICABLE.on(expression, expression.operationReference, leftType, rightType)) + val isProperEqualityChecksEnabled = + context.languageVersionSettings.supportsFeature(LanguageFeature.ProperEqualityChecksInBuilderInferenceCalls) + val shouldReportWarnings = !isProperEqualityChecksEnabled + && context.inferenceSession is BuilderInferenceSession + && context.trace.get(BindingContext.MARKED_EQUALIY_CALL_PROPER_IN_BUILDER_INFERENCE, expression) != null + val diagnostic = if (shouldReportWarnings) Errors.EQUALITY_NOT_APPLICABLE_WARNING else Errors.EQUALITY_NOT_APPLICABLE + + context.trace.report(diagnostic.on(expression, expression.operationReference, leftType, rightType)) } else { checkEnumsForCompatibility(context, expression, leftType, rightType) } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java index 1f7d53b54de..29b44c3ada1 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/BasicExpressionTypingVisitor.java @@ -48,6 +48,7 @@ import org.jetbrains.kotlin.resolve.bindingContextUtil.BindingContextUtilsKt; import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver; import org.jetbrains.kotlin.resolve.calls.CallExpressionResolver; import org.jetbrains.kotlin.resolve.calls.checkers.*; +import org.jetbrains.kotlin.resolve.calls.inference.BuilderInferenceSession; import org.jetbrains.kotlin.resolve.calls.model.DataFlowInfoForArgumentsImpl; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall; import org.jetbrains.kotlin.resolve.calls.model.ResolvedCallImpl; @@ -1181,6 +1182,16 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } } KotlinTypeInfo rightTypeInfo = facade.getTypeInfo(right, contextWithDataFlow); + + KotlinType leftType = leftTypeInfo.getType(); + KotlinType rightType = rightTypeInfo.getType(); + + boolean isBuilderInferenceContext = context.inferenceSession instanceof BuilderInferenceSession; + + if (leftType != null && rightType != null && !TypeIntersector.isIntersectionEmpty(leftType, rightType) && isBuilderInferenceContext) { + context.trace.record(MARKED_EQUALIY_CALL_PROPER_IN_BUILDER_INFERENCE, expression); + } + return rightTypeInfo.replaceType(components.builtIns.getBooleanType()); } diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypes.fir.kt b/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypes.fir.kt new file mode 100644 index 00000000000..168abd6f8af --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypes.fir.kt @@ -0,0 +1,20 @@ +// !LANGUAGE: -ProperEqualityChecksInBuilderInferenceCalls +// WITH_STDLIB + +fun main(x: Long, y: Int) { + sequence { + 1L == 3 + x == 3 + 3 == 1L + 3 == x + y == x + + 1L === 3 + x === 3 + 3 === 1L + 3 === x + y === x + + yield("") + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypes.kt b/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypes.kt new file mode 100644 index 00000000000..fd17d11e72a --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypes.kt @@ -0,0 +1,20 @@ +// !LANGUAGE: -ProperEqualityChecksInBuilderInferenceCalls +// WITH_STDLIB + +fun main(x: Long, y: Int) { + sequence { + 1L == 3 + x == 3 + 3 == 1L + 3 == x + y == x + + 1L === 3 + x === 3 + 3 === 1L + 3 === x + y === x + + yield("") + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksWithIlt.txt b/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypes.txt similarity index 100% rename from compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksWithIlt.txt rename to compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypes.txt diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypesProgressive.fir.kt b/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypesProgressive.fir.kt new file mode 100644 index 00000000000..2f8ed407c2e --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypesProgressive.fir.kt @@ -0,0 +1,20 @@ +// !LANGUAGE: +ProperEqualityChecksInBuilderInferenceCalls +// WITH_STDLIB + +fun main(x: Long, y: Int) { + sequence { + 1L == 3 + x == 3 + 3 == 1L + 3 == x + y == x + + 1L === 3 + x === 3 + 3 === 1L + 3 === x + y === x + + yield("") + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksWithIlt.kt b/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypesProgressive.kt similarity index 90% rename from compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksWithIlt.kt rename to compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypesProgressive.kt index 2ddeb80a888..00cd1b13f48 100644 --- a/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksWithIlt.kt +++ b/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypesProgressive.kt @@ -1,4 +1,5 @@ -// WITH_RUNTIME +// !LANGUAGE: +ProperEqualityChecksInBuilderInferenceCalls +// WITH_STDLIB fun main(x: Long, y: Int) { sequence { diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypesProgressive.txt b/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypesProgressive.txt new file mode 100644 index 00000000000..87cec176885 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypesProgressive.txt @@ -0,0 +1,3 @@ +package + +public fun main(/*0*/ x: kotlin.Long, /*1*/ y: kotlin.Int): kotlin.Unit diff --git a/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksWithIlt.fir.kt b/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksWithIlt.fir.kt deleted file mode 100644 index d828d96a7c8..00000000000 --- a/compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksWithIlt.fir.kt +++ /dev/null @@ -1,19 +0,0 @@ -// WITH_RUNTIME - -fun main(x: Long, y: Int) { - sequence { - 1L == 3 - x == 3 - 3 == 1L - 3 == x - y == x - - 1L === 3 - x === 3 - 3 === 1L - 3 === x - y === x - - yield("") - } -} \ No newline at end of file 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 c73d4e2d776..c959df3529f 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 @@ -14017,6 +14017,18 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/inference/builderInference/changingResolveIfDontUseBuilderInference.kt"); } + @Test + @TestMetadata("equalityChecksOnIntegerTypes.kt") + public void testEqualityChecksOnIntegerTypes() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypes.kt"); + } + + @Test + @TestMetadata("equalityChecksOnIntegerTypesProgressive.kt") + public void testEqualityChecksOnIntegerTypesProgressive() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/builderInference/equalityChecksOnIntegerTypesProgressive.kt"); + } + @Test @TestMetadata("kt47744.kt") public void testKt47744() 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 f29f1ac637b..87a77984615 100644 --- a/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt +++ b/compiler/util/src/org/jetbrains/kotlin/config/LanguageVersionSettings.kt @@ -255,6 +255,7 @@ enum class LanguageFeature( ProgressionsChangingResolve(KOTLIN_1_8), // KT-49276 ForbidSuperDelegationToAbstractFakeOverride(KOTLIN_1_8), // KT-49017 ForbidSuperDelegationToAbstractAnyMethod(KOTLIN_1_8), // KT-38078 + ProperEqualityChecksInBuilderInferenceCalls(KOTLIN_1_8, kind = BUG_FIX), // 1.9