From 309050d956bac099d0c6117bfc91f68e9911550b Mon Sep 17 00:00:00 2001 From: Dmitriy Novozhilov Date: Mon, 29 Jun 2020 15:12:21 +0300 Subject: [PATCH] [FIR] Add `ExtensionFunctionType` attribute #KT-39034 Fixed --- .../inference/nestedExtensionFunctionType.kt | 19 ++++++++++++++++ .../inference/nestedExtensionFunctionType.txt | 22 +++++++++++++++++++ .../fir/FirDiagnosticsTestGenerated.java | 5 +++++ ...DiagnosticsWithLightTreeTestGenerated.java | 5 +++++ .../fir/types/CompilerConeAttributes.kt | 12 ++++++++++ .../kotlin/fir/resolve/calls/Arguments.kt | 16 -------------- .../fir/resolve/calls/ResolutionStages.kt | 2 +- .../providers/impl/FirTypeResolverImpl.kt | 3 ++- .../jetbrains/kotlin/fir/types/TypeUtils.kt | 14 ++++++++++++ .../kotlin/fir/types/FirTypeUtils.kt | 1 + .../diagnostics/tests/inline/labeled.fir.kt | 4 ++-- .../diagnostics/tests/labels/kt4247.fir.kt | 11 ---------- .../diagnostics/tests/labels/kt4247.kt | 1 + 13 files changed, 84 insertions(+), 31 deletions(-) create mode 100644 compiler/fir/analysis-tests/testData/resolve/inference/nestedExtensionFunctionType.kt create mode 100644 compiler/fir/analysis-tests/testData/resolve/inference/nestedExtensionFunctionType.txt delete mode 100644 compiler/testData/diagnostics/tests/labels/kt4247.fir.kt diff --git a/compiler/fir/analysis-tests/testData/resolve/inference/nestedExtensionFunctionType.kt b/compiler/fir/analysis-tests/testData/resolve/inference/nestedExtensionFunctionType.kt new file mode 100644 index 00000000000..a27f1e46c48 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/inference/nestedExtensionFunctionType.kt @@ -0,0 +1,19 @@ +// ISSUE: KT-39034 + +interface A + +fun test_0(a: A, f: A.() -> Unit) { + a.f() +} + +fun test_1(a: A, ys: List Unit>) { + for (y in ys) { + a.y() + } +} + +fun test_2(a: A, vararg zs: A.() -> Unit) { + for (z in zs) { + a.z() + } +} \ No newline at end of file diff --git a/compiler/fir/analysis-tests/testData/resolve/inference/nestedExtensionFunctionType.txt b/compiler/fir/analysis-tests/testData/resolve/inference/nestedExtensionFunctionType.txt new file mode 100644 index 00000000000..202a7b253ca --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/inference/nestedExtensionFunctionType.txt @@ -0,0 +1,22 @@ +FILE: nestedExtensionFunctionType.kt + public abstract interface A : R|kotlin/Any| { + } + public final fun test_0(a: R|A|, f: R|A.() -> kotlin/Unit|): R|kotlin/Unit| { + R|/f|.R|FakeOverride|(R|/a|) + } + public final fun test_1(a: R|A|, ys: R|kotlin/collections/List>|): R|kotlin/Unit| { + lval : R|kotlin/collections/Iterator>| = R|/ys|.R|FakeOverride>|>|() + while(R|/|.R|kotlin/collections/Iterator.hasNext|()) { + lval y: R|(A) -> kotlin/Unit| = R|/|.R|FakeOverride kotlin/Unit|>|() + R|/y|.R|FakeOverride|(R|/a|) + } + + } + public final fun test_2(a: R|A|, vararg zs: @R|kotlin/ExtensionFunctionType|() R|kotlin/Array>|): R|kotlin/Unit| { + lval : R|kotlin/collections/Iterator>| = R|/zs|.R|FakeOverride>|>|() + while(R|/|.R|kotlin/collections/Iterator.hasNext|()) { + lval z: R|(A) -> kotlin/Unit| = R|/|.R|FakeOverride kotlin/Unit|>|() + R|/z|.R|FakeOverride|(R|/a|) + } + + } diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java index 4091d9e6c9d..68d111fd96f 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -1479,6 +1479,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/analysis-tests/testData/resolve/inference/lambdaAsReturnStatementOfLambda.kt"); } + @TestMetadata("nestedExtensionFunctionType.kt") + public void testNestedExtensionFunctionType() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/inference/nestedExtensionFunctionType.kt"); + } + @TestMetadata("nestedLambdas.kt") public void testNestedLambdas() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/inference/nestedLambdas.kt"); diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java index 60607ad68ce..56c706fc607 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java @@ -1479,6 +1479,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/analysis-tests/testData/resolve/inference/lambdaAsReturnStatementOfLambda.kt"); } + @TestMetadata("nestedExtensionFunctionType.kt") + public void testNestedExtensionFunctionType() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/inference/nestedExtensionFunctionType.kt"); + } + @TestMetadata("nestedLambdas.kt") public void testNestedLambdas() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/inference/nestedLambdas.kt"); diff --git a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/CompilerConeAttributes.kt b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/CompilerConeAttributes.kt index 8ae94c9d25a..b5a8011f399 100644 --- a/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/CompilerConeAttributes.kt +++ b/compiler/fir/cones/src/org/jetbrains/kotlin/fir/types/CompilerConeAttributes.kt @@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.types import org.jetbrains.kotlin.name.ClassId import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.Name +import org.jetbrains.kotlin.utils.addToStdlib.runIf import kotlin.reflect.KClass object CompilerConeAttributes { @@ -30,7 +31,18 @@ object CompilerConeAttributes { override val key: KClass = NoInfer::class } + + object ExtensionFunctionType : ConeAttribute() { + val ANNOTATION_CLASS_ID = ClassId(FqName("kotlin"), Name.identifier("ExtensionFunctionType")) + + override fun union(other: ExtensionFunctionType?): ExtensionFunctionType? = other + override fun intersect(other: ExtensionFunctionType?): ExtensionFunctionType? = this + override fun isSubtypeOf(other: ExtensionFunctionType?): Boolean = true + + override val key: KClass = ExtensionFunctionType::class + } } val ConeAttributes.exact: CompilerConeAttributes.Exact? by ConeAttributes.attributeAccessor() val ConeAttributes.noInfer: CompilerConeAttributes.NoInfer? by ConeAttributes.attributeAccessor() +val ConeAttributes.extensionFunctionType: CompilerConeAttributes.ExtensionFunctionType? by ConeAttributes.attributeAccessor() 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 2863a938ddf..809014d79ac 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 @@ -359,19 +359,3 @@ internal fun FirExpression.getExpectedType( fun ConeKotlinType.varargElementType(session: FirSession): ConeKotlinType { return this.arrayElementType() ?: 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/ResolutionStages.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt index 1728b2fc043..7b8758ae026 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/calls/ResolutionStages.kt @@ -97,7 +97,7 @@ internal sealed class CheckReceivers : ResolutionStage() { val receiverType = callable.receiverTypeRef?.coneTypeUnsafe() if (receiverType != null) return receiverType val returnTypeRef = callable.returnTypeRef as? FirResolvedTypeRef ?: return null - if (!returnTypeRef.isExtensionFunctionType(bodyResolveComponents.session)) return null + if (!returnTypeRef.type.isExtensionFunctionType(bodyResolveComponents.session)) return null return (returnTypeRef.type.typeArguments.firstOrNull() as? ConeKotlinTypeProjection)?.type } } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt index de22c57476e..f4a6bcf0189 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/providers/impl/FirTypeResolverImpl.kt @@ -101,7 +101,8 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver { return ConeClassLikeTypeImpl( resolveBuiltInQualified(classId, session).toLookupTag(), parameters.toTypedArray(), - typeRef.isMarkedNullable + typeRef.isMarkedNullable, + attributes ) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt index 558f27e1f84..cffab96b066 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/types/TypeUtils.kt @@ -5,11 +5,15 @@ package org.jetbrains.kotlin.fir.types +import org.jetbrains.kotlin.fir.FirSession +import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall +import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.toSymbol import org.jetbrains.kotlin.fir.symbols.ConeClassLikeLookupTag import org.jetbrains.kotlin.fir.symbols.ConeClassifierLookupTag import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl +import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl import org.jetbrains.kotlin.name.ClassId @@ -18,6 +22,7 @@ import org.jetbrains.kotlin.types.AbstractNullabilityChecker import org.jetbrains.kotlin.types.AbstractStrictEqualityTypeChecker import org.jetbrains.kotlin.types.AbstractTypeCheckerContext import org.jetbrains.kotlin.types.Variance +import org.jetbrains.kotlin.utils.addToStdlib.safeAs object ConeNullabilityChecker { fun isSubtypeOfAny(context: ConeTypeContext, type: ConeKotlinType): Boolean { @@ -217,3 +222,12 @@ fun ConeClassifierLookupTag.constructType(typeArguments: Array error("! ${this::class}") } } + +fun FirTypeRef.isExtensionFunctionType(session: FirSession): Boolean { + return coneTypeSafe()?.isExtensionFunctionType(session) == true +} + +fun ConeKotlinType.isExtensionFunctionType(session: FirSession): Boolean { + val type = this.lowerBoundIfFlexible().fullyExpandedType(session) + return type.attributes.extensionFunctionType != null +} \ No newline at end of file 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 105ab7fb819..aad08b2abad 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 @@ -86,6 +86,7 @@ fun List.computeTypeAttributes(): ConeAttributes { when (type.lookupTag.classId) { CompilerConeAttributes.Exact.ANNOTATION_CLASS_ID -> attributes += CompilerConeAttributes.Exact CompilerConeAttributes.NoInfer.ANNOTATION_CLASS_ID -> attributes += CompilerConeAttributes.NoInfer + CompilerConeAttributes.ExtensionFunctionType.ANNOTATION_CLASS_ID -> attributes += CompilerConeAttributes.ExtensionFunctionType } } return ConeAttributes.create(attributes) diff --git a/compiler/testData/diagnostics/tests/inline/labeled.fir.kt b/compiler/testData/diagnostics/tests/inline/labeled.fir.kt index b991c098c68..15dee73802a 100644 --- a/compiler/testData/diagnostics/tests/inline/labeled.fir.kt +++ b/compiler/testData/diagnostics/tests/inline/labeled.fir.kt @@ -2,11 +2,11 @@ inline fun foo(bar1: (String.() -> Int) -> Int, bar2: (()->Int) -> Int) { bar1 label@ { - this@label.length + this@label.length } bar1 { - this.length + this.length } //unmute after KT-4247 fix //bar1 { diff --git a/compiler/testData/diagnostics/tests/labels/kt4247.fir.kt b/compiler/testData/diagnostics/tests/labels/kt4247.fir.kt deleted file mode 100644 index 25b5f2cb56e..00000000000 --- a/compiler/testData/diagnostics/tests/labels/kt4247.fir.kt +++ /dev/null @@ -1,11 +0,0 @@ -//KT-4247 LABEL_NAME_CLASH - -fun foo(bar1: (String.() -> Int) -> Int) { - bar1 { - this.length - } - - bar1 { - this@bar1.length - } -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/labels/kt4247.kt b/compiler/testData/diagnostics/tests/labels/kt4247.kt index 4160394e1f0..eb99cff3ee1 100644 --- a/compiler/testData/diagnostics/tests/labels/kt4247.kt +++ b/compiler/testData/diagnostics/tests/labels/kt4247.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL //KT-4247 LABEL_NAME_CLASH fun foo(bar1: (String.() -> Int) -> Int) {