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 f6508927a95..df20f0e00c2 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 @@ -542,7 +542,10 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer) ) af = af.transformValueParameters(ImplicitToErrorTypeTransformer, null) val bodyExpectedType = returnTypeRefFromResolvedAtom ?: expectedTypeRef - af = transformFunction(af, withExpectedType(bodyExpectedType)).single as FirAnonymousFunction + val labelName = af.label?.name?.let { Name.identifier(it) } + withLabelAndReceiverType(labelName, af, af.receiverTypeRef?.coneTypeSafe()) { + af = transformFunction(af, withExpectedType(bodyExpectedType)).single as FirAnonymousFunction + } // To separate function and separate commit val writer = FirCallCompletionResultsWriterTransformer( session, @@ -601,49 +604,58 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer) private inline fun withLabelAndReceiverType( labelName: Name?, owner: FirDeclaration, - type: ConeKotlinType, + type: ConeKotlinType?, block: () -> T ): T { - val implicitCompanionValues = mutableListOf>() - val implicitReceiverValue = when (owner) { - is FirClass<*> -> { - // Questionable: performance - (owner as? FirRegularClass)?.companionObject?.let { companion -> - implicitCompanionValues += ImplicitDispatchReceiverValue( - companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION - ) - } - lookupSuperTypes(owner, lookupInterfaces = false, deep = true, useSiteSession = session).mapNotNull { - val superClass = (it as? ConeClassLikeType)?.lookupTag?.toSymbol(session)?.fir as? FirRegularClass - superClass?.companionObject?.let { companion -> + val implicitCompanionValues: List> + if (type != null) { + implicitCompanionValues = mutableListOf() + val implicitReceiverValue = when (owner) { + is FirClass<*> -> { + // Questionable: performance + (owner as? FirRegularClass)?.companionObject?.let { companion -> implicitCompanionValues += ImplicitDispatchReceiverValue( - companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION_FROM_SUPERTYPE + companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION ) } + lookupSuperTypes(owner, lookupInterfaces = false, deep = true, useSiteSession = session).mapNotNull { + val superClass = (it as? ConeClassLikeType)?.lookupTag?.toSymbol(session)?.fir as? FirRegularClass + superClass?.companionObject?.let { companion -> + implicitCompanionValues += ImplicitDispatchReceiverValue( + companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION_FROM_SUPERTYPE + ) + } + } + // --- + ImplicitDispatchReceiverValue(owner.symbol, type, session, scopeSession) + } + is FirFunction<*> -> { + ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession) + } + is FirVariable<*> -> { + ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession) + } + else -> { + throw IllegalArgumentException("Incorrect label & receiver owner: ${owner.javaClass}") } - // --- - ImplicitDispatchReceiverValue(owner.symbol, type, session, scopeSession) } - is FirFunction<*> -> { - ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession) + for (implicitCompanionValue in implicitCompanionValues.asReversed()) { + implicitReceiverStack.add(null, implicitCompanionValue) } - is FirVariable<*> -> { - ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession) - } - else -> { - throw IllegalArgumentException("Incorrect label & receiver owner: ${owner.javaClass}") + implicitReceiverStack.add(labelName, implicitReceiverValue) + } else { + implicitCompanionValues = emptyList() + } + try { + return block() + } finally { + if (type != null) { + implicitReceiverStack.pop(labelName) + for (implicitCompanionValue in implicitCompanionValues) { + implicitReceiverStack.pop(null) + } } } - for (implicitCompanionValue in implicitCompanionValues.asReversed()) { - implicitReceiverStack.add(null, implicitCompanionValue) - } - implicitReceiverStack.add(labelName, implicitReceiverValue) - val result = block() - implicitReceiverStack.pop(labelName) - for (implicitCompanionValue in implicitCompanionValues) { - implicitReceiverStack.pop(null) - } - return result } private fun storeVariableReturnType(variable: FirVariable<*>) { diff --git a/compiler/fir/resolve/testData/resolve/arguments/extensionLambdaInDefaultArgument.kt b/compiler/fir/resolve/testData/resolve/arguments/extensionLambdaInDefaultArgument.kt new file mode 100644 index 00000000000..9ecc8487742 --- /dev/null +++ b/compiler/fir/resolve/testData/resolve/arguments/extensionLambdaInDefaultArgument.kt @@ -0,0 +1,5 @@ +fun test( + val f: String.() -> Int = { length } +): Int { + return "".f() +} \ No newline at end of file diff --git a/compiler/fir/resolve/testData/resolve/problems/extensionLambdaInDefaultArgument.txt b/compiler/fir/resolve/testData/resolve/arguments/extensionLambdaInDefaultArgument.txt similarity index 66% rename from compiler/fir/resolve/testData/resolve/problems/extensionLambdaInDefaultArgument.txt rename to compiler/fir/resolve/testData/resolve/arguments/extensionLambdaInDefaultArgument.txt index 2aea57f213b..7c42da7e6a0 100644 --- a/compiler/fir/resolve/testData/resolve/problems/extensionLambdaInDefaultArgument.txt +++ b/compiler/fir/resolve/testData/resolve/arguments/extensionLambdaInDefaultArgument.txt @@ -1,6 +1,6 @@ FILE: extensionLambdaInDefaultArgument.kt - public final fun test(f: R|kotlin/String.() -> kotlin/Int| = fun R|kotlin/String|.(): R|ERROR CLASS: Unresolved name: length| { - ^ # + public final fun test(f: R|kotlin/String.() -> kotlin/Int| = fun R|kotlin/String|.(): R|kotlin/Int| { + ^ this@R|special/anonymous|.R|kotlin/String.length| } ): R|kotlin/Int| { ^test R|/f|.R|FakeOverride|(String()) diff --git a/compiler/fir/resolve/testData/resolve/problems/extensionLambdaInDefaultArgument.kt b/compiler/fir/resolve/testData/resolve/problems/extensionLambdaInDefaultArgument.kt deleted file mode 100644 index 8458adad7b2..00000000000 --- a/compiler/fir/resolve/testData/resolve/problems/extensionLambdaInDefaultArgument.kt +++ /dev/null @@ -1,5 +0,0 @@ -fun test( - val f: String.() -> Int = { length } -): Int { - return "".f() -} \ No newline at end of file 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 5d05feeba38..3888118758b 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsTestGenerated.java @@ -380,6 +380,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/resolve/testData/resolve/arguments/defaultFromOverrides.kt"); } + @TestMetadata("extensionLambdaInDefaultArgument.kt") + public void testExtensionLambdaInDefaultArgument() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/arguments/extensionLambdaInDefaultArgument.kt"); + } + @TestMetadata("fieldPlusAssign.kt") public void testFieldPlusAssign() throws Exception { runTest("compiler/fir/resolve/testData/resolve/arguments/fieldPlusAssign.kt"); @@ -1352,11 +1357,6 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/resolve/testData/resolve/problems/definitelyNotNullAndOriginalType.kt"); } - @TestMetadata("extensionLambdaInDefaultArgument.kt") - public void testExtensionLambdaInDefaultArgument() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/problems/extensionLambdaInDefaultArgument.kt"); - } - @TestMetadata("javaAccessorConversion.kt") public void testJavaAccessorConversion() throws Exception { runTest("compiler/fir/resolve/testData/resolve/problems/javaAccessorConversion.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 5d5053ee003..7f8f7179479 100644 --- a/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/resolve/tests/org/jetbrains/kotlin/fir/FirDiagnosticsWithLightTreeTestGenerated.java @@ -380,6 +380,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/resolve/testData/resolve/arguments/defaultFromOverrides.kt"); } + @TestMetadata("extensionLambdaInDefaultArgument.kt") + public void testExtensionLambdaInDefaultArgument() throws Exception { + runTest("compiler/fir/resolve/testData/resolve/arguments/extensionLambdaInDefaultArgument.kt"); + } + @TestMetadata("fieldPlusAssign.kt") public void testFieldPlusAssign() throws Exception { runTest("compiler/fir/resolve/testData/resolve/arguments/fieldPlusAssign.kt"); @@ -1352,11 +1357,6 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/resolve/testData/resolve/problems/definitelyNotNullAndOriginalType.kt"); } - @TestMetadata("extensionLambdaInDefaultArgument.kt") - public void testExtensionLambdaInDefaultArgument() throws Exception { - runTest("compiler/fir/resolve/testData/resolve/problems/extensionLambdaInDefaultArgument.kt"); - } - @TestMetadata("javaAccessorConversion.kt") public void testJavaAccessorConversion() throws Exception { runTest("compiler/fir/resolve/testData/resolve/problems/javaAccessorConversion.kt"); diff --git a/compiler/testData/diagnostics/tests/functionAsExpression/ScopeCheck.fir.kt b/compiler/testData/diagnostics/tests/functionAsExpression/ScopeCheck.fir.kt index 39fcc22ac00..c7976fa07ac 100644 --- a/compiler/testData/diagnostics/tests/functionAsExpression/ScopeCheck.fir.kt +++ b/compiler/testData/diagnostics/tests/functionAsExpression/ScopeCheck.fir.kt @@ -9,7 +9,7 @@ fun test(param: String) { val local_val = 4 val bar = fun B.(fun_param: Int) { param.length - b_fun() + b_fun() val inner_bar = local_val + fun_param bar diff --git a/compiler/testData/diagnostics/tests/labels/kt591.fir.kt b/compiler/testData/diagnostics/tests/labels/kt591.fir.kt index 0235783feee..9730d35605a 100644 --- a/compiler/testData/diagnostics/tests/labels/kt591.fir.kt +++ b/compiler/testData/diagnostics/tests/labels/kt591.fir.kt @@ -4,7 +4,7 @@ fun test() { val a: (Int?).() -> Unit = a@{ if (this != null) { val b: String.() -> Unit = { - this@a.times(5) // a@ Unresolved + this@a.times(5) // a@ Unresolved } } } diff --git a/compiler/testData/diagnostics/tests/regressions/kt306.fir.kt b/compiler/testData/diagnostics/tests/regressions/kt306.fir.kt index 73c9a1dac4d..dba4b547214 100644 --- a/compiler/testData/diagnostics/tests/regressions/kt306.fir.kt +++ b/compiler/testData/diagnostics/tests/regressions/kt306.fir.kt @@ -2,15 +2,15 @@ fun test() { (fun Foo.() { - bar() + bar() (fun Barr.() { - this.bar() - bar() + this.bar() + bar() }) }) (fun Barr.() { - this.bar() - bar() + this.bar() + bar() }) } diff --git a/compiler/testData/diagnostics/tests/thisAndSuper/thisInFunctionLiterals.fir.kt b/compiler/testData/diagnostics/tests/thisAndSuper/thisInFunctionLiterals.fir.kt index c4d4e6382a6..225d2282096 100644 --- a/compiler/testData/diagnostics/tests/thisAndSuper/thisInFunctionLiterals.fir.kt +++ b/compiler/testData/diagnostics/tests/thisAndSuper/thisInFunctionLiterals.fir.kt @@ -5,14 +5,14 @@ class A(val a:Int) { fun Byte.xx() : Double.() -> Any { checkSubtype(this) val a: Double.() -> Unit = { - checkSubtype(this) + checkSubtype(this) checkSubtype(this@xx) checkSubtype(this@B) checkSubtype(this@A) } - val b: Double.() -> Unit = a@{ checkSubtype(this@a) + checkSubtype(this@xx) } + val b: Double.() -> Unit = a@{ checkSubtype(this@a) + checkSubtype(this@xx) } val c = a@{ -> this@a + checkSubtype(this@xx) } - return (a@{checkSubtype(this@a) + checkSubtype(this@xx)}) + return (a@{checkSubtype(this@a) + checkSubtype(this@xx)}) } } } \ No newline at end of file