Implement resolution of desctructuring declarations in lambdas

#KT-5828 In Progress
This commit is contained in:
Denis Zharkov
2016-09-15 17:56:59 +03:00
parent ace3655824
commit e975d32196
27 changed files with 640 additions and 37 deletions
@@ -26,6 +26,7 @@ import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.KtNodeTypes;
import org.jetbrains.kotlin.lexer.KtTokens; import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.psi.stubs.KotlinParameterStub; import org.jetbrains.kotlin.psi.stubs.KotlinParameterStub;
import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes; import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementTypes;
@@ -120,6 +121,14 @@ public class KtParameter extends KtNamedDeclarationStub<KotlinParameterStub> imp
return findChildByType(VAL_VAR_TOKEN_SET); return findChildByType(VAL_VAR_TOKEN_SET);
} }
@Nullable
public KtDestructuringDeclaration getDestructuringDeclaration() {
// No destructuring declaration in stubs
if (getStub() != null) return null;
return findChildByType(KtNodeTypes.DESTRUCTURING_DECLARATION);
}
private static final TokenSet VAL_VAR_TOKEN_SET = TokenSet.create(KtTokens.VAL_KEYWORD, KtTokens.VAR_KEYWORD); private static final TokenSet VAL_VAR_TOKEN_SET = TokenSet.create(KtTokens.VAL_KEYWORD, KtTokens.VAR_KEYWORD);
@Override @Override
@@ -49,14 +49,13 @@ import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfoFactory;
import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil; import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyTypeAliasDescriptor; import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyTypeAliasDescriptor;
import org.jetbrains.kotlin.resolve.scopes.*; import org.jetbrains.kotlin.resolve.scopes.*;
import org.jetbrains.kotlin.resolve.scopes.receivers.TransientReceiver;
import org.jetbrains.kotlin.resolve.scopes.utils.ScopeUtilsKt; import org.jetbrains.kotlin.resolve.scopes.utils.ScopeUtilsKt;
import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt; import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
import org.jetbrains.kotlin.storage.StorageManager; import org.jetbrains.kotlin.storage.StorageManager;
import org.jetbrains.kotlin.types.*; import org.jetbrains.kotlin.types.*;
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker; import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices; import org.jetbrains.kotlin.types.expressions.*;
import org.jetbrains.kotlin.types.expressions.FunctionsTypingVisitor;
import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor;
import java.util.*; import java.util.*;
@@ -79,6 +78,7 @@ public class DescriptorResolver {
private final OverloadChecker overloadChecker; private final OverloadChecker overloadChecker;
private final LanguageVersionSettings languageVersionSettings; private final LanguageVersionSettings languageVersionSettings;
private final FunctionsTypingVisitor functionsTypingVisitor; private final FunctionsTypingVisitor functionsTypingVisitor;
private final DestructuringDeclarationResolver destructuringDeclarationResolver;
public DescriptorResolver( public DescriptorResolver(
@NotNull AnnotationResolver annotationResolver, @NotNull AnnotationResolver annotationResolver,
@@ -90,7 +90,8 @@ public class DescriptorResolver {
@NotNull ExpressionTypingServices expressionTypingServices, @NotNull ExpressionTypingServices expressionTypingServices,
@NotNull OverloadChecker overloadChecker, @NotNull OverloadChecker overloadChecker,
@NotNull LanguageVersionSettings languageVersionSettings, @NotNull LanguageVersionSettings languageVersionSettings,
@NotNull FunctionsTypingVisitor functionsTypingVisitor @NotNull FunctionsTypingVisitor functionsTypingVisitor,
@NotNull DestructuringDeclarationResolver destructuringDeclarationResolver
) { ) {
this.annotationResolver = annotationResolver; this.annotationResolver = annotationResolver;
this.builtIns = builtIns; this.builtIns = builtIns;
@@ -102,6 +103,7 @@ public class DescriptorResolver {
this.overloadChecker = overloadChecker; this.overloadChecker = overloadChecker;
this.languageVersionSettings = languageVersionSettings; this.languageVersionSettings = languageVersionSettings;
this.functionsTypingVisitor = functionsTypingVisitor; this.functionsTypingVisitor = functionsTypingVisitor;
this.destructuringDeclarationResolver = destructuringDeclarationResolver;
} }
public List<KotlinType> resolveSupertypes( public List<KotlinType> resolveSupertypes(
@@ -285,19 +287,35 @@ public class DescriptorResolver {
} }
} }
ValueParameterDescriptorImpl valueParameterDescriptor = new ValueParameterDescriptorImpl( KtDestructuringDeclaration destructuringDeclaration = valueParameter.getDestructuringDeclaration();
List<VariableDescriptor> destructuringVariables;
if (destructuringDeclaration != null) {
destructuringVariables = destructuringDeclarationResolver.resolveLocalVariablesFromDestructuringDeclaration(
scope, destructuringDeclaration, new TransientReceiver(type), /* initializer = */ null,
ExpressionTypingContext.newContext(trace, scope, DataFlowInfoFactory.EMPTY, TypeUtils.NO_EXPECTED_TYPE)
);
}
else {
destructuringVariables = null;
}
ValueParameterDescriptorImpl valueParameterDescriptor = ValueParameterDescriptorImpl.createWithDestructuringDeclarations(
owner, owner,
null, null,
index, index,
valueParameterAnnotations, valueParameterAnnotations,
KtPsiUtil.safeName(valueParameter.getName()), destructuringVariables == null
? KtPsiUtil.safeName(valueParameter.getName())
: Name.special("<name for destructuring parameter " + index + ">"),
variableType, variableType,
valueParameter.hasDefaultValue(), valueParameter.hasDefaultValue(),
valueParameter.hasModifier(CROSSINLINE_KEYWORD), valueParameter.hasModifier(CROSSINLINE_KEYWORD),
valueParameter.hasModifier(NOINLINE_KEYWORD), valueParameter.hasModifier(NOINLINE_KEYWORD),
valueParameter.hasModifier(COROUTINE_KEYWORD), valueParameter.hasModifier(COROUTINE_KEYWORD),
varargElementType, varargElementType,
KotlinSourceElementKt.toSourceElement(valueParameter) KotlinSourceElementKt.toSourceElement(valueParameter),
destructuringVariables
); );
trace.record(BindingContext.VALUE_PARAMETER, valueParameter, valueParameterDescriptor); trace.record(BindingContext.VALUE_PARAMETER, valueParameter, valueParameterDescriptor);
@@ -22,6 +22,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor; import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor;
import org.jetbrains.kotlin.descriptors.impl.ReceiverParameterDescriptorImpl; import org.jetbrains.kotlin.descriptors.impl.ReceiverParameterDescriptorImpl;
import org.jetbrains.kotlin.descriptors.impl.ValueParameterDescriptorImpl;
import org.jetbrains.kotlin.resolve.coroutine.CoroutineReceiverValue; import org.jetbrains.kotlin.resolve.coroutine.CoroutineReceiverValue;
import org.jetbrains.kotlin.resolve.scopes.*; import org.jetbrains.kotlin.resolve.scopes.*;
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver; import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver;
@@ -89,7 +90,17 @@ public class FunctionDescriptorUtil {
handler.addClassifierDescriptor(typeParameter); handler.addClassifierDescriptor(typeParameter);
} }
for (ValueParameterDescriptor valueParameterDescriptor : descriptor.getValueParameters()) { for (ValueParameterDescriptor valueParameterDescriptor : descriptor.getValueParameters()) {
handler.addVariableDescriptor(valueParameterDescriptor); if (valueParameterDescriptor instanceof ValueParameterDescriptorImpl.WithDestructuringDeclaration) {
List<VariableDescriptor> entries =
((ValueParameterDescriptorImpl.WithDestructuringDeclaration) valueParameterDescriptor)
.getDestructuringVariables();
for (VariableDescriptor entry : entries) {
handler.addVariableDescriptor(entry);
}
}
else {
handler.addVariableDescriptor(valueParameterDescriptor);
}
} }
return Unit.INSTANCE; return Unit.INSTANCE;
} }
@@ -412,7 +412,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
KotlinType elementType = expectedParameterType == null ? ErrorUtils.createErrorType("Loop range has no type") : expectedParameterType; KotlinType elementType = expectedParameterType == null ? ErrorUtils.createErrorType("Loop range has no type") : expectedParameterType;
TransientReceiver iteratorNextAsReceiver = new TransientReceiver(elementType); TransientReceiver iteratorNextAsReceiver = new TransientReceiver(elementType);
components.annotationResolver.resolveAnnotationsWithArguments(loopScope, multiParameter.getModifierList(), context.trace); components.annotationResolver.resolveAnnotationsWithArguments(loopScope, multiParameter.getModifierList(), context.trace);
components.destructuringDeclarationResolver.defineLocalVariablesFromMultiDeclaration( components.destructuringDeclarationResolver.defineLocalVariablesFromDestructuringDeclaration(
loopScope, multiParameter, iteratorNextAsReceiver, loopRange, context loopScope, multiParameter, iteratorNextAsReceiver, loopRange, context
); );
components.modifiersChecker.withTrace(context.trace).checkModifiersForDestructuringDeclaration(multiParameter); components.modifiersChecker.withTrace(context.trace).checkModifiersForDestructuringDeclaration(multiParameter);
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.types.expressions package org.jetbrains.kotlin.types.expressions
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.KtDestructuringDeclaration import org.jetbrains.kotlin.psi.KtDestructuringDeclaration
@@ -25,6 +26,7 @@ import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.DataClassDescriptorResolver import org.jetbrains.kotlin.resolve.DataClassDescriptorResolver
import org.jetbrains.kotlin.resolve.LocalVariableResolver import org.jetbrains.kotlin.resolve.LocalVariableResolver
import org.jetbrains.kotlin.resolve.TypeResolver import org.jetbrains.kotlin.resolve.TypeResolver
import org.jetbrains.kotlin.resolve.scopes.LexicalScope
import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue
import org.jetbrains.kotlin.types.ErrorUtils import org.jetbrains.kotlin.types.ErrorUtils
@@ -37,23 +39,37 @@ class DestructuringDeclarationResolver(
private val localVariableResolver: LocalVariableResolver, private val localVariableResolver: LocalVariableResolver,
private val typeResolver: TypeResolver private val typeResolver: TypeResolver
) { ) {
fun defineLocalVariablesFromMultiDeclaration( fun resolveLocalVariablesFromDestructuringDeclaration(
scope: LexicalScope,
destructuringDeclaration: KtDestructuringDeclaration,
receiver: ReceiverValue?,
initializer: KtExpression?,
context: ExpressionTypingContext
): List<VariableDescriptor> {
val result = arrayListOf<VariableDescriptor>()
for ((componentIndex, entry) in destructuringDeclaration.entries.withIndex()) {
val componentName = DataClassDescriptorResolver.createComponentName(componentIndex + 1)
val componentType = resolveComponentFunctionAndGetType(componentName, context, entry, receiver, initializer)
val variableDescriptor = localVariableResolver.resolveLocalVariableDescriptorWithType(scope, entry, componentType, context.trace)
result.add(variableDescriptor)
}
return result
}
fun defineLocalVariablesFromDestructuringDeclaration(
writableScope: LexicalWritableScope, writableScope: LexicalWritableScope,
destructuringDeclaration: KtDestructuringDeclaration, destructuringDeclaration: KtDestructuringDeclaration,
receiver: ReceiverValue?, receiver: ReceiverValue?,
initializer: KtExpression?, initializer: KtExpression?,
context: ExpressionTypingContext context: ExpressionTypingContext
) { ) = resolveLocalVariablesFromDestructuringDeclaration(
for ((componentIndex, entry) in destructuringDeclaration.entries.withIndex()) { writableScope, destructuringDeclaration, receiver, initializer, context
val componentName = DataClassDescriptorResolver.createComponentName(componentIndex + 1) ).forEach {
ExpressionTypingUtils.checkVariableShadowing(writableScope, context.trace, it)
val componentType = resolveComponentFunctionAndGetType(componentName, context, entry, receiver, initializer) writableScope.addVariableDescriptor(it)
val variableDescriptor = localVariableResolver.resolveLocalVariableDescriptorWithType(writableScope, entry, componentType, context.trace)
ExpressionTypingUtils.checkVariableShadowing(writableScope, context.trace, variableDescriptor)
writableScope.addVariableDescriptor(variableDescriptor)
}
} }
private fun resolveComponentFunctionAndGetType( private fun resolveComponentFunctionAndGetType(
@@ -65,12 +81,12 @@ class DestructuringDeclarationResolver(
): KotlinType { ): KotlinType {
fun errorType() = ErrorUtils.createErrorType("$componentName() return type") fun errorType() = ErrorUtils.createErrorType("$componentName() return type")
if (receiver == null || initializer == null) return errorType() if (receiver == null) return errorType()
val expectedType = getExpectedTypeForComponent(context, entry) val expectedType = getExpectedTypeForComponent(context, entry)
val results = fakeCallResolver.resolveFakeCall( val results = fakeCallResolver.resolveFakeCall(
context.replaceExpectedType(expectedType), receiver, componentName, context.replaceExpectedType(expectedType), receiver, componentName,
entry, initializer, FakeCallKind.COMPONENT, emptyList() entry, initializer ?: entry, FakeCallKind.COMPONENT, emptyList()
) )
if (!results.isSuccess) { if (!results.isSuccess) {
@@ -82,7 +98,9 @@ class DestructuringDeclarationResolver(
val functionReturnType = results.resultingDescriptor.returnType val functionReturnType = results.resultingDescriptor.returnType
if (functionReturnType != null && !TypeUtils.noExpectedType(expectedType) if (functionReturnType != null && !TypeUtils.noExpectedType(expectedType)
&& !KotlinTypeChecker.DEFAULT.isSubtypeOf(functionReturnType, expectedType) ) { && !KotlinTypeChecker.DEFAULT.isSubtypeOf(functionReturnType, expectedType) ) {
context.trace.report(Errors.COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH.on(initializer, componentName, functionReturnType, expectedType)) context.trace.report(
Errors.COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH.on(
initializer ?: entry, componentName, functionReturnType, expectedType))
} }
return functionReturnType ?: errorType() return functionReturnType ?: errorType()
} }
@@ -112,6 +112,12 @@ public class ExpressionTypingUtils {
if (oldDescriptor != null && isLocal(variableDescriptor.getContainingDeclaration(), oldDescriptor)) { if (oldDescriptor != null && isLocal(variableDescriptor.getContainingDeclaration(), oldDescriptor)) {
PsiElement declaration = DescriptorToSourceUtils.descriptorToDeclaration(variableDescriptor); PsiElement declaration = DescriptorToSourceUtils.descriptorToDeclaration(variableDescriptor);
if (declaration != null) { if (declaration != null) {
if (declaration instanceof KtDestructuringDeclarationEntry && declaration.getParent().getParent() instanceof KtParameter) {
// foo { a, (a, b) -> } -- do not report NAME_SHADOWING on the second 'a', because REDECLARATION must be reported here
PsiElement oldElement = DescriptorToSourceUtils.descriptorToDeclaration(oldDescriptor);
if (oldElement != null && oldElement.getParent().equals(declaration.getParent().getParent().getParent())) return;
}
trace.report(Errors.NAME_SHADOWING.on(declaration, variableDescriptor.getName().asString())); trace.report(Errors.NAME_SHADOWING.on(declaration, variableDescriptor.getName().asString()));
} }
} }
@@ -134,7 +134,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
facade, initializer, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT)) : null; facade, initializer, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT)) : null;
components.destructuringDeclarationResolver components.destructuringDeclarationResolver
.defineLocalVariablesFromMultiDeclaration(scope, multiDeclaration, expressionReceiver, initializer, context); .defineLocalVariablesFromDestructuringDeclaration(scope, multiDeclaration, expressionReceiver, initializer, context);
components.modifiersChecker.withTrace(context.trace).checkModifiersForDestructuringDeclaration(multiDeclaration); components.modifiersChecker.withTrace(context.trace).checkModifiersForDestructuringDeclaration(multiDeclaration);
components.identifierChecker.checkDeclaration(multiDeclaration, context.trace); components.identifierChecker.checkDeclaration(multiDeclaration, context.trace);
@@ -4,13 +4,13 @@ val receiverWithParameter = { Int.<!ILLEGAL_SELECTOR!>(<!UNRESOLVED_REFERENCE!>a
val receiverAndReturnType = { Int.(<!SYNTAX!><!>)<!SYNTAX!>: Int -> 5<!> } val receiverAndReturnType = { Int.(<!SYNTAX!><!>)<!SYNTAX!>: Int -> 5<!> }
val receiverAndReturnTypeWithParameter = { Int.(<!UNRESOLVED_REFERENCE!>a<!><!SYNTAX!><!SYNTAX!><!>: Int): Int -> 5<!> } val receiverAndReturnTypeWithParameter = { Int.(<!UNRESOLVED_REFERENCE!>a<!><!SYNTAX!><!SYNTAX!><!>: Int): Int -> 5<!> }
val returnType = { (<!SYNTAX!><!>)<!SYNTAX!>: Int -> 5<!> } val returnType = { (<!SYNTAX!><!>): Int -> 5 }
val returnTypeWithParameter = { (<!UNRESOLVED_REFERENCE!>b<!><!SYNTAX!><!SYNTAX!><!>: Int): Int -> 5<!> } val returnTypeWithParameter = { (<!COMPONENT_FUNCTION_MISSING!>b: Int<!>): Int -> 5 }
val receiverWithFunctionType = { ((Int)<!SYNTAX!><!> <!SYNTAX!>-> Int).() -><!> } val receiverWithFunctionType = { ((Int)<!SYNTAX!><!> <!SYNTAX!>-> Int).() -><!> }
val parenthesizedParameters = { (<!UNRESOLVED_REFERENCE!>a<!><!SYNTAX!><!SYNTAX!><!>: Int) -><!> } val parenthesizedParameters = { <!CANNOT_INFER_PARAMETER_TYPE!>(a: Int)<!> -> }
val parenthesizedParameters2 = { (<!UNRESOLVED_REFERENCE!>b<!>) <!SYNTAX!>-><!> } val parenthesizedParameters2 = { <!CANNOT_INFER_PARAMETER_TYPE!>(b)<!> -> }
val none = { -> } val none = { -> }
@@ -7,12 +7,12 @@ public val newSyntax3: (???, kotlin.Int) -> kotlin.Unit
public val newSyntax4: (kotlin.Int, ???) -> kotlin.Unit public val newSyntax4: (kotlin.Int, ???) -> kotlin.Unit
public val none: () -> kotlin.Unit public val none: () -> kotlin.Unit
public val parameterWithFunctionType: (((kotlin.Int) -> kotlin.Int) -> [ERROR : No type element]) -> kotlin.Unit public val parameterWithFunctionType: (((kotlin.Int) -> kotlin.Int) -> [ERROR : No type element]) -> kotlin.Unit
public val parenthesizedParameters: () -> ??? public val parenthesizedParameters: (???) -> kotlin.Unit
public val parenthesizedParameters2: () -> ??? public val parenthesizedParameters2: (???) -> kotlin.Unit
public val receiver: () -> ??? public val receiver: () -> ???
public val receiverAndReturnType: () -> ??? public val receiverAndReturnType: () -> ???
public val receiverAndReturnTypeWithParameter: () -> ??? public val receiverAndReturnTypeWithParameter: () -> ???
public val receiverWithFunctionType: () -> kotlin.Int.Companion public val receiverWithFunctionType: () -> kotlin.Int.Companion
public val receiverWithParameter: () -> ??? public val receiverWithParameter: () -> ???
public val returnType: () -> ??? public val returnType: (kotlin.Int) -> kotlin.Int
public val returnTypeWithParameter: () -> ??? public val returnTypeWithParameter: (kotlin.Int) -> kotlin.Int
@@ -0,0 +1,47 @@
// !CHECK_TYPE
// !DIAGNOSTICS: -UNUSED_PARAMETER
data class A(val x: Int, val y: String)
data class B(val u: Double, val w: Short)
// first parameter of the functional type of 'x' can only be inferred from a lambda parameter explicit type specification
fun <X, Y> foo(y: Y, x: (X, Y) -> Unit) {}
fun bar(aInstance: A, bInstance: B) {
foo("") {
(a, b): A, c ->
a checkType { _<Int>() }
b checkType { _<String>() }
c checkType { _<String>() }
}
foo(aInstance) {
a: String, (b, c) ->
a checkType { _<String>() }
b checkType { _<Int>() }
c checkType { _<String>() }
}
foo(bInstance) {
(a, b): A, (c, d) ->
a checkType { _<Int>() }
b checkType { _<String>() }
c checkType { _<Double>() }
d checkType { _<Short>() }
}
<!TYPE_INFERENCE_NO_INFORMATION_FOR_PARAMETER!>foo<!>(bInstance) {
<!CANNOT_INFER_PARAMETER_TYPE!>(a, b)<!>, (c, d) ->
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>a<!> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Int>() }
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>b<!> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() }
c checkType { _<Double>() }
d checkType { _<Short>() }
}
foo<A, B>(bInstance) {
(a, b), (c, d) ->
a checkType { _<Int>() }
b checkType { _<String>() }
c checkType { _<Double>() }
d checkType { _<Short>() }
}
}
@@ -0,0 +1,28 @@
package
public fun bar(/*0*/ aInstance: A, /*1*/ bInstance: B): kotlin.Unit
public fun </*0*/ X, /*1*/ Y> foo(/*0*/ y: Y, /*1*/ x: (X, Y) -> kotlin.Unit): kotlin.Unit
public final data class A {
public constructor A(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String)
public final val x: kotlin.Int
public final val y: kotlin.String
public final operator /*synthesized*/ fun component1(): kotlin.Int
public final operator /*synthesized*/ fun component2(): kotlin.String
public final /*synthesized*/ fun copy(/*0*/ x: kotlin.Int = ..., /*1*/ y: kotlin.String = ...): A
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
public final data class B {
public constructor B(/*0*/ u: kotlin.Double, /*1*/ w: kotlin.Short)
public final val u: kotlin.Double
public final val w: kotlin.Short
public final operator /*synthesized*/ fun component1(): kotlin.Double
public final operator /*synthesized*/ fun component2(): kotlin.Short
public final /*synthesized*/ fun copy(/*0*/ u: kotlin.Double = ..., /*1*/ w: kotlin.Short = ...): B
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
@@ -0,0 +1,51 @@
// !CHECK_TYPE
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A
operator fun A.component1() = 1
operator fun A.component2() = ""
class B
class D {
operator fun A.component1() = 1.0
operator fun A.component2() = ' '
operator fun B.component1() = 1.0
operator fun B.component2() = ' '
}
fun foo(block: (A) -> Unit) { }
fun foobaz(block: D.(B) -> Unit) { }
fun foobar(block: D.(A) -> Unit) { }
fun bar() {
foo { (a, b) ->
a checkType { _<Int>() }
b checkType { _<String>() }
}
foo { (a: Int, b: String) ->
a checkType { _<Int>() }
b checkType { _<String>() }
}
// From KEEP: Component-functions are resolved in the scope that contains the lambda
foobaz { (<!COMPONENT_FUNCTION_MISSING!>a<!>, <!COMPONENT_FUNCTION_MISSING!>b<!>) ->
}
// From KEEP: Component-functions are resolved in the scope that contains the lambda
// So `component1`/`component2` for lambda parameters were resolved to the top-level extensions
foobar { (a, b) ->
a checkType { _<Int>() }
b checkType { _<String>() }
}
// the following code fails with exception, see KT-13873
// foobarbaz {
// component1: B.() -> Int,
// component2: B.() -> String,
// (a, b): B ->
//
// }
}
@@ -0,0 +1,33 @@
package
public fun bar(): kotlin.Unit
public fun foo(/*0*/ block: (A) -> kotlin.Unit): kotlin.Unit
public fun foobar(/*0*/ block: D.(A) -> kotlin.Unit): kotlin.Unit
public fun foobaz(/*0*/ block: D.(B) -> kotlin.Unit): kotlin.Unit
public operator fun A.component1(): kotlin.Int
public operator fun A.component2(): kotlin.String
public final class A {
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
}
public final class B {
public constructor B()
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
}
public final class D {
public constructor D()
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
public final operator fun A.component1(): kotlin.Double
public final operator fun B.component1(): kotlin.Double
public final operator fun A.component2(): kotlin.Char
public final operator fun B.component2(): kotlin.Char
}
@@ -0,0 +1,33 @@
// !CHECK_TYPE
// !DIAGNOSTICS: -UNUSED_PARAMETER
data class A(val x: Int, val y: String)
data class B(val u: Double, val w: Short)
fun <T> Iterable<T>.foo(x: (T) -> Unit) {}
fun bar(aList: List<A>) {
aList.foo { (a, b) ->
a checkType { _<Int>() }
b checkType { _<String>() }
}
aList.foo { (a: Int, b: String) ->
a checkType { _<Int>() }
b checkType { _<String>() }
}
aList.foo { (a, b): A ->
a checkType { _<Int>() }
b checkType { _<String>() }
}
aList.foo { (<!COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH!>a: String<!>, b) ->
a checkType { _<Int>() }
b checkType { _<String>() }
}
aList.<!TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS!>foo<!> { (a, b): B ->
b checkType { <!TYPE_MISMATCH!>_<!><Int>() }
a checkType { <!TYPE_MISMATCH!>_<!><String>() }
}
}
@@ -0,0 +1,28 @@
package
public fun bar(/*0*/ aList: kotlin.collections.List<A>): kotlin.Unit
public fun </*0*/ T> kotlin.collections.Iterable<T>.foo(/*0*/ x: (T) -> kotlin.Unit): kotlin.Unit
public final data class A {
public constructor A(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String)
public final val x: kotlin.Int
public final val y: kotlin.String
public final operator /*synthesized*/ fun component1(): kotlin.Int
public final operator /*synthesized*/ fun component2(): kotlin.String
public final /*synthesized*/ fun copy(/*0*/ x: kotlin.Int = ..., /*1*/ y: kotlin.String = ...): A
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
public final data class B {
public constructor B(/*0*/ u: kotlin.Double, /*1*/ w: kotlin.Short)
public final val u: kotlin.Double
public final val w: kotlin.Short
public final operator /*synthesized*/ fun component1(): kotlin.Double
public final operator /*synthesized*/ fun component2(): kotlin.Short
public final /*synthesized*/ fun copy(/*0*/ u: kotlin.Double = ..., /*1*/ w: kotlin.Short = ...): B
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
@@ -0,0 +1,31 @@
// !CHECK_TYPE
// !DIAGNOSTICS: -UNUSED_VARIABLE
data class A(val x: Int, val y: String)
fun bar() {
val x = { (a, b): A ->
a checkType { _<Int>() }
b checkType { _<String>() }
}
x checkType { _<(A) -> Unit>() }
val y = { (a: Int, b): A ->
a checkType { _<Int>() }
b checkType { _<String>() }
}
y checkType { _<(A) -> Unit>() }
val y2 = { (a: Number, b): A ->
a checkType { _<Int>() }
b checkType { _<String>() }
}
y2 checkType { _<(A) -> Unit>() }
val z = { <!CANNOT_INFER_PARAMETER_TYPE!>(a: Int, b: String)<!> ->
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>a<!> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><Int>() }
<!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>b<!> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>checkType<!> { <!UNRESOLVED_REFERENCE!>_<!><String>() }
}
}
@@ -0,0 +1,15 @@
package
public fun bar(): kotlin.Unit
public final data class A {
public constructor A(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String)
public final val x: kotlin.Int
public final val y: kotlin.String
public final operator /*synthesized*/ fun component1(): kotlin.Int
public final operator /*synthesized*/ fun component2(): kotlin.String
public final /*synthesized*/ fun copy(/*0*/ x: kotlin.Int = ..., /*1*/ y: kotlin.String = ...): A
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
@@ -0,0 +1,29 @@
// !CHECK_TYPE
// !DIAGNOSTICS: -UNUSED_PARAMETER
data class A(val x: Int, val y: String)
data class B(val u: Double, val w: Short)
fun foo(block: (A, B) -> Unit) { }
fun bar() {
foo { (<!REDECLARATION!>a<!>, <!REDECLARATION!>a<!>), b ->
a checkType { <!TYPE_MISMATCH!>_<!><Int>() }
b checkType { <!TYPE_MISMATCH!>_<!><String>() }
}
foo { (<!REDECLARATION!>a<!>, b), <!REDECLARATION!>a<!> ->
a checkType { <!TYPE_MISMATCH!>_<!><Int>() }
b checkType { _<String>() }
}
foo { <!REDECLARATION!>a<!>, (<!REDECLARATION!>a<!>, b) ->
a checkType { <!TYPE_MISMATCH!>_<!><Int>() }
b checkType { <!TYPE_MISMATCH!>_<!><String>() }
}
foo { (a, <!REDECLARATION!>b<!>), (c, <!REDECLARATION!>b<!>) ->
a checkType { _<Int>() }
b checkType { <!TYPE_MISMATCH!>_<!><String>() }
c checkType { <!TYPE_MISMATCH!>_<!><B>() }
}
}
@@ -0,0 +1,28 @@
package
public fun bar(): kotlin.Unit
public fun foo(/*0*/ block: (A, B) -> kotlin.Unit): kotlin.Unit
public final data class A {
public constructor A(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String)
public final val x: kotlin.Int
public final val y: kotlin.String
public final operator /*synthesized*/ fun component1(): kotlin.Int
public final operator /*synthesized*/ fun component2(): kotlin.String
public final /*synthesized*/ fun copy(/*0*/ x: kotlin.Int = ..., /*1*/ y: kotlin.String = ...): A
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
public final data class B {
public constructor B(/*0*/ u: kotlin.Double, /*1*/ w: kotlin.Short)
public final val u: kotlin.Double
public final val w: kotlin.Short
public final operator /*synthesized*/ fun component1(): kotlin.Double
public final operator /*synthesized*/ fun component2(): kotlin.Short
public final /*synthesized*/ fun copy(/*0*/ u: kotlin.Double = ..., /*1*/ w: kotlin.Short = ...): B
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
@@ -0,0 +1,25 @@
// !CHECK_TYPE
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
data class A(val x: Int, val y: String)
fun foo(block: (A) -> Unit) { }
fun bar(a: Double) {
val b = 1.toShort()
// Do not report NAME_SHADOWING on lambda destructured parameter, the same way as for common parameters
foo { (a, b) ->
a checkType { _<Int>() }
b checkType { _<String>() }
}
foo { (c, d) ->
c checkType { _<Int>() }
d checkType { _<String>() }
foo { (a, c) ->
a checkType { _<Int>() }
c checkType { _<String>() }
d checkType { _<String>() }
}
}
}
@@ -0,0 +1,16 @@
package
public fun bar(/*0*/ a: kotlin.Double): kotlin.Unit
public fun foo(/*0*/ block: (A) -> kotlin.Unit): kotlin.Unit
public final data class A {
public constructor A(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String)
public final val x: kotlin.Int
public final val y: kotlin.String
public final operator /*synthesized*/ fun component1(): kotlin.Int
public final operator /*synthesized*/ fun component2(): kotlin.String
public final /*synthesized*/ fun copy(/*0*/ x: kotlin.Int = ..., /*1*/ y: kotlin.String = ...): A
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
@@ -0,0 +1,53 @@
// !CHECK_TYPE
// !DIAGNOSTICS: -UNUSED_PARAMETER
data class A(val x: Int, val y: String)
data class B(val u: Double, val w: Short)
fun foo(block: (A) -> Unit) { }
fun foobar(block: (A, B) -> Unit) { }
fun bar() {
foo { (a, b) ->
a checkType { _<Int>() }
b checkType { _<String>() }
}
foo { (a: Int, b: String) ->
a checkType { _<Int>() }
b checkType { _<String>() }
}
foo { (a, b): A ->
a checkType { _<Int>() }
b checkType { _<String>() }
}
foobar { (a, b), c ->
a checkType { _<Int>() }
b checkType { _<String>() }
c checkType { _<B>() }
}
foobar { a, (b, c) ->
a checkType { _<A>() }
b checkType { _<Double>() }
c checkType { _<Short>() }
}
foobar { (a, b), (c, d) ->
a checkType { _<Int>() }
b checkType { _<String>() }
c checkType { _<Double>() }
d checkType { _<Short>() }
}
foo { (<!COMPONENT_FUNCTION_RETURN_TYPE_MISMATCH!>a: String<!>, b) ->
a checkType { _<Int>() }
b checkType { _<String>() }
}
foo { <!EXPECTED_PARAMETER_TYPE_MISMATCH!>(a, b): B<!> ->
a checkType { _<Double>() }
b checkType { _<Short>() }
}
}
@@ -0,0 +1,29 @@
package
public fun bar(): kotlin.Unit
public fun foo(/*0*/ block: (A) -> kotlin.Unit): kotlin.Unit
public fun foobar(/*0*/ block: (A, B) -> kotlin.Unit): kotlin.Unit
public final data class A {
public constructor A(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String)
public final val x: kotlin.Int
public final val y: kotlin.String
public final operator /*synthesized*/ fun component1(): kotlin.Int
public final operator /*synthesized*/ fun component2(): kotlin.String
public final /*synthesized*/ fun copy(/*0*/ x: kotlin.Int = ..., /*1*/ y: kotlin.String = ...): A
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
public final data class B {
public constructor B(/*0*/ u: kotlin.Double, /*1*/ w: kotlin.Short)
public final val u: kotlin.Double
public final val w: kotlin.Short
public final operator /*synthesized*/ fun component1(): kotlin.Double
public final operator /*synthesized*/ fun component2(): kotlin.Short
public final /*synthesized*/ fun copy(/*0*/ u: kotlin.Double = ..., /*1*/ w: kotlin.Short = ...): B
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
}
@@ -7470,6 +7470,57 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("compiler/testData/diagnostics/tests/functionLiterals/destructuringInLambdas")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class DestructuringInLambdas extends AbstractDiagnosticsTest {
public void testAllFilesPresentInDestructuringInLambdas() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/functionLiterals/destructuringInLambdas"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("complexInference.kt")
public void testComplexInference() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/destructuringInLambdas/complexInference.kt");
doTest(fileName);
}
@TestMetadata("extensionComponents.kt")
public void testExtensionComponents() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/destructuringInLambdas/extensionComponents.kt");
doTest(fileName);
}
@TestMetadata("inferredFunctionalType.kt")
public void testInferredFunctionalType() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/destructuringInLambdas/inferredFunctionalType.kt");
doTest(fileName);
}
@TestMetadata("noExpectedType.kt")
public void testNoExpectedType() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/destructuringInLambdas/noExpectedType.kt");
doTest(fileName);
}
@TestMetadata("redeclaration.kt")
public void testRedeclaration() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/destructuringInLambdas/redeclaration.kt");
doTest(fileName);
}
@TestMetadata("shadowing.kt")
public void testShadowing() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/destructuringInLambdas/shadowing.kt");
doTest(fileName);
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/functionLiterals/destructuringInLambdas/simple.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/diagnostics/tests/functionLiterals/return") @TestMetadata("compiler/testData/diagnostics/tests/functionLiterals/return")
@TestDataPath("$PROJECT_ROOT") @TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class) @RunWith(JUnit3RunnerWithInners.class)
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeSubstitutor import org.jetbrains.kotlin.types.TypeSubstitutor
class ValueParameterDescriptorImpl( open class ValueParameterDescriptorImpl(
containingDeclaration: CallableDescriptor, containingDeclaration: CallableDescriptor,
original: ValueParameterDescriptor?, original: ValueParameterDescriptor?,
override val index: Int, override val index: Int,
@@ -36,6 +36,50 @@ class ValueParameterDescriptorImpl(
override val varargElementType: KotlinType?, override val varargElementType: KotlinType?,
source: SourceElement source: SourceElement
) : VariableDescriptorImpl(containingDeclaration, annotations, name, outType, source), ValueParameterDescriptor { ) : VariableDescriptorImpl(containingDeclaration, annotations, name, outType, source), ValueParameterDescriptor {
companion object {
@JvmStatic
fun getDestructuringVariablesOrNull(valueParameterDescriptor: ValueParameterDescriptor) =
(valueParameterDescriptor as? ValueParameterDescriptorImpl.WithDestructuringDeclaration)?.destructuringVariables
@JvmStatic
fun createWithDestructuringDeclarations(containingDeclaration: CallableDescriptor,
original: ValueParameterDescriptor?,
index: Int,
annotations: Annotations,
name: Name,
outType: KotlinType,
declaresDefaultValue: Boolean,
isCrossinline: Boolean,
isNoinline: Boolean, isCoroutine: Boolean, varargElementType: KotlinType?,
source: SourceElement,
destructuringVariables: List<VariableDescriptor>?
): ValueParameterDescriptorImpl =
if (destructuringVariables == null)
ValueParameterDescriptorImpl(containingDeclaration, original, index, annotations, name, outType,
declaresDefaultValue, isCrossinline, isNoinline, isCoroutine, varargElementType, source)
else
WithDestructuringDeclaration(containingDeclaration, original, index, annotations, name, outType,
declaresDefaultValue, isCrossinline, isNoinline, isCoroutine, varargElementType, source,
destructuringVariables)
}
class WithDestructuringDeclaration internal constructor(
containingDeclaration: CallableDescriptor,
original: ValueParameterDescriptor?,
index: Int,
annotations: Annotations, name: Name,
outType: KotlinType,
declaresDefaultValue: Boolean,
isCrossinline: Boolean,
isNoinline: Boolean, isCoroutine: Boolean, varargElementType: KotlinType?,
source: SourceElement,
val destructuringVariables: List<VariableDescriptor>
) : ValueParameterDescriptorImpl(
containingDeclaration, original, index, annotations, name, outType, declaresDefaultValue,
isCrossinline, isNoinline, isCoroutine,
varargElementType, source)
private val original: ValueParameterDescriptor = original ?: this private val original: ValueParameterDescriptor = original ?: this
override fun getContainingDeclaration() = super.getContainingDeclaration() as CallableDescriptor override fun getContainingDeclaration() = super.getContainingDeclaration() as CallableDescriptor