Generate private methods in TraitImpl as private, don't generate delegation to private trait methods
This commit is contained in:
@@ -93,14 +93,14 @@ public class CodegenUtil {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public static Map<FunctionDescriptor, FunctionDescriptor> getTraitMethods(ClassDescriptor descriptor) {
|
public static Map<FunctionDescriptor, FunctionDescriptor> getNonPrivateTraitMethods(ClassDescriptor descriptor) {
|
||||||
Map<FunctionDescriptor, FunctionDescriptor> result = new LinkedHashMap<FunctionDescriptor, FunctionDescriptor>();
|
Map<FunctionDescriptor, FunctionDescriptor> result = new LinkedHashMap<FunctionDescriptor, FunctionDescriptor>();
|
||||||
for (DeclarationDescriptor declaration : DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().getMemberScope())) {
|
for (DeclarationDescriptor declaration : DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().getMemberScope())) {
|
||||||
if (!(declaration instanceof CallableMemberDescriptor)) continue;
|
if (!(declaration instanceof CallableMemberDescriptor)) continue;
|
||||||
|
|
||||||
CallableMemberDescriptor inheritedMember = (CallableMemberDescriptor) declaration;
|
CallableMemberDescriptor inheritedMember = (CallableMemberDescriptor) declaration;
|
||||||
CallableMemberDescriptor traitMember = ImplKt.findTraitImplementation(inheritedMember);
|
CallableMemberDescriptor traitMember = ImplKt.findTraitImplementation(inheritedMember);
|
||||||
if (traitMember == null) continue;
|
if (traitMember == null || Visibilities.isPrivate(traitMember.getVisibility())) continue;
|
||||||
|
|
||||||
assert traitMember.getModality() != Modality.ABSTRACT : "Cannot delegate to abstract trait method: " + inheritedMember;
|
assert traitMember.getModality() != Modality.ABSTRACT : "Cannot delegate to abstract trait method: " + inheritedMember;
|
||||||
|
|
||||||
|
|||||||
@@ -325,9 +325,6 @@ public class AsmUtil {
|
|||||||
private static Integer specialCaseVisibility(@NotNull MemberDescriptor memberDescriptor) {
|
private static Integer specialCaseVisibility(@NotNull MemberDescriptor memberDescriptor) {
|
||||||
DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration();
|
DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration();
|
||||||
Visibility memberVisibility = memberDescriptor.getVisibility();
|
Visibility memberVisibility = memberDescriptor.getVisibility();
|
||||||
if (isJvmInterface(containingDeclaration)) {
|
|
||||||
return memberVisibility == Visibilities.PRIVATE ? NO_FLAG_PACKAGE_PRIVATE : ACC_PUBLIC;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (memberVisibility == Visibilities.LOCAL && memberDescriptor instanceof CallableMemberDescriptor) {
|
if (memberVisibility == Visibilities.LOCAL && memberDescriptor instanceof CallableMemberDescriptor) {
|
||||||
return ACC_PUBLIC;
|
return ACC_PUBLIC;
|
||||||
|
|||||||
@@ -77,6 +77,8 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtClassOrObject> {
|
|||||||
|
|
||||||
generatePrimaryConstructorProperties();
|
generatePrimaryConstructorProperties();
|
||||||
generateConstructors();
|
generateConstructors();
|
||||||
|
generateDefaultImplsIfNeeded();
|
||||||
|
|
||||||
for (KtObjectDeclaration companion : companions) {
|
for (KtObjectDeclaration companion : companions) {
|
||||||
generateDeclaration(companion);
|
generateDeclaration(companion);
|
||||||
}
|
}
|
||||||
@@ -109,6 +111,10 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtClassOrObject> {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void generateDefaultImplsIfNeeded() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean shouldProcessFirst(KtDeclaration declaration) {
|
private static boolean shouldProcessFirst(KtDeclaration declaration) {
|
||||||
return !(declaration instanceof KtProperty || declaration instanceof KtNamedFunction);
|
return !(declaration instanceof KtProperty || declaration instanceof KtNamedFunction);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void generateBody() {
|
protected void generateDefaultImplsIfNeeded() {
|
||||||
if (isInterface(descriptor) && !isLocal) {
|
if (isInterface(descriptor) && !isLocal) {
|
||||||
Type defaultImplsType = state.getTypeMapper().mapDefaultImpls(descriptor);
|
Type defaultImplsType = state.getTypeMapper().mapDefaultImpls(descriptor);
|
||||||
ClassBuilder defaultImplsBuilder =
|
ClassBuilder defaultImplsBuilder =
|
||||||
@@ -242,7 +242,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
ClassContext defaultImplsContext = parentContext.intoDefaultImplsClass(descriptor, (ClassContext) context, state);
|
ClassContext defaultImplsContext = parentContext.intoDefaultImplsClass(descriptor, (ClassContext) context, state);
|
||||||
new InterfaceImplBodyCodegen(myClass, defaultImplsContext, defaultImplsBuilder, state, this).generate();
|
new InterfaceImplBodyCodegen(myClass, defaultImplsContext, defaultImplsBuilder, state, this).generate();
|
||||||
}
|
}
|
||||||
super.generateBody();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -378,7 +377,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
|
|
||||||
generateDelegates(delegationFieldsInfo);
|
generateDelegates(delegationFieldsInfo);
|
||||||
|
|
||||||
generateSyntheticAccessors();
|
if (!isInterface(descriptor) || kind == OwnerKind.DEFAULT_IMPLS) {
|
||||||
|
generateSyntheticAccessors();
|
||||||
|
}
|
||||||
|
|
||||||
generateEnumMethods();
|
generateEnumMethods();
|
||||||
|
|
||||||
@@ -1332,7 +1333,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
private void generateTraitMethods() {
|
private void generateTraitMethods() {
|
||||||
if (isInterface(descriptor)) return;
|
if (isInterface(descriptor)) return;
|
||||||
|
|
||||||
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.getTraitMethods(descriptor).entrySet()) {
|
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.getNonPrivateTraitMethods(descriptor).entrySet()) {
|
||||||
FunctionDescriptor traitFun = entry.getKey();
|
FunctionDescriptor traitFun = entry.getKey();
|
||||||
//skip java 8 default methods
|
//skip java 8 default methods
|
||||||
if (!(traitFun instanceof JavaCallableMemberDescriptor)) {
|
if (!(traitFun instanceof JavaCallableMemberDescriptor)) {
|
||||||
|
|||||||
@@ -103,6 +103,8 @@ public class InterfaceImplBodyCodegen(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
generateSyntheticAccessors()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateDelegationToSuperTraitImpl(descriptor: FunctionDescriptor, implementation: FunctionDescriptor) {
|
private fun generateDelegationToSuperTraitImpl(descriptor: FunctionDescriptor, implementation: FunctionDescriptor) {
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ import static org.jetbrains.kotlin.codegen.AsmUtil.isPrimitive;
|
|||||||
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
|
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.SYNTHESIZED;
|
||||||
import static org.jetbrains.kotlin.resolve.BindingContext.VARIABLE;
|
import static org.jetbrains.kotlin.resolve.BindingContext.VARIABLE;
|
||||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
|
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isCompanionObject;
|
||||||
|
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface;
|
||||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isStaticDeclaration;
|
import static org.jetbrains.kotlin.resolve.DescriptorUtils.isStaticDeclaration;
|
||||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.*;
|
||||||
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
import static org.jetbrains.kotlin.resolve.jvm.diagnostics.JvmDeclarationOrigin.NO_ORIGIN;
|
||||||
@@ -684,7 +685,7 @@ public abstract class MemberCodegen<T extends KtElement/* TODO: & JetDeclaration
|
|||||||
((AccessorForCallableDescriptor) accessorDescriptor).getSuperCallTarget() != null
|
((AccessorForCallableDescriptor) accessorDescriptor).getSuperCallTarget() != null
|
||||||
);
|
);
|
||||||
|
|
||||||
boolean hasDispatchReceiver = !isStaticDeclaration(functionDescriptor);
|
boolean hasDispatchReceiver = !isStaticDeclaration(functionDescriptor) && !isInterface(functionDescriptor.getContainingDeclaration());
|
||||||
int reg = hasDispatchReceiver ? 1 : 0;
|
int reg = hasDispatchReceiver ? 1 : 0;
|
||||||
boolean accessorIsConstructor = accessorDescriptor instanceof AccessorForConstructorDescriptor;
|
boolean accessorIsConstructor = accessorDescriptor instanceof AccessorForConstructorDescriptor;
|
||||||
if (!accessorIsConstructor && functionDescriptor instanceof ConstructorDescriptor) {
|
if (!accessorIsConstructor && functionDescriptor instanceof ConstructorDescriptor) {
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.context;
|
|||||||
import kotlin.jvm.functions.Function0;
|
import kotlin.jvm.functions.Function0;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.annotations.ReadOnly;
|
||||||
import org.jetbrains.kotlin.codegen.*;
|
import org.jetbrains.kotlin.codegen.*;
|
||||||
import org.jetbrains.kotlin.codegen.binding.MutableClosure;
|
import org.jetbrains.kotlin.codegen.binding.MutableClosure;
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
@@ -27,7 +28,6 @@ import org.jetbrains.kotlin.descriptors.*;
|
|||||||
import org.jetbrains.kotlin.load.java.JavaVisibilities;
|
import org.jetbrains.kotlin.load.java.JavaVisibilities;
|
||||||
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
|
import org.jetbrains.kotlin.load.java.descriptors.SamConstructorDescriptor;
|
||||||
import org.jetbrains.kotlin.psi.KtFile;
|
import org.jetbrains.kotlin.psi.KtFile;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
|
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
|
||||||
import org.jetbrains.kotlin.storage.NullableLazyValue;
|
import org.jetbrains.kotlin.storage.NullableLazyValue;
|
||||||
@@ -505,6 +505,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
@ReadOnly
|
||||||
public Collection<? extends AccessorForCallableDescriptor<?>> getAccessors() {
|
public Collection<? extends AccessorForCallableDescriptor<?>> getAccessors() {
|
||||||
return accessors == null ? Collections.<AccessorForCallableDescriptor<CallableMemberDescriptor>>emptySet() : accessors.values();
|
return accessors == null ? Collections.<AccessorForCallableDescriptor<CallableMemberDescriptor>>emptySet() : accessors.values();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.codegen.context
|
package org.jetbrains.kotlin.codegen.context
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.codegen.AccessorForCallableDescriptor
|
||||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper
|
import org.jetbrains.kotlin.codegen.state.JetTypeMapper
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
@@ -33,4 +34,11 @@ class DefaultImplsClassContext(
|
|||||||
override fun getCompanionObjectContext(): CodegenContext<*>? {
|
override fun getCompanionObjectContext(): CodegenContext<*>? {
|
||||||
return interfaceContext.companionObjectContext
|
return interfaceContext.companionObjectContext
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getAccessors(): Collection<AccessorForCallableDescriptor<*>> {
|
||||||
|
val accessors = super.getAccessors()
|
||||||
|
val alreadyExistKeys = accessors.map ({ Pair(it.calleeDescriptor, it.superCallTarget) })
|
||||||
|
val filtered = interfaceContext.accessors.toMap ({ Pair(it.calleeDescriptor, it.superCallTarget) }, {it}) - alreadyExistKeys
|
||||||
|
return accessors + filtered.values
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -758,7 +758,7 @@ public class JetTypeMapper {
|
|||||||
ClassDescriptor ownerForDefault = (ClassDescriptor) baseMethodDescriptor.getContainingDeclaration();
|
ClassDescriptor ownerForDefault = (ClassDescriptor) baseMethodDescriptor.getContainingDeclaration();
|
||||||
ownerForDefaultImpl = isJvmInterface(ownerForDefault) ? mapDefaultImpls(ownerForDefault) : mapClass(ownerForDefault);
|
ownerForDefaultImpl = isJvmInterface(ownerForDefault) ? mapDefaultImpls(ownerForDefault) : mapClass(ownerForDefault);
|
||||||
|
|
||||||
if (isInterface && (superCall || descriptor.getVisibility() == Visibilities.PRIVATE)) {
|
if (isInterface && (superCall || descriptor.getVisibility() == Visibilities.PRIVATE || isAccessor(descriptor))) {
|
||||||
thisClass = mapClass(currentOwner);
|
thisClass = mapClass(currentOwner);
|
||||||
if (declarationOwner instanceof JavaClassDescriptor) {
|
if (declarationOwner instanceof JavaClassDescriptor) {
|
||||||
invokeOpcode = INVOKESPECIAL;
|
invokeOpcode = INVOKESPECIAL;
|
||||||
|
|||||||
+3
-5
@@ -1,11 +1,9 @@
|
|||||||
public interface PrivateInTrait {
|
public interface PrivateInTrait {
|
||||||
final class DefaultImpls {
|
final class DefaultImpls {
|
||||||
@org.jetbrains.annotations.NotNull
|
private static java.lang.String getNn(PrivateInTrait $this) { /* compiled code */ }
|
||||||
static java.lang.String getNn(PrivateInTrait $this) { /* compiled code */ }
|
|
||||||
|
|
||||||
static void setNn(@org.jetbrains.annotations.NotNull PrivateInTrait $this, java.lang.String value) { /* compiled code */ }
|
private static void setNn(PrivateInTrait $this, java.lang.String value) { /* compiled code */ }
|
||||||
|
|
||||||
@org.jetbrains.annotations.Nullable
|
private static java.lang.String getN(PrivateInTrait $this) { /* compiled code */ }
|
||||||
static java.lang.String getN(PrivateInTrait $this) { /* compiled code */ }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
interface Z{
|
||||||
|
|
||||||
|
private fun extension(): String {
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object Z2 : Z {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box() : String {
|
||||||
|
val size = Class.forName("Z2").declaredMethods.size
|
||||||
|
if (size != 0) return "fail: $size"
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
var result = "fail"
|
||||||
|
|
||||||
|
interface B {
|
||||||
|
|
||||||
|
private fun test() {
|
||||||
|
result = "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
class Z {
|
||||||
|
fun ztest(b: B) {
|
||||||
|
b.test()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class C : B
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
B.Z().ztest(C())
|
||||||
|
return result
|
||||||
|
}
|
||||||
+12
@@ -7876,6 +7876,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("noPrivateDelegation.kt")
|
||||||
|
public void testNoPrivateDelegation() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/noPrivateDelegation.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("syntheticAccessor.kt")
|
||||||
|
public void testSyntheticAccessor() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/syntheticAccessor.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("traitImplDelegationWithCovariantOverride.kt")
|
@TestMetadata("traitImplDelegationWithCovariantOverride.kt")
|
||||||
public void testTraitImplDelegationWithCovariantOverride() throws Exception {
|
public void testTraitImplDelegationWithCovariantOverride() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/traitImplDelegationWithCovariantOverride.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/traitImplDelegationWithCovariantOverride.kt");
|
||||||
|
|||||||
+1
-1
@@ -232,7 +232,7 @@ public class ClassTranslator private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun generateBridgesToTraitImpl(properties: MutableList<JsPropertyInitializer>) {
|
private fun generateBridgesToTraitImpl(properties: MutableList<JsPropertyInitializer>) {
|
||||||
for (entry in CodegenUtil.getTraitMethods(descriptor).entrySet()) {
|
for (entry in CodegenUtil.getNonPrivateTraitMethods(descriptor).entrySet()) {
|
||||||
if (!areNamesEqual(entry.getKey(), entry.getValue())) {
|
if (!areNamesEqual(entry.getKey(), entry.getValue())) {
|
||||||
properties.add(generateDelegateCall(entry.getValue(), entry.getKey(), JsLiteral.THIS, context()))
|
properties.add(generateDelegateCall(entry.getValue(), entry.getKey(), JsLiteral.THIS, context()))
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user