diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index 1044853d5d8..01d6002a875 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -340,6 +340,7 @@ public interface Errors { DiagnosticFactory1 TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH = DiagnosticFactory1.create(ERROR); DiagnosticFactory1 TYPE_INFERENCE_UPPER_BOUND_VIOLATED = DiagnosticFactory1.create(ERROR); + DiagnosticFactory2 TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH = DiagnosticFactory2.create(ERROR); Collection TYPE_INFERENCE_ERRORS = Lists.newArrayList(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER, TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS, TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH, TYPE_INFERENCE_UPPER_BOUND_VIOLATED); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java index c15fd9dd371..a13d6fa80dd 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/DefaultErrorMessages.java @@ -35,8 +35,6 @@ import java.util.Iterator; import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.diagnostics.rendering.Renderers.*; -import static org.jetbrains.jet.lang.diagnostics.rendering.Renderers.RENDER_TYPE; -import static org.jetbrains.jet.lang.diagnostics.rendering.Renderers.TO_STRING; /** * @author Evgeny Gerashchenko @@ -399,6 +397,7 @@ public class DefaultErrorMessages { MAP.put(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER, "Type inference failed: {0}", TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER_RENDERER); MAP.put(TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH, "Type inference failed: {0}", TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH_RENDERER); MAP.put(TYPE_INFERENCE_UPPER_BOUND_VIOLATED, "{0}", TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER); + MAP.put(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH, "Type inference failed. Expected type mismatch: found: {0} required: {1}", RENDER_TYPE, RENDER_TYPE); MAP.put(WRONG_NUMBER_OF_TYPE_ARGUMENTS, "{0,choice,0#No type arguments|1#Type argument|1<{0,number,integer} type argument} expected", null); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java index 140343a8444..223d2032f79 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/Renderers.java @@ -256,10 +256,10 @@ public class Renderers { assert firstUnknownParameter != null; return renderer - .text(TabledDescriptorRenderer.newText().normal("Not enough information to infer parameter ") + .text(newText().normal("Not enough information to infer parameter ") .strong(firstUnknownParameter.getName()) .normal(" in ")) - .table(TabledDescriptorRenderer.newTable() + .table(newTable() .descriptor(inferenceErrorData.descriptor) .text("Please specify it explicitly.")); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/TabledDescriptorRenderer.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/TabledDescriptorRenderer.java index d9360915696..65f82c9d199 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/TabledDescriptorRenderer.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/rendering/TabledDescriptorRenderer.java @@ -22,9 +22,7 @@ import com.google.common.collect.Lists; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; -import org.jetbrains.jet.lang.diagnostics.rendering.TabledDescriptorRenderer.TableRenderer.DescriptorRow; -import org.jetbrains.jet.lang.diagnostics.rendering.TabledDescriptorRenderer.TableRenderer.FunctionArgumentsRow; -import org.jetbrains.jet.lang.diagnostics.rendering.TabledDescriptorRenderer.TableRenderer.TableRow; +import org.jetbrains.jet.lang.diagnostics.rendering.TabledDescriptorRenderer.TableRenderer.*; import org.jetbrains.jet.lang.diagnostics.rendering.TabledDescriptorRenderer.TextRenderer.TextElement; import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition; import org.jetbrains.jet.lang.types.JetType; @@ -63,7 +61,6 @@ public class TabledDescriptorRenderer { } } - public final List rows = Lists.newArrayList(); public TableRenderer descriptor(CallableDescriptor descriptor) { @@ -95,7 +92,6 @@ public class TabledDescriptorRenderer { } public static class TextRenderer implements TableOrTextRenderer, TableRow { - public static enum TextElementType {STRONG, ERROR, DEFAULT} public static class TextElement { public TextElementType type; @@ -248,4 +244,5 @@ public class TabledDescriptorRenderer { return new TabledDescriptorRenderer(); } + public static enum TextElementType { STRONG, ERROR, DEFAULT } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index 84f8a23c4d9..56777fa8be8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -365,7 +365,7 @@ public class CallResolver { List argumentTypes = checkValueArgumentTypes(context, resolvedCall, context.trace).argumentTypes; JetType receiverType = resolvedCall.getReceiverArgument().exists() ? resolvedCall.getReceiverArgument().getType() : null; tracing.typeInferenceFailed(context.trace, - InferenceErrorData.create(descriptor, constraintsSystem, argumentTypes, receiverType)); + InferenceErrorData.create(descriptor, constraintsSystem, argumentTypes, receiverType, context.expectedType)); resolvedCall.addStatus(ResolutionStatus.TYPE_INFERENCE_ERROR); failed.add(resolvedCall); return; @@ -761,7 +761,7 @@ public class CallResolver { List argumentTypes = checkingResult.argumentTypes; JetType receiverType = candidateCall.getReceiverArgument().exists() ? candidateCall.getReceiverArgument().getType() : null; context.tracing.typeInferenceFailed(context.trace, - InferenceErrorData.create(candidate, constraintsBuilderWithRightTypeParameters, argumentTypes, receiverType)); + InferenceErrorData.create(candidate, constraintsBuilderWithRightTypeParameters, argumentTypes, receiverType, context.expectedType)); return TYPE_INFERENCE_ERROR.combine(argumentsStatus); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java index ab98e68add0..9645ef18020 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/ResolutionTask.java @@ -27,6 +27,8 @@ import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; +import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition; +import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintsSystem; import org.jetbrains.jet.lang.resolve.calls.inference.InferenceErrorData; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.scopes.JetScope; @@ -233,20 +235,26 @@ public class ResolutionTask extends R } @Override - public void typeInferenceFailed(@NotNull BindingTrace trace, @NotNull InferenceErrorData inferenceErrorData) { - assert !inferenceErrorData.constraintsSystem.isSuccessful(); - if (inferenceErrorData.constraintsSystem.hasErrorInConstrainingTypes()) { + public void typeInferenceFailed(@NotNull BindingTrace trace, @NotNull InferenceErrorData data) { + ConstraintsSystem constraintsSystem = data.constraintsSystem; + assert !constraintsSystem.isSuccessful(); + if (constraintsSystem.hasErrorInConstrainingTypes()) { return; } - if (inferenceErrorData.constraintsSystem.hasTypeConstructorMismatch()) { - trace.report(TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH.on(reference, inferenceErrorData)); + if (constraintsSystem.hasExpectedTypeMismatch()) { + JetType returnType = data.descriptor.getReturnType(); + assert returnType != null; + trace.report(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH.on(reference, returnType, data.expectedType)); } - else if (inferenceErrorData.constraintsSystem.hasConflictingConstraints()) { - trace.report(TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS.on(reference, inferenceErrorData)); + else if (constraintsSystem.hasTypeConstructorMismatch()) { + trace.report(TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH.on(reference, data)); + } + else if (constraintsSystem.hasConflictingConstraints()) { + trace.report(TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS.on(reference, data)); } else { - assert inferenceErrorData.constraintsSystem.hasUnknownParameters(); - trace.report(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on(reference, inferenceErrorData)); + assert constraintsSystem.hasUnknownParameters(); + trace.report(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER.on(reference, data)); } } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsSystem.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsSystem.java index 1eb876d3ab2..6002c6d0048 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsSystem.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsSystem.java @@ -99,6 +99,11 @@ public interface ConstraintsSystem { */ boolean hasTypeConstructorMismatchAt(@NotNull ConstraintPosition constraintPosition); + /** + * Returns true if there is type constructor mismatch only in {@link ConstraintPosition.EXPECTED_TYPE_POSITION}. + */ + boolean hasExpectedTypeMismatch(); + /** * Returns true if there is an error in constraining types.

* Is used not to generate type inference error if there was one in argument types. diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsSystemImpl.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsSystemImpl.java index c308704061f..38b509f7af9 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsSystemImpl.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/ConstraintsSystemImpl.java @@ -89,6 +89,11 @@ public class ConstraintsSystemImpl implements ConstraintsSystem { return errorConstraintPositions.contains(constraintPosition); } + @Override + public boolean hasExpectedTypeMismatch() { + return errorConstraintPositions.size() == 1 && errorConstraintPositions.contains(ConstraintPosition.EXPECTED_TYPE_POSITION); + } + @Override public boolean hasErrorInConstrainingTypes() { return hasErrorInConstrainingTypes; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/InferenceErrorData.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/InferenceErrorData.java index 7d44eef2367..b0a0d78b2f5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/InferenceErrorData.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/inference/InferenceErrorData.java @@ -20,6 +20,7 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeUtils; import java.util.List; @@ -30,22 +31,25 @@ public class InferenceErrorData { public final CallableDescriptor descriptor; public final ConstraintsSystem constraintsSystem; public final JetType receiverArgumentType; + public final JetType expectedType; public final List valueArgumentsTypes; private InferenceErrorData(@NotNull CallableDescriptor descriptor, @NotNull ConstraintsSystem constraintsSystem, - @Nullable List valueArgumentsTypes, @Nullable JetType receiverArgumentType) { + @Nullable List valueArgumentsTypes, @Nullable JetType receiverArgumentType, @Nullable JetType expectedType) { this.descriptor = descriptor; this.constraintsSystem = constraintsSystem; this.receiverArgumentType = receiverArgumentType; this.valueArgumentsTypes = valueArgumentsTypes; + this.expectedType = expectedType; } public static InferenceErrorData create(@NotNull CallableDescriptor descriptor, @NotNull ConstraintsSystem constraintsSystem, - @NotNull List valueArgumentsTypes, @Nullable JetType receiverArgumentType) { - return new InferenceErrorData(descriptor, constraintsSystem, valueArgumentsTypes, receiverArgumentType); + @NotNull List valueArgumentsTypes, @Nullable JetType receiverArgumentType, @Nullable JetType expectedType) { + return new InferenceErrorData(descriptor, constraintsSystem, valueArgumentsTypes, receiverArgumentType, + expectedType != TypeUtils.NO_EXPECTED_TYPE ? expectedType : null); } public static InferenceErrorData create(@NotNull CallableDescriptor descriptor, @NotNull ConstraintsSystem constraintsSystem) { - return new InferenceErrorData(descriptor, constraintsSystem, null, null); + return new InferenceErrorData(descriptor, constraintsSystem, null, null, null); } } diff --git a/compiler/testData/diagnostics/tests/inference/typeInferenceExpectedTypeMismatch.kt b/compiler/testData/diagnostics/tests/inference/typeInferenceExpectedTypeMismatch.kt new file mode 100644 index 00000000000..29ceac5cdec --- /dev/null +++ b/compiler/testData/diagnostics/tests/inference/typeInferenceExpectedTypeMismatch.kt @@ -0,0 +1,11 @@ +package typeInferenceExpectedTypeMismatch + +import java.util.* + +fun test() { + val s : Set = newList() +} + +fun newList() : ArrayList { + return ArrayList() +} diff --git a/idea/src/org/jetbrains/jet/plugin/highlighter/HtmlTabledDescriptorRenderer.java b/idea/src/org/jetbrains/jet/plugin/highlighter/HtmlTabledDescriptorRenderer.java index 4a894816d30..9278ed3bd62 100644 --- a/idea/src/org/jetbrains/jet/plugin/highlighter/HtmlTabledDescriptorRenderer.java +++ b/idea/src/org/jetbrains/jet/plugin/highlighter/HtmlTabledDescriptorRenderer.java @@ -23,9 +23,7 @@ import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.diagnostics.rendering.TabledDescriptorRenderer; -import org.jetbrains.jet.lang.diagnostics.rendering.TabledDescriptorRenderer.TableRenderer.DescriptorRow; -import org.jetbrains.jet.lang.diagnostics.rendering.TabledDescriptorRenderer.TableRenderer.FunctionArgumentsRow; -import org.jetbrains.jet.lang.diagnostics.rendering.TabledDescriptorRenderer.TableRenderer.TableRow; +import org.jetbrains.jet.lang.diagnostics.rendering.TabledDescriptorRenderer.TableRenderer.*; import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.resolve.DescriptorRenderer; @@ -33,6 +31,7 @@ import org.jetbrains.jet.resolve.DescriptorRenderer; import java.util.Iterator; import java.util.List; +import static org.jetbrains.jet.plugin.highlighter.IdeRenderers.HTML_RENDER_TYPE; import static org.jetbrains.jet.plugin.highlighter.IdeRenderers.error; import static org.jetbrains.jet.plugin.highlighter.IdeRenderers.strong; @@ -41,21 +40,26 @@ import static org.jetbrains.jet.plugin.highlighter.IdeRenderers.strong; */ public class HtmlTabledDescriptorRenderer extends TabledDescriptorRenderer { + @Override protected void renderText(TextRenderer textRenderer, StringBuilder result) { for (TextRenderer.TextElement element : textRenderer.elements) { - if (element.type == TextRenderer.TextElementType.DEFAULT) { - result.append(element.text); - } - else if (element.type == TextRenderer.TextElementType.ERROR) { - result.append(error(element.text)); - } - else if (element.type == TextRenderer.TextElementType.STRONG) { - result.append(strong(element.text)); - } + renderText(result, element.type, element.text); } } - private int countRowsNumber(TableRenderer table) { + private static void renderText(StringBuilder result, TextElementType elementType, String text) { + if (elementType == TextElementType.DEFAULT) { + result.append(text); + } + else if (elementType == TextElementType.ERROR) { + result.append(error(text)); + } + else if (elementType == TextElementType.STRONG) { + result.append(strong(text)); + } + } + + private int countColumnNumber(TableRenderer table) { int argumentsNumber = 0; for (TableRow row : table.rows) { if (row instanceof DescriptorRow) { @@ -79,7 +83,7 @@ public class HtmlTabledDescriptorRenderer extends TabledDescriptorRenderer { @Override protected void renderTable(TableRenderer table, StringBuilder result) { if (table.rows.isEmpty()) return; - int rowsNumber = countRowsNumber(table); + int rowsNumber = countColumnNumber(table); result.append(""); @@ -221,4 +225,15 @@ public class HtmlTabledDescriptorRenderer extends TabledDescriptorRenderer { private static void tdRightBoldColspan(StringBuilder builder, int colspan, String text) { builder.append(""); } + + public static String tableForTypes(String message, String firstDescription, TextElementType firstType, String secondDescription, TextElementType secondType) { + StringBuilder result = new StringBuilder(); + result.append("").append(message); + result.append("
").append(text).append("
").append(firstDescription).append(""); + renderText(result, firstType, "{0}"); + result.append("
").append(secondDescription).append(""); + renderText(result, secondType, "{1}"); + result.append("
"); + return result.toString(); + } } diff --git a/idea/src/org/jetbrains/jet/plugin/highlighter/IdeErrorMessages.java b/idea/src/org/jetbrains/jet/plugin/highlighter/IdeErrorMessages.java index c38fe48838f..891243cb660 100644 --- a/idea/src/org/jetbrains/jet/plugin/highlighter/IdeErrorMessages.java +++ b/idea/src/org/jetbrains/jet/plugin/highlighter/IdeErrorMessages.java @@ -25,8 +25,11 @@ import org.jetbrains.jet.resolve.DescriptorRenderer; import static org.jetbrains.jet.lang.diagnostics.Errors.*; import static org.jetbrains.jet.lang.diagnostics.rendering.Renderers.RENDER_CLASS_OR_OBJECT; import static org.jetbrains.jet.lang.diagnostics.rendering.Renderers.TO_STRING; +import static org.jetbrains.jet.lang.diagnostics.rendering.TabledDescriptorRenderer.TextElementType; +import static org.jetbrains.jet.plugin.highlighter.HtmlTabledDescriptorRenderer.tableForTypes; import static org.jetbrains.jet.plugin.highlighter.IdeRenderers.*; + /** * @see DefaultErrorMessages * @@ -47,6 +50,9 @@ public class IdeErrorMessages { MAP.put(TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS, "Type inference failed: {0}", HTML_TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS_RENDERER); MAP.put(TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER, "Type inference failed: {0}", HTML_TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER_RENDERER); MAP.put(TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH, "Type inference failed: {0}", HTML_TYPE_INFERENCE_TYPE_CONSTRUCTOR_MISMATCH_RENDERER); + MAP.put(TYPE_INFERENCE_EXPECTED_TYPE_MISMATCH, tableForTypes("Type inference failed. Expected type mismatch: ", + "found: ", TextElementType.ERROR, + "required: ", TextElementType.STRONG), HTML_RENDER_TYPE, HTML_RENDER_TYPE); MAP.put(TYPE_INFERENCE_UPPER_BOUND_VIOLATED, "{0}", HTML_TYPE_INFERENCE_UPPER_BOUND_VIOLATED_RENDERER); MAP.put(WRONG_SETTER_PARAMETER_TYPE, "Setter parameter type must be equal to the type of the property." +