From 70d49999accf77221ab50e90dd657f5f30c9beb9 Mon Sep 17 00:00:00 2001 From: Egor Kulikov Date: Thu, 13 Jul 2023 17:37:48 +0000 Subject: [PATCH] [FIR] Generate an error primary constructor when super call is invalid Merge-request: KT-MR-11026 Merged-by: Egor Kulikov --- .../file/structure/FileStructureElement.kt | 6 +- .../calls/qualifiedCallInsideSuperCall3.txt | 29 +-- .../calls/qualifiedCallInsideSuperCall4.txt | 33 ++- .../calls/qualifiedCallInsideSuperCall5.txt | 4 + ...CompilerTestFE10TestdataTestGenerated.java | 6 + ...sticCompilerFE10TestDataTestGenerated.java | 6 + .../explicitDelegationCallRequired.fir.txt | 4 + .../explicitDelegationCallRequired.kt | 2 +- .../interfaceWithSuperclass.fir.txt | 9 + .../supertypeInitializedInInterface.fir.txt | 18 ++ .../supertypeInitializedInInterface.kt | 2 +- ...itializedWithoutPrimaryConstructor.fir.txt | 4 + .../resolve/suppress/withSuppression.fir.txt | 4 + .../resolve/suppress/withSuppression.kt | 2 +- ...eeOldFrontendDiagnosticsTestGenerated.java | 6 + ...siOldFrontendDiagnosticsTestGenerated.java | 6 + .../LightTreeRawFirDeclarationBuilder.kt | 53 ++--- .../kotlin/fir/builder/PsiRawFirBuilder.kt | 21 +- .../classWithWrongSuperCall.lazyBodies.txt | 8 + .../declarations/classWithWrongSuperCall.txt | 20 ++ .../builder/FirErrorConstructorBuilder.kt | 112 ++++++++++ .../declarations/impl/FirErrorConstructor.kt | 192 ++++++++++++++++++ .../fir/renderer/FirDeclarationRenderer.kt | 4 + .../fir/tree/generator/BuilderConfigurator.kt | 2 +- .../generator/ImplementationConfigurator.kt | 5 + .../classWithFunctionSupertype_after.fir.kt | 12 +- .../classWithFunctionSupertype_before.fir.kt | 12 +- .../errorInsideDelegationCallNoPrimary.fir.kt | 5 + .../errorInsideDelegationCallNoPrimary.kt | 5 + .../test/runners/DiagnosticTestGenerated.java | 6 + 30 files changed, 523 insertions(+), 75 deletions(-) create mode 100644 compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirErrorConstructorBuilder.kt create mode 100644 compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirErrorConstructor.kt create mode 100644 compiler/testData/diagnostics/tests/constructorConsistency/errorInsideDelegationCallNoPrimary.fir.kt create mode 100644 compiler/testData/diagnostics/tests/constructorConsistency/errorInsideDelegationCallNoPrimary.kt diff --git a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureElement.kt b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureElement.kt index 921527fd758..46750b58237 100644 --- a/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureElement.kt +++ b/analysis/low-level-api-fir/src/org/jetbrains/kotlin/analysis/low/level/api/fir/file/structure/FileStructureElement.kt @@ -15,6 +15,7 @@ import org.jetbrains.kotlin.analysis.low.level.api.fir.diagnostics.SingleNonLoca import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.correspondingProperty import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.impl.FirErrorConstructor import org.jetbrains.kotlin.fir.declarations.impl.FirPrimaryConstructor import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol @@ -148,7 +149,10 @@ internal class NonReanalyzableClassDeclarationStructureElement( } override fun visitConstructor(constructor: FirConstructor, data: MutableMap) { - if (constructor is FirPrimaryConstructor && constructor.source?.kind == KtFakeSourceElementKind.ImplicitConstructor) { + if ( + (constructor is FirPrimaryConstructor || constructor is FirErrorConstructor) && + constructor.source?.kind == KtFakeSourceElementKind.ImplicitConstructor + ) { NonReanalyzableNonClassDeclarationStructureElement.Recorder.visitConstructor(constructor, data) } } diff --git a/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/qualifiedCallInsideSuperCall3.txt b/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/qualifiedCallInsideSuperCall3.txt index fa48fc1ac4f..6d4840a6abd 100644 --- a/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/qualifiedCallInsideSuperCall3.txt +++ b/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/qualifiedCallInsideSuperCall3.txt @@ -1,14 +1,9 @@ KT element: KtNameReferenceExpression -FIR element: FirRegularClassImpl +FIR element: FirResolvedNamedReferenceImpl FIR source kind: KtRealSourceElementKind FIR element rendered: -public final [ResolvedTo(BODY_RESOLVE)] object C : R|A| { - public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=C] constructor(): R|C| { - super() - } - -} +R|/A.prop| FIR FILE: FILE: [ResolvedTo(IMPORTS)] qualifiedCallInsideSuperCall3.kt @@ -18,17 +13,27 @@ FILE: [ResolvedTo(IMPORTS)] qualifiedCallInsideSuperCall3.kt LAZY_super } - public final [ResolvedTo(STATUS)] val prop: R|kotlin/String| = LAZY_EXPRESSION - public [ResolvedTo(STATUS)] [ContainingClassKey=A] get(): R|kotlin/String| + public final [ResolvedTo(CONTRACTS)] val prop: R|kotlin/String| = String() + public [ResolvedTo(CONTRACTS)] [ContainingClassKey=A] get(): R|kotlin/String| } - public? final? [ResolvedTo(RAW_FIR)] object B : A { - private [ResolvedTo(RAW_FIR)] [ContainingClassKey=B] constructor(): R|B| { - LAZY_super + public final [ResolvedTo(STATUS)] object B : R|A| { + private [ResolvedTo(STATUS)] [ContainingClassKey=B] constructor(): R|B| { + LAZY_super } } public final [ResolvedTo(BODY_RESOLVE)] object C : R|A| { + private [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=C] error_constructor(): R|C| { + super([ResolvedTo(RAW_FIR)] fun R|A|.(): R|kotlin/Unit| { + local final [ResolvedTo(RAW_FIR)] fun foo(): R|kotlin/String| { + ^foo Q|B|.R|/A.prop|.R|kotlin/String.toString|() + } + + } + ) + } + public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=C] constructor(): R|C| { super() } diff --git a/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/qualifiedCallInsideSuperCall4.txt b/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/qualifiedCallInsideSuperCall4.txt index b0a19f97cee..630b7df1a15 100644 --- a/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/qualifiedCallInsideSuperCall4.txt +++ b/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/qualifiedCallInsideSuperCall4.txt @@ -1,20 +1,9 @@ KT element: KtNameReferenceExpression -FIR element: FirRegularClassImpl +FIR element: FirResolvedNamedReferenceImpl FIR source kind: KtRealSourceElementKind FIR element rendered: -public final [ResolvedTo(BODY_RESOLVE)] class G : R|A| { - public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=G] constructor(): R|G| { - super([ResolvedTo(RAW_FIR)] fun R|A|.(): R|kotlin/Unit| { - local final [ResolvedTo(RAW_FIR)] fun foo(): R|kotlin/String| { - ^foo Q|C|.R|/A.prop|.R|kotlin/String.toString|() - } - - } - ) - } - -} +R|/A.prop| FIR FILE: FILE: [ResolvedTo(IMPORTS)] qualifiedCallInsideSuperCall4.kt @@ -28,9 +17,9 @@ FILE: [ResolvedTo(IMPORTS)] qualifiedCallInsideSuperCall4.kt public [ResolvedTo(CONTRACTS)] [ContainingClassKey=A] get(): R|kotlin/String| } - public? final? [ResolvedTo(RAW_FIR)] object B : A { - private [ResolvedTo(RAW_FIR)] [ContainingClassKey=B] constructor(): R|B| { - LAZY_super + public final [ResolvedTo(STATUS)] object B : R|A| { + private [ResolvedTo(STATUS)] [ContainingClassKey=B] constructor(): R|B| { + LAZY_super } } @@ -41,6 +30,16 @@ FILE: [ResolvedTo(IMPORTS)] qualifiedCallInsideSuperCall4.kt } public final [ResolvedTo(BODY_RESOLVE)] class G : R|A| { + public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=G] error_constructor(): R|G| { + super([ResolvedTo(RAW_FIR)] fun R|A|.(): R|kotlin/Unit| { + local final [ResolvedTo(RAW_FIR)] fun foo(): R|kotlin/String| { + ^foo Q|B|.R|/A.prop|.R|kotlin/String.toString|() + } + + } + ) + } + public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=G] constructor(): R|G| { super([ResolvedTo(RAW_FIR)] fun R|A|.(): R|kotlin/Unit| { local final [ResolvedTo(RAW_FIR)] fun foo(): R|kotlin/String| { @@ -51,4 +50,4 @@ FILE: [ResolvedTo(IMPORTS)] qualifiedCallInsideSuperCall4.kt ) } - } + } \ No newline at end of file diff --git a/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/qualifiedCallInsideSuperCall5.txt b/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/qualifiedCallInsideSuperCall5.txt index 1fb980cc60f..02e9d4387aa 100644 --- a/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/qualifiedCallInsideSuperCall5.txt +++ b/analysis/low-level-api-fir/testdata/getOrBuildFir/calls/qualifiedCallInsideSuperCall5.txt @@ -30,6 +30,10 @@ FILE: [ResolvedTo(IMPORTS)] qualifiedCallInsideSuperCall5.kt } public final [ResolvedTo(STATUS)] class G : R|A| { + public [ResolvedTo(STATUS)] [ContainingClassKey=G] error_constructor(): R|G| { + LAZY_super + } + public [ResolvedTo(BODY_RESOLVE)] [ContainingClassKey=G] constructor(): R|G| { super([ResolvedTo(RAW_FIR)] fun R|A|.(): R|kotlin/Unit| { local final [ResolvedTo(RAW_FIR)] fun foo(): R|kotlin/String| { 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 2c8a7269e82..595e77d215d 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 @@ -5990,6 +5990,12 @@ public class DiagnosticCompilerTestFE10TestdataTestGenerated extends AbstractDia runTest("compiler/testData/diagnostics/tests/constructorConsistency/derivedProperty.kt"); } + @Test + @TestMetadata("errorInsideDelegationCallNoPrimary.kt") + public void testErrorInsideDelegationCallNoPrimary() throws Exception { + runTest("compiler/testData/diagnostics/tests/constructorConsistency/errorInsideDelegationCallNoPrimary.kt"); + } + @Test @TestMetadata("getset.kt") public void testGetset() 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 073577c299e..90d368e2484 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 @@ -5990,6 +5990,12 @@ public class LLFirPreresolvedReversedDiagnosticCompilerFE10TestDataTestGenerated runTest("compiler/testData/diagnostics/tests/constructorConsistency/derivedProperty.kt"); } + @Test + @TestMetadata("errorInsideDelegationCallNoPrimary.kt") + public void testErrorInsideDelegationCallNoPrimary() throws Exception { + runTest("compiler/testData/diagnostics/tests/constructorConsistency/errorInsideDelegationCallNoPrimary.kt"); + } + @Test @TestMetadata("getset.kt") public void testGetset() throws Exception { diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/explicitDelegationCallRequired.fir.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/explicitDelegationCallRequired.fir.txt index 4d82ac2c95e..d7f99c16cef 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/explicitDelegationCallRequired.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/explicitDelegationCallRequired.fir.txt @@ -20,6 +20,10 @@ FILE: explicitDelegationCallRequired.kt } public final class C : R|A| { + public error_constructor(): R|C| { + super(Int(20)) + } + public constructor(): R|C| { super() } diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/explicitDelegationCallRequired.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/explicitDelegationCallRequired.kt index 1412e6668eb..071f26b28ed 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/explicitDelegationCallRequired.kt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/explicitDelegationCallRequired.kt @@ -9,7 +9,7 @@ class B : A { class C : A(20) { constructor() - constructor(z: String) : this() + constructor(z: String) : this() } class D() : A(20) { diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/interfaceWithSuperclass.fir.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/interfaceWithSuperclass.fir.txt index 22788fadf1a..5a0509cfe92 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/interfaceWithSuperclass.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/interfaceWithSuperclass.fir.txt @@ -6,6 +6,10 @@ FILE: interfaceWithSuperclass.kt } public abstract interface B : R|A| { + public error_constructor(): R|B| { + super() + } + } public abstract interface C : R|kotlin/Any| { } @@ -16,4 +20,9 @@ FILE: interfaceWithSuperclass.kt } public abstract interface E : R|A|, R|C|, R|D| { + public error_constructor(): R|E| { + super() + super() + } + } diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/supertypeInitializedInInterface.fir.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/supertypeInitializedInInterface.fir.txt index 7cb8016475b..9bb00388abb 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/supertypeInitializedInInterface.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/supertypeInitializedInInterface.fir.txt @@ -2,6 +2,10 @@ FILE: supertypeInitializedInInterface.kt public abstract interface A : R|kotlin/Any| { } public abstract interface B : R|A| { + public error_constructor(): R|B| { + super() + } + } public open class C : R|kotlin/Any| { public constructor(): R|C| { @@ -10,8 +14,22 @@ FILE: supertypeInitializedInInterface.kt } public abstract interface D : R|C| { + public error_constructor(): R|D| { + super() + } + } public abstract interface E : R|kotlin/Any| { + public error_constructor(): R|E| { + super() + } + } public abstract interface F : R|A|, R|B|, R|C|, R|D|, R|kotlin/Any| { + public error_constructor(): R|F| { + super() + super() + super() + } + } diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/supertypeInitializedInInterface.kt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/supertypeInitializedInInterface.kt index c2f3e30e6e0..9c08dcca7e2 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/supertypeInitializedInInterface.kt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/supertypeInitializedInInterface.kt @@ -1,6 +1,6 @@ interface A -interface B : A() +interface B : A() open class C diff --git a/compiler/fir/analysis-tests/testData/resolve/diagnostics/supertypeInitializedWithoutPrimaryConstructor.fir.txt b/compiler/fir/analysis-tests/testData/resolve/diagnostics/supertypeInitializedWithoutPrimaryConstructor.fir.txt index 596b9f4e4f9..7a149b38ea8 100644 --- a/compiler/fir/analysis-tests/testData/resolve/diagnostics/supertypeInitializedWithoutPrimaryConstructor.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/diagnostics/supertypeInitializedWithoutPrimaryConstructor.fir.txt @@ -36,6 +36,10 @@ FILE: supertypeInitializedWithoutPrimaryConstructor.kt } public final class G : R|C| { + public error_constructor(): R|G| { + super(Int(10)) + } + public constructor(): R|G| { super(Int(1)) } diff --git a/compiler/fir/analysis-tests/testData/resolve/suppress/withSuppression.fir.txt b/compiler/fir/analysis-tests/testData/resolve/suppress/withSuppression.fir.txt index c65d5601c98..04f383500a2 100644 --- a/compiler/fir/analysis-tests/testData/resolve/suppress/withSuppression.fir.txt +++ b/compiler/fir/analysis-tests/testData/resolve/suppress/withSuppression.fir.txt @@ -20,6 +20,10 @@ FILE: withSuppression.kt public abstract interface A : R|kotlin/Any| { } public abstract interface B : R|@R|kotlin/Suppress|(names = vararg(String(SUPERTYPE_INITIALIZED_IN_INTERFACE))) A| { + public error_constructor(): R|B| { + super() + } + } public final data class D : R|kotlin/Any| { @R|kotlin/Suppress|(names = vararg(String(DATA_CLASS_VARARG_PARAMETER))) public constructor(vararg x: R|kotlin/Array|): R|D| { diff --git a/compiler/fir/analysis-tests/testData/resolve/suppress/withSuppression.kt b/compiler/fir/analysis-tests/testData/resolve/suppress/withSuppression.kt index b32b51fc938..470648f86ae 100644 --- a/compiler/fir/analysis-tests/testData/resolve/suppress/withSuppression.kt +++ b/compiler/fir/analysis-tests/testData/resolve/suppress/withSuppression.kt @@ -15,6 +15,6 @@ typealias Alias = @Suppress("TYPEALIAS_SHOULD_EXPAND_TO_CLASS") T interface A -interface B : @Suppress("SUPERTYPE_INITIALIZED_IN_INTERFACE") A() +interface B : @Suppress("SUPERTYPE_INITIALIZED_IN_INTERFACE") A() data class D @Suppress("DATA_CLASS_VARARG_PARAMETER") constructor(vararg val x: String) 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 1ca47a02462..68f3d03bd58 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 @@ -5990,6 +5990,12 @@ public class FirLightTreeOldFrontendDiagnosticsTestGenerated extends AbstractFir runTest("compiler/testData/diagnostics/tests/constructorConsistency/derivedProperty.kt"); } + @Test + @TestMetadata("errorInsideDelegationCallNoPrimary.kt") + public void testErrorInsideDelegationCallNoPrimary() throws Exception { + runTest("compiler/testData/diagnostics/tests/constructorConsistency/errorInsideDelegationCallNoPrimary.kt"); + } + @Test @TestMetadata("getset.kt") public void testGetset() 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 799714249ba..760a1cd7847 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 @@ -5996,6 +5996,12 @@ public class FirPsiOldFrontendDiagnosticsTestGenerated extends AbstractFirPsiDia runTest("compiler/testData/diagnostics/tests/constructorConsistency/derivedProperty.kt"); } + @Test + @TestMetadata("errorInsideDelegationCallNoPrimary.kt") + public void testErrorInsideDelegationCallNoPrimary() throws Exception { + runTest("compiler/testData/diagnostics/tests/constructorConsistency/errorInsideDelegationCallNoPrimary.kt"); + } + @Test @TestMetadata("getset.kt") public void testGetset() throws Exception { diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt index f89e11ddee4..4193499959f 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/LightTreeRawFirDeclarationBuilder.kt @@ -891,12 +891,15 @@ class LightTreeRawFirDeclarationBuilder( isEnumEntry: Boolean = false, containingClassIsExpectClass: Boolean ): PrimaryConstructor? { - if (primaryConstructor == null && !classWrapper.isEnumEntry() && classWrapper.hasSecondaryConstructor) return null - val classKind = classWrapper.classBuilder.classKind - if (primaryConstructor == null && - (containingClassIsExpectClass && classKind != ClassKind.ENUM_CLASS && classKind != ClassKind.ENUM_ENTRY) - ) return null - if (primaryConstructor == null && classWrapper.isInterface()) return null + fun ClassKind.isEnumRelated(): Boolean = this == ClassKind.ENUM_CLASS || this == ClassKind.ENUM_ENTRY + val shouldGenerateImplicitConstructor = + (classWrapper.isEnumEntry() || !classWrapper.hasSecondaryConstructor) && + !classWrapper.isInterface() && + (!containingClassIsExpectClass || classWrapper.classBuilder.classKind.isEnumRelated()) + val isErrorConstructor = primaryConstructor == null && !shouldGenerateImplicitConstructor + if (isErrorConstructor && classWrapper.delegatedSuperCalls.isEmpty()) { + return null + } val constructorSymbol = FirConstructorSymbol(callableIdForClassConstructor()) var modifiers = Modifier() @@ -963,25 +966,29 @@ class LightTreeRawFirDeclarationBuilder( isFromEnumClass = classWrapper.isEnum() } + val builder = if (isErrorConstructor) FirErrorConstructorBuilder() else FirPrimaryConstructorBuilder() + builder.apply { + source = primaryConstructor?.toFirSourceElement() + ?: selfTypeSource?.fakeElement(KtFakeSourceElementKind.ImplicitConstructor) + moduleData = baseModuleData + origin = FirDeclarationOrigin.Source + returnTypeRef = classWrapper.delegatedSelfTypeRef + dispatchReceiverType = classWrapper.obtainDispatchReceiverForConstructor() + this.status = status + symbol = constructorSymbol + annotations += modifiers.annotations + typeParameters += constructorTypeParametersFromConstructedClass(classWrapper.classBuilder.typeParameters) + this.valueParameters += valueParameters.map { it.firValueParameter } + delegatedConstructor = firDelegatedCall + this.body = null + this.contextReceivers.addAll(convertContextReceivers(classNode)) + } + return PrimaryConstructor( - buildPrimaryConstructor { - source = primaryConstructor?.toFirSourceElement() - ?: selfTypeSource?.fakeElement(KtFakeSourceElementKind.ImplicitConstructor) - moduleData = baseModuleData - origin = FirDeclarationOrigin.Source - returnTypeRef = classWrapper.delegatedSelfTypeRef - dispatchReceiverType = classWrapper.obtainDispatchReceiverForConstructor() - this.status = status - symbol = constructorSymbol - annotations += modifiers.annotations - typeParameters += constructorTypeParametersFromConstructedClass(classWrapper.classBuilder.typeParameters) - this.valueParameters += valueParameters.map { it.firValueParameter } - delegatedConstructor = firDelegatedCall - this.body = null - this.contextReceivers.addAll(convertContextReceivers(classNode)) - }.apply { + builder.build().apply { containingClassForStaticMemberAttr = currentDispatchReceiverType()!!.lookupTag - }, valueParameters + }, + valueParameters, ) } 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 fa3231c400d..1849089bb41 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 @@ -956,10 +956,17 @@ open class PsiRawFirBuilder( // TODO: in case we have no primary constructor, // it may be not possible to determine delegated super type right here delegatedSuperTypeRef = delegatedSuperTypeRef ?: defaultDelegatedSuperTypeRef - val shouldGenerateImplicitPrimaryConstructor = - !hasExplicitPrimaryConstructor() && !hasSecondaryConstructors() && !(containingClassIsExpectClass && classKind != ClassKind.ENUM_CLASS) - if (primaryConstructor != null || (this !is KtClass || !this.isInterface()) && shouldGenerateImplicitPrimaryConstructor) { + // We are never here as part of enum entry + val shouldGenerateImplicitPrimaryConstructor = + !hasSecondaryConstructors() && + !(containingClassIsExpectClass && classKind != ClassKind.ENUM_CLASS) && + (this !is KtClass || !this.isInterface()) + + val hasPrimaryConstructor = primaryConstructor != null || shouldGenerateImplicitPrimaryConstructor + + + if (hasPrimaryConstructor || superTypeCallEntry != null) { val firPrimaryConstructor = primaryConstructor.toFirConstructor( superTypeCallEntry, delegatedSuperTypeRef, @@ -969,6 +976,7 @@ open class PsiRawFirBuilder( allSuperTypeCallEntries, containingClassIsExpectClass, copyConstructedTypeRefWithImplicitSource = true, + isErrorConstructor = !hasPrimaryConstructor, ) container.declarations += firPrimaryConstructor } @@ -988,6 +996,7 @@ open class PsiRawFirBuilder( allSuperTypeCallEntries: List>, containingClassIsExpectClass: Boolean, copyConstructedTypeRefWithImplicitSource: Boolean, + isErrorConstructor: Boolean = false, ): FirConstructor { val constructorSource = this?.toFirSourceElement() ?: owner.toKtPsiSourceElement(KtFakeSourceElementKind.ImplicitConstructor) @@ -1040,7 +1049,8 @@ open class PsiRawFirBuilder( isFromSealedClass = owner.hasModifier(SEALED_KEYWORD) && explicitVisibility !== Visibilities.Private isFromEnumClass = owner.hasModifier(ENUM_KEYWORD) } - return buildPrimaryConstructor { + val builder = if (isErrorConstructor) FirErrorConstructorBuilder() else FirPrimaryConstructorBuilder() + builder.apply { source = constructorSource moduleData = baseModuleData origin = FirDeclarationOrigin.Source @@ -1054,9 +1064,8 @@ open class PsiRawFirBuilder( this@toFirConstructor?.extractAnnotationsTo(this) this@toFirConstructor?.extractValueParametersTo(this, symbol, ValueParameterDeclaration.PRIMARY_CONSTRUCTOR) this.body = null - }.apply { - containingClassForStaticMemberAttr = currentDispatchReceiverType()!!.lookupTag } + return builder.build().apply { containingClassForStaticMemberAttr = currentDispatchReceiverType()!!.lookupTag } } private fun KtClassOrObject.obtainDispatchReceiverForConstructor(): ConeClassLikeType? = diff --git a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/classWithWrongSuperCall.lazyBodies.txt b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/classWithWrongSuperCall.lazyBodies.txt index f18877a52d7..ee371873725 100644 --- a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/classWithWrongSuperCall.lazyBodies.txt +++ b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/classWithWrongSuperCall.lazyBodies.txt @@ -33,12 +33,20 @@ FILE: classWithWrongSuperCall.kt } public? final? class F : A { + public? error_constructor(): R|F| { + LAZY_super + } + public? constructor(): R|F| { LAZY_super } } public? final? class G : A { + public? error_constructor(): R|G| { + LAZY_super + } + public? constructor(): R|G| { LAZY_super } diff --git a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/classWithWrongSuperCall.txt b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/classWithWrongSuperCall.txt index 2233fd84d53..2c87390f4a8 100644 --- a/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/classWithWrongSuperCall.txt +++ b/compiler/fir/raw-fir/psi2fir/testData/rawBuilder/declarations/classWithWrongSuperCall.txt @@ -54,12 +54,32 @@ FILE: classWithWrongSuperCall.kt } public? final? class F : A { + public? [ContainingClassKey=F] error_constructor(): R|F| { + super(fun .(): { + local final? fun foo(): { + ^foo B#.prop#.toString#() + } + + } + ) + } + public? [ContainingClassKey=F] constructor(): R|F| { super() } } public? final? class G : A { + public? [ContainingClassKey=G] error_constructor(): R|G| { + super(fun .(): { + local final? fun foo(): { + ^foo B#.prop#.toString#() + } + + } + ) + } + public? [ContainingClassKey=G] constructor(): R|G| { super(fun .(): { local final? fun foo(): { diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirErrorConstructorBuilder.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirErrorConstructorBuilder.kt new file mode 100644 index 00000000000..03e3a659ce8 --- /dev/null +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/builder/FirErrorConstructorBuilder.kt @@ -0,0 +1,112 @@ +/* + * Copyright 2010-2023 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. + */ + +@file:Suppress("DuplicatedCode", "unused") + +package org.jetbrains.kotlin.fir.declarations.builder + +import kotlin.contracts.* +import org.jetbrains.kotlin.KtSourceElement +import org.jetbrains.kotlin.fir.FirImplementationDetail +import org.jetbrains.kotlin.fir.FirModuleData +import org.jetbrains.kotlin.fir.builder.FirAnnotationContainerBuilder +import org.jetbrains.kotlin.fir.builder.FirBuilderDsl +import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty +import org.jetbrains.kotlin.fir.contracts.FirContractDescription +import org.jetbrains.kotlin.fir.contracts.impl.FirEmptyContractDescription +import org.jetbrains.kotlin.fir.declarations.DeprecationsProvider +import org.jetbrains.kotlin.fir.declarations.FirConstructor +import org.jetbrains.kotlin.fir.declarations.FirContextReceiver +import org.jetbrains.kotlin.fir.declarations.FirDeclarationAttributes +import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin +import org.jetbrains.kotlin.fir.declarations.FirDeclarationStatus +import org.jetbrains.kotlin.fir.declarations.FirReceiverParameter +import org.jetbrains.kotlin.fir.declarations.FirResolvePhase +import org.jetbrains.kotlin.fir.declarations.FirResolveState +import org.jetbrains.kotlin.fir.declarations.FirTypeParameterRef +import org.jetbrains.kotlin.fir.declarations.FirValueParameter +import org.jetbrains.kotlin.fir.declarations.ResolveStateAccess +import org.jetbrains.kotlin.fir.declarations.UnresolvedDeprecationProvider +import org.jetbrains.kotlin.fir.declarations.asResolveState +import org.jetbrains.kotlin.fir.declarations.builder.FirAbstractConstructorBuilder +import org.jetbrains.kotlin.fir.declarations.impl.FirErrorConstructor +import org.jetbrains.kotlin.fir.expressions.FirAnnotation +import org.jetbrains.kotlin.fir.expressions.FirBlock +import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall +import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference +import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol +import org.jetbrains.kotlin.fir.types.ConeSimpleKotlinType +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.fir.visitors.* +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource + +/* + * This file was generated automatically + * DO NOT MODIFY IT MANUALLY + */ + +@FirBuilderDsl +class FirErrorConstructorBuilder : FirAbstractConstructorBuilder, FirAnnotationContainerBuilder { + override var source: KtSourceElement? = null + override var resolvePhase: FirResolvePhase = FirResolvePhase.RAW_FIR + override lateinit var moduleData: FirModuleData + override lateinit var origin: FirDeclarationOrigin + override var attributes: FirDeclarationAttributes = FirDeclarationAttributes() + override val typeParameters: MutableList = mutableListOf() + override lateinit var status: FirDeclarationStatus + override lateinit var returnTypeRef: FirTypeRef + override var receiverParameter: FirReceiverParameter? = null + override var deprecationsProvider: DeprecationsProvider = UnresolvedDeprecationProvider + override var containerSource: DeserializedContainerSource? = null + override var dispatchReceiverType: ConeSimpleKotlinType? = null + override val contextReceivers: MutableList = mutableListOf() + override val valueParameters: MutableList = mutableListOf() + override var contractDescription: FirContractDescription = FirEmptyContractDescription + override val annotations: MutableList = mutableListOf() + override lateinit var symbol: FirConstructorSymbol + override var delegatedConstructor: FirDelegatedConstructorCall? = null + override var body: FirBlock? = null + + @OptIn(FirImplementationDetail::class) + override fun build(): FirConstructor { + return FirErrorConstructor( + source, + resolvePhase, + moduleData, + origin, + attributes, + typeParameters, + status, + returnTypeRef, + receiverParameter, + deprecationsProvider, + containerSource, + dispatchReceiverType, + contextReceivers.toMutableOrEmpty(), + valueParameters, + contractDescription, + annotations.toMutableOrEmpty(), + symbol, + delegatedConstructor, + body, + ) + } + + + @Deprecated("Modification of 'controlFlowGraphReference' has no impact for FirErrorConstructorBuilder", level = DeprecationLevel.HIDDEN) + override var controlFlowGraphReference: FirControlFlowGraphReference? + get() = throw IllegalStateException() + set(_) { + throw IllegalStateException() + } +} + +@OptIn(ExperimentalContracts::class) +inline fun buildErrorConstructor(init: FirErrorConstructorBuilder.() -> Unit): FirConstructor { + contract { + callsInPlace(init, kotlin.contracts.InvocationKind.EXACTLY_ONCE) + } + return FirErrorConstructorBuilder().apply(init).build() +} diff --git a/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirErrorConstructor.kt b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirErrorConstructor.kt new file mode 100644 index 00000000000..af1d5e9727b --- /dev/null +++ b/compiler/fir/tree/gen/org/jetbrains/kotlin/fir/declarations/impl/FirErrorConstructor.kt @@ -0,0 +1,192 @@ +/* + * Copyright 2010-2023 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. + */ + +@file:Suppress("DuplicatedCode", "unused") + +package org.jetbrains.kotlin.fir.declarations.impl + +import org.jetbrains.kotlin.KtSourceElement +import org.jetbrains.kotlin.fir.FirImplementationDetail +import org.jetbrains.kotlin.fir.FirModuleData +import org.jetbrains.kotlin.fir.contracts.FirContractDescription +import org.jetbrains.kotlin.fir.declarations.DeprecationsProvider +import org.jetbrains.kotlin.fir.declarations.FirConstructor +import org.jetbrains.kotlin.fir.declarations.FirContextReceiver +import org.jetbrains.kotlin.fir.declarations.FirDeclarationAttributes +import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin +import org.jetbrains.kotlin.fir.declarations.FirDeclarationStatus +import org.jetbrains.kotlin.fir.declarations.FirReceiverParameter +import org.jetbrains.kotlin.fir.declarations.FirResolvePhase +import org.jetbrains.kotlin.fir.declarations.FirResolveState +import org.jetbrains.kotlin.fir.declarations.FirTypeParameterRef +import org.jetbrains.kotlin.fir.declarations.FirValueParameter +import org.jetbrains.kotlin.fir.declarations.asResolveState +import org.jetbrains.kotlin.fir.expressions.FirAnnotation +import org.jetbrains.kotlin.fir.expressions.FirBlock +import org.jetbrains.kotlin.fir.expressions.FirDelegatedConstructorCall +import org.jetbrains.kotlin.fir.references.FirControlFlowGraphReference +import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol +import org.jetbrains.kotlin.fir.types.ConeSimpleKotlinType +import org.jetbrains.kotlin.fir.types.FirTypeRef +import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource +import org.jetbrains.kotlin.fir.visitors.* +import org.jetbrains.kotlin.fir.MutableOrEmptyList +import org.jetbrains.kotlin.fir.builder.toMutableOrEmpty +import org.jetbrains.kotlin.fir.declarations.ResolveStateAccess + +/* + * This file was generated automatically + * DO NOT MODIFY IT MANUALLY + */ + +class FirErrorConstructor @FirImplementationDetail constructor( + override val source: KtSourceElement?, + resolvePhase: FirResolvePhase, + override val moduleData: FirModuleData, + override val origin: FirDeclarationOrigin, + override val attributes: FirDeclarationAttributes, + override val typeParameters: MutableList, + override var status: FirDeclarationStatus, + override var returnTypeRef: FirTypeRef, + override var receiverParameter: FirReceiverParameter?, + override var deprecationsProvider: DeprecationsProvider, + override val containerSource: DeserializedContainerSource?, + override val dispatchReceiverType: ConeSimpleKotlinType?, + override var contextReceivers: MutableOrEmptyList, + override val valueParameters: MutableList, + override var contractDescription: FirContractDescription, + override var annotations: MutableOrEmptyList, + override val symbol: FirConstructorSymbol, + override var delegatedConstructor: FirDelegatedConstructorCall?, + override var body: FirBlock?, +) : FirConstructor() { + override var controlFlowGraphReference: FirControlFlowGraphReference? = null + override val isPrimary: Boolean get() = false + + init { + symbol.bind(this) + @OptIn(ResolveStateAccess::class) + resolveState = resolvePhase.asResolveState() + } + + override fun acceptChildren(visitor: FirVisitor, data: D) { + typeParameters.forEach { it.accept(visitor, data) } + status.accept(visitor, data) + returnTypeRef.accept(visitor, data) + receiverParameter?.accept(visitor, data) + contextReceivers.forEach { it.accept(visitor, data) } + controlFlowGraphReference?.accept(visitor, data) + valueParameters.forEach { it.accept(visitor, data) } + contractDescription.accept(visitor, data) + annotations.forEach { it.accept(visitor, data) } + delegatedConstructor?.accept(visitor, data) + body?.accept(visitor, data) + } + + override fun transformChildren(transformer: FirTransformer, data: D): FirErrorConstructor { + transformTypeParameters(transformer, data) + transformStatus(transformer, data) + transformReturnTypeRef(transformer, data) + transformReceiverParameter(transformer, data) + contextReceivers.transformInplace(transformer, data) + controlFlowGraphReference = controlFlowGraphReference?.transform(transformer, data) + transformValueParameters(transformer, data) + transformContractDescription(transformer, data) + transformAnnotations(transformer, data) + transformDelegatedConstructor(transformer, data) + transformBody(transformer, data) + return this + } + + override fun transformTypeParameters(transformer: FirTransformer, data: D): FirErrorConstructor { + typeParameters.transformInplace(transformer, data) + return this + } + + override fun transformStatus(transformer: FirTransformer, data: D): FirErrorConstructor { + status = status.transform(transformer, data) + return this + } + + override fun transformReturnTypeRef(transformer: FirTransformer, data: D): FirErrorConstructor { + returnTypeRef = returnTypeRef.transform(transformer, data) + return this + } + + override fun transformReceiverParameter(transformer: FirTransformer, data: D): FirErrorConstructor { + receiverParameter = receiverParameter?.transform(transformer, data) + return this + } + + override fun transformValueParameters(transformer: FirTransformer, data: D): FirErrorConstructor { + valueParameters.transformInplace(transformer, data) + return this + } + + override fun transformContractDescription(transformer: FirTransformer, data: D): FirErrorConstructor { + contractDescription = contractDescription.transform(transformer, data) + return this + } + + override fun transformAnnotations(transformer: FirTransformer, data: D): FirErrorConstructor { + annotations.transformInplace(transformer, data) + return this + } + + override fun transformDelegatedConstructor(transformer: FirTransformer, data: D): FirErrorConstructor { + delegatedConstructor = delegatedConstructor?.transform(transformer, data) + return this + } + + override fun transformBody(transformer: FirTransformer, data: D): FirErrorConstructor { + body = body?.transform(transformer, data) + return this + } + + override fun replaceStatus(newStatus: FirDeclarationStatus) { + status = newStatus + } + + override fun replaceReturnTypeRef(newReturnTypeRef: FirTypeRef) { + returnTypeRef = newReturnTypeRef + } + + override fun replaceReceiverParameter(newReceiverParameter: FirReceiverParameter?) { + receiverParameter = newReceiverParameter + } + + override fun replaceDeprecationsProvider(newDeprecationsProvider: DeprecationsProvider) { + deprecationsProvider = newDeprecationsProvider + } + + override fun replaceContextReceivers(newContextReceivers: List) { + contextReceivers = newContextReceivers.toMutableOrEmpty() + } + + override fun replaceControlFlowGraphReference(newControlFlowGraphReference: FirControlFlowGraphReference?) { + controlFlowGraphReference = newControlFlowGraphReference + } + + override fun replaceValueParameters(newValueParameters: List) { + valueParameters.clear() + valueParameters.addAll(newValueParameters) + } + + override fun replaceContractDescription(newContractDescription: FirContractDescription) { + contractDescription = newContractDescription + } + + override fun replaceAnnotations(newAnnotations: List) { + annotations = newAnnotations.toMutableOrEmpty() + } + + override fun replaceDelegatedConstructor(newDelegatedConstructor: FirDelegatedConstructorCall?) { + delegatedConstructor = newDelegatedConstructor + } + + override fun replaceBody(newBody: FirBlock?) { + body = newBody + } +} diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirDeclarationRenderer.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirDeclarationRenderer.kt index baef45f38b3..8e8016c01cf 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirDeclarationRenderer.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/renderer/FirDeclarationRenderer.kt @@ -6,6 +6,7 @@ package org.jetbrains.kotlin.fir.renderer import org.jetbrains.kotlin.fir.declarations.* +import org.jetbrains.kotlin.fir.declarations.impl.FirErrorConstructor import org.jetbrains.kotlin.fir.isCatchParameter import org.jetbrains.kotlin.util.capitalizeDecapitalize.toLowerCaseAsciiOnly @@ -23,6 +24,9 @@ open class FirDeclarationRenderer { typeRenderer.render(it) printer.print(".") } + if (declaration is FirErrorConstructor) { + printer.print("error_") + } printer.print("constructor") return } diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt index c837661079d..ac12da0e399 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/BuilderConfigurator.kt @@ -89,7 +89,7 @@ object BuilderConfigurator : AbstractBuilderConfigurator(FirTree fields from functionCall } - for (constructorType in listOf("FirPrimaryConstructor", "FirConstructorImpl")) { + for (constructorType in listOf("FirPrimaryConstructor", "FirConstructorImpl", "FirErrorConstructor")) { builder(constructor, constructorType) { parents += abstractConstructorBuilder defaultNull("delegatedConstructor") diff --git a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt index 9184ad22303..2f2ffb8798c 100644 --- a/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt +++ b/compiler/fir/tree/tree-generator/src/org/jetbrains/kotlin/fir/tree/generator/ImplementationConfigurator.kt @@ -26,6 +26,11 @@ object ImplementationConfigurator : AbstractFirTreeImplementationConfigurator() defaultTrue("isPrimary", withGetter = true) } + impl(constructor, "FirErrorConstructor") { + publicImplementation() + defaultFalse("isPrimary", withGetter = true) + } + impl(typeParameterRef, "FirOuterClassTypeParameterRef") { publicImplementation() } diff --git a/compiler/testData/diagnostics/tests/classObjects/classWithFunctionSupertype_after.fir.kt b/compiler/testData/diagnostics/tests/classObjects/classWithFunctionSupertype_after.fir.kt index ddab9fcf98e..74a3465596d 100644 --- a/compiler/testData/diagnostics/tests/classObjects/classWithFunctionSupertype_after.fir.kt +++ b/compiler/testData/diagnostics/tests/classObjects/classWithFunctionSupertype_after.fir.kt @@ -9,9 +9,9 @@ abstract class D : suspend () -> Int() abstract class E : (suspend () -> Int)() abstract class F : kotlin.coroutines.SuspendFunction0() -interface IA : () -> Int() -interface IB : (() -> Int)() -interface IC : Function0() -interface ID : suspend () -> Int() -interface IE : (suspend () -> Int)() -interface IF : kotlin.coroutines.SuspendFunction0() +interface IA : () -> Int() +interface IB : (() -> Int)() +interface IC : Function0() +interface ID : suspend () -> Int() +interface IE : (suspend () -> Int)() +interface IF : kotlin.coroutines.SuspendFunction0() diff --git a/compiler/testData/diagnostics/tests/classObjects/classWithFunctionSupertype_before.fir.kt b/compiler/testData/diagnostics/tests/classObjects/classWithFunctionSupertype_before.fir.kt index 905fec8ca7b..4868761d923 100644 --- a/compiler/testData/diagnostics/tests/classObjects/classWithFunctionSupertype_before.fir.kt +++ b/compiler/testData/diagnostics/tests/classObjects/classWithFunctionSupertype_before.fir.kt @@ -9,9 +9,9 @@ abstract class D : suspend () -> Int() abstract class E : (suspend () -> Int)() abstract class F : kotlin.coroutines.SuspendFunction0() -interface IA : () -> Int() -interface IB : (() -> Int)() -interface IC : Function0() -interface ID : suspend () -> Int() -interface IE : (suspend () -> Int)() -interface IF : kotlin.coroutines.SuspendFunction0() +interface IA : () -> Int() +interface IB : (() -> Int)() +interface IC : Function0() +interface ID : suspend () -> Int() +interface IE : (suspend () -> Int)() +interface IF : kotlin.coroutines.SuspendFunction0() diff --git a/compiler/testData/diagnostics/tests/constructorConsistency/errorInsideDelegationCallNoPrimary.fir.kt b/compiler/testData/diagnostics/tests/constructorConsistency/errorInsideDelegationCallNoPrimary.fir.kt new file mode 100644 index 00000000000..ae72be1b556 --- /dev/null +++ b/compiler/testData/diagnostics/tests/constructorConsistency/errorInsideDelegationCallNoPrimary.fir.kt @@ -0,0 +1,5 @@ +open class A(i: Int) + +class B : A(x) { + constructor(i: Int) : super(i) +} diff --git a/compiler/testData/diagnostics/tests/constructorConsistency/errorInsideDelegationCallNoPrimary.kt b/compiler/testData/diagnostics/tests/constructorConsistency/errorInsideDelegationCallNoPrimary.kt new file mode 100644 index 00000000000..ba2ba870568 --- /dev/null +++ b/compiler/testData/diagnostics/tests/constructorConsistency/errorInsideDelegationCallNoPrimary.kt @@ -0,0 +1,5 @@ +open class A(i: Int) + +class B : A(x) { + constructor(i: Int) : super(i) +} 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 1db952e3deb..9b8ac192d99 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 @@ -5996,6 +5996,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest { runTest("compiler/testData/diagnostics/tests/constructorConsistency/derivedProperty.kt"); } + @Test + @TestMetadata("errorInsideDelegationCallNoPrimary.kt") + public void testErrorInsideDelegationCallNoPrimary() throws Exception { + runTest("compiler/testData/diagnostics/tests/constructorConsistency/errorInsideDelegationCallNoPrimary.kt"); + } + @Test @TestMetadata("getset.kt") public void testGetset() throws Exception {