From 09cc2ae27f0153da31502b34275e5d9d67b0c5b8 Mon Sep 17 00:00:00 2001 From: Mikhail Zarechenskiy Date: Mon, 22 Apr 2019 00:18:20 +0300 Subject: [PATCH] [NI] Initial support of "not enough information" diagnostic #KT-30590 In Progress --- .../fir/FirDiagnosticsSmokeTestGenerated.java | 5 +++++ .../org/jetbrains/kotlin/diagnostics/Errors.java | 2 ++ .../rendering/DefaultErrorMessages.java | 2 ++ .../calls/DiagnosticReporterByTrackingStrategy.kt | 15 ++++++++++++++- .../tower/KotlinToResolvedCallTransformer.kt | 14 +++++++++++--- .../components/KotlinConstraintSystemCompleter.kt | 2 +- .../model/ConstraintPositionAndErrors.kt | 5 ++++- .../inferTypeFromUnresolvedArgument.kt | 9 +++++++++ .../inferTypeFromUnresolvedArgument.txt | 4 ++++ .../kotlin/checkers/DiagnosticsTestGenerated.java | 5 +++++ .../javac/DiagnosticsUsingJavacTestGenerated.java | 5 +++++ 11 files changed, 62 insertions(+), 6 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inference/reportingImprovements/inferTypeFromUnresolvedArgument.kt create mode 100644 compiler/testData/diagnostics/tests/inference/reportingImprovements/inferTypeFromUnresolvedArgument.txt 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 00cd2a7640c..41b923e30c8 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsSmokeTestGenerated.java @@ -10532,6 +10532,11 @@ public class FirDiagnosticsSmokeTestGenerated extends AbstractFirDiagnosticsSmok runTest("compiler/testData/diagnostics/tests/inference/reportingImprovements/FunctionPlaceholder.kt"); } + @TestMetadata("inferTypeFromUnresolvedArgument.kt") + public void testInferTypeFromUnresolvedArgument() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/reportingImprovements/inferTypeFromUnresolvedArgument.kt"); + } + @TestMetadata("NoAmbiguityForDifferentFunctionTypes.kt") public void testNoAmbiguityForDifferentFunctionTypes() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/reportingImprovements/NoAmbiguityForDifferentFunctionTypes.kt"); diff --git a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java index d0c0f9c55c7..f558c674635 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/Errors.java @@ -735,6 +735,8 @@ public interface Errors { DiagnosticFactory0 CANNOT_INFER_PARAMETER_TYPE = DiagnosticFactory0.create(ERROR); DiagnosticFactory1 TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER = DiagnosticFactory1.create(ERROR); + DiagnosticFactory1 TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 TYPE_INFERENCE_CANNOT_CAPTURE_TYPES = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR = DiagnosticFactory1.create(ERROR); 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 c7f74b12642..f01dc47f122 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/diagnostics/rendering/DefaultErrorMessages.java @@ -831,6 +831,8 @@ public class DefaultErrorMessages { MAP.put(TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS, "Type inference failed: {0}", TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS_RENDERER); MAP.put(TYPE_INFERENCE_CANNOT_CAPTURE_TYPES, "Type inference failed: {0}", TYPE_INFERENCE_CANNOT_CAPTURE_TYPES_RENDERER); MAP.put(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER, "Type inference failed: {0}", TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER_RENDERER); + MAP.put(NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER, "Not enough information to infer type variable {0}", STRING); + MAP.put(TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR, "Type inference failed: {0}", TYPE_INFERENCE_PARAMETER_CONSTRAINT_ERROR_RENDERER); MAP.put(TYPE_INFERENCE_INCORPORATION_ERROR, "Type inference failed. Please try to specify type arguments explicitly."); MAP.put(TYPE_INFERENCE_ONLY_INPUT_TYPES, "Type inference failed. The value of the type parameter {0} should be mentioned in input types " + 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 13617bc4857..06091d31578 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/DiagnosticReporterByTrackingStrategy.kt @@ -32,7 +32,8 @@ class DiagnosticReporterByTrackingStrategy( val constantExpressionEvaluator: ConstantExpressionEvaluator, val context: BasicCallResolutionContext, val psiKotlinCall: PSIKotlinCall, - val dataFlowValueFactory: DataFlowValueFactory + val dataFlowValueFactory: DataFlowValueFactory, + val allDiagnostics: List ) : DiagnosticReporter { private val trace = context.trace as TrackingBindingTrace private val tracingStrategy: TracingStrategy get() = psiKotlinCall.tracingStrategy @@ -245,6 +246,18 @@ class DiagnosticReporterByTrackingStrategy( ) } } + + NotEnoughInformationForTypeParameter::class.java -> { + val error = diagnostic as NotEnoughInformationForTypeParameter + val call = error.resolvedAtom.atom?.safeAs()?.psiCall ?: call + val expression = call.calleeExpression ?: return + val typeVariableName = when (val typeVariable = error.typeVariable) { + is TypeVariableFromCallableDescriptor -> typeVariable.originalTypeParameter.name.asString() + is TypeVariableForLambdaReturnType -> "return type of lambda" + else -> error("Unsupported type variable: $typeVariable") + } + trace.report(NEW_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on(expression, typeVariableName)) + } } } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt index d5ca820299f..e217d312efe 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/resolve/calls/tower/KotlinToResolvedCallTransformer.kt @@ -423,13 +423,21 @@ class KotlinToResolvedCallTransformer( ) { val trackingTrace = TrackingBindingTrace(trace) val newContext = context.replaceBindingTrace(trackingTrace) - val diagnosticReporter = - DiagnosticReporterByTrackingStrategy(constantExpressionEvaluator, newContext, completedCallAtom.atom.psiKotlinCall, context.dataFlowValueFactory) val diagnosticHolder = KotlinDiagnosticsHolder.SimpleHolder() additionalDiagnosticReporter.reportAdditionalDiagnostics(completedCallAtom, resultingDescriptor, diagnosticHolder, diagnostics) - for (diagnostic in diagnostics + diagnosticHolder.getDiagnostics()) { + val allDiagnostics = diagnostics + diagnosticHolder.getDiagnostics() + + val diagnosticReporter = DiagnosticReporterByTrackingStrategy( + constantExpressionEvaluator, + newContext, + completedCallAtom.atom.psiKotlinCall, + context.dataFlowValueFactory, + allDiagnostics + ) + + for (diagnostic in allDiagnostics) { trackingTrace.reported = false diagnostic.report(diagnosticReporter) 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 1e3ce7cd624..6a7d9020ee2 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 @@ -87,7 +87,7 @@ class KotlinConstraintSystemCompleter( fixVariable(c, topLevelType, variableWithConstraints, postponedKtPrimitives) if (!variableForFixation.hasProperConstraint) { - c.addError(NotEnoughInformationForTypeParameter(variableWithConstraints.typeVariable)) + c.addError(NotEnoughInformationForTypeParameter(variableWithConstraints.typeVariable, topLevelAtoms.first())) } continue } 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 76007e657dc..cbbc742ccbf 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 @@ -101,7 +101,10 @@ class CapturedTypeFromSubtyping( val position: ConstraintPosition ) : ConstraintSystemCallDiagnostic(INAPPLICABLE) -class NotEnoughInformationForTypeParameter(val typeVariable: TypeVariableMarker) : ConstraintSystemCallDiagnostic(INAPPLICABLE) +class NotEnoughInformationForTypeParameter( + val typeVariable: TypeVariableMarker, + val resolvedAtom: ResolvedAtom +) : ConstraintSystemCallDiagnostic(INAPPLICABLE) class ConstrainingTypeIsError( val typeVariable: TypeVariableMarker, diff --git a/compiler/testData/diagnostics/tests/inference/reportingImprovements/inferTypeFromUnresolvedArgument.kt b/compiler/testData/diagnostics/tests/inference/reportingImprovements/inferTypeFromUnresolvedArgument.kt new file mode 100644 index 00000000000..b065052ca44 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/reportingImprovements/inferTypeFromUnresolvedArgument.kt @@ -0,0 +1,9 @@ +// !WITH_NEW_INFERENCE +// !DIAGNOSTICS: -UNUSED_PARAMETER + +fun id2(x: K, s: String): K = x + +fun test() { + id2(unresolved, "foo") + id2(unresolved, 42) +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/inference/reportingImprovements/inferTypeFromUnresolvedArgument.txt b/compiler/testData/diagnostics/tests/inference/reportingImprovements/inferTypeFromUnresolvedArgument.txt new file mode 100644 index 00000000000..7acd852fee9 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/reportingImprovements/inferTypeFromUnresolvedArgument.txt @@ -0,0 +1,4 @@ +package + +public fun id2(/*0*/ x: K, /*1*/ s: kotlin.String): K +public fun test(): kotlin.Unit diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 0f6c10ec28d..08b635e83b1 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -10539,6 +10539,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { runTest("compiler/testData/diagnostics/tests/inference/reportingImprovements/FunctionPlaceholder.kt"); } + @TestMetadata("inferTypeFromUnresolvedArgument.kt") + public void testInferTypeFromUnresolvedArgument() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/reportingImprovements/inferTypeFromUnresolvedArgument.kt"); + } + @TestMetadata("NoAmbiguityForDifferentFunctionTypes.kt") public void testNoAmbiguityForDifferentFunctionTypes() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/reportingImprovements/NoAmbiguityForDifferentFunctionTypes.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java index e8c368c0c6b..cc9e545e15d 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/javac/DiagnosticsUsingJavacTestGenerated.java @@ -10534,6 +10534,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing runTest("compiler/testData/diagnostics/tests/inference/reportingImprovements/FunctionPlaceholder.kt"); } + @TestMetadata("inferTypeFromUnresolvedArgument.kt") + public void testInferTypeFromUnresolvedArgument() throws Exception { + runTest("compiler/testData/diagnostics/tests/inference/reportingImprovements/inferTypeFromUnresolvedArgument.kt"); + } + @TestMetadata("NoAmbiguityForDifferentFunctionTypes.kt") public void testNoAmbiguityForDifferentFunctionTypes() throws Exception { runTest("compiler/testData/diagnostics/tests/inference/reportingImprovements/NoAmbiguityForDifferentFunctionTypes.kt");