From e0fb586aafb50a87585b084f16fcca5a91c055e1 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Mon, 19 Aug 2019 01:51:04 +0300 Subject: [PATCH] [NI] Don't loose diagnostic after type variable fixation #KT-24488 Fixed --- .../fir/resolve/calls/InferenceCompletion.kt | 2 +- .../fir/FirDiagnosticsSmokeTestGenerated.java | 5 +++++ .../DiagnosticReporterByTrackingStrategy.kt | 18 ++++++++++++++++++ .../calls/components/KotlinCallCompleter.kt | 2 ++ .../KotlinConstraintSystemCompleter.kt | 17 ++++++++++------- .../model/ConstraintPositionAndErrors.kt | 2 +- .../inference/model/NewConstraintSystemImpl.kt | 8 ++++++-- .../cstWithTypeContainingNonFixedVariable.kt | 10 ++++------ .../tests/inference/commonSystem/kt32818.kt | 2 +- ...ostponedCompletionWithExactAnnotation_ni.kt | 4 ++-- .../diagnostics/tests/regressions/kt24488.kt | 15 +++++++++++++++ .../diagnostics/notLinked/dfa/neg/1.kt | 2 +- .../checkers/DiagnosticsTestGenerated.java | 5 +++++ .../DiagnosticsUsingJavacTestGenerated.java | 5 +++++ .../kotlin/nj2k/inference/common/Solver.kt | 2 +- 15 files changed, 77 insertions(+), 22 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/regressions/kt24488.kt diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/InferenceCompletion.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/InferenceCompletion.kt index 59d2645e4be..5e699634ea0 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/InferenceCompletion.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/InferenceCompletion.kt @@ -152,7 +152,7 @@ class ConstraintSystemCompleter(val components: InferenceComponents) { direction: TypeVariableDirectionCalculator.ResolveDirection ) { val resultType = components.resultTypeResolver.findResultType(c, variableWithConstraints, direction) - c.fixVariable(variableWithConstraints.typeVariable, resultType) + c.fixVariable(variableWithConstraints.typeVariable, resultType, atom = null) // TODO: obtain atom for diagnostics } private fun analyzePostponeArgumentIfPossible( 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 806372c7746..db127d74d92 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java @@ -17240,6 +17240,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok runTest("compiler/testData/diagnostics/tests/regressions/kt2376.kt"); } + @TestMetadata("kt24488.kt") + public void testKt24488() throws Exception { + runTest("compiler/testData/diagnostics/tests/regressions/kt24488.kt"); + } + @TestMetadata("kt251.kt") public void testKt251() throws Exception { runTest("compiler/testData/diagnostics/tests/regressions/kt251.kt"); 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 4f063208eb2..9f5812322da 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt @@ -317,6 +317,24 @@ class DiagnosticReporterByTrackingStrategy( ) ) } + + (position as? FixVariableConstraintPosition)?.let { + val morePreciseDiagnosticExists = allDiagnostics.any { other -> + other is NewConstraintError && other.position.from !is FixVariableConstraintPosition + } + if (morePreciseDiagnosticExists) return + + val call = it.resolvedAtom?.atom?.safeAs()?.psiCall ?: call + val expression = call.calleeExpression ?: return + + trace.reportDiagnosticOnce( + TYPE_MISMATCH.on( + expression, + constraintError.upperKotlinType, + constraintError.lowerKotlinType + ) + ) + } } CapturedTypeFromSubtyping::class.java -> { 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 9dbeeae3b58..5b55d05ee71 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 @@ -10,6 +10,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.NewConstraintSystem import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode +import org.jetbrains.kotlin.resolve.calls.inference.model.Constraint import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage.Empty.hasContradiction import org.jetbrains.kotlin.resolve.calls.inference.model.ExpectedTypeConstraintPosition import org.jetbrains.kotlin.resolve.calls.model.* @@ -19,6 +20,7 @@ import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.TypeUtils import org.jetbrains.kotlin.types.UnwrappedType import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext +import org.jetbrains.kotlin.types.model.defaultType import org.jetbrains.kotlin.types.model.isIntegerLiteralTypeConstructor import org.jetbrains.kotlin.types.model.typeConstructor import org.jetbrains.kotlin.types.typeUtil.contains diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt index 30020e99d9e..a9b0d31d7f3 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/components/KotlinConstraintSystemCompleter.kt @@ -41,7 +41,7 @@ class KotlinConstraintSystemCompleter( // mutable operations fun addError(error: KotlinCallDiagnostic) - fun fixVariable(variable: TypeVariableMarker, resultType: KotlinTypeMarker) + fun fixVariable(variable: TypeVariableMarker, resultType: KotlinTypeMarker, atom: ResolvedAtom?) } fun runCompletion( @@ -87,7 +87,7 @@ class KotlinConstraintSystemCompleter( val variableWithConstraints = c.notFixedTypeVariables.getValue(variableForFixation.variable) if (variableForFixation.hasProperConstraint) - fixVariable(c, topLevelType, variableWithConstraints, postponedKtPrimitives) + fixVariable(c, topLevelType, variableWithConstraints, postponedKtPrimitives, topLevelAtoms) else processVariableWhenNotEnoughInformation(c, variableWithConstraints, topLevelAtoms) @@ -206,19 +206,22 @@ class KotlinConstraintSystemCompleter( c: Context, topLevelType: UnwrappedType, variableWithConstraints: VariableWithConstraints, - postponedResolveKtPrimitives: List + postponedResolveKtPrimitives: List, + topLevelAtoms: List ) { val direction = TypeVariableDirectionCalculator(c, postponedResolveKtPrimitives, topLevelType).getDirection(variableWithConstraints) - fixVariable(c, variableWithConstraints, direction) + fixVariable(c, variableWithConstraints, direction, topLevelAtoms) } fun fixVariable( c: Context, variableWithConstraints: VariableWithConstraints, - direction: TypeVariableDirectionCalculator.ResolveDirection + direction: TypeVariableDirectionCalculator.ResolveDirection, + topLevelAtoms: List ) { val resultType = resultTypeResolver.findResultType(c, variableWithConstraints, direction) - c.fixVariable(variableWithConstraints.typeVariable, resultType) + val resolvedAtom = findResolvedAtomBy(variableWithConstraints.typeVariable, topLevelAtoms) ?: topLevelAtoms.firstOrNull() + c.fixVariable(variableWithConstraints.typeVariable, resultType, resolvedAtom) } private fun processVariableWhenNotEnoughInformation( @@ -238,7 +241,7 @@ class KotlinConstraintSystemCompleter( else ErrorUtils.createErrorType("Cannot infer type variable $typeVariable") - c.fixVariable(typeVariable, resultErrorType) + c.fixVariable(typeVariable, resultErrorType, resolvedAtom) } private fun findResolvedAtomBy(typeVariable: TypeVariableMarker, topLevelAtoms: List): ResolvedAtom? { diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt index 7dd616fcd14..980d795b627 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/ConstraintPositionAndErrors.kt @@ -53,7 +53,7 @@ class ReceiverConstraintPosition(val argument: KotlinCallArgument) : ConstraintP override fun toString() = "Receiver $argument" } -class FixVariableConstraintPosition(val variable: TypeVariableMarker) : ConstraintPosition() { +class FixVariableConstraintPosition(val variable: TypeVariableMarker, val resolvedAtom: ResolvedAtom?) : ConstraintPosition() { override fun toString() = "Fix variable $variable" } diff --git a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt index 6bd4583bb74..bdb7a069929 100644 --- a/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt +++ b/compiler/resolution/src/org/jetbrains/kotlin/resolve/calls/inference/model/NewConstraintSystemImpl.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintS import org.jetbrains.kotlin.resolve.calls.inference.components.ResultTypeResolver import org.jetbrains.kotlin.resolve.calls.model.KotlinCallDiagnostic import org.jetbrains.kotlin.resolve.calls.model.OnlyInputTypesDiagnostic +import org.jetbrains.kotlin.resolve.calls.model.ResolvedAtom import org.jetbrains.kotlin.types.IntersectionTypeConstructor import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.checker.NewKotlinTypeChecker @@ -247,10 +248,13 @@ class NewConstraintSystemImpl( } // KotlinConstraintSystemCompleter.Context - override fun fixVariable(variable: TypeVariableMarker, resultType: KotlinTypeMarker) { + override fun fixVariable(variable: TypeVariableMarker, resultType: KotlinTypeMarker, atom: ResolvedAtom?) { checkState(State.BUILDING, State.COMPLETION) - constraintInjector.addInitialEqualityConstraint(this, variable.defaultType(), resultType, FixVariableConstraintPosition(variable)) + constraintInjector.addInitialEqualityConstraint( + this, variable.defaultType(), resultType, FixVariableConstraintPosition(variable, atom) + ) + val variableWithConstraints = notFixedTypeVariables.remove(variable.freshTypeConstructor()) checkOnlyInputTypesAnnotation(variableWithConstraints, resultType) diff --git a/compiler/testData/diagnostics/tests/inference/commonSystem/cstWithTypeContainingNonFixedVariable.kt b/compiler/testData/diagnostics/tests/inference/commonSystem/cstWithTypeContainingNonFixedVariable.kt index 6a1f1dfb9d5..ece139a8b99 100644 --- a/compiler/testData/diagnostics/tests/inference/commonSystem/cstWithTypeContainingNonFixedVariable.kt +++ b/compiler/testData/diagnostics/tests/inference/commonSystem/cstWithTypeContainingNonFixedVariable.kt @@ -59,13 +59,11 @@ fun testVariableWithBound() { ")!>c1 - // should be an error after variable fixation - val c2 = select(SubInv(), createWithNumberBound()) + val c2 = select(SubInv(), createWithNumberBound()) ")!>c2 - // should be an error after variable fixation - val c3 = select(SubInv(), createWithIntBound()) + val c3 = select(SubInv(), createWithIntBound()) ")!>c3 } @@ -78,13 +76,13 @@ fun testCapturedVariable() { val c1 = select(SubInv(), createInvOut()) - ")!>c1 + ")!>c1 val c2 = select(createSubInvOut(), createInvOut()) ")!>c2 - val c3 = select(SubInv(), createInvIn()) + val c3 = select(SubInv(), createInvIn()) ")!>c3 } diff --git a/compiler/testData/diagnostics/tests/inference/commonSystem/kt32818.kt b/compiler/testData/diagnostics/tests/inference/commonSystem/kt32818.kt index 9ac95c8770a..5ab9d19b96b 100644 --- a/compiler/testData/diagnostics/tests/inference/commonSystem/kt32818.kt +++ b/compiler/testData/diagnostics/tests/inference/commonSystem/kt32818.kt @@ -2,4 +2,4 @@ fun nullable(): T? = null -val value = nullable() ?: nullable() \ No newline at end of file +val value = nullable() ?: nullable() \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/commonSystem/postponedCompletionWithExactAnnotation_ni.kt b/compiler/testData/diagnostics/tests/inference/commonSystem/postponedCompletionWithExactAnnotation_ni.kt index 14a2970acda..2c3d7222ac0 100644 --- a/compiler/testData/diagnostics/tests/inference/commonSystem/postponedCompletionWithExactAnnotation_ni.kt +++ b/compiler/testData/diagnostics/tests/inference/commonSystem/postponedCompletionWithExactAnnotation_ni.kt @@ -11,13 +11,13 @@ fun elvisExact(x: K?, y: K): @kotlin.internal.Exact K = y fun materialize(): T? = null fun test(nullableSample: ISample, any: Any) { - elvisSimple( + elvisSimple( nullableSample, materialize() ) elvisSimple( - elvisSimple(nullableSample, materialize()), + elvisSimple(nullableSample, materialize()), any ) diff --git a/compiler/testData/diagnostics/tests/regressions/kt24488.kt b/compiler/testData/diagnostics/tests/regressions/kt24488.kt new file mode 100644 index 00000000000..1574cb8d248 --- /dev/null +++ b/compiler/testData/diagnostics/tests/regressions/kt24488.kt @@ -0,0 +1,15 @@ +// !WITH_NEW_INFERENCE +// SKIP_TXT + +class Bar { + val a: Array? = null +} + +fun foo(bar: Bar) = bar.a?.asIterable() ?: emptyArray() + +fun Array.asIterable(): Iterable = TODO() + +fun testFrontend() { + val bar = Bar() + foo(bar) +} \ No newline at end of file diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/1.kt b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/1.kt index dcbe4462eee..90089af0dd4 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/1.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/dfa/neg/1.kt @@ -272,7 +272,7 @@ fun case_16() { // TESTCASE NUMBER: 17 val case_17 = if (nullableIntProperty == null == true == false) 0 else { nullableIntProperty - nullableIntProperty.java + nullableIntProperty.java } //TESTCASE NUMBER: 18 diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index eb80149e0a7..85bc38eb509 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -17252,6 +17252,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/regressions/kt2376.kt"); } + @TestMetadata("kt24488.kt") + public void testKt24488() throws Exception { + runTest("compiler/testData/diagnostics/tests/regressions/kt24488.kt"); + } + @TestMetadata("kt251.kt") public void testKt251() throws Exception { runTest("compiler/testData/diagnostics/tests/regressions/kt251.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index 6d130390a7b..158f84bae5d 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -17242,6 +17242,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/regressions/kt2376.kt"); } + @TestMetadata("kt24488.kt") + public void testKt24488() throws Exception { + runTest("compiler/testData/diagnostics/tests/regressions/kt24488.kt"); + } + @TestMetadata("kt251.kt") public void testKt251() throws Exception { runTest("compiler/testData/diagnostics/tests/regressions/kt251.kt"); diff --git a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/Solver.kt b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/Solver.kt index ab3d666972e..60304e46609 100644 --- a/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/Solver.kt +++ b/nj2k/nj2k-services/src/org/jetbrains/kotlin/nj2k/inference/common/Solver.kt @@ -186,7 +186,7 @@ internal class Solver( } is EqualsConstraint -> { (constraint.left.safeAs() - ?: constraint.right.safeAs()) + ?: constraint.right.safeAs()) ?.let { return it.typeVariable } } }