diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt index f6138bf0609..03796ddf1ff 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDataClassConverters.kt @@ -2440,6 +2440,12 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert token, ) } + add(FirErrors.UNSUPPORTED_CLASS_LITERALS_WITH_EMPTY_LHS) { firDiagnostic -> + UnsupportedClassLiteralsWithEmptyLhsImpl( + firDiagnostic as KtPsiDiagnostic, + token, + ) + } add(FirErrors.NOTHING_TO_OVERRIDE) { firDiagnostic -> NothingToOverrideImpl( firSymbolBuilder.callableBuilder.buildCallableSymbol(firDiagnostic.a), diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt index 528445ee15c..43907e6d52a 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnostics.kt @@ -1730,6 +1730,10 @@ sealed interface KtFirDiagnostic : KtDiagnosticWithPsi { val lhsType: KtType } + interface UnsupportedClassLiteralsWithEmptyLhs : KtFirDiagnostic { + override val diagnosticClass get() = UnsupportedClassLiteralsWithEmptyLhs::class + } + interface NothingToOverride : KtFirDiagnostic { override val diagnosticClass get() = NothingToOverride::class val declaration: KtCallableSymbol diff --git a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt index 5658b6043fc..2142a92dd4e 100644 --- a/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt +++ b/analysis/analysis-api-fir/src/org/jetbrains/kotlin/analysis/api/fir/diagnostics/KtFirDiagnosticsImpl.kt @@ -2080,6 +2080,11 @@ internal class ExpressionOfNullableTypeInClassLiteralLhsImpl( token: KtLifetimeToken, ) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.ExpressionOfNullableTypeInClassLiteralLhs +internal class UnsupportedClassLiteralsWithEmptyLhsImpl( + firDiagnostic: KtPsiDiagnostic, + token: KtLifetimeToken, +) : KtAbstractFirDiagnostic(firDiagnostic, token), KtFirDiagnostic.UnsupportedClassLiteralsWithEmptyLhs + internal class NothingToOverrideImpl( override val declaration: KtCallableSymbol, firDiagnostic: KtPsiDiagnostic, 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 18e0ab8adf3..23c6daa93b9 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 @@ -297,6 +297,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/Dollar.kt"); } + @Test + @TestMetadata("emptyLhsClassLiterals.kt") + public void testEmptyLhsClassLiterals() throws Exception { + runTest("compiler/testData/diagnostics/tests/emptyLhsClassLiterals.kt"); + } + @Test @TestMetadata("EnumEntryAsType.kt") public void testEnumEntryAsType() 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 f02c7cadcc9..9e585066ede 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 @@ -297,6 +297,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/Dollar.kt"); } + @Test + @TestMetadata("emptyLhsClassLiterals.kt") + public void testEmptyLhsClassLiterals() throws Exception { + runTest("compiler/testData/diagnostics/tests/emptyLhsClassLiterals.kt"); + } + @Test @TestMetadata("EnumEntryAsType.kt") public void testEnumEntryAsType() 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 2144906c1c0..830727e76ba 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 @@ -297,6 +297,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/Dollar.kt"); } + @Test + @TestMetadata("emptyLhsClassLiterals.kt") + public void testEmptyLhsClassLiterals() throws Exception { + runTest("compiler/testData/diagnostics/tests/emptyLhsClassLiterals.kt"); + } + @Test @TestMetadata("EnumEntryAsType.kt") public void testEnumEntryAsType() 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 3d58d54e6ae..6bcd034c23c 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 @@ -297,6 +297,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/Dollar.kt"); } + @Test + @TestMetadata("emptyLhsClassLiterals.kt") + public void testEmptyLhsClassLiterals() throws Exception { + runTest("compiler/testData/diagnostics/tests/emptyLhsClassLiterals.kt"); + } + @Test @TestMetadata("EnumEntryAsType.kt") public void testEnumEntryAsType() throws Exception { diff --git a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt index 7de25b33cb6..f34c9cb0cda 100644 --- a/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt +++ b/compiler/fir/checkers/checkers-component-generator/src/org/jetbrains/kotlin/fir/checkers/generator/diagnostics/FirDiagnosticsList.kt @@ -806,6 +806,7 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") { val EXPRESSION_OF_NULLABLE_TYPE_IN_CLASS_LITERAL_LHS by error { parameter("lhsType") } + val UNSUPPORTED_CLASS_LITERALS_WITH_EMPTY_LHS by error() } val OVERRIDES by object : DiagnosticGroup("overrides") { diff --git a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt index f686e2c9df1..d5a6771ba77 100644 --- a/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt +++ b/compiler/fir/checkers/gen/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrors.kt @@ -463,6 +463,7 @@ object FirErrors { val CLASS_LITERAL_LHS_NOT_A_CLASS by error0() val NULLABLE_TYPE_IN_CLASS_LITERAL_LHS by error0() val EXPRESSION_OF_NULLABLE_TYPE_IN_CLASS_LITERAL_LHS by error1() + val UNSUPPORTED_CLASS_LITERALS_WITH_EMPTY_LHS by error0() // overrides val NOTHING_TO_OVERRIDE by error1>(SourceElementPositioningStrategies.OVERRIDE_MODIFIER) diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt index 4d979140561..93c945f3ed2 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/FirErrorsDefaultMessages.kt @@ -595,6 +595,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSAFE_INFIX_CALL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSAFE_OPERATOR_CALL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSIGNED_LITERAL_WITHOUT_DECLARATIONS_ON_CLASSPATH import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED +import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_CLASS_LITERALS_WITH_EMPTY_LHS import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_CONTEXTUAL_DECLARATION_CALL import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNSUPPORTED_FEATURE import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.UNUSED_VARIABLE @@ -1359,6 +1360,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { "Expression in a class literal has a nullable type ''{0}'', use !! to make the type non-nullable", RENDER_TYPE ) + map.put(UNSUPPORTED_CLASS_LITERALS_WITH_EMPTY_LHS, "Class literals with empty left hand side are unsupported") // Value classes map.put(VALUE_CLASS_NOT_TOP_LEVEL, "Value class cannot be local or inner") @@ -2002,7 +2004,7 @@ object FirErrorsDefaultMessages : BaseDiagnosticRendererFactory() { map.put(USELESS_CAST, "No cast needed") map.put(UNCHECKED_CAST, "Unchecked cast: ''{0}'' to ''{1}''", RENDER_TYPE, RENDER_TYPE) map.put(USELESS_IS_CHECK, "Check for instance is always ''{0}''", TO_STRING) - map.put(DYNAMIC_NOT_ALLOWED, "Dynamic types are not allowed in this position"); + map.put(DYNAMIC_NOT_ALLOWED, "Dynamic types are not allowed in this position") map.put(IS_ENUM_ENTRY, "'is' over enum entry is not allowed, use comparison instead") map.put(ENUM_ENTRY_AS_TYPE, "Use of enum entry names as types is not allowed, use enum type instead") diff --git a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt index 797f1c64895..c944f71c937 100644 --- a/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt +++ b/compiler/fir/checkers/src/org/jetbrains/kotlin/fir/analysis/diagnostics/coneDiagnosticToFirDiagnostic.kt @@ -151,6 +151,7 @@ private fun ConeDiagnostic.toKtDiagnostic( is ConeAmbiguouslyResolvedAnnotationArgument -> FirErrors.AMBIGUOUS_ANNOTATION_ARGUMENT.createOn(source, listOfNotNull(symbolFromCompilerPhase, symbolFromAnnotationArgumentsPhase)) is ConeAmbiguousFunctionTypeKinds -> FirErrors.AMBIGUOUS_FUNCTION_TYPE_KIND.createOn(source, kinds) + is ConeUnsupportedClassLiteralsWithEmptyLhs -> FirErrors.UNSUPPORTED_CLASS_LITERALS_WITH_EMPTY_LHS.createOn(source) else -> throw IllegalArgumentException("Unsupported diagnostic type: ${this.javaClass}") } diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt index 2bf457c1fff..5d2b71ab84c 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirExpressionBuilder.kt @@ -463,11 +463,13 @@ class LightTreeRawFirExpressionBuilder( if (it.isExpression()) firReceiverExpression = getAsFirExpression(it, "No receiver in class literal") } + val classLiteralSource = classLiteralExpression.toFirSourceElement() + return buildGetClassCall { - source = classLiteralExpression.toFirSourceElement() + source = classLiteralSource argumentList = buildUnaryArgumentList( firReceiverExpression - ?: buildErrorExpression(null, ConeSyntaxDiagnostic("No receiver in class literal")) + ?: buildErrorExpression(classLiteralSource, ConeUnsupportedClassLiteralsWithEmptyLhs) ) } } diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt index 1267dc4771d..f378a3caf0f 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiRawFirBuilder.kt @@ -276,9 +276,12 @@ open class PsiRawFirBuilder( kind: DiagnosticKind = DiagnosticKind.ExpressionExpected ): FirExpression = toFirExpression { ConeSimpleDiagnostic(errorReason, kind) } - private inline fun KtElement?.toFirExpression(diagnosticFn: () -> ConeDiagnostic): FirExpression { + private inline fun KtElement?.toFirExpression( + sourceWhenThisIsNull: PsiElement? = null, + diagnosticFn: () -> ConeDiagnostic, + ): FirExpression { if (this == null) { - return buildErrorExpression(source = null, diagnosticFn()) + return buildErrorExpression(source = sourceWhenThisIsNull?.toFirSourceElement(), diagnosticFn()) } val result = when (val fir = convertElement(this, null)) { @@ -2929,7 +2932,11 @@ open class PsiRawFirBuilder( override fun visitClassLiteralExpression(expression: KtClassLiteralExpression, data: FirElement?): FirElement { return buildGetClassCall { source = expression.toFirSourceElement() - argumentList = buildUnaryArgumentList(expression.receiverExpression.toFirExpression("No receiver in class literal")) + argumentList = buildUnaryArgumentList( + expression.receiverExpression.toFirExpression(sourceWhenThisIsNull = expression) { + ConeUnsupportedClassLiteralsWithEmptyLhs + } + ) } } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt index 239aae077e3..0414fd44404 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/diagnostics/ConeSimpleDiagnostic.kt @@ -71,6 +71,10 @@ class ConeAmbiguousFunctionTypeKinds(val kinds: List) : ConeDi get() = "There are multiple function kinds for functional type ref" } +object ConeUnsupportedClassLiteralsWithEmptyLhs : ConeDiagnostic { + override val reason: String get() = "No receiver in class literal" +} + enum class DiagnosticKind { ExpressionExpected, NotLoopLabel, diff --git a/compiler/testData/diagnostics/tests/callableReference/unsupported/classLiteralsWithEmptyLHS.fir.kt b/compiler/testData/diagnostics/tests/callableReference/unsupported/classLiteralsWithEmptyLHS.fir.kt deleted file mode 100644 index 8b6132d8fdf..00000000000 --- a/compiler/testData/diagnostics/tests/callableReference/unsupported/classLiteralsWithEmptyLHS.fir.kt +++ /dev/null @@ -1,17 +0,0 @@ -fun regular() { - ::class - - with(Any()) { - ::class - } -} - -fun Any.extension() { - ::class -} - -class A { - fun member() { - ::class - } -} \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/callableReference/unsupported/classLiteralsWithEmptyLHS.kt b/compiler/testData/diagnostics/tests/callableReference/unsupported/classLiteralsWithEmptyLHS.kt index 5e8e98039bc..10915ab3679 100644 --- a/compiler/testData/diagnostics/tests/callableReference/unsupported/classLiteralsWithEmptyLHS.kt +++ b/compiler/testData/diagnostics/tests/callableReference/unsupported/classLiteralsWithEmptyLHS.kt @@ -1,3 +1,4 @@ +// FIR_IDENTICAL fun regular() { ::class diff --git a/compiler/testData/diagnostics/tests/emptyLhsClassLiterals.kt b/compiler/testData/diagnostics/tests/emptyLhsClassLiterals.kt new file mode 100644 index 00000000000..7cb4c1e5134 --- /dev/null +++ b/compiler/testData/diagnostics/tests/emptyLhsClassLiterals.kt @@ -0,0 +1,6 @@ +// FIR_IDENTICAL +// ISSUE: KT-59165 + +fun regular() { + ::class // K1: Error, K2: compiles +} 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 4941edc8aad..86de8d7671d 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 @@ -297,6 +297,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/Dollar.kt"); } + @Test + @TestMetadata("emptyLhsClassLiterals.kt") + public void testEmptyLhsClassLiterals() throws Exception { + runTest("compiler/testData/diagnostics/tests/emptyLhsClassLiterals.kt"); + } + @Test @TestMetadata("EnumEntryAsType.kt") public void testEnumEntryAsType() throws Exception {