FIR: Support type aliases to function types in resolution

This commit is contained in:
Denis Zharkov
2020-02-05 15:23:02 +03:00
parent 7249d2f889
commit 6f6281a3f3
15 changed files with 172 additions and 104 deletions
@@ -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<ConeKotlinType>()?.isBuiltinFunctionalType == true
else -> argument.typeRef.coneTypeSafe<ConeKotlinType>()?.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<FirTypeAliasSymbol>()?.fir ?: return false
if (typeAlias.expandedTypeRef.annotations.any(FirAnnotationCall::isExtensionFunctionAnnotationCall)) return true
return false
}
@@ -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<ConeKotlinType?>
get() {
require(this is ConeClassLikeType)
return typeArguments.dropLast(1).map {
(it as? ConeTypedProjection)?.type
}
private fun ConeKotlinType.valueParameterTypes(session: FirSession): List<ConeKotlinType?> {
require(this is ConeClassLikeType)
return fullyExpandedType(session).typeArguments.dropLast(1).map {
(it as? ConeTypedProjection)?.type
}
}
private val FirAnonymousFunction.returnType get() = returnTypeRef.coneTypeSafe<ConeKotlinType>()
private val FirAnonymousFunction.receiverType get() = receiverTypeRef?.coneTypeSafe<ConeKotlinType>()
@@ -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<FunctionExpression>()
val typeVariable = TypeVariableForLambdaReturnType(argument, "_L")
@@ -124,7 +122,8 @@ private fun extraLambdaInfo(
?: expectedType?.typeArguments?.singleOrNull()?.safeAs<ConeTypedProjection>()?.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<ConeKotlinType>() ?: 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<FunctionExpression>()
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<ConeKotlinType> {
private fun extractLambdaParameters(
expectedType: ConeKotlinType,
argument: FirAnonymousFunction,
expectedTypeIsExtensionFunctionType: Boolean,
session: FirSession
): List<ConeKotlinType> {
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<ConeKotlinType?> {
return valueParameterTypes.let {
private fun ConeKotlinType.extractParametersForFunctionalType(
isExtensionFunctionType: Boolean,
session: FirSession
): List<ConeKotlinType?> {
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<ConeKotlinType>
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<ConeKotlinType>, 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
)
@@ -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)
}
}
@@ -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
}
}
}
}
}
@@ -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<ConeIntegerLiteralType>().getApproximatedType(expectedType))
resultType =
typeRef.resolvedTypeFromPrototype(typeRef.coneTypeUnsafe<ConeIntegerLiteralType>().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<FirStatement> {
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<FirStatement> {
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<ConeKotlinType>()
if (initialType != null) {
@@ -373,4 +376,4 @@ private fun ConeKotlinType.approximateIfPossible(expectedType: ConeKotlinType?)
getApproximatedType(expectedType)
} else {
this
}
}
@@ -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
@@ -0,0 +1,11 @@
private typealias A = String.(Int) -> Int
private fun b(a: A) {
"b".a(1)
}
fun main() {
b {
length + it
}
}
@@ -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|<local>/a|.R|FakeOverride<kotlin/Function2.invoke: R|kotlin/Int|>|(String(b), Int(1))
}
public final fun main(): R|kotlin/Unit| {
R|/b|(<L> = b@fun R|kotlin/String|.<anonymous>(it: R|kotlin/Int|): R|kotlin/Int| {
this@R|special/anonymous|.R|kotlin/String.length|.R|kotlin/Int.plus|(R|<local>/it|)
}
)
}
@@ -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");
@@ -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");
@@ -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("|")
}
@@ -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
}
}
@@ -16,9 +16,9 @@ fun buildB() {
val a2 = applyRestrictions2()
val a3 = applyRestrictions3("foo")
B.Builder().<!UNRESOLVED_REFERENCE!>a1<!>()
B.Builder().<!UNRESOLVED_REFERENCE!>a2<!>()
B.Builder().<!UNRESOLVED_REFERENCE!>a3<!>()
B.Builder().a1()
B.Builder().a2()
B.Builder().a3()
}
// additional example from #KT-34820
@@ -16,7 +16,7 @@ fun buildB() {
val a2 = applyRestrictions2()
val a3 = applyRestrictions3("foo")
B.Builder().<!UNRESOLVED_REFERENCE!>a1<!>()
B.Builder().<!UNRESOLVED_REFERENCE!>a2<!>()
B.Builder().<!UNRESOLVED_REFERENCE!>a3<!>()
B.Builder().a1()
B.Builder().a2()
B.Builder().a3()
}
@@ -36,13 +36,13 @@ class W4(val f: L2) {
}
fun test1() { // to extension lambda 0
val w10 = <!INAPPLICABLE_CANDIDATE!>W1<!> { this } // oi+ ni+
val w10 = W1 { this } // oi+ ni+
val i10: E0 = id { this } // o1- ni+
val j10 = <!INAPPLICABLE_CANDIDATE!>id<!><E0> { 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 = <!INAPPLICABLE_CANDIDATE!>W1<!> { i: Int -> i } // oi- ni-
val i11: E0 = id { i: Int -> i } // o1+ ni+
val w12 = <!INAPPLICABLE_CANDIDATE!>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<E0> { it } // this or it: oi- ni-
val o14 = <!INAPPLICABLE_CANDIDATE!>W1<!> { -> 0 } // oi+ ni+
val o14 = W1 { -> 0 } // oi+ ni+
}
fun test2() { // to extension lambda 1
val w20 = <!INAPPLICABLE_CANDIDATE!>W2<!> { this + <!UNRESOLVED_REFERENCE!>it<!>.<!UNRESOLVED_REFERENCE!>length<!> } // oi+ ni+
val w20 = W2 { this + it.length } // oi+ ni+
val i20: E1 = id { this + <!UNRESOLVED_REFERENCE!>it<!>.<!UNRESOLVED_REFERENCE!>length<!> } // oi- ni+
val w21 = <!INAPPLICABLE_CANDIDATE!>W2<!> { this } // oi+ ni+
val w21 = W2 { this } // oi+ ni+
val i21: E1 = id { this } // oi- ni+
val f21 = <!INAPPLICABLE_CANDIDATE!>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 = <!INAPPLICABLE_CANDIDATE!>W2<!> { s -> this + s.<!UNRESOLVED_REFERENCE!>length<!> } // oi+ ni+
val w22 = W2 { s -> this + s.length } // oi+ ni+
val i22: E1 = id { s -> this + s.<!UNRESOLVED_REFERENCE!>length<!> } // oi+ ni+
val w23 = <!INAPPLICABLE_CANDIDATE!>W2<!> { s -> s.<!UNRESOLVED_REFERENCE!>length<!> } // oi+ ni+
val w23 = W2 { s -> s.length } // oi+ ni+
val i23: E1 = id { s -> s.<!UNRESOLVED_REFERENCE!>length<!> } // oi+ ni+
val w24 = <!INAPPLICABLE_CANDIDATE!>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 = <!INAPPLICABLE_CANDIDATE!>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 = <!INAPPLICABLE_CANDIDATE!>W2<!> { i: Int, s -> i <!AMBIGUITY!>+<!> s.<!UNRESOLVED_REFERENCE!>length<!> } // oi- ni-
val i28: E1 = id { i: Int, s -> i <!AMBIGUITY!>+<!> s.<!UNRESOLVED_REFERENCE!>length<!> } // oi- ni-
val w29 = W2 { i: Int, s: String -> i + s.length } // oi- ni-
val w29 = <!INAPPLICABLE_CANDIDATE!>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 = <!INAPPLICABLE_CANDIDATE!>W3<!> { i -> i } // oi+ ni+
val w30 = W3 { i -> i } // oi+ ni+
val i30: L1 = id { i -> i } // oi+ ni+
val w31 = <!INAPPLICABLE_CANDIDATE!>W3<!> { <!UNRESOLVED_REFERENCE!>it<!> } // oi+ ni+
val w31 = W3 { it } // oi+ ni+
val i31: L1 = id { <!UNRESOLVED_REFERENCE!>it<!> } // oi- ni+
val j31 = <!INAPPLICABLE_CANDIDATE!>id<!><L1> { <!UNRESOLVED_REFERENCE!>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<L1> { this } // this or it: oi- ni-
val w33 = W3(fun Int.(): Int = this) // oi- ni+
val w33 = <!INAPPLICABLE_CANDIDATE!>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 = <!INAPPLICABLE_CANDIDATE!>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)