FIR: don't create delegated constructor call in expect

#KT-51756 Fixed
This commit is contained in:
Mikhail Glukhikh
2022-03-29 16:06:40 +03:00
parent 16027b4531
commit aaebb7a30e
12 changed files with 105 additions and 34 deletions
@@ -3225,6 +3225,12 @@ public class DiagnosisCompilerFirTestdataTestGenerated extends AbstractDiagnosis
runTest("compiler/fir/analysis-tests/testData/resolve/problems/doubleGenericDiamond.kt"); runTest("compiler/fir/analysis-tests/testData/resolve/problems/doubleGenericDiamond.kt");
} }
@Test
@TestMetadata("expectConstructor.kt")
public void testExpectConstructor() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/expectConstructor.kt");
}
@Test @Test
@TestMetadata("fakeTypeMismatchOnExtensionReference.kt") @TestMetadata("fakeTypeMismatchOnExtensionReference.kt")
public void testFakeTypeMismatchOnExtensionReference() throws Exception { public void testFakeTypeMismatchOnExtensionReference() throws Exception {
@@ -2844,6 +2844,11 @@ public class LazyBodyIsNotTouchedTilContractsPhaseTestGenerated extends Abstract
runTest("compiler/fir/analysis-tests/testData/resolve/problems/doubleGenericDiamond.kt"); runTest("compiler/fir/analysis-tests/testData/resolve/problems/doubleGenericDiamond.kt");
} }
@TestMetadata("expectConstructor.kt")
public void testExpectConstructor() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/expectConstructor.kt");
}
@TestMetadata("fakeTypeMismatchOnExtensionReference.kt") @TestMetadata("fakeTypeMismatchOnExtensionReference.kt")
public void testFakeTypeMismatchOnExtensionReference() throws Exception { public void testFakeTypeMismatchOnExtensionReference() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/fakeTypeMismatchOnExtensionReference.kt"); runTest("compiler/fir/analysis-tests/testData/resolve/problems/fakeTypeMismatchOnExtensionReference.kt");
@@ -0,0 +1,31 @@
FILE: expectConstructor.kt
public open class Base : R|kotlin/Any| {
public constructor(v: R|kotlin/String|): R|Base| {
super<R|kotlin/Any|>()
}
}
public final expect class Derived : R|Base| {
public expect constructor(v: R|kotlin/String|): R|Derived|
}
public open expect class ExpectBase : R|kotlin/Any| {
public expect constructor(v: R|kotlin/String|): R|ExpectBase|
}
public final expect class ExpectDerived : R|ExpectBase| {
public expect constructor(v: R|kotlin/String|): R|ExpectDerived|
}
public open expect class IOException : R|kotlin/Any| {
public expect constructor(message: R|kotlin/String|, cause: R|kotlin/Throwable?|): R|IOException|
public expect constructor(message: R|kotlin/String|): R|IOException| {
super<R|kotlin/Any|>()
}
}
public final expect class EOFException : R|IOException| {
public expect constructor(message: R|kotlin/String|): R|EOFException|
}
@@ -0,0 +1,13 @@
open class Base(v: String)
expect class Derived(v: String) : Base
expect open class ExpectBase(v: String)
expect class ExpectDerived(v: String) : ExpectBase
expect open class IOException(message: String, cause: Throwable?) {
<!PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED!>constructor(message: String)<!>
}
expect class EOFException(message: String) : IOException
@@ -1,9 +1,7 @@
Module: m1-common Module: m1-common
FILE: common.kt FILE: common.kt
public open expect class A<T> : R|kotlin/Any| { public open expect class A<T> : R|kotlin/Any| {
public expect constructor<T>(): R|A<T>| { public expect constructor<T>(): R|A<T>|
super<R|kotlin/Any|>()
}
public open expect fun foo(arg: R|T|): R|kotlin/Unit| public open expect fun foo(arg: R|T|): R|kotlin/Unit|
@@ -1,9 +1,7 @@
Module: m1-common Module: m1-common
FILE: common.kt FILE: common.kt
public open expect class A : R|kotlin/Any| { public open expect class A : R|kotlin/Any| {
public expect constructor(): R|A| { public expect constructor(): R|A|
super<R|kotlin/Any|>()
}
public final expect fun foo(): R|kotlin/Unit| public final expect fun foo(): R|kotlin/Unit|
@@ -1,9 +1,7 @@
Module: m1-common Module: m1-common
FILE: common.kt FILE: common.kt
public open expect class A : R|kotlin/Any| { public open expect class A : R|kotlin/Any| {
public expect constructor(): R|A| { public expect constructor(): R|A|
super<R|kotlin/Any|>()
}
public final expect fun foo(): R|kotlin/Unit| public final expect fun foo(): R|kotlin/Unit|
@@ -3225,6 +3225,12 @@ public class FirDiagnosticTestGenerated extends AbstractFirDiagnosticTest {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/doubleGenericDiamond.kt"); runTest("compiler/fir/analysis-tests/testData/resolve/problems/doubleGenericDiamond.kt");
} }
@Test
@TestMetadata("expectConstructor.kt")
public void testExpectConstructor() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/expectConstructor.kt");
}
@Test @Test
@TestMetadata("fakeTypeMismatchOnExtensionReference.kt") @TestMetadata("fakeTypeMismatchOnExtensionReference.kt")
public void testFakeTypeMismatchOnExtensionReference() throws Exception { public void testFakeTypeMismatchOnExtensionReference() throws Exception {
@@ -3225,6 +3225,12 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/problems/doubleGenericDiamond.kt"); runTest("compiler/fir/analysis-tests/testData/resolve/problems/doubleGenericDiamond.kt");
} }
@Test
@TestMetadata("expectConstructor.kt")
public void testExpectConstructor() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/problems/expectConstructor.kt");
}
@Test @Test
@TestMetadata("fakeTypeMismatchOnExtensionReference.kt") @TestMetadata("fakeTypeMismatchOnExtensionReference.kt")
public void testFakeTypeMismatchOnExtensionReference() throws Exception { public void testFakeTypeMismatchOnExtensionReference() throws Exception {
@@ -56,6 +56,7 @@ import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.lexer.KtTokens.* import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.name.* import org.jetbrains.kotlin.name.*
import org.jetbrains.kotlin.utils.addToStdlib.runIf import org.jetbrains.kotlin.utils.addToStdlib.runIf
import org.jetbrains.kotlin.utils.addToStdlib.runUnless
class DeclarationsConverter( class DeclarationsConverter(
session: FirSession, session: FirSession,
@@ -711,6 +712,7 @@ class DeclarationsConverter(
} }
val enumEntryName = identifier.nameAsSafeName() val enumEntryName = identifier.nameAsSafeName()
val containingClassIsExpectClass = classWrapper.hasExpect() || context.containerIsExpect
return buildEnumEntry { return buildEnumEntry {
source = enumEntry.toFirSourceElement() source = enumEntry.toFirSourceElement()
moduleData = baseModuleData moduleData = baseModuleData
@@ -720,7 +722,7 @@ class DeclarationsConverter(
symbol = FirEnumEntrySymbol(CallableId(context.currentClassId, enumEntryName)) symbol = FirEnumEntrySymbol(CallableId(context.currentClassId, enumEntryName))
status = FirDeclarationStatusImpl(Visibilities.Public, Modality.FINAL).apply { status = FirDeclarationStatusImpl(Visibilities.Public, Modality.FINAL).apply {
isStatic = true isStatic = true
isExpect = classWrapper.hasExpect() || context.containerIsExpect isExpect = containingClassIsExpectClass
} }
if (classWrapper.hasDefaultConstructor && enumEntry.getChildNodeByType(INITIALIZER_LIST) == null && if (classWrapper.hasDefaultConstructor && enumEntry.getChildNodeByType(INITIALIZER_LIST) == null &&
modifiers.annotations.isEmpty() && classBodyNode == null modifiers.annotations.isEmpty() && classBodyNode == null
@@ -762,7 +764,7 @@ class DeclarationsConverter(
enumClassWrapper, enumClassWrapper,
superTypeCallEntry?.toFirSourceElement(), superTypeCallEntry?.toFirSourceElement(),
isEnumEntry = true, isEnumEntry = true,
containingClassIsExpectClass = false containingClassIsExpectClass = containingClassIsExpectClass
)?.let { declarations += it.firConstructor } )?.let { declarations += it.firConstructor }
classBodyNode?.also { classBodyNode?.also {
// Use ANONYMOUS_OBJECT_NAME for the owner class id of enum entry declarations // Use ANONYMOUS_OBJECT_NAME for the owner class id of enum entry declarations
@@ -828,7 +830,9 @@ class DeclarationsConverter(
): PrimaryConstructor? { ): PrimaryConstructor? {
if (primaryConstructor == null && !classWrapper.isEnumEntry() && classWrapper.hasSecondaryConstructor) return null if (primaryConstructor == null && !classWrapper.isEnumEntry() && classWrapper.hasSecondaryConstructor) return null
val classKind = classWrapper.classBuilder.classKind val classKind = classWrapper.classBuilder.classKind
if (primaryConstructor == null && (containingClassIsExpectClass && classKind != ClassKind.ENUM_CLASS)) return null if (primaryConstructor == null &&
(containingClassIsExpectClass && classKind != ClassKind.ENUM_CLASS && classKind != ClassKind.ENUM_ENTRY)
) return null
if (classWrapper.isInterface()) return null if (classWrapper.isInterface()) return null
var modifiers = Modifier() var modifiers = Modifier()
@@ -841,26 +845,28 @@ class DeclarationsConverter(
} }
val defaultVisibility = classWrapper.defaultConstructorVisibility() val defaultVisibility = classWrapper.defaultConstructorVisibility()
val firDelegatedCall = buildDelegatedConstructorCall { val firDelegatedCall = runUnless(containingClassIsExpectClass) {
source = delegatedConstructorSource ?: selfTypeSource?.fakeElement(KtFakeSourceElementKind.DelegatingConstructorCall) buildDelegatedConstructorCall {
constructedTypeRef = classWrapper.delegatedSuperTypeRef.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef) source = delegatedConstructorSource ?: selfTypeSource?.fakeElement(KtFakeSourceElementKind.DelegatingConstructorCall)
isThis = false constructedTypeRef = classWrapper.delegatedSuperTypeRef.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef)
calleeReference = buildExplicitSuperReference { isThis = false
//[dirty] in case of enum classWrapper.delegatedSuperTypeRef.source is whole enum source calleeReference = buildExplicitSuperReference {
source = if (!isEnumEntry) { //[dirty] in case of enum classWrapper.delegatedSuperTypeRef.source is whole enum source
classWrapper.delegatedSuperTypeRef.source?.fakeElement(KtFakeSourceElementKind.DelegatingConstructorCall) source = if (!isEnumEntry) {
?: this@buildDelegatedConstructorCall.source?.fakeElement(KtFakeSourceElementKind.DelegatingConstructorCall) classWrapper.delegatedSuperTypeRef.source?.fakeElement(KtFakeSourceElementKind.DelegatingConstructorCall)
} else { ?: this@buildDelegatedConstructorCall.source?.fakeElement(KtFakeSourceElementKind.DelegatingConstructorCall)
delegatedConstructorSource } else {
?.lighterASTNode delegatedConstructorSource
?.getChildNodeByType(CONSTRUCTOR_CALLEE) ?.lighterASTNode
?.toFirSourceElement(KtFakeSourceElementKind.DelegatingConstructorCall) ?.getChildNodeByType(CONSTRUCTOR_CALLEE)
?: this@buildDelegatedConstructorCall.source ?.toFirSourceElement(KtFakeSourceElementKind.DelegatingConstructorCall)
} ?: this@buildDelegatedConstructorCall.source
}
superTypeRef = this@buildDelegatedConstructorCall.constructedTypeRef superTypeRef = this@buildDelegatedConstructorCall.constructedTypeRef
}
extractArgumentsFrom(classWrapper.superTypeCallEntry)
} }
extractArgumentsFrom(classWrapper.superTypeCallEntry)
} }
val explicitVisibility = runIf(primaryConstructor != null) { val explicitVisibility = runIf(primaryConstructor != null) {
@@ -837,6 +837,7 @@ open class RawFirBuilder(
delegatedSelfTypeRef ?: delegatedSuperTypeRef!!, delegatedSelfTypeRef ?: delegatedSuperTypeRef!!,
owner = this, owner = this,
containerTypeParameters, containerTypeParameters,
containingClassIsExpectClass,
body = null body = null
) )
container.declarations += firPrimaryConstructor container.declarations += firPrimaryConstructor
@@ -851,12 +852,13 @@ open class RawFirBuilder(
delegatedSelfTypeRef: FirTypeRef, delegatedSelfTypeRef: FirTypeRef,
owner: KtClassOrObject, owner: KtClassOrObject,
ownerTypeParameters: List<FirTypeParameterRef>, ownerTypeParameters: List<FirTypeParameterRef>,
containingClassIsExpectClass: Boolean,
body: FirBlock? = null body: FirBlock? = null
): FirConstructor { ): FirConstructor {
val constructorCall = superTypeCallEntry?.toFirSourceElement() val constructorCall = superTypeCallEntry?.toFirSourceElement()
val constructorSource = this?.toFirSourceElement() val constructorSource = this?.toFirSourceElement()
?: owner.toKtPsiSourceElement(KtFakeSourceElementKind.ImplicitConstructor) ?: owner.toKtPsiSourceElement(KtFakeSourceElementKind.ImplicitConstructor)
val firDelegatedCall = buildDelegatedConstructorCall { val firDelegatedCall = if (containingClassIsExpectClass) null else buildDelegatedConstructorCall {
source = constructorCall ?: constructorSource.fakeElement(KtFakeSourceElementKind.DelegatingConstructorCall) source = constructorCall ?: constructorSource.fakeElement(KtFakeSourceElementKind.DelegatingConstructorCall)
constructedTypeRef = delegatedSuperTypeRef.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef) constructedTypeRef = delegatedSuperTypeRef.copyWithNewSourceKind(KtFakeSourceElementKind.ImplicitTypeRef)
isThis = false isThis = false
@@ -945,6 +947,7 @@ open class RawFirBuilder(
ownerClassHasDefaultConstructor: Boolean ownerClassHasDefaultConstructor: Boolean
): FirDeclaration { ): FirDeclaration {
val ktEnumEntry = this@toFirEnumEntry val ktEnumEntry = this@toFirEnumEntry
val containingClassIsExpectClass = hasExpectModifier() || this@RawFirBuilder.context.containerIsExpect
return buildEnumEntry { return buildEnumEntry {
source = toFirSourceElement() source = toFirSourceElement()
moduleData = baseModuleData moduleData = baseModuleData
@@ -953,7 +956,7 @@ open class RawFirBuilder(
name = nameAsSafeName name = nameAsSafeName
status = FirDeclarationStatusImpl(Visibilities.Public, Modality.FINAL).apply { status = FirDeclarationStatusImpl(Visibilities.Public, Modality.FINAL).apply {
isStatic = true isStatic = true
isExpect = hasExpectModifier() || this@RawFirBuilder.context.containerIsExpect isExpect = containingClassIsExpectClass
} }
symbol = FirEnumEntrySymbol(callableIdForName(nameAsSafeName)) symbol = FirEnumEntrySymbol(callableIdForName(nameAsSafeName))
if (ownerClassHasDefaultConstructor && ktEnumEntry.initializerList == null && if (ownerClassHasDefaultConstructor && ktEnumEntry.initializerList == null &&
@@ -992,7 +995,8 @@ open class RawFirBuilder(
correctedEnumSelfTypeRef, correctedEnumSelfTypeRef,
delegatedEntrySelfType, delegatedEntrySelfType,
owner = ktEnumEntry, owner = ktEnumEntry,
typeParameters typeParameters,
containingClassIsExpectClass
) )
// Use ANONYMOUS_OBJECT_NAME for the owner class id for enum entry declarations (see KT-42351) // Use ANONYMOUS_OBJECT_NAME for the owner class id for enum entry declarations (see KT-42351)
withChildClassName(SpecialNames.ANONYMOUS, forceLocalContext = true, isExpect = false) { withChildClassName(SpecialNames.ANONYMOUS, forceLocalContext = true, isExpect = false) {
@@ -2,7 +2,7 @@
// FILE: common.kt // FILE: common.kt
expect enum class En(x: Int) { expect enum class En(x: Int) {
<!NONE_APPLICABLE!>E1,<!> E1,
E2(42), E2(42),
; ;