Unbox inline class parameter of lambda if underlying type is Any or Any?
The inline class is boxed when we pass it as lambda argument, now we unbox it. If the underlying type is not Any or Any?, bridge method does the unboxing. #KT-32450 Fixed #KT-39923 Fixed #KT-32228 Fixed #KT-40282 Fixed
This commit is contained in:
@@ -31,6 +31,7 @@ import org.jetbrains.kotlin.load.kotlin.header.KotlinClassHeader;
|
||||
import org.jetbrains.kotlin.metadata.ProtoBuf;
|
||||
import org.jetbrains.kotlin.psi.KtElement;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.InlineClassesUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilsKt;
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOriginKt;
|
||||
@@ -367,6 +368,11 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
value = StackValue.local(slot, type, bridgeParameterKotlinTypes.get(i));
|
||||
slot += type.getSize();
|
||||
}
|
||||
if (InlineClassesCodegenUtilKt.isInlineClassWithUnderlyingTypeAnyOrAnyN(parameterType) &&
|
||||
functionReferenceCall == null
|
||||
) {
|
||||
parameterType = InlineClassesUtilsKt.unsubstitutedUnderlyingParameter(parameterType).getType();
|
||||
}
|
||||
value.put(typeMapper.mapType(calleeParameter), parameterType, iv);
|
||||
}
|
||||
|
||||
|
||||
@@ -1995,6 +1995,21 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
|
||||
StackValue localOrCaptured = findLocalOrCapturedValue(descriptor);
|
||||
if (localOrCaptured != null) {
|
||||
if (descriptor instanceof ValueParameterDescriptor) {
|
||||
KotlinType inlineClassType = ((ValueParameterDescriptor) descriptor).getType();
|
||||
if (InlineClassesCodegenUtilKt.isInlineClassWithUnderlyingTypeAnyOrAnyN(inlineClassType) &&
|
||||
InlineClassesCodegenUtilKt.isGenericParameter((CallableDescriptor) descriptor) &&
|
||||
// TODO: HACK around bridgeGenerationCrossinline
|
||||
!(context instanceof InlineLambdaContext) &&
|
||||
// Do not unbox parameters of suspend lambda, they are unboxed in `invoke` method
|
||||
!CoroutineCodegenUtilKt.isInvokeSuspendOfLambda(context.getFunctionDescriptor())
|
||||
) {
|
||||
KotlinType underlyingType = InlineClassesUtilsKt.underlyingRepresentation(
|
||||
(ClassDescriptor) inlineClassType.getConstructor().getDeclarationDescriptor()).getType();
|
||||
return StackValue.underlyingValueOfInlineClass(
|
||||
typeMapper.mapType(underlyingType), underlyingType, localOrCaptured);
|
||||
}
|
||||
}
|
||||
return localOrCaptured;
|
||||
}
|
||||
throw new UnsupportedOperationException("don't know how to generate reference " + descriptor);
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 2010-2020 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.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.codegen
|
||||
|
||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.impl.AnonymousFunctionDescriptor
|
||||
import org.jetbrains.kotlin.resolve.isInlineClassType
|
||||
import org.jetbrains.kotlin.resolve.underlyingRepresentation
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.isAnyOrNullableAny
|
||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||
|
||||
fun KotlinType.isInlineClassWithUnderlyingTypeAnyOrAnyN(): Boolean {
|
||||
if (!isInlineClassType()) return false
|
||||
val classDescriptor = constructor.declarationDescriptor as? ClassDescriptor ?: return false
|
||||
return classDescriptor.underlyingRepresentation()?.type?.isAnyOrNullableAny() == true
|
||||
}
|
||||
|
||||
fun CallableDescriptor.isGenericParameter(): Boolean {
|
||||
if (this !is ValueParameterDescriptor) return false
|
||||
if (containingDeclaration is AnonymousFunctionDescriptor) return true
|
||||
val index = containingDeclaration.valueParameters.indexOf(this)
|
||||
return containingDeclaration.overriddenDescriptors.any { it.original.valueParameters[index].type.isTypeParameter() }
|
||||
}
|
||||
Reference in New Issue
Block a user