From 6f6281a3f316edb2dd7b02d800af1864b53faeb7 Mon Sep 17 00:00:00 2001 From: Denis Zharkov Date: Wed, 5 Feb 2020 15:23:02 +0300 Subject: [PATCH] FIR: Support type aliases to function types in resolution --- .../kotlin/fir/resolve/calls/Arguments.kt | 24 ++- .../fir/resolve/calls/PostponedArguments.kt | 137 ++++++++++-------- .../kotlin/fir/resolve/calls/ResolverParts.kt | 3 +- .../fir/resolve/calls/TowerResolveManager.kt | 4 +- ...rCallCompletionResultsWriterTransformer.kt | 19 ++- .../FirDeclarationsResolveTransformer.kt | 2 +- .../testData/resolve/functionTypeAlias.kt | 11 ++ .../testData/resolve/functionTypeAlias.txt | 11 ++ .../fir/FirDiagnosticsTestGenerated.java | 5 + ...DiagnosticsWithLightTreeTestGenerated.java | 5 + .../org/jetbrains/kotlin/fir/FirRenderer.kt | 4 +- .../kotlin/fir/types/FirTypeUtils.kt | 9 +- ...9returnTypeWithTypealiasSubtitution.fir.kt | 6 +- ...ithTypealiasSubtitutionOldInference.fir.kt | 6 +- .../tests/regressions/kt30245.fir.kt | 30 ++-- 15 files changed, 172 insertions(+), 104 deletions(-) create mode 100644 compiler/fir/resolve/testData/resolve/functionTypeAlias.kt create mode 100644 compiler/fir/resolve/testData/resolve/functionTypeAlias.txt diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt index d4ada8c462d..e731baf8bb6 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/Arguments.kt @@ -12,6 +12,8 @@ import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.inferenceContext import org.jetbrains.kotlin.fir.references.FirResolvedNamedReference +import org.jetbrains.kotlin.fir.resolve.fullyExpandedType +import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.firUnsafe import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType import org.jetbrains.kotlin.fir.resolve.withNullability @@ -19,11 +21,13 @@ import org.jetbrains.kotlin.fir.returnExpressions import org.jetbrains.kotlin.fir.scopes.impl.FirILTTypeRefPlaceHolder import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperator import org.jetbrains.kotlin.fir.scopes.impl.FirIntegerOperatorCall +import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol import org.jetbrains.kotlin.fir.types.* import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder import org.jetbrains.kotlin.resolve.calls.inference.addSubtypeConstraintIfCompatible import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystemConstraintPosition import org.jetbrains.kotlin.types.model.CaptureStatus +import org.jetbrains.kotlin.utils.addToStdlib.safeAs fun Candidate.resolveArgumentExpression( @@ -299,14 +303,14 @@ private fun Candidate.getExpectedTypeWithSAMConversion( argument: FirExpression, candidateExpectedType: ConeKotlinType ): ConeKotlinType? { - if (candidateExpectedType.isBuiltinFunctionalType) return null + if (candidateExpectedType.isBuiltinFunctionalType(session)) return null // TODO: if (!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionPerArgument)) return null val firNamedFunction = symbol.fir as? FirSimpleFunction ?: return null if (!samResolver.shouldRunSamConversionForFunction(firNamedFunction)) return null val argumentIsFunctional = when ((argument as? FirWrappedArgumentExpression)?.expression ?: argument) { is FirAnonymousFunction, is FirCallableReferenceAccess -> true - else -> argument.typeRef.coneTypeSafe()?.isBuiltinFunctionalType == true + else -> argument.typeRef.coneTypeSafe()?.isBuiltinFunctionalType(session) == true } if (!argumentIsFunctional) return null @@ -335,3 +339,19 @@ internal fun FirExpression.getExpectedType( private fun ConeKotlinType.varargElementType(session: FirSession): ConeKotlinType { return this.arrayElementType(session) ?: error("Failed to extract! ${this.render()}!") } + +fun FirTypeRef.isExtensionFunctionType(session: FirSession): Boolean { + if (annotations.any(FirAnnotationCall::isExtensionFunctionAnnotationCall)) return true + + if (this !is FirResolvedTypeRef) return false + val type = type as? ConeClassLikeType ?: return false + if (type.fullyExpandedType(session) === type) return false + + val typeAlias = type.lookupTag + .toSymbol(session) + ?.safeAs()?.fir ?: return false + + if (typeAlias.expandedTypeRef.annotations.any(FirAnnotationCall::isExtensionFunctionAnnotationCall)) return true + + return false +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/PostponedArguments.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/PostponedArguments.kt index 9f2ed94dc28..13c2c9b15d8 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/PostponedArguments.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/PostponedArguments.kt @@ -5,11 +5,13 @@ package org.jetbrains.kotlin.fir.resolve.calls +import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.resolve.DoubleColonLHS import org.jetbrains.kotlin.fir.resolve.createFunctionalType +import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.symbols.StandardClassIds import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl import org.jetbrains.kotlin.fir.types.* @@ -31,8 +33,8 @@ fun Candidate.preprocessLambdaArgument( } val resolvedArgument = - extractLambdaInfoFromFunctionalType(expectedType, expectedTypeRef, argument) - ?: extraLambdaInfo(expectedType, expectedTypeRef, argument, csBuilder) + extractLambdaInfoFromFunctionalType(expectedType, expectedTypeRef, argument, bodyResolveComponents.session) + ?: extraLambdaInfo(expectedType, expectedTypeRef, argument, csBuilder, bodyResolveComponents.session) if (expectedType != null) { // TODO: add SAM conversion processing @@ -53,51 +55,45 @@ fun Candidate.preprocessCallableReference( expectedType: ConeKotlinType ) { val lhs = bodyResolveComponents.doubleColonExpressionResolver.resolveDoubleColonLHS(argument) - postponedAtoms += ResolvedCallableReferenceAtom(argument, expectedType, lhs) + postponedAtoms += ResolvedCallableReferenceAtom(argument, expectedType, lhs, bodyResolveComponents.session) } -val ConeKotlinType.isBuiltinFunctionalType: Boolean - get() { - return when (this) { - is ConeClassLikeType -> this.lookupTag.classId.asString().startsWith("kotlin/Function") - else -> false - } +fun ConeKotlinType.isBuiltinFunctionalType(session: FirSession): Boolean { + return when (this) { + is ConeClassLikeType -> fullyExpandedType(session).lookupTag.classId.asString().startsWith("kotlin/Function") + else -> false } +} - -private val ConeKotlinType.isSuspendFunctionType: Boolean - get() { - val type = this - return when (type) { - is ConeClassLikeType -> { - val classId = type.lookupTag.classId - classId.packageFqName.asString() == "kotlin" && classId.relativeClassName.asString().startsWith("SuspendFunction") - } - else -> false +fun ConeKotlinType.isSuspendFunctionType(session: FirSession): Boolean { + return when (val type = this) { + is ConeClassLikeType -> { + val classId = type.fullyExpandedType(session).lookupTag.classId + classId.packageFqName.asString() == "kotlin" && classId.relativeClassName.asString().startsWith("SuspendFunction") } + else -> false } +} -private fun ConeKotlinType.receiverType(expectedTypeRef: FirTypeRef): ConeKotlinType? { - if (expectedTypeRef.isExtensionFunctionType()) { - return (this.typeArguments.first() as ConeTypedProjection).type +fun ConeKotlinType.receiverType(expectedTypeRef: FirTypeRef, session: FirSession): ConeKotlinType? { + if (isBuiltinFunctionalType(session) && expectedTypeRef.isExtensionFunctionType(session)) { + return ((this as ConeClassLikeType).fullyExpandedType(session).typeArguments.first() as ConeTypedProjection).type } return null } -val ConeKotlinType.returnType: ConeKotlinType? - get() { - require(this is ConeClassLikeType) - val projection = typeArguments.last() - return (projection as? ConeTypedProjection)?.type - } +fun ConeKotlinType.returnType(session: FirSession): ConeKotlinType? { + require(this is ConeClassLikeType) + val projection = fullyExpandedType(session).typeArguments.last() + return (projection as? ConeTypedProjection)?.type +} -val ConeKotlinType.valueParameterTypes: List - get() { - require(this is ConeClassLikeType) - return typeArguments.dropLast(1).map { - (it as? ConeTypedProjection)?.type - } +private fun ConeKotlinType.valueParameterTypes(session: FirSession): List { + require(this is ConeClassLikeType) + return fullyExpandedType(session).typeArguments.dropLast(1).map { + (it as? ConeTypedProjection)?.type } +} private val FirAnonymousFunction.returnType get() = returnTypeRef.coneTypeSafe() private val FirAnonymousFunction.receiverType get() = receiverTypeRef?.coneTypeSafe() @@ -107,13 +103,15 @@ private fun extraLambdaInfo( expectedType: ConeKotlinType?, expectedTypeRef: FirTypeRef, argument: FirAnonymousFunction, - csBuilder: ConstraintSystemBuilder + csBuilder: ConstraintSystemBuilder, + session: FirSession ): ResolvedLambdaAtom { // val builtIns = csBuilder.builtIns - val isSuspend = expectedType?.isSuspendFunctionType ?: false + val isSuspend = expectedType?.isSuspendFunctionType(session) ?: false val isFunctionSupertype = - expectedType != null && expectedType.lowerBoundIfFlexible().isBuiltinFunctionalType//isNotNullOrNullableFunctionSupertype(expectedType) + expectedType != null && expectedType.lowerBoundIfFlexible() + .isBuiltinFunctionalType(session)//isNotNullOrNullableFunctionSupertype(expectedType) val argumentAsFunctionExpression = argument//.safeAs() val typeVariable = TypeVariableForLambdaReturnType(argument, "_L") @@ -124,7 +122,8 @@ private fun extraLambdaInfo( ?: expectedType?.typeArguments?.singleOrNull()?.safeAs()?.type?.takeIf { isFunctionSupertype } ?: typeVariable.defaultType - val nothingType = argument.session.builtinTypes.nothingType.type //StandardClassIds.Nothing(argument.session.firSymbolProvider).constructType(emptyArray(), false) + val nothingType = argument.session.builtinTypes.nothingType + .type //StandardClassIds.Nothing(argument.session.firSymbolProvider).constructType(emptyArray(), false) val parameters = argument.valueParameters?.map { it.returnTypeRef.coneTypeSafe() ?: nothingType } ?: emptyList() @@ -138,20 +137,23 @@ private fun extraLambdaInfo( internal fun extractLambdaInfoFromFunctionalType( expectedType: ConeKotlinType?, expectedTypeRef: FirTypeRef, - argument: FirAnonymousFunction + argument: FirAnonymousFunction, + session: FirSession ): ResolvedLambdaAtom? { if (expectedType == null) return null - if (expectedType is ConeFlexibleType) return extractLambdaInfoFromFunctionalType(expectedType.lowerBound, expectedTypeRef, argument) - if (!expectedType.isBuiltinFunctionalType) return null + if (expectedType is ConeFlexibleType) { + return extractLambdaInfoFromFunctionalType(expectedType.lowerBound, expectedTypeRef, argument, session) + } + if (!expectedType.isBuiltinFunctionalType(session)) return null val argumentAsFunctionExpression = argument//.safeAs() - val receiverType = argumentAsFunctionExpression.receiverType ?: expectedType.receiverType(expectedTypeRef) - val returnType = argumentAsFunctionExpression.returnType ?: expectedType.returnType ?: return null - val parameters = extractLambdaParameters(expectedType, argument, expectedTypeRef.isExtensionFunctionType()) + val receiverType = argumentAsFunctionExpression.receiverType ?: expectedType.receiverType(expectedTypeRef, session) + val returnType = argumentAsFunctionExpression.returnType ?: expectedType.returnType(session) ?: return null + val parameters = extractLambdaParameters(expectedType, argument, expectedTypeRef.isExtensionFunctionType(session), session) return ResolvedLambdaAtom( argument, - expectedType.isSuspendFunctionType, + expectedType.isSuspendFunctionType(session), receiverType, parameters, returnType, @@ -159,12 +161,16 @@ internal fun extractLambdaInfoFromFunctionalType( ) } -private fun extractLambdaParameters(expectedType: ConeKotlinType, argument: FirAnonymousFunction, expectedTypeIsExtensionFunctionType: Boolean): List { +private fun extractLambdaParameters( + expectedType: ConeKotlinType, + argument: FirAnonymousFunction, + expectedTypeIsExtensionFunctionType: Boolean, + session: FirSession +): List { val parameters = argument.valueParameters - val expectedParameters = expectedType.extractParametersForFunctionalType(expectedTypeIsExtensionFunctionType) - - val nullableAnyType = argument.session.builtinTypes.nullableAnyType.type //StandardClassIds.Any(argument.session.firSymbolProvider).constructType(emptyArray(), true) + val expectedParameters = expectedType.extractParametersForFunctionalType(expectedTypeIsExtensionFunctionType, session) + val nullableAnyType = argument.session.builtinTypes.nullableAnyType.type if (parameters.isEmpty()) { return expectedParameters.map { it?.type ?: nullableAnyType } } @@ -175,8 +181,11 @@ private fun extractLambdaParameters(expectedType: ConeKotlinType, argument: FirA } } -private fun ConeKotlinType.extractParametersForFunctionalType(isExtensionFunctionType: Boolean): List { - return valueParameterTypes.let { +private fun ConeKotlinType.extractParametersForFunctionalType( + isExtensionFunctionType: Boolean, + session: FirSession +): List { + return valueParameterTypes(session).let { if (isExtensionFunctionType) { it.drop(1) } else { @@ -217,7 +226,8 @@ class ResolvedLambdaAtom( class ResolvedCallableReferenceAtom( val reference: FirCallableReferenceAccess, val expectedType: ConeKotlinType?, - val lhs: DoubleColonLHS? + val lhs: DoubleColonLHS?, + private val session: FirSession ) : PostponedResolvedAtomMarker { override var analyzed: Boolean = false var postponed: Boolean = false @@ -227,23 +237,27 @@ class ResolvedCallableReferenceAtom( override val inputTypes: Collection get() { if (!postponed) return emptyList() - return extractInputOutputTypesFromCallableReferenceExpectedType(expectedType)?.inputTypes ?: listOfNotNull(expectedType) + return extractInputOutputTypesFromCallableReferenceExpectedType(expectedType, session)?.inputTypes + ?: listOfNotNull(expectedType) } override val outputType: ConeKotlinType? get() { if (!postponed) return null - return extractInputOutputTypesFromCallableReferenceExpectedType(expectedType)?.outputType + return extractInputOutputTypesFromCallableReferenceExpectedType(expectedType, session)?.outputType } } private data class InputOutputTypes(val inputTypes: List, val outputType: ConeKotlinType) -private fun extractInputOutputTypesFromCallableReferenceExpectedType(expectedType: ConeKotlinType?): InputOutputTypes? { +private fun extractInputOutputTypesFromCallableReferenceExpectedType( + expectedType: ConeKotlinType?, + session: FirSession +): InputOutputTypes? { if (expectedType == null) return null return when { - expectedType.isBuiltinFunctionalType || expectedType.isSuspendFunctionType -> - extractInputOutputTypesFromFunctionType(expectedType) + expectedType.isBuiltinFunctionalType(session) || expectedType.isSuspendFunctionType(session) -> + extractInputOutputTypesFromFunctionType(expectedType, session) // ReflectionTypes.isBaseTypeForNumberedReferenceTypes(expectedType) -> // InputOutputTypes(emptyList(), expectedType.arguments.single().type.unwrap()) @@ -267,9 +281,12 @@ private fun extractInputOutputTypesFromCallableReferenceExpectedType(expectedTyp } } -private fun extractInputOutputTypesFromFunctionType(functionType: ConeKotlinType): InputOutputTypes { +private fun extractInputOutputTypesFromFunctionType( + functionType: ConeKotlinType, + session: FirSession +): InputOutputTypes { val receiver = null// TODO: functionType.receiverType() - val parameters = functionType.valueParameterTypes.map { + val parameters = functionType.valueParameterTypes(session).map { it ?: ConeClassLikeTypeImpl( ConeClassLikeLookupTagImpl(StandardClassIds.Nothing), emptyArray(), isNullable = false @@ -277,7 +294,7 @@ private fun extractInputOutputTypesFromFunctionType(functionType: ConeKotlinType } val inputTypes = /*listOfNotNull(receiver) +*/ parameters - val outputType = functionType.returnType ?: ConeClassLikeTypeImpl( + val outputType = functionType.returnType(session) ?: ConeClassLikeTypeImpl( ConeClassLikeLookupTagImpl(StandardClassIds.Any), emptyArray(), isNullable = true ) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt index b0460bf7e76..2d919f67561 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolverParts.kt @@ -99,8 +99,7 @@ internal sealed class CheckReceivers : ResolutionStage() { val receiverType = (callable.receiverTypeRef as FirResolvedTypeRef?)?.type if (receiverType != null) return receiverType val returnTypeRef = callable.returnTypeRef as? FirResolvedTypeRef ?: return null - if (!returnTypeRef.isExtensionFunctionType()) return null - return (returnTypeRef.type.typeArguments.firstOrNull() as? ConeTypedProjection)?.type + return returnTypeRef.type.receiverType(returnTypeRef, bodyResolveComponents.session) } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerResolveManager.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerResolveManager.kt index 14f45e1698f..56a8c46dc53 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerResolveManager.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/TowerResolveManager.kt @@ -168,7 +168,7 @@ class TowerResolveManager internal constructor(private val towerResolver: FirTow for (invokeReceiverCandidate in invokeReceiverCollector.bestCandidates()) { val symbol = invokeReceiverCandidate.symbol as FirCallableSymbol<*> - val isExtensionFunctionType = symbol.fir.returnTypeRef.isExtensionFunctionType() + val isExtensionFunctionType = symbol.fir.returnTypeRef.isExtensionFunctionType(towerResolver.components.session) if (invokeBuiltinExtensionMode && !isExtensionFunctionType) { continue } @@ -303,4 +303,4 @@ class TowerResolveManager internal constructor(private val towerResolver: FirTow } } } -} \ No newline at end of file +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt index 0d2ae26148a..bcca01b721c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirCallCompletionResultsWriterTransformer.kt @@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.references.impl.FirResolvedNamedReferenceImpl import org.jetbrains.kotlin.fir.resolve.calls.Candidate import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate import org.jetbrains.kotlin.fir.resolve.calls.isBuiltinFunctionalType +import org.jetbrains.kotlin.fir.resolve.calls.returnType import org.jetbrains.kotlin.fir.resolve.constructFunctionalTypeRef import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.substituteOrNull @@ -187,7 +188,8 @@ class FirCallCompletionResultsWriterTransformer( result = when (result) { is FirIntegerOperatorCall -> { val expectedType = data?.getExpectedType(functionCall) - resultType = typeRef.resolvedTypeFromPrototype(typeRef.coneTypeUnsafe().getApproximatedType(expectedType)) + resultType = + typeRef.resolvedTypeFromPrototype(typeRef.coneTypeUnsafe().getApproximatedType(expectedType)) result.transformArguments(this, expectedType?.toExpectedType()).transformSingle(integerApproximator, expectedType) } else -> { @@ -238,9 +240,9 @@ class FirCallCompletionResultsWriterTransformer( private fun Candidate.createArgumentsMapping(): ExpectedArgumentType? { return argumentMapping?.map { (argument, valueParameter) -> - val expectedType = valueParameter.returnTypeRef.substitute(this) - argument.unwrapArgument() to expectedType - } + val expectedType = valueParameter.returnTypeRef.substitute(this) + argument.unwrapArgument() to expectedType + } ?.toMap()?.toExpectedType() } @@ -248,7 +250,8 @@ class FirCallCompletionResultsWriterTransformer( delegatedConstructorCall: FirDelegatedConstructorCall, data: ExpectedArgumentType? ): CompositeTransformResult { - val calleeReference = delegatedConstructorCall.calleeReference as? FirNamedReferenceWithCandidate ?: return delegatedConstructorCall.compose() + val calleeReference = + delegatedConstructorCall.calleeReference as? FirNamedReferenceWithCandidate ?: return delegatedConstructorCall.compose() val result = delegatedConstructorCall.transformArguments(this, calleeReference.candidate.createArgumentsMapping()) return result.transformCalleeReference( @@ -276,8 +279,8 @@ class FirCallCompletionResultsWriterTransformer( data: ExpectedArgumentType? ): CompositeTransformResult { val expectedReturnType = data?.getExpectedType(anonymousFunction) - ?.takeIf { it.isBuiltinFunctionalType } - ?.let { it.typeArguments.last() as? ConeClassLikeType } + ?.takeIf { it.isBuiltinFunctionalType(session) } + ?.returnType(session) as? ConeClassLikeType val initialType = anonymousFunction.returnTypeRef.coneTypeSafe() if (initialType != null) { @@ -373,4 +376,4 @@ private fun ConeKotlinType.approximateIfPossible(expectedType: ConeKotlinType?) getApproximatedType(expectedType) } else { this -} \ No newline at end of file +} diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index 44a3738864c..264381e819d 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -416,7 +416,7 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer) val expectedTypeRef = (data as? ResolutionMode.WithExpectedType)?.expectedTypeRef ?: FirImplicitTypeRefImpl(null) val resolvedLambdaAtom = (expectedTypeRef as? FirResolvedTypeRef)?.let { extractLambdaInfoFromFunctionalType( - it.type, it, anonymousFunction + it.type, it, anonymousFunction, session ) } var af = anonymousFunction diff --git a/compiler/fir/resolve/testData/resolve/functionTypeAlias.kt b/compiler/fir/resolve/testData/resolve/functionTypeAlias.kt new file mode 100644 index 00000000000..f1c5c818cc2 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/functionTypeAlias.kt @@ -0,0 +1,11 @@ +private typealias A = String.(Int) -> Int + +private fun b(a: A) { + "b".a(1) +} + +fun main() { + b { + length + it + } +} diff --git a/compiler/fir/resolve/testData/resolve/functionTypeAlias.txt b/compiler/fir/resolve/testData/resolve/functionTypeAlias.txt new file mode 100644 index 00000000000..ef69d2174f3 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/functionTypeAlias.txt @@ -0,0 +1,11 @@ +FILE: functionTypeAlias.kt + private final typealias A = R|kotlin/String.(kotlin/Int) -> kotlin/Int| + private final fun b(a: R|A|): R|kotlin/Unit| { + R|/a|.R|FakeOverride|(String(b), Int(1)) + } + public final fun main(): R|kotlin/Unit| { + R|/b|( = b@fun R|kotlin/String|.(it: R|kotlin/Int|): R|kotlin/Int| { + this@R|special/anonymous|.R|kotlin/String.length|.R|kotlin/Int.plus|(R|/it|) + } + ) + } diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index 3340ac63189..8dc865f90c6 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -128,6 +128,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/resolve/testData/resolve/ft.kt"); } + @TestMetadata("functionTypeAlias.kt") + public void testFunctionTypeAlias() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/functionTypeAlias.kt"); + } + @TestMetadata("functionTypes.kt") public void testFunctionTypes() throws Exception { runTest("compiler/fir/resolve/testData/resolve/functionTypes.kt"); diff --git a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java index 90404bb7548..4b903412f31 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java @@ -128,6 +128,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/resolve/testData/resolve/ft.kt"); } + @TestMetadata("functionTypeAlias.kt") + public void testFunctionTypeAlias() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/functionTypeAlias.kt"); + } + @TestMetadata("functionTypes.kt") public void testFunctionTypes() throws Exception { runTest("compiler/fir/resolve/testData/resolve/functionTypes.kt"); diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt index 1b7c77ac375..bb472c76085 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirRenderer.kt @@ -769,7 +769,9 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() { annotations.renderAnnotations() print("R|") val coneType = resolvedTypeRef.type - print(coneType.renderFunctionType(kind, resolvedTypeRef.isExtensionFunctionType())) + print(coneType.renderFunctionType(kind, resolvedTypeRef.annotations.any { + it.isExtensionFunctionAnnotationCall + })) print("|") } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt index 1fab8a0b049..bab7127700b 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/types/FirTypeUtils.kt @@ -5,6 +5,7 @@ package org.jetbrains.kotlin.fir.types +import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall import org.jetbrains.kotlin.fir.expressions.FirConstKind import org.jetbrains.kotlin.fir.symbols.StandardClassIds @@ -38,12 +39,6 @@ val FirFunctionTypeRef.parametersCount: Int const val EXTENSION_FUNCTION_ANNOTATION = "kotlin/ExtensionFunctionType" -fun FirTypeRef.isExtensionFunctionType(): Boolean { - return annotations.any { - it.isExtensionFunctionAnnotationCall - } -} - val FirAnnotationCall.isExtensionFunctionAnnotationCall: Boolean get() = (this as? FirAnnotationCall)?.let { (it.annotationTypeRef as? FirResolvedTypeRef)?.let { @@ -64,4 +59,4 @@ fun ConeClassLikeType.toConstKind(): FirConstKind<*>? = when (lookupTag.classId) StandardClassIds.Int -> FirConstKind.Int StandardClassIds.Long -> FirConstKind.Long else -> null -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/inference/substitutions/kt32189returnTypeWithTypealiasSubtitution.fir.kt b/compiler/testData/diagnostics/tests/inference/substitutions/kt32189returnTypeWithTypealiasSubtitution.fir.kt index 450d0ba1b93..9ff15b91a24 100644 --- a/compiler/testData/diagnostics/tests/inference/substitutions/kt32189returnTypeWithTypealiasSubtitution.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/substitutions/kt32189returnTypeWithTypealiasSubtitution.fir.kt @@ -16,9 +16,9 @@ fun buildB() { val a2 = applyRestrictions2() val a3 = applyRestrictions3("foo") - B.Builder().a1() - B.Builder().a2() - B.Builder().a3() + B.Builder().a1() + B.Builder().a2() + B.Builder().a3() } // additional example from #KT-34820 diff --git a/compiler/testData/diagnostics/tests/inference/substitutions/kt32189returnTypeWithTypealiasSubtitutionOldInference.fir.kt b/compiler/testData/diagnostics/tests/inference/substitutions/kt32189returnTypeWithTypealiasSubtitutionOldInference.fir.kt index cf0a40467b2..b610eb5ffe2 100644 --- a/compiler/testData/diagnostics/tests/inference/substitutions/kt32189returnTypeWithTypealiasSubtitutionOldInference.fir.kt +++ b/compiler/testData/diagnostics/tests/inference/substitutions/kt32189returnTypeWithTypealiasSubtitutionOldInference.fir.kt @@ -16,7 +16,7 @@ fun buildB() { val a2 = applyRestrictions2() val a3 = applyRestrictions3("foo") - B.Builder().a1() - B.Builder().a2() - B.Builder().a3() + B.Builder().a1() + B.Builder().a2() + B.Builder().a3() } diff --git a/compiler/testData/diagnostics/tests/regressions/kt30245.fir.kt b/compiler/testData/diagnostics/tests/regressions/kt30245.fir.kt index 70b7f9955db..5ebafaa1404 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt30245.fir.kt +++ b/compiler/testData/diagnostics/tests/regressions/kt30245.fir.kt @@ -36,13 +36,13 @@ class W4(val f: L2) { } fun test1() { // to extension lambda 0 - val w10 = W1 { this } // oi+ ni+ + val w10 = W1 { this } // oi+ ni+ val i10: E0 = id { this } // o1- ni+ val j10 = id { this } // oi+ ni+ val f10 = W1(fun Int.(): Int = this) // oi+ ni+ val g10: E0 = id(fun Int.(): Int = this) // oi+ ni+ - val w11 = W1 { i: Int -> i } // oi- ni- + val w11 = W1 { i: Int -> i } // oi- ni- val i11: E0 = id { i: Int -> i } // o1+ ni+ val w12 = W1 { i -> i } // oi- ni- val i12: E0 = id { i -> i } // oi- ni- @@ -53,23 +53,23 @@ fun test1() { // to extension lambda 0 // val i13: E0 = id { it } // this or it: oi- ni- // val j13 = id { it } // this or it: oi- ni- - val o14 = W1 { -> 0 } // oi+ ni+ + val o14 = W1 { -> 0 } // oi+ ni+ } fun test2() { // to extension lambda 1 - val w20 = W2 { this + it.length } // oi+ ni+ + val w20 = W2 { this + it.length } // oi+ ni+ val i20: E1 = id { this + it.length } // oi- ni+ - val w21 = W2 { this } // oi+ ni+ + val w21 = W2 { this } // oi+ ni+ val i21: E1 = id { this } // oi- ni+ - val f21 = W2(fun Int.(String): Int = this) // oi+ ni+ + val f21 = W2(fun Int.(String): Int = this) // oi+ ni+ val g21: E1 = id(fun Int.(String): Int = this) // oi+ ni+ - val w22 = W2 { s -> this + s.length } // oi+ ni+ + val w22 = W2 { s -> this + s.length } // oi+ ni+ val i22: E1 = id { s -> this + s.length } // oi+ ni+ - val w23 = W2 { s -> s.length } // oi+ ni+ + val w23 = W2 { s -> s.length } // oi+ ni+ val i23: E1 = id { s -> s.length } // oi+ ni+ - val w24 = W2 { s: String -> this + s.length } // oi+ ni+ + val w24 = W2 { s: String -> this + s.length } // oi+ ni+ // val i24: E1 = id { s: String -> this + s.length } //oi- ni- - val w25 = W2 { s: String -> s.length } // oi+ ni+ + val w25 = W2 { s: String -> s.length } // oi+ ni+ // val i25: E1 = id { s: String -> s.length } // oi- ni- // yet unsupported cases with ambiguity for the lambda conversion (commented constructors in wrappers above) @@ -80,7 +80,7 @@ fun test2() { // to extension lambda 1 val w28 = W2 { i: Int, s -> i + s.length } // oi- ni- val i28: E1 = id { i: Int, s -> i + s.length } // oi- ni- - val w29 = W2 { i: Int, s: String -> i + s.length } // oi- ni- + val w29 = W2 { i: Int, s: String -> i + s.length } // oi- ni- val i29: E1 = id { i: Int, s: String -> i + s.length } // oi+ ni+ // yet unsupported cases with ambiguity for the lambda conversion (commented constructors in wrappers above) @@ -89,9 +89,9 @@ fun test2() { // to extension lambda 1 } fun test3() { // to non-extension lambda 1 - val w30 = W3 { i -> i } // oi+ ni+ + val w30 = W3 { i -> i } // oi+ ni+ val i30: L1 = id { i -> i } // oi+ ni+ - val w31 = W3 { it } // oi+ ni+ + val w31 = W3 { it } // oi+ ni+ val i31: L1 = id { it } // oi- ni+ val j31 = id { it } // oi+ ni+ @@ -100,7 +100,7 @@ fun test3() { // to non-extension lambda 1 // val i32: L1 = id { this } // this or it: oi- ni- // val j32 = id { this } // this or it: oi- ni- - val w33 = W3(fun Int.(): Int = this) // oi- ni+ + val w33 = W3(fun Int.(): Int = this) // oi- ni+ val i33: L1 = id(fun Int.(): Int = this) // oi+ ni+ // yet unsupported cases with ambiguity for the lambda conversion (commented constructors in wrappers above) @@ -108,7 +108,7 @@ fun test3() { // to non-extension lambda 1 } fun test4() { // to non-extension lambda 2 - val w30 = W4 { i, s -> i } // oi+ ni+ + val w30 = W4 { i, s -> i } // oi+ ni+ val i30: L2 = id { i, s -> i } // oi+ ni+ // yet unsupported cases with ambiguity for the lambda conversion (commented constructors in wrappers above)