FIR: permit * as FunctionN type argument
`() -> *` is not valid, but `F<*>` where `typealias F<T> = () -> T` is.
This commit is contained in:
+6
@@ -17022,6 +17022,12 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
||||
runTest("compiler/testData/codegen/box/inference/kt42130.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("lambdaWithStarReturn.kt")
|
||||
public void testLambdaWithStarReturn() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/lambdaWithStarReturn.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("lambdasWithExtensionFunctionType.kt")
|
||||
public void testLambdasWithExtensionFunctionType() throws Exception {
|
||||
|
||||
@@ -508,7 +508,7 @@ fun FirExpression.isFunctional(
|
||||
session, scopeSession, classLikeExpectedFunctionType, shouldCalculateReturnTypesOfFakeOverrides = false
|
||||
) ?: return false
|
||||
// Make sure the contributed `invoke` is indeed a wanted functional type by checking if types are compatible.
|
||||
val expectedReturnType = classLikeExpectedFunctionType.returnType(session)!!.lowerBoundIfFlexible()
|
||||
val expectedReturnType = classLikeExpectedFunctionType.returnType(session).lowerBoundIfFlexible()
|
||||
val returnTypeCompatible =
|
||||
expectedReturnType is ConeTypeParameterType ||
|
||||
AbstractTypeChecker.isSubtypeOf(
|
||||
@@ -529,7 +529,7 @@ fun FirExpression.isFunctional(
|
||||
val parameterPairs =
|
||||
invokeSymbol.fir.valueParameters.zip(classLikeExpectedFunctionType.valueParameterTypesIncludingReceiver(session))
|
||||
return parameterPairs.all { (invokeParameter, expectedParameter) ->
|
||||
val expectedParameterType = expectedParameter!!.lowerBoundIfFlexible()
|
||||
val expectedParameterType = expectedParameter.lowerBoundIfFlexible()
|
||||
expectedParameterType is ConeTypeParameterType ||
|
||||
AbstractTypeChecker.isSubtypeOf(
|
||||
session.inferenceComponents.ctx.newBaseTypeCheckerContext(
|
||||
|
||||
+29
-44
@@ -202,22 +202,28 @@ fun ConeKotlinType.isKClassType(): Boolean {
|
||||
}
|
||||
|
||||
fun ConeKotlinType.receiverType(session: FirSession): ConeKotlinType? {
|
||||
if (isBuiltinFunctionalType(session) && isExtensionFunctionType(session)) {
|
||||
return (this.fullyExpandedType(session).typeArguments.first() as ConeKotlinTypeProjection).type
|
||||
if (!isBuiltinFunctionalType(session) || !isExtensionFunctionType(session)) return null
|
||||
return when (val projection = fullyExpandedType(session).typeArguments.first()) {
|
||||
is ConeKotlinTypeProjection -> projection.type
|
||||
is ConeStarProjection -> session.builtinTypes.nothingType.type
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
fun ConeKotlinType.returnType(session: FirSession): ConeKotlinType? {
|
||||
fun ConeKotlinType.returnType(session: FirSession): ConeKotlinType {
|
||||
require(this is ConeClassLikeType)
|
||||
val projection = fullyExpandedType(session).typeArguments.last()
|
||||
return (projection as? ConeKotlinTypeProjection)?.type
|
||||
return when (val projection = fullyExpandedType(session).typeArguments.last()) {
|
||||
is ConeKotlinTypeProjection -> projection.type
|
||||
is ConeStarProjection -> session.builtinTypes.nullableAnyType.type
|
||||
}
|
||||
}
|
||||
|
||||
fun ConeKotlinType.valueParameterTypesIncludingReceiver(session: FirSession): List<ConeKotlinType?> {
|
||||
fun ConeKotlinType.valueParameterTypesIncludingReceiver(session: FirSession): List<ConeKotlinType> {
|
||||
require(this is ConeClassLikeType)
|
||||
return fullyExpandedType(session).typeArguments.dropLast(1).map {
|
||||
(it as? ConeKotlinTypeProjection)?.type
|
||||
when (it) {
|
||||
is ConeKotlinTypeProjection -> it.type
|
||||
is ConeStarProjection -> session.builtinTypes.nothingType.type
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -252,11 +258,22 @@ fun extractLambdaInfoFromFunctionalType(
|
||||
// Simply { }, i.e., function literals without body. Raw FIR added an implicit return with an implicit unit type ref.
|
||||
if (lastStatement?.source?.kind is FirFakeSourceElementKind.ImplicitReturn &&
|
||||
(lastStatement as? FirReturnExpression)?.result?.source?.kind is FirFakeSourceElementKind.ImplicitUnit
|
||||
) {
|
||||
)
|
||||
session.builtinTypes.unitType.type
|
||||
} else
|
||||
argument.returnType ?: expectedType.returnType(session) ?: return null
|
||||
val parameters = extractLambdaParameters(expectedType, argument, expectedType.isExtensionFunctionType(session), session)
|
||||
else
|
||||
argument.returnType ?: expectedType.returnType(session)
|
||||
val expectedParameters = expectedType.valueParameterTypesIncludingReceiver(session).let {
|
||||
if (expectedType.isExtensionFunctionType(session)) it.drop(1) else it
|
||||
}
|
||||
val parameters = if (argument.valueParameters.isEmpty()) {
|
||||
expectedParameters
|
||||
} else {
|
||||
// TODO: `(A) -> B` is permitted as `A.() -> B` if it's an anonymous function, not a lambda;
|
||||
// e.g. `fun (x: Any?) = x` can be used as `Any?.() -> Any?`, but `{ it -> it }` cannot.
|
||||
argument.valueParameters.mapIndexed { index, parameter ->
|
||||
parameter.returnTypeRef.coneTypeSafe() ?: expectedParameters.getOrNull(index) ?: session.builtinTypes.nothingType.type
|
||||
}
|
||||
}
|
||||
|
||||
return ResolvedLambdaAtom(
|
||||
argument,
|
||||
@@ -269,35 +286,3 @@ fun extractLambdaInfoFromFunctionalType(
|
||||
candidate
|
||||
)
|
||||
}
|
||||
|
||||
private fun extractLambdaParameters(
|
||||
expectedType: ConeKotlinType,
|
||||
argument: FirAnonymousFunction,
|
||||
expectedTypeIsExtensionFunctionType: Boolean,
|
||||
session: FirSession
|
||||
): List<ConeKotlinType> {
|
||||
val parameters = argument.valueParameters
|
||||
val expectedParameters = expectedType.extractParametersForFunctionalType(expectedTypeIsExtensionFunctionType, session)
|
||||
|
||||
val nullableAnyType = argument.session.builtinTypes.nullableAnyType.type
|
||||
if (parameters.isEmpty()) {
|
||||
return expectedParameters.map { it?.type ?: nullableAnyType }
|
||||
}
|
||||
|
||||
return parameters.mapIndexed { index, parameter ->
|
||||
parameter.returnTypeRef.coneTypeSafe() ?: expectedParameters.getOrNull(index) ?: nullableAnyType
|
||||
}
|
||||
}
|
||||
|
||||
private fun ConeKotlinType.extractParametersForFunctionalType(
|
||||
isExtensionFunctionType: Boolean,
|
||||
session: FirSession
|
||||
): List<ConeKotlinType?> {
|
||||
return valueParameterTypesIncludingReceiver(session).let {
|
||||
if (isExtensionFunctionType) {
|
||||
it.drop(1)
|
||||
} else {
|
||||
it
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-20
@@ -164,7 +164,7 @@ internal fun extractInputOutputTypesFromCallableReferenceExpectedType(
|
||||
|
||||
return when {
|
||||
expectedType.isBuiltinFunctionalType(session) ->
|
||||
extractInputOutputTypesFromFunctionType(expectedType, session)
|
||||
InputOutputTypes(expectedType.valueParameterTypesIncludingReceiver(session), expectedType.returnType(session))
|
||||
|
||||
// ReflectionTypes.isBaseTypeForNumberedReferenceTypes(expectedType) ->
|
||||
// InputOutputTypes(emptyList(), expectedType.arguments.single().type.unwrap())
|
||||
@@ -187,22 +187,3 @@ internal fun extractInputOutputTypesFromCallableReferenceExpectedType(
|
||||
else -> null
|
||||
}
|
||||
}
|
||||
|
||||
private fun extractInputOutputTypesFromFunctionType(
|
||||
functionType: ConeKotlinType,
|
||||
session: FirSession
|
||||
): InputOutputTypes {
|
||||
val parameters = functionType.valueParameterTypesIncludingReceiver(session).map {
|
||||
it ?: ConeClassLikeTypeImpl(
|
||||
ConeClassLikeLookupTagImpl(StandardClassIds.Nothing), emptyArray(),
|
||||
isNullable = false
|
||||
)
|
||||
}
|
||||
|
||||
val outputType = functionType.returnType(session) ?: ConeClassLikeTypeImpl(
|
||||
ConeClassLikeLookupTagImpl(StandardClassIds.Any), emptyArray(),
|
||||
isNullable = true
|
||||
)
|
||||
|
||||
return InputOutputTypes(parameters, outputType)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
fun invoke(f: Function1<Any?, *>) = f("OK")
|
||||
|
||||
fun box() = invoke { it } as String
|
||||
Vendored
+1
-1
@@ -228,7 +228,7 @@ fun main() {
|
||||
val x70: (Int) -> Unit = selectNumber(id(fun (it) { }), id {}, id {})
|
||||
val x71: String.() -> Unit = select(<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, kotlin.Unit>")!>id(fun String.() { })<!>, <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.String, kotlin.Unit>")!>id(fun(x: String) {})<!>)
|
||||
val x72: String.() -> Unit = select(fun String.() { }, fun(x: String) {}) // must be error
|
||||
select(id(fun String.(x: String) {}), id(fun(x: String, y: String) { }), fun (x, y) { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Any?")!>y<!> })
|
||||
select(id(fun String.(x: String) {}), id(fun(x: String, y: String) { }), fun (x, y) { <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.String")!>x<!>;<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Nothing")!>y<!> })
|
||||
select(id<Int.(String) -> Unit>(fun (x, y) {}), { x: Int, y: String -> x }) // receiver of anonymous function must be specified explicitly
|
||||
select(id<Int.(String) -> Unit>(fun Int.(y) {}), { x: Int, y: String -> x })
|
||||
<!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Function1<kotlin.Number, java.io.Serializable>")!>select(A3(), fun (x) = "", { a -> <!DEBUG_INFO_EXPRESSION_TYPE("kotlin.Number")!>a<!> })<!>
|
||||
|
||||
+6
@@ -17004,6 +17004,12 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
runTest("compiler/testData/codegen/box/inference/kt42130.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("lambdaWithStarReturn.kt")
|
||||
public void testLambdaWithStarReturn() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/lambdaWithStarReturn.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("lambdasWithExtensionFunctionType.kt")
|
||||
public void testLambdasWithExtensionFunctionType() throws Exception {
|
||||
|
||||
+6
@@ -17022,6 +17022,12 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
||||
runTest("compiler/testData/codegen/box/inference/kt42130.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("lambdaWithStarReturn.kt")
|
||||
public void testLambdaWithStarReturn() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/lambdaWithStarReturn.kt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@TestMetadata("lambdasWithExtensionFunctionType.kt")
|
||||
public void testLambdasWithExtensionFunctionType() throws Exception {
|
||||
|
||||
+5
@@ -14086,6 +14086,11 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
||||
runTest("compiler/testData/codegen/box/inference/kt42130.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaWithStarReturn.kt")
|
||||
public void testLambdaWithStarReturn() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/lambdaWithStarReturn.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdasWithExtensionFunctionType.kt")
|
||||
public void testLambdasWithExtensionFunctionType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/lambdasWithExtensionFunctionType.kt");
|
||||
|
||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java
Generated
+5
@@ -12370,6 +12370,11 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
||||
runTest("compiler/testData/codegen/box/inference/kt42130.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaWithStarReturn.kt")
|
||||
public void testLambdaWithStarReturn() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/lambdaWithStarReturn.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdasWithExtensionFunctionType.kt")
|
||||
public void testLambdasWithExtensionFunctionType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/lambdasWithExtensionFunctionType.kt");
|
||||
|
||||
Generated
+5
@@ -11791,6 +11791,11 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/inference/kt42130.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaWithStarReturn.kt")
|
||||
public void testLambdaWithStarReturn() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/lambdaWithStarReturn.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdasWithExtensionFunctionType.kt")
|
||||
public void testLambdasWithExtensionFunctionType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/lambdasWithExtensionFunctionType.kt");
|
||||
|
||||
Generated
+5
@@ -11856,6 +11856,11 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
||||
runTest("compiler/testData/codegen/box/inference/kt42130.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaWithStarReturn.kt")
|
||||
public void testLambdaWithStarReturn() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/lambdaWithStarReturn.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdasWithExtensionFunctionType.kt")
|
||||
public void testLambdasWithExtensionFunctionType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/lambdasWithExtensionFunctionType.kt");
|
||||
|
||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java
Generated
+5
@@ -6256,6 +6256,11 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
||||
runTest("compiler/testData/codegen/box/inference/kt42130.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdaWithStarReturn.kt")
|
||||
public void testLambdaWithStarReturn() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/lambdaWithStarReturn.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("lambdasWithExtensionFunctionType.kt")
|
||||
public void testLambdasWithExtensionFunctionType() throws Exception {
|
||||
runTest("compiler/testData/codegen/box/inference/lambdasWithExtensionFunctionType.kt");
|
||||
|
||||
Reference in New Issue
Block a user