Propagate KotlinType to callable reference receivers
This commit is contained in:
@@ -438,13 +438,25 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
mv.visitCode();
|
||||
InstructionAdapter iv = new InstructionAdapter(mv);
|
||||
|
||||
Pair<Integer, Type> receiverIndexAndType =
|
||||
Pair<Integer, FieldInfo> receiverIndexAndFieldInfo =
|
||||
CallableReferenceUtilKt.generateClosureFieldsInitializationFromParameters(iv, closure, args);
|
||||
if (shouldHaveBoundReferenceReceiver && receiverIndexAndType == null) {
|
||||
if (shouldHaveBoundReferenceReceiver && receiverIndexAndFieldInfo == null) {
|
||||
throw new AssertionError("No bound reference receiver in constructor parameters: " + args);
|
||||
}
|
||||
int boundReferenceReceiverParameterIndex = shouldHaveBoundReferenceReceiver ? receiverIndexAndType.getFirst() : -1;
|
||||
Type boundReferenceReceiverType = shouldHaveBoundReferenceReceiver ? receiverIndexAndType.getSecond() : null;
|
||||
|
||||
int boundReceiverParameterIndex;
|
||||
Type boundReceiverType;
|
||||
KotlinType boundReceiverKotlinType;
|
||||
if (shouldHaveBoundReferenceReceiver) {
|
||||
boundReceiverParameterIndex = receiverIndexAndFieldInfo.getFirst();
|
||||
boundReceiverType = receiverIndexAndFieldInfo.getSecond().getFieldType();
|
||||
boundReceiverKotlinType = receiverIndexAndFieldInfo.getSecond().getFieldKotlinType();
|
||||
}
|
||||
else {
|
||||
boundReceiverParameterIndex = -1;
|
||||
boundReceiverType = null;
|
||||
boundReceiverKotlinType = null;
|
||||
}
|
||||
|
||||
iv.load(0, superClassAsmType);
|
||||
|
||||
@@ -454,7 +466,7 @@ public class ClosureCodegen extends MemberCodegen<KtElement> {
|
||||
int arity = calculateArity();
|
||||
iv.iconst(arity);
|
||||
if (shouldHaveBoundReferenceReceiver) {
|
||||
CallableReferenceUtilKt.loadBoundReferenceReceiverParameter(iv, boundReferenceReceiverParameterIndex, boundReferenceReceiverType);
|
||||
CallableReferenceUtilKt.loadBoundReferenceReceiverParameter(iv, boundReceiverParameterIndex, boundReceiverType, boundReceiverKotlinType);
|
||||
superClassConstructorDescriptor = "(ILjava/lang/Object;)V";
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -3053,7 +3053,9 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
FunctionDescriptor functionDescriptor = bindingContext.get(FUNCTION, expression);
|
||||
if (functionDescriptor != null) {
|
||||
FunctionReferenceGenerationStrategy strategy = new FunctionReferenceGenerationStrategy(
|
||||
state, functionDescriptor, resolvedCall, receiver != null ? receiver.type : null, null, false
|
||||
state, functionDescriptor, resolvedCall,
|
||||
receiver != null ? new JvmKotlinType(receiver.type, receiver.kotlinType) : null,
|
||||
null, false
|
||||
);
|
||||
|
||||
return genClosure(
|
||||
@@ -3092,10 +3094,10 @@ public class ExpressionCodegen extends KtVisitor<StackValue, StackValue> impleme
|
||||
element.getContainingFile()
|
||||
);
|
||||
|
||||
Type receiverAsmType = receiverValue != null ? receiverValue.type : null;
|
||||
PropertyReferenceCodegen codegen = new PropertyReferenceCodegen(
|
||||
state, parentCodegen, context.intoAnonymousClass(classDescriptor, this, OwnerKind.IMPLEMENTATION),
|
||||
element, classBuilder, variableDescriptor, target, receiverAsmType
|
||||
element, classBuilder, variableDescriptor, target,
|
||||
receiverValue != null ? new JvmKotlinType(receiverValue.type, receiverValue.kotlinType) : null
|
||||
);
|
||||
codegen.generate();
|
||||
|
||||
|
||||
+6
-3
@@ -20,6 +20,7 @@ import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter;
|
||||
|
||||
@@ -51,6 +52,7 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
||||
private final FunctionDescriptor referencedFunction;
|
||||
private final FunctionDescriptor functionDescriptor;
|
||||
private final Type receiverType; // non-null for bound references
|
||||
private final KotlinType receiverKotlinType;
|
||||
private final StackValue receiverValue;
|
||||
private final boolean isInliningStrategy;
|
||||
|
||||
@@ -58,7 +60,7 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
||||
@NotNull GenerationState state,
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@NotNull ResolvedCall<?> resolvedCall,
|
||||
@Nullable Type receiverType,
|
||||
@Nullable JvmKotlinType receiverJvmKotlinType,
|
||||
@Nullable StackValue receiverValue,
|
||||
boolean isInliningStrategy
|
||||
) {
|
||||
@@ -73,7 +75,8 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
||||
this.referencedFunction = referencedFunction;
|
||||
this.functionDescriptor = functionDescriptor;
|
||||
}
|
||||
this.receiverType = receiverType;
|
||||
this.receiverType = receiverJvmKotlinType != null ? receiverJvmKotlinType.getType() : null;
|
||||
this.receiverKotlinType = receiverJvmKotlinType != null ? receiverJvmKotlinType.getKotlinType() : null;
|
||||
this.receiverValue = receiverValue;
|
||||
this.isInliningStrategy = isInliningStrategy;
|
||||
assert receiverType != null || receiverValue == null
|
||||
@@ -240,7 +243,7 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
||||
if (receiverType != null) {
|
||||
ClassDescriptor classDescriptor = (ClassDescriptor) codegen.getContext().getParentContext().getContextDescriptor();
|
||||
Type asmType = codegen.getState().getTypeMapper().mapClass(classDescriptor);
|
||||
return CallableReferenceUtilKt.capturedBoundReferenceReceiver(asmType, receiverType, isInliningStrategy);
|
||||
return CallableReferenceUtilKt.capturedBoundReferenceReceiver(asmType, receiverType, receiverKotlinType, isInliningStrategy);
|
||||
}
|
||||
|
||||
// 0 is this (the callable reference class), 1 is the invoke() method's first parameter
|
||||
|
||||
@@ -31,7 +31,9 @@ import org.jetbrains.kotlin.psi.KtElement
|
||||
import org.jetbrains.kotlin.resolve.DescriptorFactory
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.PropertyImportedFromObject
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
||||
import org.jetbrains.kotlin.resolve.descriptorUtil.getSuperClassNotAny
|
||||
import org.jetbrains.kotlin.resolve.isUnderlyingPropertyOfInlineClass
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.*
|
||||
import org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
|
||||
@@ -52,8 +54,11 @@ class PropertyReferenceCodegen(
|
||||
classBuilder: ClassBuilder,
|
||||
private val localVariableDescriptorForReference: VariableDescriptor,
|
||||
private val target: VariableDescriptor,
|
||||
private val receiverType: Type?
|
||||
private val boundReceiverJvmKotlinType: JvmKotlinType?
|
||||
) : MemberCodegen<KtElement>(state, parentCodegen, context, expression, classBuilder) {
|
||||
|
||||
private val boundReceiverType = boundReceiverJvmKotlinType?.type
|
||||
|
||||
private val classDescriptor = context.contextDescriptor
|
||||
private val asmType = typeMapper.mapClass(classDescriptor)
|
||||
|
||||
@@ -72,9 +77,9 @@ class PropertyReferenceCodegen(
|
||||
private val wrapperMethod = getWrapperMethodForPropertyReference(target, getFunction.valueParameters.size)
|
||||
|
||||
private val closure = bindingContext.get(CodegenBinding.CLOSURE, classDescriptor)!!.apply {
|
||||
assert((capturedReceiverFromOuterContext != null) == (receiverType != null)) {
|
||||
assert((capturedReceiverFromOuterContext != null) == (boundReceiverType != null)) {
|
||||
"Bound property reference can only be generated with the type of the receiver. " +
|
||||
"Captured type = $capturedReceiverFromOuterContext, actual type = $receiverType"
|
||||
"Captured type = $capturedReceiverFromOuterContext, actual type = $boundReceiverType"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,16 +134,16 @@ class PropertyReferenceCodegen(
|
||||
private fun generateConstructor() {
|
||||
generateMethod("property reference init", 0, constructor) {
|
||||
val shouldHaveBoundReferenceReceiver = closure.isForBoundCallableReference()
|
||||
val receiverIndexAndType = generateClosureFieldsInitializationFromParameters(closure, constructorArgs)
|
||||
val receiverIndexAndFieldInfo = generateClosureFieldsInitializationFromParameters(closure, constructorArgs)
|
||||
|
||||
if (receiverIndexAndType == null) {
|
||||
if (receiverIndexAndFieldInfo == null) {
|
||||
assert(!shouldHaveBoundReferenceReceiver) { "No bound reference receiver in constructor parameters: $constructorArgs" }
|
||||
load(0, OBJECT_TYPE)
|
||||
invokespecial(superAsmType.internalName, "<init>", "()V", false)
|
||||
} else {
|
||||
val (receiverIndex, receiverType) = receiverIndexAndType
|
||||
val (receiverIndex, receiverFieldInfo) = receiverIndexAndFieldInfo
|
||||
load(0, OBJECT_TYPE)
|
||||
loadBoundReferenceReceiverParameter(receiverIndex, receiverType)
|
||||
loadBoundReferenceReceiverParameter(receiverIndex, receiverFieldInfo.fieldType, receiverFieldInfo.fieldKotlinType)
|
||||
invokespecial(superAsmType.internalName, "<init>", "(Ljava/lang/Object;)V", false)
|
||||
}
|
||||
}
|
||||
@@ -155,7 +160,7 @@ class PropertyReferenceCodegen(
|
||||
getFunction,
|
||||
target,
|
||||
asmType,
|
||||
receiverType,
|
||||
boundReceiverJvmKotlinType,
|
||||
element,
|
||||
state,
|
||||
false
|
||||
@@ -176,7 +181,7 @@ class PropertyReferenceCodegen(
|
||||
setFunction,
|
||||
target,
|
||||
asmType,
|
||||
receiverType,
|
||||
boundReceiverJvmKotlinType,
|
||||
element,
|
||||
state,
|
||||
false
|
||||
@@ -284,19 +289,39 @@ class PropertyReferenceCodegen(
|
||||
}
|
||||
|
||||
class PropertyReferenceGenerationStrategy(
|
||||
val isGetter: Boolean,
|
||||
private val isGetter: Boolean,
|
||||
private val originalFunctionDesc: FunctionDescriptor,
|
||||
val target: VariableDescriptor,
|
||||
val asmType: Type,
|
||||
val receiverType: Type?,
|
||||
val expression: KtElement,
|
||||
private val target: VariableDescriptor,
|
||||
private val asmType: Type,
|
||||
boundReceiverJvmKotlinType: JvmKotlinType?,
|
||||
private val expression: KtElement,
|
||||
state: GenerationState,
|
||||
private val isInliningStrategy: Boolean
|
||||
) :
|
||||
FunctionGenerationStrategy.CodegenBased(state) {
|
||||
|
||||
private val boundReceiverType = boundReceiverJvmKotlinType?.type
|
||||
private val boundReceiverKotlinType = boundReceiverJvmKotlinType?.kotlinType
|
||||
|
||||
private val expectedReceiverKotlinType =
|
||||
target.extensionReceiverParameter?.type
|
||||
?: (target.containingDeclaration as? ClassDescriptor)?.defaultType
|
||||
|
||||
private val expectedReceiverType =
|
||||
if (expectedReceiverKotlinType != null)
|
||||
state.typeMapper.mapType(expectedReceiverKotlinType)
|
||||
else {
|
||||
assert(boundReceiverType == null) {
|
||||
"$target: no expected receiver, boundReceiverType is $boundReceiverType"
|
||||
}
|
||||
null
|
||||
}
|
||||
|
||||
override fun doGenerateBody(codegen: ExpressionCodegen, signature: JvmMethodSignature) {
|
||||
val v = codegen.v
|
||||
val typeMapper = state.typeMapper
|
||||
val targetKotlinType = target.type
|
||||
|
||||
if (target is PropertyImportedFromObject) {
|
||||
val containingObject = target.containingObject
|
||||
StackValue
|
||||
@@ -304,31 +329,51 @@ class PropertyReferenceCodegen(
|
||||
.put(typeMapper.mapClass(containingObject), containingObject.defaultType, v)
|
||||
}
|
||||
|
||||
if (receiverType != null) {
|
||||
val expectedReceiver =
|
||||
target.extensionReceiverParameter?.type ?: (target.containingDeclaration as? ClassDescriptor)?.defaultType
|
||||
val expectedReceiverType = if (expectedReceiver != null) typeMapper.mapType(expectedReceiver) else receiverType
|
||||
capturedBoundReferenceReceiver(asmType, expectedReceiverType, isInliningStrategy).put(expectedReceiverType, v)
|
||||
if (boundReceiverType != null) {
|
||||
capturedBoundReferenceReceiver(asmType, boundReceiverType, boundReceiverKotlinType, isInliningStrategy)
|
||||
.put(expectedReceiverType!!, expectedReceiverKotlinType, v)
|
||||
} else {
|
||||
val receivers = originalFunctionDesc.valueParameters.dropLast(if (isGetter) 0 else 1)
|
||||
receivers.forEachIndexed { i, valueParameterDescriptor ->
|
||||
StackValue.local(i + 1, OBJECT_TYPE).put(typeMapper.mapType(valueParameterDescriptor), valueParameterDescriptor.type, v)
|
||||
val nullableAny = valueParameterDescriptor.builtIns.nullableAnyType
|
||||
StackValue.local(i + 1, OBJECT_TYPE, nullableAny)
|
||||
.put(typeMapper.mapType(valueParameterDescriptor), valueParameterDescriptor.type, v)
|
||||
}
|
||||
}
|
||||
|
||||
val value = if (target is LocalVariableDescriptor) {
|
||||
codegen.findLocalOrCapturedValue(target)!!
|
||||
} else {
|
||||
codegen.intermediateValueForProperty(target as PropertyDescriptor, false, null, StackValue.none())
|
||||
val value = when {
|
||||
target is LocalVariableDescriptor -> codegen.findLocalOrCapturedValue(target)!!
|
||||
|
||||
target.isUnderlyingPropertyOfInlineClass() -> {
|
||||
if (expectedReceiverType == null)
|
||||
throw AssertionError("$target: boundReceiverType=$boundReceiverType, expectedReceiverType is null")
|
||||
|
||||
val receiver =
|
||||
if (boundReceiverType != null)
|
||||
StackValue.onStack(expectedReceiverType, expectedReceiverKotlinType)
|
||||
else
|
||||
StackValue.none()
|
||||
|
||||
StackValue.underlyingValueOfInlineClass(typeMapper.mapType(targetKotlinType), targetKotlinType, receiver)
|
||||
}
|
||||
|
||||
else -> codegen.intermediateValueForProperty(target as PropertyDescriptor, false, null, StackValue.none())
|
||||
}
|
||||
|
||||
codegen.markStartLineNumber(expression)
|
||||
val type = target.type
|
||||
|
||||
if (isGetter) {
|
||||
value.put(OBJECT_TYPE, type, v)
|
||||
value.put(OBJECT_TYPE, targetKotlinType, v)
|
||||
} else {
|
||||
val functionDescriptor = codegen.context.functionDescriptor
|
||||
value.store(StackValue.local(codegen.frameMap.getIndex(functionDescriptor.valueParameters.last()), OBJECT_TYPE, type), v)
|
||||
value.store(
|
||||
StackValue.local(
|
||||
codegen.frameMap.getIndex(
|
||||
codegen.context.functionDescriptor.valueParameters.last()
|
||||
),
|
||||
OBJECT_TYPE, targetKotlinType
|
||||
),
|
||||
v
|
||||
)
|
||||
}
|
||||
v.areturn(signature.returnType)
|
||||
}
|
||||
|
||||
@@ -24,10 +24,17 @@ import org.jetbrains.kotlin.psi.KtCallableReferenceExpression
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.resolve.source.KotlinSourceElement
|
||||
import org.jetbrains.kotlin.types.KotlinType
|
||||
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.InstructionAdapter
|
||||
|
||||
fun capturedBoundReferenceReceiver(ownerType: Type, expectedReceiverType: Type, isInliningStrategy: Boolean): StackValue =
|
||||
fun capturedBoundReferenceReceiver(
|
||||
ownerType: Type,
|
||||
expectedReceiverType: Type,
|
||||
expectedReceiverKotlinType: KotlinType?,
|
||||
isInliningStrategy: Boolean
|
||||
): StackValue =
|
||||
StackValue.operation(expectedReceiverType) { iv ->
|
||||
iv.load(0, ownerType)
|
||||
iv.getfield(
|
||||
@@ -36,7 +43,8 @@ fun capturedBoundReferenceReceiver(ownerType: Type, expectedReceiverType: Type,
|
||||
if (isInliningStrategy) AsmUtil.CAPTURED_RECEIVER_FIELD else AsmUtil.BOUND_REFERENCE_RECEIVER,
|
||||
AsmTypes.OBJECT_TYPE.descriptor
|
||||
)
|
||||
StackValue.coerce(AsmTypes.OBJECT_TYPE, expectedReceiverType, iv)
|
||||
val nullableAny = expectedReceiverKotlinType?.run { builtIns.nullableAnyType }
|
||||
StackValue.coerce(AsmTypes.OBJECT_TYPE, nullableAny, expectedReceiverType, expectedReceiverKotlinType, iv)
|
||||
}
|
||||
|
||||
fun ClassDescriptor.isSyntheticClassForCallableReference(): Boolean =
|
||||
@@ -49,9 +57,10 @@ fun CalculatedClosure.isForCallableReference(): Boolean =
|
||||
fun CalculatedClosure.isForBoundCallableReference(): Boolean =
|
||||
isForCallableReference() && capturedReceiverFromOuterContext != null
|
||||
|
||||
fun InstructionAdapter.loadBoundReferenceReceiverParameter(index: Int, type: Type) {
|
||||
fun InstructionAdapter.loadBoundReferenceReceiverParameter(index: Int, type: Type, kotlinType: KotlinType?) {
|
||||
load(index, type)
|
||||
StackValue.coerce(type, AsmTypes.OBJECT_TYPE, this)
|
||||
val nullableAny = kotlinType?.run { builtIns.nullableAnyType }
|
||||
StackValue.coerce(type, kotlinType, AsmTypes.OBJECT_TYPE, nullableAny, this)
|
||||
}
|
||||
|
||||
fun CalculatedClosure.isBoundReferenceReceiverField(fieldInfo: FieldInfo): Boolean =
|
||||
@@ -61,26 +70,21 @@ fun CalculatedClosure.isBoundReferenceReceiverField(fieldInfo: FieldInfo): Boole
|
||||
fun InstructionAdapter.generateClosureFieldsInitializationFromParameters(
|
||||
closure: CalculatedClosure,
|
||||
args: List<FieldInfo>
|
||||
): Pair<Int, Type>? {
|
||||
): Pair<Int, FieldInfo>? {
|
||||
var k = 1
|
||||
var boundReferenceReceiverParameterIndex = -1
|
||||
var boundReferenceReceiverType: Type? = null
|
||||
var boundReferenceReceiverFieldInfo: FieldInfo? = null
|
||||
for (fieldInfo in args) {
|
||||
if (closure.isBoundReferenceReceiverField(fieldInfo)) {
|
||||
boundReferenceReceiverParameterIndex = k
|
||||
boundReferenceReceiverType = fieldInfo.fieldType
|
||||
boundReferenceReceiverFieldInfo = fieldInfo
|
||||
k += fieldInfo.fieldType.size
|
||||
continue
|
||||
}
|
||||
k = AsmUtil.genAssignInstanceFieldFromParam(fieldInfo, k, this)
|
||||
}
|
||||
|
||||
return when {
|
||||
boundReferenceReceiverType != null ->
|
||||
Pair(boundReferenceReceiverParameterIndex, boundReferenceReceiverType)
|
||||
else ->
|
||||
null
|
||||
}
|
||||
return boundReferenceReceiverFieldInfo?.let { Pair(boundReferenceReceiverParameterIndex, it) }
|
||||
}
|
||||
|
||||
fun computeExpectedNumberOfReceivers(referencedFunction: FunctionDescriptor, isBound: Boolean): Int {
|
||||
|
||||
@@ -172,17 +172,20 @@ class PsiSourceCompilerForInline(private val codegen: ExpressionCodegen, overrid
|
||||
val strategy = when (expression) {
|
||||
is KtCallableReferenceExpression -> {
|
||||
val resolvedCall = expression.callableReference.getResolvedCallWithAssert(state.bindingContext)
|
||||
val receiverType = JvmCodegenUtil.getBoundCallableReferenceReceiver(resolvedCall)?.type?.let(state.typeMapper::mapType)
|
||||
val receiverKotlinType = JvmCodegenUtil.getBoundCallableReferenceReceiver(resolvedCall)?.type
|
||||
val receiverType = receiverKotlinType?.let(state.typeMapper::mapType)
|
||||
val boundReceiverJvmKotlinType = receiverType?.let { JvmKotlinType(receiverType, receiverKotlinType) }
|
||||
|
||||
if (isLambda && lambdaInfo!!.isPropertyReference) {
|
||||
val asmType = state.typeMapper.mapClass(lambdaInfo.classDescriptor)
|
||||
val info = lambdaInfo.propertyReferenceInfo
|
||||
PropertyReferenceCodegen.PropertyReferenceGenerationStrategy(
|
||||
true, info!!.getFunction, info.target, asmType, receiverType,
|
||||
true, info!!.getFunction, info.target, asmType,
|
||||
boundReceiverJvmKotlinType,
|
||||
lambdaInfo.functionWithBodyOrCallableReference, state, true
|
||||
)
|
||||
} else {
|
||||
FunctionReferenceGenerationStrategy(state, descriptor, resolvedCall, receiverType, null, true)
|
||||
FunctionReferenceGenerationStrategy(state, descriptor, resolvedCall, boundReceiverJvmKotlinType, null, true)
|
||||
}
|
||||
}
|
||||
is KtFunctionLiteral -> ClosureGenerationStrategy(state, expression as KtDeclarationWithBody)
|
||||
|
||||
@@ -58,7 +58,7 @@ fun KotlinType.isNullableUnderlyingType(): Boolean {
|
||||
return TypeUtils.isNullableType(underlyingType)
|
||||
}
|
||||
|
||||
fun PropertyDescriptor.isUnderlyingPropertyOfInlineClass(): Boolean {
|
||||
fun VariableDescriptor.isUnderlyingPropertyOfInlineClass(): Boolean {
|
||||
val containingDeclaration = this.containingDeclaration
|
||||
if (!containingDeclaration.isInlineClass()) return false
|
||||
|
||||
|
||||
Reference in New Issue
Block a user