diff --git a/analysis/low-level-api-fir/testdata/lazyResolve/classes/functionInValueClass.kt b/analysis/low-level-api-fir/testdata/lazyResolve/classes/functionInValueClass.kt new file mode 100644 index 00000000000..fd779b99735 --- /dev/null +++ b/analysis/low-level-api-fir/testdata/lazyResolve/classes/functionInValueClass.kt @@ -0,0 +1,4 @@ +@JvmInline +value class Value(val value: Int) { + fun resolveMe() {} +} diff --git a/analysis/low-level-api-fir/testdata/lazyResolve/classes/functionInValueClass.txt b/analysis/low-level-api-fir/testdata/lazyResolve/classes/functionInValueClass.txt new file mode 100644 index 00000000000..481b77440ac --- /dev/null +++ b/analysis/low-level-api-fir/testdata/lazyResolve/classes/functionInValueClass.txt @@ -0,0 +1,187 @@ + +RAW_FIR: +FILE: functionInValueClass.kt + @JvmInline() public? final? inline [RAW_FIR] class Value : R|kotlin/Any| { + public? [RAW_FIR] [ContainingClassKey=Value] constructor([RAW_FIR] [CorrespondingProperty=/Value.value] value: Int): R|Value| { + super() + } + + public? final? [RAW_FIR] [IsFromPrimaryConstructor=true] val value: Int = R|/value| + public? [RAW_FIR] [ContainingClassKey=Value] get(): Int + + public? final? [RAW_FIR] fun resolveMe(): R|kotlin/Unit| { LAZY_BLOCK } + + } + +IMPORTS: +FILE: functionInValueClass.kt + @JvmInline() public? final? inline [RAW_FIR] class Value : R|kotlin/Any| { + public? [RAW_FIR] [ContainingClassKey=Value] constructor([RAW_FIR] [CorrespondingProperty=/Value.value] value: Int): R|Value| { + super() + } + + public? final? [RAW_FIR] [IsFromPrimaryConstructor=true] val value: Int = R|/value| + public? [RAW_FIR] [ContainingClassKey=Value] get(): Int + + public? final? [RAW_FIR] fun resolveMe(): R|kotlin/Unit| { LAZY_BLOCK } + + } + +COMPILER_REQUIRED_ANNOTATIONS: +FILE: functionInValueClass.kt + @JvmInline() public? final? inline [RAW_FIR] class Value : R|kotlin/Any| { + public? [RAW_FIR] [ContainingClassKey=Value] constructor([RAW_FIR] [CorrespondingProperty=/Value.value] value: Int): R|Value| { + super() + } + + public? final? [RAW_FIR] [IsFromPrimaryConstructor=true] val value: Int = R|/value| + public? [RAW_FIR] [ContainingClassKey=Value] get(): Int + + public? final? [COMPILER_REQUIRED_ANNOTATIONS] fun resolveMe(): R|kotlin/Unit| { LAZY_BLOCK } + + } + +COMPANION_GENERATION: +FILE: functionInValueClass.kt + @JvmInline() public? final? inline [RAW_FIR] class Value : R|kotlin/Any| { + public? [RAW_FIR] [ContainingClassKey=Value] constructor([RAW_FIR] [CorrespondingProperty=/Value.value] value: Int): R|Value| { + super() + } + + public? final? [RAW_FIR] [IsFromPrimaryConstructor=true] val value: Int = R|/value| + public? [RAW_FIR] [ContainingClassKey=Value] get(): Int + + public? final? [COMPANION_GENERATION] fun resolveMe(): R|kotlin/Unit| { LAZY_BLOCK } + + } + +SUPER_TYPES: +FILE: functionInValueClass.kt + @JvmInline() public? final? inline [RAW_FIR] class Value : R|kotlin/Any| { + public? [RAW_FIR] [ContainingClassKey=Value] constructor([RAW_FIR] [CorrespondingProperty=/Value.value] value: Int): R|Value| { + super() + } + + public? final? [RAW_FIR] [IsFromPrimaryConstructor=true] val value: Int = R|/value| + public? [RAW_FIR] [ContainingClassKey=Value] get(): Int + + public? final? [SUPER_TYPES] fun resolveMe(): R|kotlin/Unit| { LAZY_BLOCK } + + } + +TYPES: +FILE: functionInValueClass.kt + @R|kotlin/jvm/JvmInline|() public? final? inline [SUPER_TYPES] class Value : R|kotlin/Any| { + public? [SUPER_TYPES] [ContainingClassKey=Value] constructor([SUPER_TYPES] [CorrespondingProperty=/Value.value] value: Int): R|Value| { + super() + } + + public? final? [SUPER_TYPES] [IsFromPrimaryConstructor=true] val value: Int = R|/value| + public? [SUPER_TYPES] [ContainingClassKey=Value] get(): Int + + public? final? [TYPES] fun resolveMe(): R|kotlin/Unit| { LAZY_BLOCK } + + } + +STATUS: +FILE: functionInValueClass.kt + @R|kotlin/jvm/JvmInline|() public final inline [SUPER_TYPES] [FirValueClassRepresentationKey=InlineClassRepresentation(underlyingPropertyName=value, underlyingType=kotlin/Int)] class Value : R|kotlin/Any| { + public? [TYPES] [ContainingClassKey=Value] constructor([TYPES] [CorrespondingProperty=/Value.value] value: R|kotlin/Int|): R|Value| { + super() + } + + public? final? [SUPER_TYPES] [IsFromPrimaryConstructor=true] val value: Int = R|/value| + public? [SUPER_TYPES] [ContainingClassKey=Value] get(): Int + + public final [STATUS] fun resolveMe(): R|kotlin/Unit| { LAZY_BLOCK } + + } + +ARGUMENTS_OF_ANNOTATIONS: +FILE: functionInValueClass.kt + @R|kotlin/jvm/JvmInline|() public final inline [SUPER_TYPES] [FirValueClassRepresentationKey=InlineClassRepresentation(underlyingPropertyName=value, underlyingType=kotlin/Int)] class Value : R|kotlin/Any| { + public? [TYPES] [ContainingClassKey=Value] constructor([TYPES] [CorrespondingProperty=/Value.value] value: R|kotlin/Int|): R|Value| { + super() + } + + public? final? [SUPER_TYPES] [IsFromPrimaryConstructor=true] val value: Int = R|/value| + public? [SUPER_TYPES] [ContainingClassKey=Value] get(): Int + + public final [ARGUMENTS_OF_ANNOTATIONS] fun resolveMe(): R|kotlin/Unit| { LAZY_BLOCK } + + } + +CONTRACTS: +FILE: functionInValueClass.kt + @R|kotlin/jvm/JvmInline|() public final inline [SUPER_TYPES] [FirValueClassRepresentationKey=InlineClassRepresentation(underlyingPropertyName=value, underlyingType=kotlin/Int)] class Value : R|kotlin/Any| { + public? [TYPES] [ContainingClassKey=Value] constructor([TYPES] [CorrespondingProperty=/Value.value] value: R|kotlin/Int|): R|Value| { + super() + } + + public? final? [SUPER_TYPES] [IsFromPrimaryConstructor=true] val value: Int = R|/value| + public? [SUPER_TYPES] [ContainingClassKey=Value] get(): Int + + public final [CONTRACTS] fun resolveMe(): R|kotlin/Unit| { + } + + } + +IMPLICIT_TYPES_BODY_RESOLVE: +FILE: functionInValueClass.kt + @R|kotlin/jvm/JvmInline|() public final inline [STATUS] [FirValueClassRepresentationKey=InlineClassRepresentation(underlyingPropertyName=value, underlyingType=kotlin/Int)] class Value : R|kotlin/Any| { + public [STATUS] [ContainingClassKey=Value] constructor([STATUS] [CorrespondingProperty=/Value.value] value: R|kotlin/Int|): R|Value| { + super() + } + + public final [STATUS] [IsFromPrimaryConstructor=true] val value: R|kotlin/Int| = R|/value| + public [STATUS] [ContainingClassKey=Value] get(): R|kotlin/Int| + + public final [IMPLICIT_TYPES_BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| { + } + + } + +EXPECT_ACTUAL_MATCHING: +FILE: functionInValueClass.kt + @R|kotlin/jvm/JvmInline|() public final inline [STATUS] [FirValueClassRepresentationKey=InlineClassRepresentation(underlyingPropertyName=value, underlyingType=kotlin/Int)] class Value : R|kotlin/Any| { + public [STATUS] [ContainingClassKey=Value] constructor([STATUS] [CorrespondingProperty=/Value.value] value: R|kotlin/Int|): R|Value| { + super() + } + + public final [STATUS] [IsFromPrimaryConstructor=true] val value: R|kotlin/Int| = R|/value| + public [STATUS] [ContainingClassKey=Value] get(): R|kotlin/Int| + + public final [EXPECT_ACTUAL_MATCHING] fun resolveMe(): R|kotlin/Unit| { + } + + } + +BODY_RESOLVE: +FILE: functionInValueClass.kt + @R|kotlin/jvm/JvmInline|() public final inline [STATUS] [FirValueClassRepresentationKey=InlineClassRepresentation(underlyingPropertyName=value, underlyingType=kotlin/Int)] class Value : R|kotlin/Any| { + public [STATUS] [ContainingClassKey=Value] constructor([STATUS] [CorrespondingProperty=/Value.value] value: R|kotlin/Int|): R|Value| { + super() + } + + public final [STATUS] [IsFromPrimaryConstructor=true] val value: R|kotlin/Int| = R|/value| + public [STATUS] [ContainingClassKey=Value] get(): R|kotlin/Int| + + public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| { + } + + } + +FILE RAW TO BODY: +FILE: functionInValueClass.kt + @R|kotlin/jvm/JvmInline|() public final inline [BODY_RESOLVE] [FirValueClassRepresentationKey=InlineClassRepresentation(underlyingPropertyName=value, underlyingType=kotlin/Int)] class Value : R|kotlin/Any| { + public [BODY_RESOLVE] [ContainingClassKey=Value] constructor([BODY_RESOLVE] [CorrespondingProperty=/Value.value] value: R|kotlin/Int|): R|Value| { + super() + } + + public final [BODY_RESOLVE] [IsFromPrimaryConstructor=true] val value: R|kotlin/Int| = R|/value| + public [BODY_RESOLVE] [ContainingClassKey=Value] get(): R|kotlin/Int| + + public final [BODY_RESOLVE] fun resolveMe(): R|kotlin/Unit| { + } + + } diff --git a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirLazyDeclarationResolveTestGenerated.java b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirLazyDeclarationResolveTestGenerated.java index c1552492b64..9ba0dff8cde 100644 --- a/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirLazyDeclarationResolveTestGenerated.java +++ b/analysis/low-level-api-fir/tests/org/jetbrains/kotlin/analysis/low/level/api/fir/FirLazyDeclarationResolveTestGenerated.java @@ -152,6 +152,12 @@ public class FirLazyDeclarationResolveTestGenerated extends AbstractFirLazyDecla public void testClassWithTypeParameters() throws Exception { runTest("analysis/low-level-api-fir/testdata/lazyResolve/classes/classWithTypeParameters.kt"); } + + @Test + @TestMetadata("functionInValueClass.kt") + public void testFunctionInValueClass() throws Exception { + runTest("analysis/low-level-api-fir/testdata/lazyResolve/classes/functionInValueClass.kt"); + } } @Nested diff --git a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/ValueClassesUtils.kt b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/ValueClassesUtils.kt index bd29b9127b5..62f7d1c60bf 100644 --- a/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/ValueClassesUtils.kt +++ b/compiler/fir/providers/src/org/jetbrains/kotlin/fir/declarations/ValueClassesUtils.kt @@ -13,6 +13,7 @@ import org.jetbrains.kotlin.fir.declarations.utils.isInline import org.jetbrains.kotlin.fir.resolve.fullyExpandedType import org.jetbrains.kotlin.fir.resolve.substitution.createTypeSubstitutorByTypeConstructor import org.jetbrains.kotlin.fir.resolve.toSymbol +import org.jetbrains.kotlin.fir.symbols.impl.FirConstructorSymbol import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase import org.jetbrains.kotlin.fir.symbols.impl.FirRegularClassSymbol import org.jetbrains.kotlin.fir.types.* @@ -47,8 +48,15 @@ fun computeValueClassRepresentation(klass: FirRegularClass, session: FirSession) return createValueClassRepresentation(session.typeContext, fields) } -private fun FirRegularClass.getValueClassUnderlyingParameters(session: FirSession): List? = - if (isInline) primaryConstructorIfAny(session)?.fir?.valueParameters else null +private fun FirRegularClass.getValueClassUnderlyingParameters(session: FirSession): List? { + if (!isInline) return null + + val primaryConstructorIfAny = primaryConstructorIfAny(session) ?: return null + // FIXME: ATM we cannot lazy-resolve value parameters individually because of KT-53573 + primaryConstructorIfAny.lazyResolveToPhase(FirResolvePhase.TYPES) + + return primaryConstructorIfAny.fir.valueParameters +} private fun isRecursiveSingleFieldValueClass( type: ConeSimpleKotlinType, diff --git a/core/compiler.common/src/org/jetbrains/kotlin/descriptors/InlineClassRepresentation.kt b/core/compiler.common/src/org/jetbrains/kotlin/descriptors/InlineClassRepresentation.kt index b575e82bc60..2ec51144aa6 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/descriptors/InlineClassRepresentation.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/descriptors/InlineClassRepresentation.kt @@ -19,4 +19,7 @@ class InlineClassRepresentation constructor( override fun containsPropertyWithName(name: Name): Boolean = underlyingPropertyName == name override fun getPropertyTypeByName(name: Name): Type? = underlyingType.takeIf { containsPropertyWithName(name) } + + override fun toString(): String = + "InlineClassRepresentation(underlyingPropertyName=$underlyingPropertyName, underlyingType=$underlyingType)" } \ No newline at end of file diff --git a/core/compiler.common/src/org/jetbrains/kotlin/descriptors/MultiFieldValueClassRepresentation.kt b/core/compiler.common/src/org/jetbrains/kotlin/descriptors/MultiFieldValueClassRepresentation.kt index a4947ba88d3..ec1a9cf8f49 100644 --- a/core/compiler.common/src/org/jetbrains/kotlin/descriptors/MultiFieldValueClassRepresentation.kt +++ b/core/compiler.common/src/org/jetbrains/kotlin/descriptors/MultiFieldValueClassRepresentation.kt @@ -18,4 +18,7 @@ class MultiFieldValueClassRepresentation( override fun containsPropertyWithName(name: Name): Boolean = name in map override fun getPropertyTypeByName(name: Name): Type? = map[name] + + override fun toString(): String = + "MultiFieldValueClassRepresentation(underlyingPropertyNamesToTypes=$underlyingPropertyNamesToTypes)" } \ No newline at end of file