Fix typechecker when initializer of destructuring declaration is unresolved or missing

This commit is contained in:
Pavel V. Talanov
2016-02-03 18:10:42 +03:00
parent a4e3dd7030
commit 7c84225cc4
7 changed files with 77 additions and 15 deletions
@@ -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()
}
@@ -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
@@ -0,0 +1,11 @@
fun useDeclaredVariables() {
val (a, b) = <!UNRESOLVED_REFERENCE!>unresolved<!>
<!UNUSED_EXPRESSION, DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>a<!>
<!UNUSED_EXPRESSION, DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>b<!>
}
fun checkersShouldRun() {
val (@A <!UNUSED_VARIABLE!>a<!>, <!UNDERSCORE_IS_RESERVED, UNUSED_VARIABLE!>_<!>) = <!UNRESOLVED_REFERENCE!>unresolved<!>
}
annotation class A
@@ -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
}
@@ -0,0 +1,11 @@
fun useDeclaredVariables() {
<!INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION!>val (a, b)<!>
<!UNUSED_EXPRESSION, DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>a<!>
<!UNUSED_EXPRESSION, DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>b<!>
}
fun checkersShouldRun() {
<!INITIALIZER_REQUIRED_FOR_DESTRUCTURING_DECLARATION!>val (@A <!UNUSED_VARIABLE!>a<!>, <!UNDERSCORE_IS_RESERVED, UNUSED_VARIABLE!>_<!>)<!>
}
annotation class A
@@ -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
}
@@ -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");