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:
@@ -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,
|
||||
|
||||
+7
-6
@@ -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
|
||||
)
|
||||
|
||||
+2
-2
@@ -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 {
|
||||
|
||||
+17
@@ -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!>{}<!>
|
||||
}
|
||||
+20
@@ -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
|
||||
}
|
||||
Vendored
+16
@@ -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!>{}<!>)
|
||||
}
|
||||
Vendored
+12
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user