Determine underlying property of inline class by its name

Previous way to distinguish "primary constructor properties" from other
 properties wasn't correct for deserialized properties, because currently
 we don't have special information about this in metadata
This commit is contained in:
Mikhail Zarechenskiy
2018-06-14 17:49:33 +03:00
parent dbd72ae53b
commit 3f462659d2
6 changed files with 38 additions and 15 deletions
@@ -1707,11 +1707,7 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
if (descriptor instanceof PropertyDescriptor) {
PropertyDescriptor propertyDescriptor = (PropertyDescriptor) descriptor;
boolean isUnderlyingPropertyOfInlineClass =
InlineClassesUtilsKt.isInlineClass(propertyDescriptor.getContainingDeclaration()) &&
JvmCodegenUtil.hasBackingField(propertyDescriptor, contextKind(), bindingContext);
if (isUnderlyingPropertyOfInlineClass) {
if (InlineClassesUtilsKt.isUnderlyingPropertyOfInlineClass(propertyDescriptor)) {
KotlinType propertyType = propertyDescriptor.getType();
return StackValue.underlyingValueOfInlineClass(typeMapper.mapType(propertyType), propertyType, receiver);
}
@@ -23,7 +23,6 @@ import org.jetbrains.kotlin.codegen.coroutines.SuspendFunctionGenerationStrategy
import org.jetbrains.kotlin.codegen.coroutines.SuspendInlineFunctionGenerationStrategy;
import org.jetbrains.kotlin.codegen.state.GenerationState;
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
import org.jetbrains.kotlin.codegen.state.TypeMapperUtilsKt;
import org.jetbrains.kotlin.config.JvmDefaultMode;
import org.jetbrains.kotlin.config.JvmTarget;
import org.jetbrains.kotlin.config.LanguageFeature;
@@ -295,8 +294,7 @@ public class FunctionCodegen {
// descriptor corresponds to the underlying value
if (functionDescriptor instanceof PropertyAccessorDescriptor) {
PropertyDescriptor property = ((PropertyAccessorDescriptor) functionDescriptor).getCorrespondingProperty();
// property for the underlying value
if (JvmCodegenUtil.hasBackingField(property, contextKind, bindingContext)) {
if (InlineClassesUtilsKt.isUnderlyingPropertyOfInlineClass(property)) {
return false;
}
}
@@ -135,7 +135,7 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
if (compatibility.allStrongIncompatibilities()) return
if (Compatible in compatibility) {
if (checkActual && requireActualModifier(descriptor, trace)) {
if (checkActual && requireActualModifier(descriptor)) {
trace.report(Errors.ACTUAL_MISSING.on(reportOn))
}
@@ -204,16 +204,14 @@ object ExpectedActualDeclarationChecker : DeclarationChecker {
// - annotation constructors, because annotation classes can only have one constructor
// - inline class primary constructors, because inline class must have primary constructor
// - value parameter inside primary constructor of inline class, because inline class must have one value parameter
private fun requireActualModifier(descriptor: MemberDescriptor, trace: BindingTrace): Boolean {
private fun requireActualModifier(descriptor: MemberDescriptor): Boolean {
return !descriptor.isAnnotationConstructor() &&
!descriptor.isPrimaryConstructorOfInlineClass() &&
!isMainPropertyOfInlineClass(descriptor, trace)
!isUnderlyingPropertyOfInlineClass(descriptor)
}
private fun isMainPropertyOfInlineClass(descriptor: MemberDescriptor, trace: BindingTrace): Boolean {
if (descriptor !is PropertyDescriptor) return false
if (!descriptor.containingDeclaration.isInlineClass()) return false
return trace.bindingContext[BindingContext.BACKING_FIELD_REQUIRED, descriptor] == true
private fun isUnderlyingPropertyOfInlineClass(descriptor: MemberDescriptor): Boolean {
return descriptor is PropertyDescriptor && descriptor.isUnderlyingPropertyOfInlineClass()
}
// This should ideally be handled by CallableMemberDescriptor.Kind, but default constructors have kind DECLARATION and non-empty source.
@@ -0,0 +1,18 @@
// FILE: A.kt
package a
@Suppress("UNSUPPORTED_FEATURE")
inline class Foo(val x: IntArray) {
val size: Int get() = x.size
}
// FILE: B.kt
import a.*
fun box(): String {
val a = Foo(intArrayOf(3, 4))
if (a.size != 2) return "Fail"
return "OK"
}
@@ -39,6 +39,11 @@ public class CompileKotlinAgainstKotlinTestGenerated extends AbstractCompileKotl
runTest("compiler/testData/compileKotlinAgainstKotlin/annotationsOnTypeAliases.kt");
}
@TestMetadata("callDeserializedPropertyOnInlineClassType.kt")
public void testCallDeserializedPropertyOnInlineClassType() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/callDeserializedPropertyOnInlineClassType.kt");
}
@TestMetadata("callsToMultifileClassFromOtherPackage.kt")
public void testCallsToMultifileClassFromOtherPackage() throws Exception {
runTest("compiler/testData/compileKotlinAgainstKotlin/callsToMultifileClassFromOtherPackage.kt");
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.resolve
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.types.KotlinType
@@ -39,3 +40,10 @@ fun KotlinType.isNullableUnderlyingType(): Boolean {
return TypeUtils.isNullableType(underlyingType)
}
fun PropertyDescriptor.isUnderlyingPropertyOfInlineClass(): Boolean {
val containingDeclaration = this.containingDeclaration
if (!containingDeclaration.isInlineClass()) return false
return (containingDeclaration as ClassDescriptor).underlyingRepresentation()?.name == this.name
}