Fix multiple exceptions related to subtypes of function types

The main change is in FunctionsTypingVisitor#visitLambdaExpression, where we
incorrectly allowed subtypes of function types to be expected type during
resolution of lambdas

Also see EA-70485

 #KT-9820 Fixed
This commit is contained in:
Alexander Udalov
2016-03-14 12:43:00 +03:00
parent 33ff1e1e29
commit 117d0bcf03
9 changed files with 103 additions and 32 deletions
@@ -16,10 +16,7 @@
package org.jetbrains.kotlin.resolve
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType
import org.jetbrains.kotlin.builtins.getValueParametersFromFunctionType
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
import org.jetbrains.kotlin.builtins.*
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.ConstructorDescriptorImpl
@@ -220,12 +217,15 @@ class FunctionDescriptorResolver(
)
}
private fun KotlinType.functionTypeExpected() = !TypeUtils.noExpectedType(this) && isFunctionTypeOrSubtype
private fun KotlinType.functionTypeExpected() = !TypeUtils.noExpectedType(this) && isFunctionType
private fun KotlinType.getReceiverType(): KotlinType? =
if (functionTypeExpected()) getReceiverTypeFromFunctionType(this) else null
private fun KotlinType.getValueParameters(owner: FunctionDescriptor): List<ValueParameterDescriptor>? =
if (functionTypeExpected()) getValueParametersFromFunctionType(owner, this) else null
if (functionTypeExpected()) {
createValueParametersFromFunctionType(owner, getParameterTypeProjectionsFromFunctionType(this))
}
else null
fun resolvePrimaryConstructorDescriptor(
scope: LexicalScope,
@@ -16,7 +16,10 @@
package org.jetbrains.kotlin.resolve.callableReferences
import org.jetbrains.kotlin.builtins.*
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.ReflectionTypes
import org.jetbrains.kotlin.builtins.createFunctionType
import org.jetbrains.kotlin.builtins.createValueParametersFromFunctionType
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.Annotations
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
@@ -210,11 +213,9 @@ private fun bindFunctionReference(expression: KtCallableReferenceExpression, typ
)
functionDescriptor.initialize(
getReceiverTypeFromFunctionType(type),
null,
emptyList(),
getValueParametersFromFunctionType(functionDescriptor, type),
getReturnTypeFromFunctionType(type),
null, null, emptyList(),
createValueParametersFromFunctionType(functionDescriptor, type.arguments.dropLast(1)),
type.arguments.last().type,
Modality.FINAL,
Visibilities.PUBLIC
)
@@ -21,7 +21,7 @@ import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.createFunctionType
import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
import org.jetbrains.kotlin.builtins.isFunctionType
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
import org.jetbrains.kotlin.descriptors.annotations.Annotations
@@ -140,7 +140,7 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
if (!expression.functionLiteral.hasBody()) return null
val expectedType = context.expectedType
val functionTypeExpected = !noExpectedType(expectedType) && expectedType.isFunctionTypeOrSubtype
val functionTypeExpected = !noExpectedType(expectedType) && expectedType.isFunctionType
val functionDescriptor = createFunctionLiteralDescriptor(expression, context)
expression.valueParameters.forEach {
@@ -0,0 +1,17 @@
class O : Function2<Int, String, Unit> {
override fun invoke(p1: Int, p2: String) {
}
}
fun test() {
val a = fun(<!UNUSED_PARAMETER!>o<!>: O) {
}
a <!TYPE_MISMATCH!>{}<!>
}
<!ABSTRACT_MEMBER_NOT_IMPLEMENTED!>class Ext<!> : <!SUPERTYPE_IS_EXTENSION_FUNCTION_TYPE!>String.() -> Unit<!> {
}
fun test2() {
val <!UNUSED_VARIABLE!>f<!>: Ext = <!TYPE_MISMATCH!>{}<!>
}
@@ -0,0 +1,20 @@
package
public fun test(): kotlin.Unit
public fun test2(): kotlin.Unit
public final class Ext : kotlin.String.() -> kotlin.Unit {
public constructor Ext()
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 abstract override /*1*/ /*fake_override*/ fun invoke(/*0*/ p1: kotlin.String): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public final class O : (kotlin.Int, kotlin.String) -> kotlin.Unit {
public constructor O()
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*/ fun invoke(/*0*/ p1: kotlin.Int, /*1*/ p2: kotlin.String): kotlin.Unit
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,16 @@
// FILE: J.java
import kotlin.jvm.functions.Function1;
public interface J extends Function1<Integer, Void> {
}
// FILE: 1.kt
fun useJ(j: J) {
j(42)
}
fun jj() {
useJ(<!TYPE_MISMATCH!>{}<!>)
}
@@ -0,0 +1,12 @@
package
public /*synthesized*/ fun J(/*0*/ function: (kotlin.Int!) -> java.lang.Void!): J
public fun jj(): kotlin.Unit
public fun useJ(/*0*/ j: J): kotlin.Unit
public interface J : (kotlin.Int!) -> java.lang.Void! {
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 abstract override /*1*/ /*fake_override*/ fun invoke(/*0*/ p1: kotlin.Int!): java.lang.Void!
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -1036,6 +1036,12 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
doTest(fileName);
}
@TestMetadata("ea70485_functionTypeInheritor.kt")
public void testEa70485_functionTypeInheritor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/regression/ea70485_functionTypeInheritor.kt");
doTest(fileName);
}
@TestMetadata("ea70880_illegalJvmName.kt")
public void testEa70880_illegalJvmName() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/regression/ea70880_illegalJvmName.kt");
@@ -1053,6 +1059,12 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/regression/kt9345.kt");
doTest(fileName);
}
@TestMetadata("kt9820_javaFunctionTypeInheritor.kt")
public void testKt9820_javaFunctionTypeInheritor() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/regression/kt9820_javaFunctionTypeInheritor.kt");
doTest(fileName);
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/reified")
@@ -63,16 +63,14 @@ fun isNumberedFunctionClassFqName(fqName: FqNameUnsafe): Boolean {
}
fun getReceiverTypeFromFunctionType(type: KotlinType): KotlinType? {
assert(type.isFunctionTypeOrSubtype) { type }
if (type.isExtensionFunctionType) {
return type.arguments.first().type
}
return null
assert(type.isFunctionType) { "Not a function type: $type" }
return if (type.isTypeAnnotatedWithExtensionFunctionType) type.arguments.first().type else null
}
fun getValueParametersFromFunctionType(functionDescriptor: FunctionDescriptor, type: KotlinType): List<ValueParameterDescriptor> {
assert(type.isFunctionTypeOrSubtype) { type }
return getParameterTypeProjectionsFromFunctionType(type).mapIndexed { i, typeProjection ->
fun createValueParametersFromFunctionType(
functionDescriptor: FunctionDescriptor, parameterTypes: List<TypeProjection>
): List<ValueParameterDescriptor> {
return parameterTypes.mapIndexed { i, typeProjection ->
ValueParameterDescriptorImpl(
functionDescriptor, null, i, Annotations.EMPTY,
Name.identifier("p${i + 1}"), typeProjection.type,
@@ -85,22 +83,17 @@ fun getValueParametersFromFunctionType(functionDescriptor: FunctionDescriptor, t
}
fun getReturnTypeFromFunctionType(type: KotlinType): KotlinType {
assert(type.isFunctionTypeOrSubtype) { type }
assert(type.isFunctionType) { "Not a function type: $type" }
return type.arguments.last().type
}
fun getParameterTypeProjectionsFromFunctionType(type: KotlinType): List<TypeProjection> {
assert(type.isFunctionTypeOrSubtype) { type }
assert(type.isFunctionType) { "Not a function type: $type" }
val arguments = type.arguments
val first = if (type.isExtensionFunctionType) 1 else 0
val last = arguments.size - 2
// TODO: fix bugs associated with this here and in neighboring methods, see KT-9820
assert(first <= last + 1) { "Not an exact function type: $type" }
val parameterTypes = ArrayList<TypeProjection>(last - first + 1)
for (i in first..last) {
parameterTypes.add(arguments[i])
}
return parameterTypes
val last = arguments.size - 1
assert(first <= last) { "Not an exact function type: $type" }
return arguments.subList(first, last)
}
fun createFunctionType(