From e10a9263d0f7febe6f83cfa6c263b7f410c61528 Mon Sep 17 00:00:00 2001 From: Brian Norman Date: Fri, 26 May 2023 09:19:09 -0500 Subject: [PATCH] [FIR] Only inherit class type parameters if inner class Nested classes which are not inner class should not be able to access type parameters of the outer class. Make sure access is not available when resolving super types. #KT-54748 Fixed --- ...CompilerTestFE10TestdataTestGenerated.java | 6 +++ ...sticCompilerFE10TestDataTestGenerated.java | 6 +++ ...eeOldFrontendDiagnosticsTestGenerated.java | 6 +++ ...siOldFrontendDiagnosticsTestGenerated.java | 6 +++ .../transformers/FirSupertypesResolution.kt | 37 ++++++++++++++----- .../body/resolve/LocalClassesNavigation.kt | 4 ++ .../classObjects/classObjectHeader.fir.kt | 4 +- .../fromSuperClassesLocal.fir.kt | 4 +- .../fromSuperClassesLocalInsideInner.fir.kt | 4 +- .../inner/innerErrorForClassObjects.fir.kt | 2 +- .../tests/inner/innerErrorForObjects.fir.kt | 2 +- .../nestedClassTypeParameterNameCollision.kt | 9 +++++ ...pturingTypeParametersFromOuterClass.fir.kt | 29 --------------- .../capturingTypeParametersFromOuterClass.kt | 1 + .../test/runners/DiagnosticTestGenerated.java | 6 +++ 15 files changed, 79 insertions(+), 47 deletions(-) create mode 100644 compiler/testData/diagnostics/tests/inner/nestedClassTypeParameterNameCollision.kt delete mode 100644 compiler/testData/diagnostics/tests/typealias/capturingTypeParametersFromOuterClass.fir.kt diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java index 3937ee6d7ad..21a4cea3ef3 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/DiagnosticCompilerTestFE10TestdataTestGenerated.java @@ -19418,6 +19418,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/inner/nestedClassNotAllowed_before.kt"); } + @Test + @TestMetadata("nestedClassTypeParameterNameCollision.kt") + public void testNestedClassTypeParameterNameCollision() throws Exception { + runTest("compiler/testData/diagnostics/tests/inner/nestedClassTypeParameterNameCollision.kt"); + } + @Test @TestMetadata("nestedObject.kt") public void testNestedObject() throws Exception { diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java index a92d1d2f167..b64520abd6e 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/diagnostic/compiler/based/LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated.java @@ -19418,6 +19418,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/inner/nestedClassNotAllowed_before.kt"); } + @Test + @TestMetadata("nestedClassTypeParameterNameCollision.kt") + public void testNestedClassTypeParameterNameCollision() throws Exception { + runTest("compiler/testData/diagnostics/tests/inner/nestedClassTypeParameterNameCollision.kt"); + } + @Test @TestMetadata("nestedObject.kt") public void testNestedObject() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java index 5c8d39a5324..40566e8e366 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirLightTreeOldFrontendDiagnosticsTestGenerated.java @@ -19418,6 +19418,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/inner/nestedClassNotAllowed_before.kt"); } + @Test + @TestMetadata("nestedClassTypeParameterNameCollision.kt") + public void testNestedClassTypeParameterNameCollision() throws Exception { + runTest("compiler/testData/diagnostics/tests/inner/nestedClassTypeParameterNameCollision.kt"); + } + @Test @TestMetadata("nestedObject.kt") public void testNestedObject() throws Exception { diff --git a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java index 09e001046c1..bb11cadfe0f 100644 --- a/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java +++ b/compiler/fir/analysis-tests/tests-gen/org/jetbrains/kotlin/test/runners/FirPsiOldFrontendDiagnosticsTestGenerated.java @@ -19424,6 +19424,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/inner/nestedClassNotAllowed_before.kt"); } + @Test + @TestMetadata("nestedClassTypeParameterNameCollision.kt") + public void testNestedClassTypeParameterNameCollision() throws Exception { + runTest("compiler/testData/diagnostics/tests/inner/nestedClassTypeParameterNameCollision.kt"); + } + @Test @TestMetadata("nestedObject.kt") public void testNestedObject() throws Exception { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt index f49cad6d677..4baddb4611a 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/FirSupertypesResolution.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.* import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType import org.jetbrains.kotlin.fir.declarations.utils.isCompanion +import org.jetbrains.kotlin.fir.declarations.utils.isInner import org.jetbrains.kotlin.fir.diagnostics.ConeSimpleDiagnostic import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.expressions.FirStatement @@ -286,24 +287,31 @@ open class FirSupertypeResolverVisitor( } } - private fun prepareScopeForNestedClasses(klass: FirClass): ScopePersistentList { - return supertypeComputationSession.getOrPutScopeForNestedClasses(klass) { - calculateScopes(klass, true) + private fun prepareScopeForNestedClasses(klass: FirClass, forStaticNestedClass: Boolean): ScopePersistentList { + return if (forStaticNestedClass) { + supertypeComputationSession.getOrPutScopeForStaticNestedClasses(klass) { + calculateScopes(klass, withCompanionScopes = true, forStaticNestedClass = true) + } + } else { + supertypeComputationSession.getOrPutScopeForNestedClasses(klass) { + calculateScopes(klass, withCompanionScopes = true, forStaticNestedClass = false) + } } } private fun prepareScopeForCompanion(klass: FirClass): ScopePersistentList { return supertypeComputationSession.getOrPutScopeForCompanion(klass) { - calculateScopes(klass, false) + calculateScopes(klass, withCompanionScopes = false, forStaticNestedClass = true) } } private fun calculateScopes( outerClass: FirClass, withCompanionScopes: Boolean, + forStaticNestedClass: Boolean, ): PersistentList { resolveAllSupertypesForOuterClass(outerClass) - return prepareScopes(outerClass).pushAll( + return prepareScopes(outerClass, forStaticNestedClass).pushAll( createOtherScopesForNestedClassesOrCompanion( klass = outerClass, session = session, @@ -338,7 +346,7 @@ open class FirSupertypeResolverVisitor( } } - private fun prepareScopes(classLikeDeclaration: FirClassLikeDeclaration): PersistentList { + private fun prepareScopes(classLikeDeclaration: FirClassLikeDeclaration, forStaticNestedClass: Boolean): PersistentList { val classId = classLikeDeclaration.symbol.classId val classModuleSession = classLikeDeclaration.moduleData.session @@ -351,7 +359,7 @@ open class FirSupertypeResolverVisitor( val parent = localClassesNavigationInfo.parentForClass[classLikeDeclaration] when { - parent != null && parent is FirClass -> prepareScopeForNestedClasses(parent) + parent != null && parent is FirClass -> prepareScopeForNestedClasses(parent, forStaticNestedClass) else -> scopeForLocalClass ?: return persistentListOf() } } @@ -361,12 +369,17 @@ open class FirSupertypeResolverVisitor( } classId.isNestedClass -> { val outerClassFir = classId.outerClassId?.let { getFirClassifierByFqName(classModuleSession, it) } as? FirRegularClass - prepareScopeForNestedClasses(outerClassFir ?: return persistentListOf()) + // TypeAliases are treated as inner classes even though they are technically not allowed + val isStatic = !classLikeDeclaration.isInner && classLikeDeclaration !is FirTypeAlias + prepareScopeForNestedClasses(outerClassFir ?: return persistentListOf(), isStatic || forStaticNestedClass) } else -> getFirClassifierContainerFileIfAny(classLikeDeclaration.symbol)?.let(::prepareFileScopes) ?: persistentListOf() } - return result.pushIfNotNull(classLikeDeclaration.typeParametersScope()) + return when { + forStaticNestedClass -> result + else -> result.pushIfNotNull(classLikeDeclaration.typeParametersScope()) + } } private fun resolveSpecificClassLikeSupertypes( @@ -386,7 +399,7 @@ open class FirSupertypeResolverVisitor( } supertypeComputationSession.startComputingSupertypes(classLikeDeclaration) - val scopes = prepareScopes(classLikeDeclaration) + val scopes = prepareScopes(classLikeDeclaration, forStaticNestedClass = false) val transformer = FirSpecificTypeResolverTransformer(session, supertypeSupplier = supertypeComputationSession.supertypesSupplier) @@ -559,6 +572,7 @@ private fun createErrorTypeRef(fir: FirElement, message: String, kind: Diagnosti open class SupertypeComputationSession { private val fileScopesMap = hashMapOf() private val scopesForNestedClassesMap = hashMapOf() + private val scopesForStaticNestedClassesMap = hashMapOf() private val scopesForCompanionMap = hashMapOf() private val supertypeStatusMap = linkedMapOf() @@ -586,6 +600,9 @@ open class SupertypeComputationSession { fun getOrPutScopeForNestedClasses(klass: FirClass, scope: () -> ScopePersistentList): ScopePersistentList = scopesForNestedClassesMap.getOrPut(klass) { scope() } + fun getOrPutScopeForStaticNestedClasses(klass: FirClass, scope: () -> ScopePersistentList): ScopePersistentList = + scopesForStaticNestedClassesMap.getOrPut(klass) { scope() } + fun getOrPutScopeForCompanion(klass: FirClass, scope: () -> ScopePersistentList): ScopePersistentList = scopesForCompanionMap.getOrPut(klass) { scope() } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/LocalClassesNavigation.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/LocalClassesNavigation.kt index 133927dd7df..4346651856c 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/LocalClassesNavigation.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/LocalClassesNavigation.kt @@ -56,6 +56,10 @@ private class NavigationInfoVisitor : FirDefaultVisitor() { visitClass(anonymousObject, null) } + override fun visitTypeAlias(typeAlias: FirTypeAlias, data: Any?) { + parentForClass[typeAlias] = currentPath.lastOrNull() + } + override fun visitClass(klass: FirClass, data: Any?) { parentForClass[klass] = currentPath.lastOrNull() currentPath.add(klass) diff --git a/compiler/testData/diagnostics/tests/classObjects/classObjectHeader.fir.kt b/compiler/testData/diagnostics/tests/classObjects/classObjectHeader.fir.kt index d7ff67b3a32..5a62573f0d0 100644 --- a/compiler/testData/diagnostics/tests/classObjects/classObjectHeader.fir.kt +++ b/compiler/testData/diagnostics/tests/classObjects/classObjectHeader.fir.kt @@ -4,6 +4,6 @@ open class ToResolve(f : (Int) -> Int) fun testFun(a : Int) = 12 class TestSome

