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
|
package org.jetbrains.kotlin.resolve
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.*
|
||||||
import org.jetbrains.kotlin.builtins.getReceiverTypeFromFunctionType
|
|
||||||
import org.jetbrains.kotlin.builtins.getValueParametersFromFunctionType
|
|
||||||
import org.jetbrains.kotlin.builtins.isFunctionTypeOrSubtype
|
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.ConstructorDescriptorImpl
|
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? =
|
private fun KotlinType.getReceiverType(): KotlinType? =
|
||||||
if (functionTypeExpected()) getReceiverTypeFromFunctionType(this) else null
|
if (functionTypeExpected()) getReceiverTypeFromFunctionType(this) else null
|
||||||
|
|
||||||
private fun KotlinType.getValueParameters(owner: FunctionDescriptor): List<ValueParameterDescriptor>? =
|
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(
|
fun resolvePrimaryConstructorDescriptor(
|
||||||
scope: LexicalScope,
|
scope: LexicalScope,
|
||||||
|
|||||||
+7
-6
@@ -16,7 +16,10 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.callableReferences
|
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.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||||
@@ -210,11 +213,9 @@ private fun bindFunctionReference(expression: KtCallableReferenceExpression, typ
|
|||||||
)
|
)
|
||||||
|
|
||||||
functionDescriptor.initialize(
|
functionDescriptor.initialize(
|
||||||
getReceiverTypeFromFunctionType(type),
|
null, null, emptyList(),
|
||||||
null,
|
createValueParametersFromFunctionType(functionDescriptor, type.arguments.dropLast(1)),
|
||||||
emptyList(),
|
type.arguments.last().type,
|
||||||
getValueParametersFromFunctionType(functionDescriptor, type),
|
|
||||||
getReturnTypeFromFunctionType(type),
|
|
||||||
Modality.FINAL,
|
Modality.FINAL,
|
||||||
Visibilities.PUBLIC
|
Visibilities.PUBLIC
|
||||||
)
|
)
|
||||||
|
|||||||
+2
-2
@@ -21,7 +21,7 @@ import com.intellij.psi.PsiElement
|
|||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
import org.jetbrains.kotlin.builtins.createFunctionType
|
import org.jetbrains.kotlin.builtins.createFunctionType
|
||||||
import org.jetbrains.kotlin.builtins.getReturnTypeFromFunctionType
|
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.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
@@ -140,7 +140,7 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
|
|||||||
if (!expression.functionLiteral.hasBody()) return null
|
if (!expression.functionLiteral.hasBody()) return null
|
||||||
|
|
||||||
val expectedType = context.expectedType
|
val expectedType = context.expectedType
|
||||||
val functionTypeExpected = !noExpectedType(expectedType) && expectedType.isFunctionTypeOrSubtype
|
val functionTypeExpected = !noExpectedType(expectedType) && expectedType.isFunctionType
|
||||||
|
|
||||||
val functionDescriptor = createFunctionLiteralDescriptor(expression, context)
|
val functionDescriptor = createFunctionLiteralDescriptor(expression, context)
|
||||||
expression.valueParameters.forEach {
|
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);
|
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")
|
@TestMetadata("ea70880_illegalJvmName.kt")
|
||||||
public void testEa70880_illegalJvmName() throws Exception {
|
public void testEa70880_illegalJvmName() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/regression/ea70880_illegalJvmName.kt");
|
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");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithStdLib/regression/kt9345.kt");
|
||||||
doTest(fileName);
|
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")
|
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/reified")
|
||||||
|
|||||||
@@ -63,16 +63,14 @@ fun isNumberedFunctionClassFqName(fqName: FqNameUnsafe): Boolean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getReceiverTypeFromFunctionType(type: KotlinType): KotlinType? {
|
fun getReceiverTypeFromFunctionType(type: KotlinType): KotlinType? {
|
||||||
assert(type.isFunctionTypeOrSubtype) { type }
|
assert(type.isFunctionType) { "Not a function type: $type" }
|
||||||
if (type.isExtensionFunctionType) {
|
return if (type.isTypeAnnotatedWithExtensionFunctionType) type.arguments.first().type else null
|
||||||
return type.arguments.first().type
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getValueParametersFromFunctionType(functionDescriptor: FunctionDescriptor, type: KotlinType): List<ValueParameterDescriptor> {
|
fun createValueParametersFromFunctionType(
|
||||||
assert(type.isFunctionTypeOrSubtype) { type }
|
functionDescriptor: FunctionDescriptor, parameterTypes: List<TypeProjection>
|
||||||
return getParameterTypeProjectionsFromFunctionType(type).mapIndexed { i, typeProjection ->
|
): List<ValueParameterDescriptor> {
|
||||||
|
return parameterTypes.mapIndexed { i, typeProjection ->
|
||||||
ValueParameterDescriptorImpl(
|
ValueParameterDescriptorImpl(
|
||||||
functionDescriptor, null, i, Annotations.EMPTY,
|
functionDescriptor, null, i, Annotations.EMPTY,
|
||||||
Name.identifier("p${i + 1}"), typeProjection.type,
|
Name.identifier("p${i + 1}"), typeProjection.type,
|
||||||
@@ -85,22 +83,17 @@ fun getValueParametersFromFunctionType(functionDescriptor: FunctionDescriptor, t
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun getReturnTypeFromFunctionType(type: KotlinType): KotlinType {
|
fun getReturnTypeFromFunctionType(type: KotlinType): KotlinType {
|
||||||
assert(type.isFunctionTypeOrSubtype) { type }
|
assert(type.isFunctionType) { "Not a function type: $type" }
|
||||||
return type.arguments.last().type
|
return type.arguments.last().type
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getParameterTypeProjectionsFromFunctionType(type: KotlinType): List<TypeProjection> {
|
fun getParameterTypeProjectionsFromFunctionType(type: KotlinType): List<TypeProjection> {
|
||||||
assert(type.isFunctionTypeOrSubtype) { type }
|
assert(type.isFunctionType) { "Not a function type: $type" }
|
||||||
val arguments = type.arguments
|
val arguments = type.arguments
|
||||||
val first = if (type.isExtensionFunctionType) 1 else 0
|
val first = if (type.isExtensionFunctionType) 1 else 0
|
||||||
val last = arguments.size - 2
|
val last = arguments.size - 1
|
||||||
// TODO: fix bugs associated with this here and in neighboring methods, see KT-9820
|
assert(first <= last) { "Not an exact function type: $type" }
|
||||||
assert(first <= last + 1) { "Not an exact function type: $type" }
|
return arguments.subList(first, last)
|
||||||
val parameterTypes = ArrayList<TypeProjection>(last - first + 1)
|
|
||||||
for (i in first..last) {
|
|
||||||
parameterTypes.add(arguments[i])
|
|
||||||
}
|
|
||||||
return parameterTypes
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createFunctionType(
|
fun createFunctionType(
|
||||||
|
|||||||
Reference in New Issue
Block a user