diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java index e6477f7cd1b..e7825116a5c 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosisCompilerTestFE10TestdataTestGenerated.java @@ -24083,6 +24083,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag runTest("compiler/testData/diagnostics/tests/regressions/kt9808.kt"); } + @Test + @TestMetadata("LocalClassReferenceChain.kt") + public void testLocalClassReferenceChain() throws Exception { + runTest("compiler/testData/diagnostics/tests/regressions/LocalClassReferenceChain.kt"); + } + @Test @TestMetadata("noThis.kt") public void testNoThis() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java index 42a99332b5d..01de14e6298 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsTestGenerated.java @@ -24083,6 +24083,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti runTest("compiler/testData/diagnostics/tests/regressions/kt9808.kt"); } + @Test + @TestMetadata("LocalClassReferenceChain.kt") + public void testLocalClassReferenceChain() throws Exception { + runTest("compiler/testData/diagnostics/tests/regressions/LocalClassReferenceChain.kt"); + } + @Test @TestMetadata("noThis.kt") public void testNoThis() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java index f939e3f976f..626e9bb9ce0 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirOldFrontendDiagnosticsWithLightTreeTestGenerated.java @@ -24083,6 +24083,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac runTest("compiler/testData/diagnostics/tests/regressions/kt9808.kt"); } + @Test + @TestMetadata("LocalClassReferenceChain.kt") + public void testLocalClassReferenceChain() throws Exception { + runTest("compiler/testData/diagnostics/tests/regressions/LocalClassReferenceChain.kt"); + } + @Test @TestMetadata("noThis.kt") public void testNoThis() throws Exception { 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 5a3a3fb8542..067798f4eb9 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 @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.FirEnumEntry import org.jetbrains.kotlin.fir.declarations.FirRegularClass import org.jetbrains.kotlin.fir.declarations.impl.FirOuterClassTypeParameterRef import org.jetbrains.kotlin.fir.declarations.utils.isEnumClass +import org.jetbrains.kotlin.fir.declarations.utils.isLocal import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeUnexpectedTypeArgumentsError import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind @@ -68,19 +69,21 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() { val qualifierResolver = session.qualifierResolver var resolvedSymbol: FirBasedSymbol<*>? = null var substitutor: ConeSubstitutor? = null - scope.processClassifiersByNameWithSubstitution(typeRef.qualifier.first().name) { symbol, substitutorFromScope -> + val qualifier = typeRef.qualifier + scope.processClassifiersByNameWithSubstitution(qualifier.first().name) { symbol, substitutorFromScope -> if (resolvedSymbol != null) return@processClassifiersByNameWithSubstitution resolvedSymbol = when (symbol) { is FirClassLikeSymbol<*> -> { - if (typeRef.qualifier.size == 1) { + if (qualifier.size == 1) { symbol } else { - qualifierResolver.resolveSymbolWithPrefix(typeRef.qualifier, symbol.classId) - ?: qualifierResolver.resolveEnumEntrySymbol(typeRef.qualifier, symbol.classId) + resolveLocalClassChain(symbol, qualifier) + ?: qualifierResolver.resolveSymbolWithPrefix(qualifier, symbol.classId) + ?: qualifierResolver.resolveEnumEntrySymbol(qualifier, symbol.classId) } } is FirTypeParameterSymbol -> { - assert(typeRef.qualifier.size == 1) + assert(qualifier.size == 1) symbol } else -> error("!") @@ -89,7 +92,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() { } // TODO: Imports - val resultSymbol: FirBasedSymbol<*>? = resolvedSymbol ?: qualifierResolver.resolveSymbol(typeRef.qualifier) + val resultSymbol: FirBasedSymbol<*>? = resolvedSymbol ?: qualifierResolver.resolveSymbol(qualifier) resultSymbol to substitutor } @@ -101,6 +104,31 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver() { } } + private fun resolveLocalClassChain(symbol: FirClassLikeSymbol<*>, qualifier: List): FirRegularClassSymbol? { + if (symbol !is FirRegularClassSymbol || !symbol.isLocal) { + return null + } + + fun resolveLocalClassChain(classSymbol: FirRegularClassSymbol, qualifierIndex: Int): FirRegularClassSymbol? { + if (qualifierIndex == qualifier.size) { + return classSymbol + } + + val qualifierName = qualifier[qualifierIndex].name + for (declarationSymbol in classSymbol.declarationSymbols) { + if (declarationSymbol is FirRegularClassSymbol) { + if (declarationSymbol.toLookupTag().name == qualifierName) { + return resolveLocalClassChain(declarationSymbol, qualifierIndex + 1) + } + } + } + + return null + } + + return resolveLocalClassChain(symbol, 1) + } + @OptIn(SymbolInternals::class) private fun FirQualifierResolver.resolveEnumEntrySymbol( qualifier: List, diff --git a/compiler/testData/diagnostics/tests/generics/capturedParameters/uncheckedCast.fir.kt b/compiler/testData/diagnostics/tests/generics/capturedParameters/uncheckedCast.fir.kt index 96b9143f201..27616233816 100644 --- a/compiler/testData/diagnostics/tests/generics/capturedParameters/uncheckedCast.fir.kt +++ b/compiler/testData/diagnostics/tests/generics/capturedParameters/uncheckedCast.fir.kt @@ -18,11 +18,11 @@ fun foo(x: Any, y: Any) : Any { } // bare type - if (y is Outer.Inner) { + if (y is Outer.Inner) { return y } - y as Outer<*>.Inner + y as Outer<*>.Inner return C() } diff --git a/compiler/testData/diagnostics/tests/regressions/LocalClassReferenceChain.kt b/compiler/testData/diagnostics/tests/regressions/LocalClassReferenceChain.kt new file mode 100644 index 00000000000..0485d8aff78 --- /dev/null +++ b/compiler/testData/diagnostics/tests/regressions/LocalClassReferenceChain.kt @@ -0,0 +1,15 @@ +// FIR_IDENTICAL +// KT-47135 + +fun test2() { + class LocalA { + inner class LocalB { + inner class LocalC { + } + } + } + + fun LocalA.LocalB.blah() { + val c: LocalA.LocalB.LocalC = LocalC() + } +} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/regressions/LocalClassReferenceChain.txt b/compiler/testData/diagnostics/tests/regressions/LocalClassReferenceChain.txt new file mode 100644 index 00000000000..c65a2992bf8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/regressions/LocalClassReferenceChain.txt @@ -0,0 +1,3 @@ +package + +public fun test2(): kotlin.Unit diff --git a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java index fdabc9b993e..dd32b556d7b 100644 --- a/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java +++ b/compiler/tests-common-new/tests-gen/org/jetbrains/kotlin/test/runners/DiagnosticTestGenerated.java @@ -24095,6 +24095,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/regressions/kt9808.kt"); } + @Test + @TestMetadata("LocalClassReferenceChain.kt") + public void testLocalClassReferenceChain() throws Exception { + runTest("compiler/testData/diagnostics/tests/regressions/LocalClassReferenceChain.kt"); + } + @Test @TestMetadata("noThis.kt") public void testNoThis() throws Exception {