diff --git a/compiler/fir/analysis-tests/testData/resolve/nested/innerTypeFromSuperClassInBody.kt b/compiler/fir/analysis-tests/testData/resolve/nested/innerTypeFromSuperClassInBody.kt new file mode 100644 index 00000000000..294bf333902 --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/nested/innerTypeFromSuperClassInBody.kt @@ -0,0 +1,15 @@ +abstract class A { + inner class Inner + fun foo(x: Inner.() -> Unit) {} +} + +object B : A() { + + fun bar() { + val y: Inner.() -> Unit = {} + foo(y) + baz(y) + } +} + +fun baz(x: (A.Inner) -> Unit) {} diff --git a/compiler/fir/analysis-tests/testData/resolve/nested/innerTypeFromSuperClassInBody.txt b/compiler/fir/analysis-tests/testData/resolve/nested/innerTypeFromSuperClassInBody.txt new file mode 100644 index 00000000000..2348d9696df --- /dev/null +++ b/compiler/fir/analysis-tests/testData/resolve/nested/innerTypeFromSuperClassInBody.txt @@ -0,0 +1,34 @@ +FILE: innerTypeFromSuperClassInBody.kt + public abstract class A : R|kotlin/Any| { + public constructor(): R|A| { + super() + } + + public final inner class Inner : R|kotlin/Any| { + public constructor(): R|A.Inner| { + super() + } + + } + + public final fun foo(x: R|A.Inner.() -> kotlin/Unit|): R|kotlin/Unit| { + } + + } + public final object B : R|A| { + private constructor(): R|B| { + super|>() + } + + public final fun bar(): R|kotlin/Unit| { + lval y: R|A.Inner.() -> kotlin/Unit| = fun R|A.Inner|.(): R|kotlin/Unit| { + ^ Unit + } + + this@R|/B|.R|SubstitutionOverride|(R|/y|) + R|/baz|(R|/y|) + } + + } + public final fun baz(x: R|(A.Inner) -> kotlin/Unit|): R|kotlin/Unit| { + } 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 6870b7065fe..4f99e0a755b 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 @@ -1923,6 +1923,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest { runTest("compiler/fir/analysis-tests/testData/resolve/nested/inner.kt"); } + @TestMetadata("innerTypeFromSuperClassInBody.kt") + public void testInnerTypeFromSuperClassInBody() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/nested/innerTypeFromSuperClassInBody.kt"); + } + @TestMetadata("innerTypes.kt") public void testInnerTypes() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/nested/innerTypes.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 3bd412f016e..5efdd60eaa8 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 @@ -1923,6 +1923,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos runTest("compiler/fir/analysis-tests/testData/resolve/nested/inner.kt"); } + @TestMetadata("innerTypeFromSuperClassInBody.kt") + public void testInnerTypeFromSuperClassInBody() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/nested/innerTypeFromSuperClassInBody.kt"); + } + @TestMetadata("innerTypes.kt") public void testInnerTypes() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/nested/innerTypes.kt"); diff --git a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java index 3b0a2d8f0b9..541a0b5d692 100644 --- a/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java +++ b/compiler/fir/analysis-tests/tests/org/jetbrains/kotlin/fir/LazyBodyIsNotTouchedTilContractsPhaseTestGenerated.java @@ -1923,6 +1923,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract runTest("compiler/fir/analysis-tests/testData/resolve/nested/inner.kt"); } + @TestMetadata("innerTypeFromSuperClassInBody.kt") + public void testInnerTypeFromSuperClassInBody() throws Exception { + runTest("compiler/fir/analysis-tests/testData/resolve/nested/innerTypeFromSuperClassInBody.kt"); + } + @TestMetadata("innerTypes.kt") public void testInnerTypes() throws Exception { runTest("compiler/fir/analysis-tests/testData/resolve/nested/innerTypes.kt"); diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/BodyResolveComponents.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/BodyResolveComponents.kt index 18dae549775..886de9e44da 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/BodyResolveComponents.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/BodyResolveComponents.kt @@ -21,6 +21,7 @@ import org.jetbrains.kotlin.fir.resolve.transformers.FirSyntheticCallGenerator import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator import org.jetbrains.kotlin.fir.scopes.FirScope import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope +import org.jetbrains.kotlin.fir.scopes.impl.wrapNestedClassifierScopeWithSubstitutionForSuperType import org.jetbrains.kotlin.fir.symbols.impl.FirAnonymousFunctionSymbol import org.jetbrains.kotlin.fir.types.ConeKotlinType import org.jetbrains.kotlin.fir.types.FirTypeRef @@ -194,9 +195,13 @@ fun SessionHolder.collectTowerDataElementsForClass(owner: FirClass<*>, defaultTy val superClassesStaticsAndCompanionReceivers = mutableListOf() for (superType in lookupSuperTypes(owner, lookupInterfaces = false, deep = true, useSiteSession = session)) { - val superClass = superType.fullyExpandedType(session).lookupTag.toSymbol(session)?.fir as? FirRegularClass ?: continue + val expandedType = superType.fullyExpandedType(session) + val superClass = expandedType.lookupTag.toSymbol(session)?.fir as? FirRegularClass ?: continue - superClass.staticScope(this)?.asTowerDataElement(isLocal = false)?.let(superClassesStaticsAndCompanionReceivers::add) + superClass.staticScope(this) + ?.wrapNestedClassifierScopeWithSubstitutionForSuperType(expandedType, session) + ?.asTowerDataElement(isLocal = false) + ?.let(superClassesStaticsAndCompanionReceivers::add) (superClass as? FirRegularClass)?.companionObject?.let { companion -> val superCompanionReceiver = ImplicitDispatchReceiverValue( diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirNestedClassifierScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirNestedClassifierScope.kt index 464a831cc02..ee6e8c45f59 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirNestedClassifierScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirNestedClassifierScope.kt @@ -43,11 +43,9 @@ class FirNestedClassifierScope(val klass: FirClass<*>) : FirScope(), FirContaini processor(matchedClass, ConeSubstitutorByMap(substitution)) } - fun getClassifierByName(name: Name): FirRegularClassSymbol? = classIndex[name] - override fun getClassifierNames(): Set = classIndex.keys override fun getCallableNames(): Set = emptySet() } -fun FirTypeParameterRef.toConeType(): ConeKotlinType = ConeTypeParameterTypeImpl(ConeTypeParameterLookupTag(symbol), isNullable = false) \ No newline at end of file +fun FirTypeParameterRef.toConeType(): ConeKotlinType = ConeTypeParameterTypeImpl(ConeTypeParameterLookupTag(symbol), isNullable = false) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirNestedClassifierScopeWithSubstitution.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirNestedClassifierScopeWithSubstitution.kt index 2440fc63890..a3fc0f9f7db 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirNestedClassifierScopeWithSubstitution.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirNestedClassifierScopeWithSubstitution.kt @@ -10,16 +10,34 @@ import org.jetbrains.kotlin.fir.declarations.isInner import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.transformers.createSubstitutionForSupertype import org.jetbrains.kotlin.fir.scopes.FirScope -import org.jetbrains.kotlin.fir.symbols.impl.FirClassifierSymbol +import org.jetbrains.kotlin.fir.scopes.getSingleClassifier +import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.types.ConeClassLikeType import org.jetbrains.kotlin.name.Name -class FirNestedClassifierScopeWithSubstitution( - private val scope: FirNestedClassifierScope, +private class FirNestedClassifierScopeWithSubstitution( + private val scope: FirScope, private val substitutor: ConeSubstitutor ) : FirScope() { + + override fun processFunctionsByName(name: Name, processor: (FirFunctionSymbol<*>) -> Unit) { + scope.processFunctionsByName(name, processor) + } + + override fun processPropertiesByName(name: Name, processor: (FirVariableSymbol<*>) -> Unit) { + scope.processPropertiesByName(name, processor) + } + + override fun processDeclaredConstructors(processor: (FirConstructorSymbol) -> Unit) { + scope.processDeclaredConstructors(processor) + } + + override fun mayContainName(name: Name): Boolean { + return scope.mayContainName(name) + } + override fun processClassifiersByNameWithSubstitution(name: Name, processor: (FirClassifierSymbol<*>, ConeSubstitutor) -> Unit) { - val matchedClass = scope.getClassifierByName(name) ?: return + val matchedClass = scope.getSingleClassifier(name) as? FirRegularClassSymbol ?: return val substitutor = substitutor.takeIf { matchedClass.fir.isInner } ?: ConeSubstitutor.Empty processor(matchedClass, substitutor) } @@ -28,9 +46,7 @@ class FirNestedClassifierScopeWithSubstitution( fun FirScope.wrapNestedClassifierScopeWithSubstitutionForSuperType( superType: ConeClassLikeType, session: FirSession -): FirScope = if (this is FirNestedClassifierScope) { +): FirScope { val substitutor = createSubstitutionForSupertype(superType, session) - FirNestedClassifierScopeWithSubstitution(this, substitutor) -} else { - this -} \ No newline at end of file + return FirNestedClassifierScopeWithSubstitution(this, substitutor) +} diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirScope.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirScope.kt index 6f6d0a54bc5..6cb30557051 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirScope.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/scopes/FirScope.kt @@ -35,6 +35,10 @@ abstract class FirScope { open fun mayContainName(name: Name) = true } +fun FirScope.getSingleClassifier(name: Name): FirClassifierSymbol<*>? = mutableListOf>().apply { + processClassifiersByName(name, this::add) +}.singleOrNull() + fun FirScope.getFunctions(name: Name): List> = mutableListOf>().apply { processFunctionsByName(name, this::add) }