diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java index 44538203e55..4a502a84e8a 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CandidateResolver.java @@ -229,30 +229,23 @@ public class CandidateResolver { constraintSystem.addSupertypeConstraint(context.expectedType, descriptor.getReturnType(), ConstraintPosition.EXPECTED_TYPE_POSITION); - if (!constraintSystem.isSuccessful()) { - resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor()); - completeNestedCallsInference(context); - List argumentTypes = checkValueArgumentTypes(context, resolvedCall, context.trace, - RESOLVE_FUNCTION_ARGUMENTS).argumentTypes; - JetType receiverType = resolvedCall.getReceiverArgument().exists() ? resolvedCall.getReceiverArgument().getType() : null; - InferenceErrorData.ExtendedInferenceErrorData errorData = InferenceErrorData - .create(descriptor, constraintSystem, argumentTypes, receiverType, context.expectedType); - - context.tracing.typeInferenceFailed(context.trace, errorData); - resolvedCall.addStatus(ResolutionStatus.OTHER_ERROR); - if (!CallResolverUtil.hasInferredReturnType(resolvedCall)) return null; - return resolvedCall.getResultingDescriptor().getReturnType(); + if (constraintSystem.hasContradiction()) { + return reportInferenceError(context); } boolean boundsAreSatisfied = ConstraintsUtil.checkBoundsAreSatisfied(constraintSystem, /*substituteOtherTypeParametersInBounds=*/true); - if (!boundsAreSatisfied) { + if (!boundsAreSatisfied || constraintSystem.hasUnknownParameters()) { ConstraintSystemImpl copy = (ConstraintSystemImpl) constraintSystem.copy(); copy.processDeclaredBoundConstraints(); boundsAreSatisfied = copy.isSuccessful() && ConstraintsUtil.checkBoundsAreSatisfied(copy, /*substituteOtherTypeParametersInBounds=*/true); if (boundsAreSatisfied) { constraintSystem = copy; + resolvedCall.setConstraintSystem(constraintSystem); } } + if (!constraintSystem.isSuccessful()) { + return reportInferenceError(context); + } if (!boundsAreSatisfied) { context.tracing.upperBoundViolated(context.trace, InferenceErrorData.create(resolvedCall.getCandidateDescriptor(), constraintSystem)); } @@ -267,12 +260,33 @@ public class CandidateResolver { if (status == ResolutionStatus.UNKNOWN_STATUS || status == ResolutionStatus.INCOMPLETE_TYPE_INFERENCE) { resolvedCall.setStatusToSuccess(); } + JetType returnType = resolvedCall.getResultingDescriptor().getReturnType(); if (isInnerCall) { PsiElement callElement = context.call.getCallElement(); if (callElement instanceof JetCallExpression) { - DataFlowUtils.checkType(resolvedCall.getResultingDescriptor().getReturnType(), (JetCallExpression) callElement, context, context.dataFlowInfo); + DataFlowUtils.checkType(returnType, (JetCallExpression) callElement, context, context.dataFlowInfo); } } + return returnType; + } + + private JetType reportInferenceError( + @NotNull CallCandidateResolutionContext context + ) { + ResolvedCallImpl resolvedCall = context.candidateCall; + ConstraintSystem constraintSystem = resolvedCall.getConstraintSystem(); + + resolvedCall.setResultingSubstitutor(constraintSystem.getResultingSubstitutor()); + completeNestedCallsInference(context); + List argumentTypes = checkValueArgumentTypes( + context, resolvedCall, context.trace, RESOLVE_FUNCTION_ARGUMENTS).argumentTypes; + JetType receiverType = resolvedCall.getReceiverArgument().exists() ? resolvedCall.getReceiverArgument().getType() : null; + InferenceErrorData.ExtendedInferenceErrorData errorData = InferenceErrorData + .create(resolvedCall.getCandidateDescriptor(), constraintSystem, argumentTypes, receiverType, context.expectedType); + + context.tracing.typeInferenceFailed(context.trace, errorData); + resolvedCall.addStatus(ResolutionStatus.OTHER_ERROR); + if (!CallResolverUtil.hasInferredReturnType(resolvedCall)) return null; return resolvedCall.getResultingDescriptor().getReturnType(); } diff --git a/compiler/testData/diagnostics/tests/inference/upperBounds/useBoundsIfUnknownParameters.kt b/compiler/testData/diagnostics/tests/inference/upperBounds/useBoundsIfUnknownParameters.kt new file mode 100644 index 00000000000..0734871e4ec --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/upperBounds/useBoundsIfUnknownParameters.kt @@ -0,0 +1,11 @@ +package Hello + +open class Base +class StringBase : Base() + +class Client>(x: X) + +fun test() { + val c = Client(StringBase()) // Type inference fails here for T. + val i : Int = c +} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java index 0d855419520..d9a61f6c701 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -2469,6 +2469,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage doTest("compiler/testData/diagnostics/tests/inference/upperBounds/kt2856.kt"); } + @TestMetadata("useBoundsIfUnknownParameters.kt") + public void testUseBoundsIfUnknownParameters() throws Exception { + doTest("compiler/testData/diagnostics/tests/inference/upperBounds/useBoundsIfUnknownParameters.kt"); + } + @TestMetadata("useBoundsToInferTypeParamsSimple.kt") public void testUseBoundsToInferTypeParamsSimple() throws Exception { doTest("compiler/testData/diagnostics/tests/inference/upperBounds/useBoundsToInferTypeParamsSimple.kt");