mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-10 08:31:29 +00:00
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
|
||||
public static Map<FunctionDescriptor, FunctionDescriptor> getTraitMethods(ClassDescriptor descriptor) {
|
||||
public static Map<FunctionDescriptor, FunctionDescriptor> getNonPrivateTraitMethods(ClassDescriptor descriptor) {
|
||||
Map<FunctionDescriptor, FunctionDescriptor> result = new LinkedHashMap<FunctionDescriptor, FunctionDescriptor>();
|
||||
for (DeclarationDescriptor declaration : DescriptorUtils.getAllDescriptors(descriptor.getDefaultType().getMemberScope())) {
|
||||
if (!(declaration instanceof CallableMemberDescriptor)) continue;
|
||||
|
||||
CallableMemberDescriptor inheritedMember = (CallableMemberDescriptor) declaration;
|
||||
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;
|
||||
|
||||
|
||||
@@ -325,9 +325,6 @@ public class AsmUtil {
|
||||
private static Integer specialCaseVisibility(@NotNull MemberDescriptor memberDescriptor) {
|
||||
DeclarationDescriptor containingDeclaration = memberDescriptor.getContainingDeclaration();
|
||||
Visibility memberVisibility = memberDescriptor.getVisibility();
|
||||
if (isJvmInterface(containingDeclaration)) {
|
||||
return memberVisibility == Visibilities.PRIVATE ? NO_FLAG_PACKAGE_PRIVATE : ACC_PUBLIC;
|
||||
}
|
||||
|
||||
if (memberVisibility == Visibilities.LOCAL && memberDescriptor instanceof CallableMemberDescriptor) {
|
||||
return ACC_PUBLIC;
|
||||
|
||||
@@ -77,6 +77,8 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtClassOrObject> {
|
||||
|
||||
generatePrimaryConstructorProperties();
|
||||
generateConstructors();
|
||||
generateDefaultImplsIfNeeded();
|
||||
|
||||
for (KtObjectDeclaration companion : companions) {
|
||||
generateDeclaration(companion);
|
||||
}
|
||||
@@ -109,6 +111,10 @@ public abstract class ClassBodyCodegen extends MemberCodegen<KtClassOrObject> {
|
||||
|
||||
}
|
||||
|
||||
protected void generateDefaultImplsIfNeeded() {
|
||||
|
||||
}
|
||||
|
||||
private static boolean shouldProcessFirst(KtDeclaration declaration) {
|
||||
return !(declaration instanceof KtProperty || declaration instanceof KtNamedFunction);
|
||||
}
|
||||
|
||||
@@ -230,7 +230,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void generateBody() {
|
||||
protected void generateDefaultImplsIfNeeded() {
|
||||
if (isInterface(descriptor) && !isLocal) {
|
||||
Type defaultImplsType = state.getTypeMapper().mapDefaultImpls(descriptor);
|
||||
ClassBuilder defaultImplsBuilder =
|
||||
@@ -242,7 +242,6 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
ClassContext defaultImplsContext = parentContext.intoDefaultImplsClass(descriptor, (ClassContext) context, state);
|
||||
new InterfaceImplBodyCodegen(myClass, defaultImplsContext, defaultImplsBuilder, state, this).generate();
|
||||
}
|
||||
super.generateBody();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -378,7 +377,9 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
generateDelegates(delegationFieldsInfo);
|
||||
|
||||
generateSyntheticAccessors();
|
||||
if (!isInterface(descriptor) || kind == OwnerKind.DEFAULT_IMPLS) {
|
||||
generateSyntheticAccessors();
|
||||
}
|
||||
|
||||
generateEnumMethods();
|
||||
|
||||
@@ -1332,7 +1333,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
private void generateTraitMethods() {
|
||||
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();
|
||||
//skip java 8 default methods
|
||||
if (!(traitFun instanceof JavaCallableMemberDescriptor)) {
|
||||
|
||||
@@ -103,6 +103,8 @@ public class InterfaceImplBodyCodegen(
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
generateSyntheticAccessors()
|
||||
}
|
||||
|
||||
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.resolve.BindingContext.VARIABLE;
|
||||
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.jvm.AsmTypes.*;
|
||||
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
|
||||
);
|
||||
|
||||
boolean hasDispatchReceiver = !isStaticDeclaration(functionDescriptor);
|
||||
boolean hasDispatchReceiver = !isStaticDeclaration(functionDescriptor) && !isInterface(functionDescriptor.getContainingDeclaration());
|
||||
int reg = hasDispatchReceiver ? 1 : 0;
|
||||
boolean accessorIsConstructor = accessorDescriptor instanceof AccessorForConstructorDescriptor;
|
||||
if (!accessorIsConstructor && functionDescriptor instanceof ConstructorDescriptor) {
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.codegen.context;
|
||||
import kotlin.jvm.functions.Function0;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.ReadOnly;
|
||||
import org.jetbrains.kotlin.codegen.*;
|
||||
import org.jetbrains.kotlin.codegen.binding.MutableClosure;
|
||||
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.descriptors.SamConstructorDescriptor;
|
||||
import org.jetbrains.kotlin.psi.KtFile;
|
||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.storage.LockBasedStorageManager;
|
||||
import org.jetbrains.kotlin.storage.NullableLazyValue;
|
||||
@@ -505,6 +505,7 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@ReadOnly
|
||||
public Collection<? extends AccessorForCallableDescriptor<?>> getAccessors() {
|
||||
return accessors == null ? Collections.<AccessorForCallableDescriptor<CallableMemberDescriptor>>emptySet() : accessors.values();
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.codegen.context
|
||||
|
||||
import org.jetbrains.kotlin.codegen.AccessorForCallableDescriptor
|
||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||
import org.jetbrains.kotlin.codegen.state.JetTypeMapper
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
@@ -33,4 +34,11 @@ class DefaultImplsClassContext(
|
||||
override fun getCompanionObjectContext(): CodegenContext<*>? {
|
||||
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();
|
||||
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);
|
||||
if (declarationOwner instanceof JavaClassDescriptor) {
|
||||
invokeOpcode = INVOKESPECIAL;
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
public interface PrivateInTrait {
|
||||
final class DefaultImpls {
|
||||
@org.jetbrains.annotations.NotNull
|
||||
static java.lang.String getNn(PrivateInTrait $this) { /* compiled code */ }
|
||||
private 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
|
||||
static java.lang.String getN(PrivateInTrait $this) { /* compiled code */ }
|
||||
private static java.lang.String getN(PrivateInTrait $this) { /* compiled code */ }
|
||||
}
|
||||
}
|
||||
16
compiler/testData/codegen/box/traits/noPrivateDelegation.kt
vendored
Normal file
16
compiler/testData/codegen/box/traits/noPrivateDelegation.kt
vendored
Normal file
@@ -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"
|
||||
}
|
||||
21
compiler/testData/codegen/box/traits/syntheticAccessor.kt
vendored
Normal file
21
compiler/testData/codegen/box/traits/syntheticAccessor.kt
vendored
Normal file
@@ -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
|
||||
}
|
||||
@@ -7876,6 +7876,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
||||
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")
|
||||
public void testTraitImplDelegationWithCovariantOverride() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/traits/traitImplDelegationWithCovariantOverride.kt");
|
||||
|
||||
@@ -232,7 +232,7 @@ public class ClassTranslator private constructor(
|
||||
}
|
||||
|
||||
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())) {
|
||||
properties.add(generateDelegateCall(entry.getValue(), entry.getKey(), JsLiteral.THIS, context()))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user