[FIR] Forbid creating abstract class instances via any qualified access

^KT-58938 Fixed
This commit is contained in:
Nikolay Lunyak
2023-06-06 11:01:25 +03:00
committed by Space Team
parent fccb391f31
commit 5daec16ce0
12 changed files with 76 additions and 14 deletions
@@ -34,6 +34,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia
runTest("compiler/testData/diagnostics/tests/AbstractAccessor.kt");
}
@Test
@TestMetadata("abstractClassReference.kt")
public void testAbstractClassReference() throws Exception {
runTest("compiler/testData/diagnostics/tests/abstractClassReference.kt");
}
@Test
@TestMetadata("AbstractInAbstractClass.kt")
public void testAbstractInAbstractClass() throws Exception {
@@ -34,6 +34,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated
runTest("compiler/testData/diagnostics/tests/AbstractAccessor.kt");
}
@Test
@TestMetadata("abstractClassReference.kt")
public void testAbstractClassReference() throws Exception {
runTest("compiler/testData/diagnostics/tests/abstractClassReference.kt");
}
@Test
@TestMetadata("AbstractInAbstractClass.kt")
public void testAbstractInAbstractClass() throws Exception {
@@ -34,6 +34,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir
runTest("compiler/testData/diagnostics/tests/AbstractAccessor.kt");
}
@Test
@TestMetadata("abstractClassReference.kt")
public void testAbstractClassReference() throws Exception {
runTest("compiler/testData/diagnostics/tests/abstractClassReference.kt");
}
@Test
@TestMetadata("AbstractInAbstractClass.kt")
public void testAbstractInAbstractClass() throws Exception {
@@ -34,6 +34,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia
runTest("compiler/testData/diagnostics/tests/AbstractAccessor.kt");
}
@Test
@TestMetadata("abstractClassReference.kt")
public void testAbstractClassReference() throws Exception {
runTest("compiler/testData/diagnostics/tests/abstractClassReference.kt");
}
@Test
@TestMetadata("AbstractInAbstractClass.kt")
public void testAbstractInAbstractClass() throws Exception {
@@ -48,6 +48,7 @@ object CommonExpressionCheckers : ExpressionCheckers() {
FirReifiedChecker,
FirSuspendCallChecker,
FirLateinitIntrinsicApplicabilityChecker,
FirAbstractClassInstantiationChecker,
)
override val callCheckers: Set<FirCallChecker>
@@ -0,0 +1,34 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.expression
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.reportOn
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.utils.isAbstract
import org.jetbrains.kotlin.fir.expressions.FirCallableReferenceAccess
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccessExpression
import org.jetbrains.kotlin.fir.references.toResolvedConstructorSymbol
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.fir.types.toRegularClassSymbol
object FirAbstractClassInstantiationChecker : FirQualifiedAccessExpressionChecker() {
override fun check(expression: FirQualifiedAccessExpression, context: CheckerContext, reporter: DiagnosticReporter) {
val constructorSymbol = expression.calleeReference.toResolvedConstructorSymbol() ?: return
val declarationClass = constructorSymbol.resolvedReturnTypeRef.coneType.toRegularClassSymbol(context.session) ?: return
if (declarationClass.isAbstract && declarationClass.classKind == ClassKind.CLASS) {
val source = when (expression) {
is FirCallableReferenceAccess -> expression.calleeReference.source
else -> expression.source
}
reporter.reportOn(source, FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS, context)
}
}
}
@@ -25,9 +25,6 @@ object FirConstructorCallChecker : FirFunctionCallChecker() {
val declarationClass = constructorSymbol.resolvedReturnTypeRef.coneType.toRegularClassSymbol(context.session)
if (declarationClass != null) {
if (declarationClass.isAbstract && declarationClass.classKind == ClassKind.CLASS) {
reporter.reportOn(expression.source, FirErrors.CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS, context)
}
if (declarationClass.classKind == ClassKind.ANNOTATION_CLASS &&
context.qualifiedAccessOrAssignmentsOrAnnotationCalls.all { call ->
call !is FirAnnotation
@@ -0,0 +1,9 @@
// FIR_IDENTICAL
// ISSUE: KT-58938
abstract class AbstractClass()
fun main(args: Array<String>) {
val abstractClass = ::<!CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS!>AbstractClass<!>
abstractClass.invoke()
}
@@ -6,7 +6,7 @@ enum class D
fun main() {
::<!UNRESOLVED_REFERENCE!>A<!>
::B
::<!CREATING_AN_INSTANCE_OF_ABSTRACT_CLASS!>B<!>
::<!CALLABLE_REFERENCE_TO_ANNOTATION_CONSTRUCTOR!>C<!> // KT-3465
::<!UNRESOLVED_REFERENCE!>D<!>
}
@@ -1,10 +0,0 @@
abstract class Abstract
fun <D> create(fn: () -> D): D {
return fn()
}
fun main() {
create(::Abstract)
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
abstract class Abstract
@@ -34,6 +34,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/AbstractAccessor.kt");
}
@Test
@TestMetadata("abstractClassReference.kt")
public void testAbstractClassReference() throws Exception {
runTest("compiler/testData/diagnostics/tests/abstractClassReference.kt");
}
@Test
@TestMetadata("AbstractInAbstractClass.kt")
public void testAbstractInAbstractClass() throws Exception {