[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");
}
@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 {
@@ -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 {
@@ -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 {
@@ -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 {
@@ -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<FirScope> {
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<FirScope> {
private fun prepareScopes(classLikeDeclaration: FirClassLikeDeclaration, forStaticNestedClass: Boolean): PersistentList<FirScope> {
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<FirFile, ScopePersistentList>()
private val scopesForNestedClassesMap = hashMapOf<FirClass, ScopePersistentList>()
private val scopesForStaticNestedClassesMap = hashMapOf<FirClass, ScopePersistentList>()
private val scopesForCompanionMap = hashMapOf<FirClass, ScopePersistentList>()
private val supertypeStatusMap = linkedMapOf<FirClassLikeDeclaration, SupertypeComputationStatus>()
@@ -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() }
@@ -56,6 +56,10 @@ private class NavigationInfoVisitor : FirDefaultVisitor<Unit, Any?>() {
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)
@@ -4,6 +4,6 @@ open class ToResolve<SomeClass>(f : (Int) -> Int)
fun testFun(a : Int) = 12
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>()
}
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>() {
@@ -26,7 +26,7 @@ private fun noParameters() = {
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>() {
@@ -11,7 +11,7 @@ class Outer<T> {
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>() {
@@ -28,7 +28,7 @@ class Outer<T> {
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>() {
@@ -1,6 +1,6 @@
open class SomeClass<T>
class TestSome<P> {
companion object : SomeClass<P>() {
companion object : SomeClass<<!UNRESOLVED_REFERENCE!>P<!>>() {
}
}
@@ -1,6 +1,6 @@
open class SomeClass<T>
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
class Outer<TO> {
@@ -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 {