From 7c84225cc4c2bc009a718bfd6387b62b6031944e Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Wed, 3 Feb 2016 18:10:42 +0300 Subject: [PATCH] Fix typechecker when initializer of destructuring declaration is unresolved or missing --- .../DestructuringDeclarationResolver.kt | 16 ++++++++------- .../ExpressionTypingVisitorForStatements.java | 20 +++++++++++-------- .../multiDeclarationAssignedUnresolved.kt | 11 ++++++++++ .../multiDeclarationAssignedUnresolved.txt | 11 ++++++++++ .../multiDeclarationMissingInitializer.kt | 11 ++++++++++ .../multiDeclarationMissingInitializer.txt | 11 ++++++++++ .../checkers/DiagnosticsTestGenerated.java | 12 +++++++++++ 7 files changed, 77 insertions(+), 15 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations/multiDeclarationAssignedUnresolved.kt create mode 100644 compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations/multiDeclarationAssignedUnresolved.txt create mode 100644 compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations/multiDeclarationMissingInitializer.kt create mode 100644 compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations/multiDeclarationMissingInitializer.txt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DestructuringDeclarationResolver.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DestructuringDeclarationResolver.kt index faa3355bd4f..c2af63878b2 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DestructuringDeclarationResolver.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/DestructuringDeclarationResolver.kt @@ -42,14 +42,14 @@ class DestructuringDeclarationResolver( fun defineLocalVariablesFromMultiDeclaration( writableScope: LexicalWritableScope, destructuringDeclaration: KtDestructuringDeclaration, - receiver: ReceiverValue, - reportErrorsOn: KtExpression, + receiver: ReceiverValue?, + initializer: KtExpression?, context: ExpressionTypingContext ) { for ((componentIndex, entry) in destructuringDeclaration.entries.withIndex()) { val componentName = createComponentName(componentIndex + 1) - val componentType = resolveComponentFunctionAndGetType(componentName, context, entry, receiver, reportErrorsOn) + val componentType = resolveComponentFunctionAndGetType(componentName, context, entry, receiver, initializer) val variableDescriptor = localVariableResolver.resolveLocalVariableDescriptorWithType(writableScope, entry, componentType, context.trace) ExpressionTypingUtils.checkVariableShadowing(writableScope, context.trace, variableDescriptor) @@ -62,15 +62,17 @@ class DestructuringDeclarationResolver( componentName: Name, context: ExpressionTypingContext, entry: KtDestructuringDeclarationEntry, - receiver: ReceiverValue, - reportErrorsOn: KtExpression + receiver: ReceiverValue?, + initializer: KtExpression? ): KotlinType { fun errorType() = ErrorUtils.createErrorType("$componentName() return type") + if (receiver == null || initializer == null) return errorType() + val expectedType = getExpectedTypeForComponent(context, entry) val results = fakeCallResolver.resolveFakeCall( context.replaceExpectedType(expectedType), receiver, componentName, - entry, reportErrorsOn, FakeCallKind.COMPONENT + entry, initializer, FakeCallKind.COMPONENT ) if (!results.isSuccess) { @@ -85,7 +87,7 @@ class DestructuringDeclarationResolver( val functionReturnType = functionDescriptor.returnType if (functionReturnType != null && !TypeUtils.noExpectedType(expectedType) && !KotlinTypeChecker.DEFAULT.isSubtypeOf(functionReturnType, expectedType) ) { - context.trace.report(Errors.COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH.on(reportErrorsOn, componentName, functionReturnType, expectedType)) + context.trace.report(Errors.COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH.on(initializer, componentName, functionReturnType, expectedType)) } return functionReturnType ?: errorType() } diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java index 51c9c4baa4c..6a33c7b8c97 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/ExpressionTypingVisitorForStatements.java @@ -117,19 +117,23 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito KtExpression initializer = multiDeclaration.getInitializer(); if (initializer == null) { context.trace.report(INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION.on(multiDeclaration)); - return TypeInfoFactoryKt.noTypeInfo(context); - } - ExpressionReceiver expressionReceiver = ExpressionTypingUtils.getExpressionReceiver( - facade, initializer, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT)); - KotlinTypeInfo typeInfo = facade.getTypeInfo(initializer, context); - if (expressionReceiver == null) { - return TypeInfoFactoryKt.noTypeInfo(context); } + + ExpressionReceiver expressionReceiver = initializer != null ? ExpressionTypingUtils.getExpressionReceiver( + facade, initializer, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT)) : null; + components.destructuringDeclarationResolver .defineLocalVariablesFromMultiDeclaration(scope, multiDeclaration, expressionReceiver, initializer, context); components.modifiersChecker.withTrace(context.trace).checkModifiersForDestructuringDeclaration(multiDeclaration); components.identifierChecker.checkDeclaration(multiDeclaration, context.trace); - return typeInfo.replaceType(components.dataFlowAnalyzer.checkStatementType(multiDeclaration, context)); + + if (expressionReceiver == null) { + return TypeInfoFactoryKt.noTypeInfo(context); + } + else { + return facade.getTypeInfo(initializer, context) + .replaceType(components.dataFlowAnalyzer.checkStatementType(multiDeclaration, context)); + } } @Override diff --git a/compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations/multiDeclarationAssignedUnresolved.kt b/compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations/multiDeclarationAssignedUnresolved.kt new file mode 100644 index 00000000000..c3b3499591f --- /dev/null +++ b/compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations/multiDeclarationAssignedUnresolved.kt @@ -0,0 +1,11 @@ +fun useDeclaredVariables() { + val (a, b) = unresolved + a + b +} + +fun checkersShouldRun() { + val (@A a, _) = unresolved +} + +annotation class A \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations/multiDeclarationAssignedUnresolved.txt b/compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations/multiDeclarationAssignedUnresolved.txt new file mode 100644 index 00000000000..761c8c75dce --- /dev/null +++ b/compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations/multiDeclarationAssignedUnresolved.txt @@ -0,0 +1,11 @@ +package + +public fun checkersShouldRun(): kotlin.Unit +public fun useDeclaredVariables(): kotlin.Unit + +public final annotation class A : kotlin.Annotation { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations/multiDeclarationMissingInitializer.kt b/compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations/multiDeclarationMissingInitializer.kt new file mode 100644 index 00000000000..cd0a8756aee --- /dev/null +++ b/compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations/multiDeclarationMissingInitializer.kt @@ -0,0 +1,11 @@ +fun useDeclaredVariables() { + val (a, b) + a + b +} + +fun checkersShouldRun() { + val (@A a, _) +} + +annotation class A \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations/multiDeclarationMissingInitializer.txt b/compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations/multiDeclarationMissingInitializer.txt new file mode 100644 index 00000000000..761c8c75dce --- /dev/null +++ b/compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations/multiDeclarationMissingInitializer.txt @@ -0,0 +1,11 @@ +package + +public fun checkersShouldRun(): kotlin.Unit +public fun useDeclaredVariables(): kotlin.Unit + +public final annotation class A : kotlin.Annotation { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java index 77f52d18456..b22f7a19bd0 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/DiagnosticsTestGenerated.java @@ -4463,6 +4463,18 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest { doTest(fileName); } + @TestMetadata("multiDeclarationAssignedUnresolved.kt") + public void testMultiDeclarationAssignedUnresolved() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations/multiDeclarationAssignedUnresolved.kt"); + doTest(fileName); + } + + @TestMetadata("multiDeclarationMissingInitializer.kt") + public void testMultiDeclarationMissingInitializer() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations/multiDeclarationMissingInitializer.kt"); + doTest(fileName); + } + @TestMetadata("RedeclarationInForLoop.kt") public void testRedeclarationInForLoop() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/declarationChecks/multiDeclarations/RedeclarationInForLoop.kt");