From ecd1c17e477c435259ff7adf8719a4cb1e0522b8 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 17 Aug 2012 21:13:28 +0400 Subject: [PATCH] Report type mismatch for component functions --- .../jet/lang/diagnostics/Errors.java | 2 ++ .../rendering/DefaultErrorMessages.java | 5 +++- .../ExpressionTypingVisitorForStatements.java | 27 ++++++++++++++++--- .../ComponentFunctionReturnTypeMismatch.kt | 8 ++++++ .../checkers/JetDiagnosticsTestGenerated.java | 5 ++++ 5 files changed, 43 insertions(+), 4 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/declarationChecks/ComponentFunctionReturnTypeMismatch.kt 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 2492d55659d..bf7e522bb69 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -100,9 +100,11 @@ public interface Errors { SimpleDiagnosticFactory MANY_FUNCTION_LITERAL_ARGUMENTS = SimpleDiagnosticFactory.create(ERROR); SimpleDiagnosticFactory PROPERTY_WITH_NO_TYPE_NO_INITIALIZER = SimpleDiagnosticFactory.create(ERROR, NAMED_ELEMENT); SimpleDiagnosticFactory VARIABLE_WITH_NO_TYPE_NO_INITIALIZER = SimpleDiagnosticFactory.create(ERROR, NAME_IDENTIFIER); + SimpleDiagnosticFactory INITIALIZER_REQUIRED_FOR_MULTIDECLARATION = SimpleDiagnosticFactory.create(ERROR, DEFAULT); DiagnosticFactory1 COMPONENT_FUNCTION_MISSING = DiagnosticFactory1.create(ERROR, DEFAULT); DiagnosticFactory2>> COMPONENT_FUNCTION_AMBIGUITY = DiagnosticFactory2.create(ERROR, DEFAULT); + DiagnosticFactory3 COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH = DiagnosticFactory3.create(ERROR, DEFAULT); SimpleDiagnosticFactory ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS = SimpleDiagnosticFactory.create(ERROR, ABSTRACT_MODIFIER); SimpleDiagnosticFactory ABSTRACT_PROPERTY_NOT_IN_CLASS = SimpleDiagnosticFactory.create(ERROR, ABSTRACT_MODIFIER); 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 0342399931e..12779c502fa 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 @@ -113,9 +113,12 @@ public class DefaultErrorMessages { MAP.put(MANY_FUNCTION_LITERAL_ARGUMENTS, "Only one function literal is allowed outside a parenthesized argument list"); MAP.put(PROPERTY_WITH_NO_TYPE_NO_INITIALIZER, "This property must either have a type annotation or be initialized"); MAP.put(VARIABLE_WITH_NO_TYPE_NO_INITIALIZER, "This variable must either have a type annotation or be initialized"); + MAP.put(INITIALIZER_REQUIRED_FOR_MULTIDECLARATION, "Initializer required for multi-declaration"); MAP.put(COMPONENT_FUNCTION_MISSING, "Multi-declaration initializer must have a ''{0}()'' function", TO_STRING); - MAP.put(COMPONENT_FUNCTION_AMBIGUITY, "Method ''{0}'' is ambiguous for this expression: {1}", TO_STRING, AMBIGUOUS_CALLS); + MAP.put(COMPONENT_FUNCTION_AMBIGUITY, "Function ''{0}()'' is ambiguous for this expression: {1}", TO_STRING, AMBIGUOUS_CALLS); + MAP.put(COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH, "''{0}()'' function returns ''{1}'', but ''{2}'' is expected", + TO_STRING, RENDER_TYPE, RENDER_TYPE); MAP.put(ABSTRACT_PROPERTY_IN_PRIMARY_CONSTRUCTOR_PARAMETERS, "This property cannot be declared abstract"); MAP.put(ABSTRACT_PROPERTY_NOT_IN_CLASS, "A property may be abstract only when defined in a class or trait"); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java index 1e3b0b0d27e..2a32e2f6e96 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingVisitorForStatements.java @@ -34,6 +34,7 @@ import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.types.ErrorUtils; import org.jetbrains.jet.lang.types.JetTypeInfo; +import org.jetbrains.jet.lang.types.checker.JetTypeChecker; import org.jetbrains.jet.lang.types.lang.JetStandardClasses; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.TypeUtils; @@ -144,11 +145,20 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito final Name componentName = Name.identifier("component" + componentIndex); componentIndex++; - JetType componentType = null; + JetType expectedType = getExpectedTypeForComponent(context, entry); OverloadResolutionResults results = - ExpressionTypingUtils.resolveFakeCall(expressionReceiver, context, componentName); + ExpressionTypingUtils.resolveFakeCall(expressionReceiver, context.replaceExpectedType(expectedType), componentName); + + JetType componentType = null; if (results.isSuccess()) { - componentType = results.getResultingDescriptor().getReturnType(); + FunctionDescriptor resultingDescriptor = results.getResultingDescriptor(); + componentType = resultingDescriptor.getReturnType(); + if (componentType != null && expectedType != TypeUtils.NO_EXPECTED_TYPE + && !JetTypeChecker.INSTANCE.isSubtypeOf(componentType, expectedType)) { + + context.trace.report( + COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH.on(initializer, componentName, componentType, expectedType)); + } } else if (results.isAmbiguity()) { context.trace.report(COMPONENT_FUNCTION_AMBIGUITY.on(initializer, componentName, results.getResultingCalls())); @@ -167,6 +177,17 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito return DataFlowUtils.checkStatementType(multiDeclaration, context, context.dataFlowInfo); } + @NotNull + private static JetType getExpectedTypeForComponent(ExpressionTypingContext context, JetMultiDeclarationEntry entry) { + JetTypeReference entryTypeRef = entry.getTypeRef(); + if (entryTypeRef != null) { + return context.expressionTypingServices.getTypeResolver().resolveType(context.scope, entryTypeRef, context.trace, true); + } + else { + return TypeUtils.NO_EXPECTED_TYPE; + } + } + @Override public JetTypeInfo visitNamedFunction(JetNamedFunction function, ExpressionTypingContext context) { SimpleFunctionDescriptor functionDescriptor = context.expressionTypingServices.getDescriptorResolver().resolveFunctionDescriptor(scope.getContainingDeclaration(), scope, function, context.trace); diff --git a/compiler/testData/diagnostics/tests/declarationChecks/ComponentFunctionReturnTypeMismatch.kt b/compiler/testData/diagnostics/tests/declarationChecks/ComponentFunctionReturnTypeMismatch.kt new file mode 100644 index 00000000000..f7b8352d99c --- /dev/null +++ b/compiler/testData/diagnostics/tests/declarationChecks/ComponentFunctionReturnTypeMismatch.kt @@ -0,0 +1,8 @@ +class A { + fun component1() : Int = 1 + fun component2() : Int = 2 +} + +fun a(aa : A) { + val (a: String, b1: String) = aa +} \ 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 ec5b8be83ea..cc534d0bf54 100644 --- a/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/checkers/JetDiagnosticsTestGenerated.java @@ -1053,6 +1053,11 @@ public class JetDiagnosticsTestGenerated extends AbstractDiagnosticsTestWithEage JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.checkers.AbstractDiagnosticsTestWithEagerResolve", new File("compiler/testData/diagnostics/tests/declarationChecks"), "kt", false); } + @TestMetadata("ComponentFunctionReturnTypeMismatch.kt") + public void testComponentFunctionReturnTypeMismatch() throws Exception { + doTest("compiler/testData/diagnostics/tests/declarationChecks/ComponentFunctionReturnTypeMismatch.kt"); + } + @TestMetadata("DataFlowInfoInMultiDecl.kt") public void testDataFlowInfoInMultiDecl() throws Exception { doTest("compiler/testData/diagnostics/tests/declarationChecks/DataFlowInfoInMultiDecl.kt");