[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
This commit is contained in:
Brian Norman
2023-05-26 09:19:09 -05:00
committed by Space Team
parent dfae730d0f
commit e10a9263d0
15 changed files with 79 additions and 47 deletions
@@ -19418,6 +19418,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/tests/inner/nestedClassNotAllowed_before.kt"); 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 @Test
@TestMetadata("nestedObject.kt") @TestMetadata("nestedObject.kt")
public void testNestedObject() throws Exception { public void testNestedObject() throws Exception {
@@ -19418,6 +19418,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/tests/inner/nestedClassNotAllowed_before.kt"); 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 @Test
@TestMetadata("nestedObject.kt") @TestMetadata("nestedObject.kt")
public void testNestedObject() throws Exception { public void testNestedObject() throws Exception {
@@ -19418,6 +19418,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/tests/inner/nestedClassNotAllowed_before.kt"); 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 @Test
@TestMetadata("nestedObject.kt") @TestMetadata("nestedObject.kt")
public void testNestedObject() throws Exception { public void testNestedObject() throws Exception {
@@ -19424,6 +19424,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/tests/inner/nestedClassNotAllowed_before.kt"); 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 @Test
@TestMetadata("nestedObject.kt") @TestMetadata("nestedObject.kt")
public void testNestedObject() throws Exception { public void testNestedObject() throws Exception {
@@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType import org.jetbrains.kotlin.fir.declarations.utils.expandedConeType
import org.jetbrains.kotlin.fir.declarations.utils.isCompanion 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.ConeSimpleDiagnostic
import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.FirStatement import org.jetbrains.kotlin.fir.expressions.FirStatement
@@ -286,24 +287,31 @@ open class FirSupertypeResolverVisitor(
} }
} }
private fun prepareScopeForNestedClasses(klass: FirClass): ScopePersistentList { private fun prepareScopeForNestedClasses(klass: FirClass, forStaticNestedClass: Boolean): ScopePersistentList {
return supertypeComputationSession.getOrPutScopeForNestedClasses(klass) { return if (forStaticNestedClass) {
calculateScopes(klass, true) 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 { private fun prepareScopeForCompanion(klass: FirClass): ScopePersistentList {
return supertypeComputationSession.getOrPutScopeForCompanion(klass) { return supertypeComputationSession.getOrPutScopeForCompanion(klass) {
calculateScopes(klass, false) calculateScopes(klass, withCompanionScopes = false, forStaticNestedClass = true)
} }
} }
private fun calculateScopes( private fun calculateScopes(
outerClass: FirClass, outerClass: FirClass,
withCompanionScopes: Boolean, withCompanionScopes: Boolean,
forStaticNestedClass: Boolean,
): PersistentList<FirScope> { ): PersistentList<FirScope> {
resolveAllSupertypesForOuterClass(outerClass) resolveAllSupertypesForOuterClass(outerClass)
return prepareScopes(outerClass).pushAll( return prepareScopes(outerClass, forStaticNestedClass).pushAll(
createOtherScopesForNestedClassesOrCompanion( createOtherScopesForNestedClassesOrCompanion(
klass = outerClass, klass = outerClass,
session = session, session = session,
@@ -338,7 +346,7 @@ open class FirSupertypeResolverVisitor(
} }
} }
private fun prepareScopes(classLikeDeclaration: FirClassLikeDeclaration): PersistentList<FirScope> { private fun prepareScopes(classLikeDeclaration: FirClassLikeDeclaration, forStaticNestedClass: Boolean): PersistentList<FirScope> {
val classId = classLikeDeclaration.symbol.classId val classId = classLikeDeclaration.symbol.classId
val classModuleSession = classLikeDeclaration.moduleData.session val classModuleSession = classLikeDeclaration.moduleData.session
@@ -351,7 +359,7 @@ open class FirSupertypeResolverVisitor(
val parent = localClassesNavigationInfo.parentForClass[classLikeDeclaration] val parent = localClassesNavigationInfo.parentForClass[classLikeDeclaration]
when { when {
parent != null && parent is FirClass -> prepareScopeForNestedClasses(parent) parent != null && parent is FirClass -> prepareScopeForNestedClasses(parent, forStaticNestedClass)
else -> scopeForLocalClass ?: return persistentListOf() else -> scopeForLocalClass ?: return persistentListOf()
} }
} }
@@ -361,12 +369,17 @@ open class FirSupertypeResolverVisitor(
} }
classId.isNestedClass -> { classId.isNestedClass -> {
val outerClassFir = classId.outerClassId?.let { getFirClassifierByFqName(classModuleSession, it) } as? FirRegularClass 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() else -> getFirClassifierContainerFileIfAny(classLikeDeclaration.symbol)?.let(::prepareFileScopes) ?: persistentListOf()
} }
return result.pushIfNotNull(classLikeDeclaration.typeParametersScope()) return when {
forStaticNestedClass -> result
else -> result.pushIfNotNull(classLikeDeclaration.typeParametersScope())
}
} }
private fun resolveSpecificClassLikeSupertypes( private fun resolveSpecificClassLikeSupertypes(
@@ -386,7 +399,7 @@ open class FirSupertypeResolverVisitor(
} }
supertypeComputationSession.startComputingSupertypes(classLikeDeclaration) supertypeComputationSession.startComputingSupertypes(classLikeDeclaration)
val scopes = prepareScopes(classLikeDeclaration) val scopes = prepareScopes(classLikeDeclaration, forStaticNestedClass = false)
val transformer = FirSpecificTypeResolverTransformer(session, supertypeSupplier = supertypeComputationSession.supertypesSupplier) val transformer = FirSpecificTypeResolverTransformer(session, supertypeSupplier = supertypeComputationSession.supertypesSupplier)
@@ -559,6 +572,7 @@ private fun createErrorTypeRef(fir: FirElement, message: String, kind: Diagnosti
open class SupertypeComputationSession { open class SupertypeComputationSession {
private val fileScopesMap = hashMapOf<FirFile, ScopePersistentList>() private val fileScopesMap = hashMapOf<FirFile, ScopePersistentList>()
private val scopesForNestedClassesMap = hashMapOf<FirClass, ScopePersistentList>() private val scopesForNestedClassesMap = hashMapOf<FirClass, ScopePersistentList>()
private val scopesForStaticNestedClassesMap = hashMapOf<FirClass, ScopePersistentList>()
private val scopesForCompanionMap = hashMapOf<FirClass, ScopePersistentList>() private val scopesForCompanionMap = hashMapOf<FirClass, ScopePersistentList>()
private val supertypeStatusMap = linkedMapOf<FirClassLikeDeclaration, SupertypeComputationStatus>() private val supertypeStatusMap = linkedMapOf<FirClassLikeDeclaration, SupertypeComputationStatus>()
@@ -586,6 +600,9 @@ open class SupertypeComputationSession {
fun getOrPutScopeForNestedClasses(klass: FirClass, scope: () -> ScopePersistentList): ScopePersistentList = fun getOrPutScopeForNestedClasses(klass: FirClass, scope: () -> ScopePersistentList): ScopePersistentList =
scopesForNestedClassesMap.getOrPut(klass) { scope() } scopesForNestedClassesMap.getOrPut(klass) { scope() }
fun getOrPutScopeForStaticNestedClasses(klass: FirClass, scope: () -> ScopePersistentList): ScopePersistentList =
scopesForStaticNestedClassesMap.getOrPut(klass) { scope() }
fun getOrPutScopeForCompanion(klass: FirClass, scope: () -> ScopePersistentList): ScopePersistentList = fun getOrPutScopeForCompanion(klass: FirClass, scope: () -> ScopePersistentList): ScopePersistentList =
scopesForCompanionMap.getOrPut(klass) { scope() } scopesForCompanionMap.getOrPut(klass) { scope() }
@@ -56,6 +56,10 @@ private class NavigationInfoVisitor : FirDefaultVisitor<Unit, Any?>() {
visitClass(anonymousObject, null) visitClass(anonymousObject, null)
} }
override fun visitTypeAlias(typeAlias: FirTypeAlias, data: Any?) {
parentForClass[typeAlias] = currentPath.lastOrNull()
}
override fun visitClass(klass: FirClass, data: Any?) { override fun visitClass(klass: FirClass, data: Any?) {
parentForClass[klass] = currentPath.lastOrNull() parentForClass[klass] = currentPath.lastOrNull()
currentPath.add(klass) currentPath.add(klass)
@@ -4,6 +4,6 @@ open class ToResolve<SomeClass>(f : (Int) -> Int)
fun testFun(a : Int) = 12 fun testFun(a : Int) = 12
class TestSome<P> { class TestSome<P> {
companion object : ToResolve<P>({testFun(it)}) { companion object : ToResolve<<!UNRESOLVED_REFERENCE!>P<!>>(<!ARGUMENT_TYPE_MISMATCH!>{testFun(it)}<!>) {
} }
} }
@@ -9,7 +9,7 @@ private fun <E> foobar() = {
fun a() = A<E, X, Y, Z>() fun a() = A<E, X, Y, Z>()
} }
typealias LocalAlias<W> = A<E, <!UNRESOLVED_REFERENCE!>X<!>, <!UNRESOLVED_REFERENCE!>Y<!>, W> typealias LocalAlias<W> = A<E, X, Y, W>
} }
class Derived : LocalOuter<Double, Short>() { class Derived : LocalOuter<Double, Short>() {
@@ -26,7 +26,7 @@ private fun noParameters() = {
fun a() = A<Any, X, Y, Z>() fun a() = A<Any, X, Y, Z>()
} }
typealias LocalAlias2<W> = A<Any, <!UNRESOLVED_REFERENCE!>X<!>, <!UNRESOLVED_REFERENCE!>Y<!>, W> typealias LocalAlias2<W> = A<Any, X, Y, W>
} }
class Derived2 : LocalOuter2<Double, Short>() { class Derived2 : LocalOuter2<Double, Short>() {
@@ -11,7 +11,7 @@ class Outer<T> {
fun a() = A<T, F, E, X, Y, Z>() fun a() = A<T, F, E, X, Y, Z>()
} }
typealias LocalAlias<W> = A<T, F, E, <!UNRESOLVED_REFERENCE!>X<!>, <!UNRESOLVED_REFERENCE!>Y<!>, W> typealias LocalAlias<W> = A<T, F, E, X, Y, W>
} }
class Derived : LocalOuter<Double, Short>() { class Derived : LocalOuter<Double, Short>() {
@@ -28,7 +28,7 @@ class Outer<T> {
fun a() = A<T, F, Any, X, Y, Z>() fun a() = A<T, F, Any, X, Y, Z>()
} }
typealias LocalAlias2<W> = A<T, F, Any, <!UNRESOLVED_REFERENCE!>X<!>, <!UNRESOLVED_REFERENCE!>Y<!>, W> typealias LocalAlias2<W> = A<T, F, Any, X, Y, W>
} }
class Derived2 : LocalOuter2<Double, Short>() { class Derived2 : LocalOuter2<Double, Short>() {
@@ -1,6 +1,6 @@
open class SomeClass<T> open class SomeClass<T>
class TestSome<P> { class TestSome<P> {
companion object : SomeClass<P>() { companion object : SomeClass<<!UNRESOLVED_REFERENCE!>P<!>>() {
} }
} }
@@ -1,6 +1,6 @@
open class SomeClass<T> open class SomeClass<T>
class TestSome<P> { class TestSome<P> {
object Some : SomeClass<P>() { object Some : SomeClass<<!UNRESOLVED_REFERENCE!>P<!>>() {
} }
} }
@@ -0,0 +1,9 @@
// FIR_IDENTICAL
// KT-54748
sealed class Result<String> {
data class Success(val value: String) : Result<String>()
class Failure(val cause: Throwable) : Result<String>()
}
fun foo(): Result<String> = Result.Success("...")
@@ -1,29 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -TOPLEVEL_TYPEALIASES_ONLY
class Outer<TO> {
typealias LTO = List<TO>
class Nested<TN> {
typealias LTO = List<TO>
typealias LTN = List<TN>
inner class Inner<TI> {
typealias LTO = List<TO>
typealias LTN = List<TN>
typealias LTI = List<TI>
}
}
}
fun <TF> foo() {
class Local<TL> {
typealias LTF = List<TF>
typealias LTL = List<<!UNRESOLVED_REFERENCE!>TL<!>>
}
fun <TLF> localfun() =
object {
typealias LTF = List<TF>
typealias LTLF = List<TLF>
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -TOPLEVEL_TYPEALIASES_ONLY // !DIAGNOSTICS: -UNUSED_VARIABLE -UNUSED_PARAMETER -TOPLEVEL_TYPEALIASES_ONLY
class Outer<TO> { class Outer<TO> {
@@ -19424,6 +19424,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/inner/nestedClassNotAllowed_before.kt"); 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 @Test
@TestMetadata("nestedObject.kt") @TestMetadata("nestedObject.kt")
public void testNestedObject() throws Exception { public void testNestedObject() throws Exception {