FIR: don't create delegated constructor call in expect
#KT-51756 Fixed
This commit is contained in:
+6
@@ -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 {
|
||||||
|
|||||||
+5
@@ -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");
|
||||||
|
|||||||
+31
@@ -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
-3
@@ -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
-3
@@ -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
-3
@@ -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|
|
||||||
|
|
||||||
|
|||||||
+6
@@ -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 {
|
||||||
|
|||||||
+6
@@ -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 {
|
||||||
|
|||||||
+27
-21
@@ -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) {
|
||||||
|
|||||||
+1
-1
@@ -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),
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user