{ - companion object : ToResolve

({testFun(it)}) { + companion object : ToResolve<P>({testFun(it)}) { } -} \ No newline at end of file +} diff --git a/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesLocal.fir.kt b/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesLocal.fir.kt index c8f20b87288..befadb24e61 100644 --- a/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesLocal.fir.kt +++ b/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesLocal.fir.kt @@ -9,7 +9,7 @@ private fun foobar() = { fun a() = A() } - typealias LocalAlias = AX, Y, W> + typealias LocalAlias = A } class Derived : LocalOuter() { @@ -26,7 +26,7 @@ private fun noParameters() = { fun a() = A() } - typealias LocalAlias2 = AX, Y, W> + typealias LocalAlias2 = A } class Derived2 : LocalOuter2() { diff --git a/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesLocalInsideInner.fir.kt b/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesLocalInsideInner.fir.kt index 49576cdaf5b..f31e8c4fb6a 100644 --- a/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesLocalInsideInner.fir.kt +++ b/compiler/testData/diagnostics/tests/generics/innerClasses/implicitArguments/fromSuperClassesLocalInsideInner.fir.kt @@ -11,7 +11,7 @@ class Outer { fun a() = A() } - typealias LocalAlias = AX, Y, W> + typealias LocalAlias = A } class Derived : LocalOuter() { @@ -28,7 +28,7 @@ class Outer { fun a() = A() } - typealias LocalAlias2 = AX, Y, W> + typealias LocalAlias2 = A } class Derived2 : LocalOuter2() { diff --git a/compiler/testData/diagnostics/tests/inner/innerErrorForClassObjects.fir.kt b/compiler/testData/diagnostics/tests/inner/innerErrorForClassObjects.fir.kt index b97b87acb82..85c710b9cbd 100644 --- a/compiler/testData/diagnostics/tests/inner/innerErrorForClassObjects.fir.kt +++ b/compiler/testData/diagnostics/tests/inner/innerErrorForClassObjects.fir.kt @@ -1,6 +1,6 @@ open class SomeClass class TestSome

{ - companion object : SomeClass

() { + companion object : SomeClass<P>() { } } diff --git a/compiler/testData/diagnostics/tests/inner/innerErrorForObjects.fir.kt b/compiler/testData/diagnostics/tests/inner/innerErrorForObjects.fir.kt index 10c14b54f07..186c9906639 100644 --- a/compiler/testData/diagnostics/tests/inner/innerErrorForObjects.fir.kt +++ b/compiler/testData/diagnostics/tests/inner/innerErrorForObjects.fir.kt @@ -1,6 +1,6 @@ open class SomeClass class TestSome

{ - object Some : SomeClass

() { + object Some : SomeClass<P>() { } } diff --git a/compiler/testData/diagnostics/tests/inner/nestedClassTypeParameterNameCollision.kt b/compiler/testData/diagnostics/tests/inner/nestedClassTypeParameterNameCollision.kt new file mode 100644 index 00000000000..7df4d44a776 --- /dev/null +++ b/compiler/testData/diagnostics/tests/inner/nestedClassTypeParameterNameCollision.kt @@ -0,0 +1,9 @@ +// FIR_IDENTICAL +// KT-54748 + +sealed class Result { + data class Success(val value: String) : Result() + class Failure(val cause: Throwable) : Result() +} + +fun foo(): Result = Result.Success("...") diff --git a/compiler/testData/diagnostics/tests/typealias/capturingTypeParametersFromOuterClass.fir.kt b/compiler/testData/diagnostics/tests/typealias/capturingTypeParametersFromOuterClass.fir.kt deleted file mode 100644 index 25a21884911..00000000000 --- a/compiler/testData/diagnostics/tests/typealias/capturingTypeParametersFromOuterClass.fir.kt +++ /dev/null @@ -1,29 +0,0 @@ -// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -TOPLEVEL_TYPEALIASES_ONLY - -class Outer { - typealias LTO = List - - class Nested { - typealias LTO = List - typealias LTN = List - - inner class Inner { - typealias LTO = List - typealias LTN = List - typealias LTI = List - } - } -} - -fun foo() { - class Local { - typealias LTF = List - typealias LTL = List<TL> - } - - fun localfun() = - object { - typealias LTF = List - typealias LTLF = List - } -} diff --git a/compiler/testData/diagnostics/tests/typealias/capturingTypeParametersFromOuterClass.kt b/compiler/testData/diagnostics/tests/typealias/capturingTypeParametersFromOuterClass.kt index 2c65e384b2a..69a760371e9 100644 --- a/compiler/testData/diagnostics/tests/typealias/capturingTypeParametersFromOuterClass.kt +++ b/compiler/testData/diagnostics/tests/typealias/capturingTypeParametersFromOuterClass.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL // !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -TOPLEVEL_TYPEALIASES_ONLY class Outer { 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 3c0eb5f4d5a..aa83bc238d9 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 @@ -19424,6 +19424,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/inner/nestedClassNotAllowed_before.kt"); } + @Test + @TestMetadata("nestedClassTypeParameterNameCollision.kt") + public void testNestedClassTypeParameterNameCollision() throws Exception { + runTest("compiler/testData/diagnostics/tests/inner/nestedClassTypeParameterNameCollision.kt"); + } + @Test @TestMetadata("nestedObject.kt") public void testNestedObject() throws Exception {