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 ff572170599..0039fda0d40 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java @@ -2393,6 +2393,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok runTest("compiler/testData/diagnostics/tests/callableReference/resolve/overloadsMember.kt"); } + @TestMetadata("resolveEqualsOperatorWithAnyExpectedType.kt") + public void testResolveEqualsOperatorWithAnyExpectedType() throws Exception { + runTest("compiler/testData/diagnostics/tests/callableReference/resolve/resolveEqualsOperatorWithAnyExpectedType.kt"); + } + @TestMetadata("valVsFun.kt") public void testValVsFun() throws Exception { runTest("compiler/testData/diagnostics/tests/callableReference/resolve/valVsFun.kt"); 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 9c617f26115..6e64372e8a5 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 @@ -201,9 +201,8 @@ class KotlinCallCompleter( val variableWithConstraints = csBuilder.currentStorage().notFixedTypeVariables[constructor] ?: return false val constraints = variableWithConstraints.constraints return constraints.isNotEmpty() && constraints.all { - !trivialConstraintTypeInferenceOracle.isTrivialConstraint(it) && - with(context) { !it.type.typeConstructor().isIntegerLiteralTypeConstructor() } && - it.kind.isLower() && csBuilder.isProperType(it.type) + with(context) { !it.type.typeConstructor().isIntegerLiteralTypeConstructor() } && + it.kind.isLower() && csBuilder.isProperType(it.type) } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt index d0e786dd390..de3912a009e 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintIncorporator.kt @@ -156,13 +156,19 @@ class ConstraintIncorporator( if (baseConstraint.kind != ConstraintKind.UPPER) { val generatedConstraintType = approximateCapturedTypes(typeForApproximation, toSuper = false) - if (!trivialConstraintTypeInferenceOracle.isGeneratedConstraintTrivial(otherConstraint, generatedConstraintType)) { + if (!trivialConstraintTypeInferenceOracle.isGeneratedConstraintTrivial( + otherConstraint, generatedConstraintType, isSubtype = true + ) + ) { addNewIncorporatedConstraint(generatedConstraintType, targetVariable.defaultType()) } } if (baseConstraint.kind != ConstraintKind.LOWER) { val generatedConstraintType = approximateCapturedTypes(typeForApproximation, toSuper = true) - if (!trivialConstraintTypeInferenceOracle.isGeneratedConstraintTrivial(otherConstraint, generatedConstraintType)) { + if (!trivialConstraintTypeInferenceOracle.isGeneratedConstraintTrivial( + otherConstraint, generatedConstraintType, isSubtype = false + ) + ) { addNewIncorporatedConstraint(targetVariable.defaultType(), generatedConstraintType) } } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt index aec7bbb85b9..219ac5631bd 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/ConstraintInjector.kt @@ -101,7 +101,11 @@ class ConstraintInjector(val constraintIncorporator: ConstraintIncorporator, val } if (constraintType.isSimpleType()) { - if (constraint.kind == UPPER && constraintType.isNullableAny()) return true // T <: Any? + if (constraint.position.from is DeclaredUpperBoundConstraintPosition && + constraint.kind == UPPER && constraintType.isNullableAny() + ) { + return true // T <: Any? + } } return false diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TrivialConstraintTypeInferenceOracle.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TrivialConstraintTypeInferenceOracle.kt index 853a8aaedd5..024bb92c860 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TrivialConstraintTypeInferenceOracle.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/TrivialConstraintTypeInferenceOracle.kt @@ -7,19 +7,19 @@ package org.jetbrains.kotlin.resolve.calls.inference.components import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintKind +import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable +import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.model.KotlinTypeMarker -import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext -import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContextDelegate +import org.jetbrains.kotlin.types.typeUtil.contains +import org.jetbrains.kotlin.types.typeUtil.isNothing +import org.jetbrains.kotlin.types.typeUtil.isNullableNothing class TrivialConstraintTypeInferenceOracle(context: TypeSystemInferenceExtensionContextDelegate) : TypeSystemInferenceExtensionContext by context { // The idea is to add knowledge that constraint `Nothing(?) <: T` is quite useless and // it's totally fine to go and resolve postponed argument without fixation T to Nothing(?). // In other words, constraint `Nothing(?) <: T` is *not* proper - fun isTrivialConstraint( - constraint: Constraint - ): Boolean { - // TODO: probably we also can take into account `T <: Any(?)` constraints + fun isNotInterestingConstraint(constraint: Constraint): Boolean { return constraint.kind == ConstraintKind.LOWER && constraint.type.typeConstructor().isNothingConstructor() } @@ -39,9 +39,11 @@ class TrivialConstraintTypeInferenceOracle(context: TypeSystemInferenceExtension // Therefore, here we avoid adding such trivial constraints to have stable constraint system fun isGeneratedConstraintTrivial( otherConstraint: Constraint, - generatedConstraintType: KotlinTypeMarker + generatedConstraintType: KotlinTypeMarker, + isSubtype: Boolean ): Boolean { - if (generatedConstraintType.isNothing()) return true + if (isSubtype && generatedConstraintType.isNothing()) return true + if (!isSubtype && generatedConstraintType.isNullableAny()) return true // If type that will be used to generate new constraint already contains `Nothing(?)`, // then we can't decide that resulting constraint will be useless diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt index f37cdfa03b3..49c08abd48f 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/VariableFixationFinder.kt @@ -107,7 +107,7 @@ class VariableFixationFinder( private fun Context.variableHasTrivialOrNonProperConstraints(variable: TypeConstructorMarker): Boolean { return notFixedTypeVariables[variable]?.constraints?.all { constraint -> val isProperConstraint = isProperArgumentConstraint(constraint) - isProperConstraint && trivialConstraintTypeInferenceOracle.isTrivialConstraint(constraint) || !isProperConstraint + isProperConstraint && trivialConstraintTypeInferenceOracle.isNotInterestingConstraint(constraint) || !isProperConstraint } ?: false } diff --git a/compiler/testData/diagnostics/tests/callableReference/resolve/resolveEqualsOperatorWithAnyExpectedType.kt b/compiler/testData/diagnostics/tests/callableReference/resolve/resolveEqualsOperatorWithAnyExpectedType.kt new file mode 100644 index 00000000000..5a9c7237ffb --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/resolve/resolveEqualsOperatorWithAnyExpectedType.kt @@ -0,0 +1,11 @@ +// !LANGUAGE: +NewInference + +interface Base + +fun materialize(): K = TODO() + +fun Base.transform(): T = materialize() + +fun test(child: Base) { + child == child.transform() +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/callableReference/resolve/resolveEqualsOperatorWithAnyExpectedType.txt b/compiler/testData/diagnostics/tests/callableReference/resolve/resolveEqualsOperatorWithAnyExpectedType.txt new file mode 100644 index 00000000000..f45cacf7c43 --- /dev/null +++ b/compiler/testData/diagnostics/tests/callableReference/resolve/resolveEqualsOperatorWithAnyExpectedType.txt @@ -0,0 +1,11 @@ +package + +public fun materialize(): K +public fun test(/*0*/ child: Base): kotlin.Unit +public fun Base.transform(): T + +public interface Base { + 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/dataFlowInfoTraversal/BinaryExpression.kt b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/BinaryExpression.kt index 46ae3651bf0..48408d23083 100644 --- a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/BinaryExpression.kt +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/BinaryExpression.kt @@ -6,6 +6,6 @@ fun foo() { val x: Int? = null bar(1 + (if (x == null) 0 else x)) - bar(if (x == null) x else x) + bar(if (x == null) x else x) if (x != null) bar(x + x/(x-x*x)) } diff --git a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ExclExcl.kt b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ExclExcl.kt index 4499a4f5fe8..317f7af809c 100644 --- a/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ExclExcl.kt +++ b/compiler/testData/diagnostics/tests/dataFlowInfoTraversal/ExclExcl.kt @@ -4,7 +4,7 @@ fun bar(x: Int) = x + 1 fun f1(x: Int?) { bar(x) if (x != null) bar(x!!) - if (x == null) bar(x!!) + if (x == null) bar(x!!) } fun f2(x: Int?) { diff --git a/compiler/testData/diagnostics/tests/delegatedProperty/inference/differentDelegatedExpressions.kt b/compiler/testData/diagnostics/tests/delegatedProperty/inference/differentDelegatedExpressions.kt index ddf52904c36..3b587e9a4c0 100644 --- a/compiler/testData/diagnostics/tests/delegatedProperty/inference/differentDelegatedExpressions.kt +++ b/compiler/testData/diagnostics/tests/delegatedProperty/inference/differentDelegatedExpressions.kt @@ -13,7 +13,7 @@ class A(outer: Outer) { var b: String by foo(getMyProperty()) var r: String by foo(outer.getContainer().getMyProperty()) var e: String by + foo(getMyProperty()) - var f: String by foo(getMyProperty()) - 1 + var f: String by foo(getMyProperty()) - 1 } fun foo(a: Any?) = MyProperty() diff --git a/compiler/testData/diagnostics/tests/nullabilityAndSmartCasts/kt2164.kt b/compiler/testData/diagnostics/tests/nullabilityAndSmartCasts/kt2164.kt index 0b4f9a7dc02..50032992b3a 100644 --- a/compiler/testData/diagnostics/tests/nullabilityAndSmartCasts/kt2164.kt +++ b/compiler/testData/diagnostics/tests/nullabilityAndSmartCasts/kt2164.kt @@ -23,8 +23,8 @@ fun main() { foo(x) } else { foo(x) - foo(x!!) - foo(x) + foo(x!!) + foo(x) } foo(x) diff --git a/compiler/testData/diagnostics/tests/overload/defaultParameters.kt b/compiler/testData/diagnostics/tests/overload/defaultParameters.kt index a3ef5a4614c..abc3d7231bc 100644 --- a/compiler/testData/diagnostics/tests/overload/defaultParameters.kt +++ b/compiler/testData/diagnostics/tests/overload/defaultParameters.kt @@ -55,5 +55,5 @@ fun test() { withGenericDefaults("") - wrong(null!!) + wrong(null!!) } \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/resolve/specialConstructions/reportTypeMismatchDeeplyOnBranches.kt b/compiler/testData/diagnostics/tests/resolve/specialConstructions/reportTypeMismatchDeeplyOnBranches.kt index cce34aa4cca..dc507807c72 100644 --- a/compiler/testData/diagnostics/tests/resolve/specialConstructions/reportTypeMismatchDeeplyOnBranches.kt +++ b/compiler/testData/diagnostics/tests/resolve/specialConstructions/reportTypeMismatchDeeplyOnBranches.kt @@ -8,15 +8,15 @@ fun test(a: Int?, b: Int?) { } fun test(a: Int?, b: Int?, c: Int?) { - bar(if (a == null) return else if (b == null) return else c) + bar(if (a == null) return else if (b == null) return else c) } fun test(a: Any?, b: Any?, c: Int?) { - bar(if (a == null) if (b == null) c else return else return) + bar(if (a == null) if (b == null) c else return else return) } fun test(a: Int?, b: Any?, c: Int?) { - bar(if (a == null) { + bar(if (a == null) { return } else { if (b == null) { diff --git a/compiler/testData/diagnostics/tests/when/kt9972.kt b/compiler/testData/diagnostics/tests/when/kt9972.kt index c2a485d038c..814813cabeb 100644 --- a/compiler/testData/diagnostics/tests/when/kt9972.kt +++ b/compiler/testData/diagnostics/tests/when/kt9972.kt @@ -1,6 +1,6 @@ // !WITH_NEW_INFERENCE fun test1(): Int { - val x: String = if (true) { + val x: String = if (true) { when { true -> Any() else -> null @@ -10,7 +10,7 @@ fun test1(): Int { } fun test2(): Int { - val x: String = when { + val x: String = when { true -> Any() else -> null } ?: return 0 diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 2d4eb02f5e0..5a4a4fcafa6 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -2400,6 +2400,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/callableReference/resolve/overloadsMember.kt"); } + @TestMetadata("resolveEqualsOperatorWithAnyExpectedType.kt") + public void testResolveEqualsOperatorWithAnyExpectedType() throws Exception { + runTest("compiler/testData/diagnostics/tests/callableReference/resolve/resolveEqualsOperatorWithAnyExpectedType.kt"); + } + @TestMetadata("valVsFun.kt") public void testValVsFun() throws Exception { runTest("compiler/testData/diagnostics/tests/callableReference/resolve/valVsFun.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 17d5a3063cd..0e96e8e1284 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -2395,6 +2395,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/callableReference/resolve/overloadsMember.kt"); } + @TestMetadata("resolveEqualsOperatorWithAnyExpectedType.kt") + public void testResolveEqualsOperatorWithAnyExpectedType() throws Exception { + runTest("compiler/testData/diagnostics/tests/callableReference/resolve/resolveEqualsOperatorWithAnyExpectedType.kt"); + } + @TestMetadata("valVsFun.kt") public void testValVsFun() throws Exception { runTest("compiler/testData/diagnostics/tests/callableReference/resolve/valVsFun.kt");