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 org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.KtNodeTypes;
import org.jetbrains.kotlin.lexer.KtTokens;
import org.jetbrains.kotlin.psi.stubs.KotlinParameterStub;
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);
}
@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);
@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.descriptors.LazyTypeAliasDescriptor;
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.source.KotlinSourceElementKt;
import org.jetbrains.kotlin.storage.StorageManager;
import org.jetbrains.kotlin.types.*;
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker;
import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
import org.jetbrains.kotlin.types.expressions.FunctionsTypingVisitor;
import org.jetbrains.kotlin.types.expressions.PreliminaryDeclarationVisitor;
import org.jetbrains.kotlin.types.expressions.*;
import java.util.*;
@@ -79,6 +78,7 @@ public class DescriptorResolver {
private final OverloadChecker overloadChecker;
private final LanguageVersionSettings languageVersionSettings;
private final FunctionsTypingVisitor functionsTypingVisitor;
private final DestructuringDeclarationResolver destructuringDeclarationResolver;
public DescriptorResolver(
@NotNull AnnotationResolver annotationResolver,
@@ -90,7 +90,8 @@ public class DescriptorResolver {
@NotNull ExpressionTypingServices expressionTypingServices,
@NotNull OverloadChecker overloadChecker,
@NotNull LanguageVersionSettings languageVersionSettings,
@NotNull FunctionsTypingVisitor functionsTypingVisitor
@NotNull FunctionsTypingVisitor functionsTypingVisitor,
@NotNull DestructuringDeclarationResolver destructuringDeclarationResolver
) {
this.annotationResolver = annotationResolver;
this.builtIns = builtIns;
@@ -102,6 +103,7 @@ public class DescriptorResolver {
this.overloadChecker = overloadChecker;
this.languageVersionSettings = languageVersionSettings;
this.functionsTypingVisitor = functionsTypingVisitor;
this.destructuringDeclarationResolver = destructuringDeclarationResolver;
}
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,
null,
index,
valueParameterAnnotations,
KtPsiUtil.safeName(valueParameter.getName()),
destructuringVariables == null
? KtPsiUtil.safeName(valueParameter.getName())
: Name.special("<name for destructuring parameter " + index + ">"),
variableType,
valueParameter.hasDefaultValue(),
valueParameter.hasModifier(CROSSINLINE_KEYWORD),
valueParameter.hasModifier(NOINLINE_KEYWORD),
valueParameter.hasModifier(COROUTINE_KEYWORD),
varargElementType,
KotlinSourceElementKt.toSourceElement(valueParameter)
KotlinSourceElementKt.toSourceElement(valueParameter),
destructuringVariables
);
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.impl.AnonymousFunctionDescriptor;
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.scopes.*;
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver;
@@ -89,7 +90,17 @@ public class FunctionDescriptorUtil {
handler.addClassifierDescriptor(typeParameter);
}
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;
}
@@ -412,7 +412,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor {
KotlinType elementType = expectedParameterType == null ? ErrorUtils.createErrorType("Loop range has no type") : expectedParameterType;
TransientReceiver iteratorNextAsReceiver = new TransientReceiver(elementType);
components.annotationResolver.resolveAnnotationsWithArguments(loopScope, multiParameter.getModifierList(), context.trace);
components.destructuringDeclarationResolver.defineLocalVariablesFromMultiDeclaration(
components.destructuringDeclarationResolver.defineLocalVariablesFromDestructuringDeclaration(
loopScope, multiParameter, iteratorNextAsReceiver, loopRange, context
);
components.modifiersChecker.withTrace(context.trace).checkModifiersForDestructuringDeclaration(multiParameter);
@@ -16,6 +16,7 @@
package org.jetbrains.kotlin.types.expressions
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.name.Name
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.LocalVariableResolver
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.receivers.ReceiverValue
import org.jetbrains.kotlin.types.ErrorUtils
@@ -37,23 +39,37 @@ class DestructuringDeclarationResolver(
private val localVariableResolver: LocalVariableResolver,
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,
destructuringDeclaration: KtDestructuringDeclaration,
receiver: ReceiverValue?,
initializer: KtExpression?,
context: ExpressionTypingContext
) {
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(writableScope, entry, componentType, context.trace)
ExpressionTypingUtils.checkVariableShadowing(writableScope, context.trace, variableDescriptor)
writableScope.addVariableDescriptor(variableDescriptor)
}
) = resolveLocalVariablesFromDestructuringDeclaration(
writableScope, destructuringDeclaration, receiver, initializer, context
).forEach {
ExpressionTypingUtils.checkVariableShadowing(writableScope, context.trace, it)
writableScope.addVariableDescriptor(it)
}
private fun resolveComponentFunctionAndGetType(
@@ -65,12 +81,12 @@ class DestructuringDeclarationResolver(
): KotlinType {
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 results = fakeCallResolver.resolveFakeCall(
context.replaceExpectedType(expectedType), receiver, componentName,
entry, initializer, FakeCallKind.COMPONENT, emptyList()
entry, initializer ?: entry, FakeCallKind.COMPONENT, emptyList()
)
if (!results.isSuccess) {
@@ -82,7 +98,9 @@ class DestructuringDeclarationResolver(
val functionReturnType = results.resultingDescriptor.returnType
if (functionReturnType != null && !TypeUtils.noExpectedType(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()
}
@@ -112,6 +112,12 @@ public class ExpressionTypingUtils {
if (oldDescriptor != null && isLocal(variableDescriptor.getContainingDeclaration(), oldDescriptor)) {
PsiElement declaration = DescriptorToSourceUtils.descriptorToDeclaration(variableDescriptor);
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()));
}
}
@@ -134,7 +134,7 @@ public class ExpressionTypingVisitorForStatements extends ExpressionTypingVisito
facade, initializer, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceContextDependency(INDEPENDENT)) : null;
components.destructuringDeclarationResolver
.defineLocalVariablesFromMultiDeclaration(scope, multiDeclaration, expressionReceiver, initializer, context);
.defineLocalVariablesFromDestructuringDeclaration(scope, multiDeclaration, expressionReceiver, initializer, context);
components.modifiersChecker.withTrace(context.trace).checkModifiersForDestructuringDeclaration(multiDeclaration);
components.identifierChecker.checkDeclaration(multiDeclaration, context.trace);
@@ -12,4 +12,4 @@ fun a() {
}
fun use(a: Any): Any = a
fun use(a: Any): Any = a
@@ -11,4 +11,4 @@ fun test() {
for ((<!REDECLARATION!>x<!>, <!NAME_SHADOWING, REDECLARATION!>x<!>) in C()) {
}
}
}
@@ -4,13 +4,13 @@ val receiverWithParameter = { Int.<!ILLEGAL_SELECTOR!>(<!UNRESOLVED_REFERENCE!>a
val receiverAndReturnType = { Int.(<!SYNTAX!><!>)<!SYNTAX!>: Int -> 5<!> }
val receiverAndReturnTypeWithParameter = { Int.(<!UNRESOLVED_REFERENCE!>a<!><!SYNTAX!><!SYNTAX!><!>: Int): Int -> 5<!> }
val returnType = { (<!SYNTAX!><!>)<!SYNTAX!>: Int -> 5<!> }
val returnTypeWithParameter = { (<!UNRESOLVED_REFERENCE!>b<!><!SYNTAX!><!SYNTAX!><!>: Int): Int -> 5<!> }
val returnType = { (<!SYNTAX!><!>): Int -> 5 }
val returnTypeWithParameter = { (<!COMPONENT_FUNCTION_MISSING!>b: Int<!>): Int -> 5 }
val receiverWithFunctionType = { ((Int)<!SYNTAX!><!> <!SYNTAX!>-> Int).() -><!> }
val parenthesizedParameters = { (<!UNRESOLVED_REFERENCE!>a<!><!SYNTAX!><!SYNTAX!><!>: Int) -><!> }
val parenthesizedParameters2 = { (<!UNRESOLVED_REFERENCE!>b<!>) <!SYNTAX!>-><!> }
val parenthesizedParameters = { <!CANNOT_INFER_PARAMETER_TYPE!>(a: Int)<!> -> }
val parenthesizedParameters2 = { <!CANNOT_INFER_PARAMETER_TYPE!>(b)<!> -> }
val none = { -> }
@@ -21,4 +21,4 @@ val newSyntax = { a: Int -> }
val newSyntax1 = { <!CANNOT_INFER_PARAMETER_TYPE!>a<!>, <!CANNOT_INFER_PARAMETER_TYPE!>b<!> -> }
val newSyntax2 = { a: Int, b: Int -> }
val newSyntax3 = { <!CANNOT_INFER_PARAMETER_TYPE!>a<!>, b: Int -> }
val newSyntax4 = { a: Int, <!CANNOT_INFER_PARAMETER_TYPE!>b<!> -> }
val newSyntax4 = { a: Int, <!CANNOT_INFER_PARAMETER_TYPE!>b<!> -> }
@@ -7,12 +7,12 @@ public val newSyntax3: (???, kotlin.Int) -> kotlin.Unit
public val newSyntax4: (kotlin.Int, ???) -> kotlin.Unit
public val none: () -> kotlin.Unit
public val parameterWithFunctionType: (((kotlin.Int) -> kotlin.Int) -> [ERROR : No type element]) -> kotlin.Unit
public val parenthesizedParameters: () -> ???
public val parenthesizedParameters2: () -> ???
public val parenthesizedParameters: (???) -> kotlin.Unit
public val parenthesizedParameters2: (???) -> kotlin.Unit
public val receiver: () -> ???
public val receiverAndReturnType: () -> ???
public val receiverAndReturnTypeWithParameter: () -> ???
public val receiverWithFunctionType: () -> kotlin.Int.Companion
public val receiverWithParameter: () -> ???
public val returnType: () -> ???
public val returnTypeWithParameter: () -> ???
public val returnType: (kotlin.Int) -> kotlin.Int
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);
}
@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")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.types.TypeSubstitutor
class ValueParameterDescriptorImpl(
open class ValueParameterDescriptorImpl(
containingDeclaration: CallableDescriptor,
original: ValueParameterDescriptor?,
override val index: Int,
@@ -36,6 +36,50 @@ class ValueParameterDescriptorImpl(
override val varargElementType: KotlinType?,
source: SourceElement
) : 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
override fun getContainingDeclaration() = super.getContainingDeclaration() as CallableDescriptor