From 5daec16ce0097558510722d135483eb2149474be Mon Sep 17 00:00:00 2001 From: Nikolay Lunyak Date: Tue, 6 Jun 2023 11:01:25 +0300 Subject: [PATCH] [FIR] Forbid creating abstract class instances via any qualified access ^KT-58938 Fixed --- ...CompilerTestFE10TestdataTestGenerated.java | 6 ++++ ...sticCompilerFE10TestDataTestGenerated.java | 6 ++++ ...eeOldFrontendDiagnosticsTestGenerated.java | 6 ++++ ...siOldFrontendDiagnosticsTestGenerated.java | 6 ++++ .../checkers/CommonExpressionCheckers.kt | 1 + .../FirAbstractClassInstantiationChecker.kt | 34 +++++++++++++++++++ .../expression/FirConstructorCallChecker.kt | 3 -- .../tests/abstractClassReference.kt | 9 +++++ .../function/abstractClassConstructors.fir.kt | 2 +- .../tests/callableReference/kt37530.fir.kt | 10 ------ .../tests/callableReference/kt37530.kt | 1 + .../test/runners/DiagnosticTestGenerated.java | 6 ++++ 12 files changed, 76 insertions(+), 14 deletions(-) create mode 100644 compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAbstractClassInstantiationChecker.kt create mode 100644 compiler/testData/diagnostics/tests/abstractClassReference.kt delete mode 100644 compiler/testData/diagnostics/tests/callableReference/kt37530.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 c6a71654104..c05f6854f66 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 @@ -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 { 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 97ba54812e5..797acff9179 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 @@ -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 { 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 f152c029f9e..13bcf922bfe 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 @@ -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 { 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 fda2ba13dde..6d700b0bc12 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 @@ -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 { diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt index 3238c2b37d5..a43167b8ed6 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/CommonExpressionCheckers.kt @@ -48,6 +48,7 @@ object CommonExpressionCheckers : ExpressionCheckers() { FirReifiedChecker, FirSuspendCallChecker, FirLateinitIntrinsicApplicabilityChecker, + FirAbstractClassInstantiationChecker, ) override val callCheckers: Set diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAbstractClassInstantiationChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAbstractClassInstantiationChecker.kt new file mode 100644 index 00000000000..57456f7aa74 --- /dev/null +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirAbstractClassInstantiationChecker.kt @@ -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) + } + } +} diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirConstructorCallChecker.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirConstructorCallChecker.kt index 449525d4084..59f4c96e981 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirConstructorCallChecker.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/checkers/expression/FirConstructorCallChecker.kt @@ -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 diff --git a/compiler/testData/diagnostics/tests/abstractClassReference.kt b/compiler/testData/diagnostics/tests/abstractClassReference.kt new file mode 100644 index 00000000000..52d170be2f8 --- /dev/null +++ b/compiler/testData/diagnostics/tests/abstractClassReference.kt @@ -0,0 +1,9 @@ +// FIR_IDENTICAL +// ISSUE: KT-58938 + +abstract class AbstractClass() + +fun main(args: Array) { + val abstractClass = ::AbstractClass + abstractClass.invoke() +} diff --git a/compiler/testData/diagnostics/tests/callableReference/function/abstractClassConstructors.fir.kt b/compiler/testData/diagnostics/tests/callableReference/function/abstractClassConstructors.fir.kt index 312d98eb1ec..dabdec37e8c 100644 --- a/compiler/testData/diagnostics/tests/callableReference/function/abstractClassConstructors.fir.kt +++ b/compiler/testData/diagnostics/tests/callableReference/function/abstractClassConstructors.fir.kt @@ -6,7 +6,7 @@ enum class D fun main() { ::A - ::B + ::B ::C // KT-3465 ::D } diff --git a/compiler/testData/diagnostics/tests/callableReference/kt37530.fir.kt b/compiler/testData/diagnostics/tests/callableReference/kt37530.fir.kt deleted file mode 100644 index bc04a045dde..00000000000 --- a/compiler/testData/diagnostics/tests/callableReference/kt37530.fir.kt +++ /dev/null @@ -1,10 +0,0 @@ - -abstract class Abstract - -fun create(fn: () -> D): D { - return fn() -} - -fun main() { - create(::Abstract) -} diff --git a/compiler/testData/diagnostics/tests/callableReference/kt37530.kt b/compiler/testData/diagnostics/tests/callableReference/kt37530.kt index 368cdcca34e..5ea30826443 100644 --- a/compiler/testData/diagnostics/tests/callableReference/kt37530.kt +++ b/compiler/testData/diagnostics/tests/callableReference/kt37530.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL abstract class Abstract 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 d6052b52f10..4b894b653d5 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 @@ -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 {