Check method abstractness during bridge generation per method not interface
This commit is contained in:
@@ -17,20 +17,18 @@
|
|||||||
package org.jetbrains.kotlin.backend.common.bridges
|
package org.jetbrains.kotlin.backend.common.bridges
|
||||||
|
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.renderer.DescriptorRenderer
|
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.resolve.OverridingUtil
|
import org.jetbrains.kotlin.resolve.OverridingUtil
|
||||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized
|
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized
|
||||||
|
|
||||||
fun <Signature> generateBridgesForFunctionDescriptor(
|
fun <Signature> generateBridgesForFunctionDescriptor(
|
||||||
descriptor: FunctionDescriptor,
|
descriptor: FunctionDescriptor,
|
||||||
signature: (FunctionDescriptor) -> Signature,
|
signature: (FunctionDescriptor) -> Signature,
|
||||||
isBodyOwner: (DeclarationDescriptor) -> Boolean
|
areDeclarationAndDefinitionSame: (CallableMemberDescriptor) -> Boolean
|
||||||
): Set<Bridge<Signature>> {
|
): Set<Bridge<Signature>> {
|
||||||
return generateBridges(DescriptorBasedFunctionHandle(descriptor, isBodyOwner), { signature(it.descriptor) })
|
return generateBridges(DescriptorBasedFunctionHandle(descriptor, areDeclarationAndDefinitionSame), { signature(it.descriptor) })
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -51,26 +49,28 @@ fun <Signature> generateBridgesForFunctionDescriptor(
|
|||||||
* eases the process of determining what bridges are already generated in our supertypes and need to be inherited, not regenerated.
|
* eases the process of determining what bridges are already generated in our supertypes and need to be inherited, not regenerated.
|
||||||
*/
|
*/
|
||||||
class DescriptorBasedFunctionHandle(
|
class DescriptorBasedFunctionHandle(
|
||||||
val descriptor: FunctionDescriptor,
|
val descriptor: FunctionDescriptor,
|
||||||
/*
|
/*
|
||||||
To generate proper bridges for non-abstract function
|
To generate proper bridges for non-abstract function
|
||||||
we should know if the function declaration and its definition in the target platform are the same or not.
|
we should know if the function declaration and its definition in the target platform are the same or not.
|
||||||
For JS and JVM8 they are placed in interface classes and we need generate bridge for such function ('isAbstract' will return false).
|
For JS and @JvmDefault JVM members they are placed in interface classes and
|
||||||
For JVM6 target function body generated in separate place (DefaultImpl) and method in interface is abstract
|
we need generate bridge for such function ('isAbstract' will return false).
|
||||||
For JVM6 target function body is generated in a separate place (DefaultImpls) and
|
For non-@JvmDefault function, its body is generated in a separate place (DefaultImpls) and
|
||||||
the method in the interface is abstract so we must not generate bridges for such cases.
|
the method in the interface is abstract so we must not generate bridges for such cases.
|
||||||
*/
|
*/
|
||||||
isBodyOwner: (DeclarationDescriptor) -> Boolean
|
areDeclarationAndDefinitionSame: (CallableMemberDescriptor) -> Boolean
|
||||||
) : FunctionHandle {
|
) : FunctionHandle {
|
||||||
private val overridden = descriptor.overriddenDescriptors.map { DescriptorBasedFunctionHandle(it.original, isBodyOwner) }
|
private val overridden = descriptor.overriddenDescriptors.map {
|
||||||
|
DescriptorBasedFunctionHandle(
|
||||||
|
it.original,
|
||||||
|
areDeclarationAndDefinitionSame
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override val isDeclaration: Boolean =
|
override val isDeclaration: Boolean = descriptor.kind.isReal || findInterfaceImplementation(descriptor) != null
|
||||||
descriptor.kind.isReal ||
|
|
||||||
findInterfaceImplementation(descriptor) != null
|
|
||||||
|
|
||||||
override val isAbstract: Boolean =
|
override val isAbstract: Boolean =
|
||||||
descriptor.modality == Modality.ABSTRACT ||
|
descriptor.modality == Modality.ABSTRACT || !areDeclarationAndDefinitionSame(descriptor)
|
||||||
isBodyOwner(descriptor.containingDeclaration)
|
|
||||||
|
|
||||||
override val isInterfaceDeclaration: Boolean
|
override val isInterfaceDeclaration: Boolean
|
||||||
get() = DescriptorUtils.isInterface(descriptor.containingDeclaration)
|
get() = DescriptorUtils.isInterface(descriptor.containingDeclaration)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.codegen.coroutines.CoroutineCodegenUtilKt;
|
|||||||
import org.jetbrains.kotlin.codegen.coroutines.SuspendFunctionGenerationStrategy;
|
import org.jetbrains.kotlin.codegen.coroutines.SuspendFunctionGenerationStrategy;
|
||||||
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
import org.jetbrains.kotlin.codegen.state.GenerationState;
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||||
|
import org.jetbrains.kotlin.config.JvmTarget;
|
||||||
import org.jetbrains.kotlin.descriptors.*;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated;
|
import org.jetbrains.kotlin.descriptors.annotations.Annotated;
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor;
|
||||||
@@ -74,6 +75,7 @@ import static org.jetbrains.kotlin.descriptors.annotations.AnnotationUtilKt.isEf
|
|||||||
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor;
|
import static org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor;
|
||||||
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
import static org.jetbrains.kotlin.resolve.DescriptorUtils.*;
|
||||||
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
|
import static org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE;
|
||||||
|
import static org.jetbrains.kotlin.resolve.jvm.annotations.AnnotationUtilKt.hasJvmDefaultAnnotation;
|
||||||
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*;
|
import static org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils.*;
|
||||||
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||||
|
|
||||||
@@ -85,10 +87,12 @@ public class FunctionCodegen {
|
|||||||
private final ClassBuilder v;
|
private final ClassBuilder v;
|
||||||
private final MemberCodegen<?> memberCodegen;
|
private final MemberCodegen<?> memberCodegen;
|
||||||
|
|
||||||
private final Function1<DeclarationDescriptor, Boolean> IS_PURE_INTERFACE_CHECKER = new Function1<DeclarationDescriptor, Boolean>() {
|
private final Function1<CallableMemberDescriptor, Boolean> DECLARATION_AND_DEFINITION_CHECKER = new Function1<CallableMemberDescriptor, Boolean>() {
|
||||||
@Override
|
@Override
|
||||||
public Boolean invoke(DeclarationDescriptor descriptor) {
|
public Boolean invoke(CallableMemberDescriptor descriptor) {
|
||||||
return JvmCodegenUtil.isInterfaceWithoutDefaults(descriptor, state);
|
return !isInterface(descriptor.getContainingDeclaration()) ||
|
||||||
|
(state.getTarget() != JvmTarget.JVM_1_6 &&
|
||||||
|
hasJvmDefaultAnnotation(descriptor));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -938,14 +942,14 @@ public class FunctionCodegen {
|
|||||||
private boolean hasSpecialBridgeMethod(@NotNull FunctionDescriptor descriptor) {
|
private boolean hasSpecialBridgeMethod(@NotNull FunctionDescriptor descriptor) {
|
||||||
if (SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor) == null) return false;
|
if (SpecialBuiltinMembers.getOverriddenBuiltinReflectingJvmDescriptor(descriptor) == null) return false;
|
||||||
return !BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(
|
return !BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(
|
||||||
descriptor, typeMapper::mapAsmMethod, IS_PURE_INTERFACE_CHECKER
|
descriptor, typeMapper::mapAsmMethod, DECLARATION_AND_DEFINITION_CHECKER
|
||||||
).isEmpty();
|
).isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void generateBridges(@NotNull FunctionDescriptor descriptor) {
|
public void generateBridges(@NotNull FunctionDescriptor descriptor) {
|
||||||
if (descriptor instanceof ConstructorDescriptor) return;
|
if (descriptor instanceof ConstructorDescriptor) return;
|
||||||
if (owner.getContextKind() == OwnerKind.DEFAULT_IMPLS) return;
|
if (owner.getContextKind() == OwnerKind.DEFAULT_IMPLS) return;
|
||||||
if (IS_PURE_INTERFACE_CHECKER.invoke(descriptor.getContainingDeclaration())) return;
|
if (!DECLARATION_AND_DEFINITION_CHECKER.invoke(descriptor)) return;
|
||||||
|
|
||||||
// equals(Any?), hashCode(), toString() never need bridges
|
// equals(Any?), hashCode(), toString() never need bridges
|
||||||
if (isMethodOfAny(descriptor)) return;
|
if (isMethodOfAny(descriptor)) return;
|
||||||
@@ -955,7 +959,7 @@ public class FunctionCodegen {
|
|||||||
Set<Bridge<Method>> bridgesToGenerate;
|
Set<Bridge<Method>> bridgesToGenerate;
|
||||||
if (!isSpecial) {
|
if (!isSpecial) {
|
||||||
bridgesToGenerate =
|
bridgesToGenerate =
|
||||||
ImplKt.generateBridgesForFunctionDescriptor(descriptor, typeMapper::mapAsmMethod, IS_PURE_INTERFACE_CHECKER);
|
ImplKt.generateBridgesForFunctionDescriptor(descriptor, typeMapper::mapAsmMethod, DECLARATION_AND_DEFINITION_CHECKER);
|
||||||
if (!bridgesToGenerate.isEmpty()) {
|
if (!bridgesToGenerate.isEmpty()) {
|
||||||
PsiElement origin = descriptor.getKind() == DECLARATION ? getSourceFromDescriptor(descriptor) : null;
|
PsiElement origin = descriptor.getKind() == DECLARATION ? getSourceFromDescriptor(descriptor) : null;
|
||||||
boolean isSpecialBridge =
|
boolean isSpecialBridge =
|
||||||
@@ -968,7 +972,7 @@ public class FunctionCodegen {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Set<BridgeForBuiltinSpecial<Method>> specials = BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(
|
Set<BridgeForBuiltinSpecial<Method>> specials = BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(
|
||||||
descriptor, typeMapper::mapAsmMethod, IS_PURE_INTERFACE_CHECKER
|
descriptor, typeMapper::mapAsmMethod, DECLARATION_AND_DEFINITION_CHECKER
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!specials.isEmpty()) {
|
if (!specials.isEmpty()) {
|
||||||
@@ -1310,7 +1314,7 @@ public class FunctionCodegen {
|
|||||||
iv.invokespecial(parentInternalName, delegateTo.getName(), delegateTo.getDescriptor(), false);
|
iv.invokespecial(parentInternalName, delegateTo.getName(), delegateTo.getDescriptor(), false);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (CodegenUtilKt.hasJvmDefaultAnnotation(descriptor)) {
|
if (hasJvmDefaultAnnotation(descriptor)) {
|
||||||
iv.invokeinterface(v.getThisName(), delegateTo.getName(), delegateTo.getDescriptor());
|
iv.invokeinterface(v.getThisName(), delegateTo.getName(), delegateTo.getDescriptor());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -1478,7 +1482,7 @@ public class FunctionCodegen {
|
|||||||
assert isInterface(containingDeclaration) : "'processInterfaceMethod' method should be called only for interfaces, but: " +
|
assert isInterface(containingDeclaration) : "'processInterfaceMethod' method should be called only for interfaces, but: " +
|
||||||
containingDeclaration;
|
containingDeclaration;
|
||||||
|
|
||||||
if (CodegenUtilKt.hasJvmDefaultAnnotation(memberDescriptor)) {
|
if (hasJvmDefaultAnnotation(memberDescriptor)) {
|
||||||
return kind != OwnerKind.DEFAULT_IMPLS;
|
return kind != OwnerKind.DEFAULT_IMPLS;
|
||||||
} else {
|
} else {
|
||||||
switch (kind) {
|
switch (kind) {
|
||||||
|
|||||||
@@ -1404,7 +1404,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void generateTraitMethods() {
|
private void generateTraitMethods() {
|
||||||
if (isInterfaceWithoutDefaults(descriptor, state)) return;
|
if (isInterface(descriptor)) return;
|
||||||
|
|
||||||
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.getNonPrivateTraitMethods(descriptor).entrySet()) {
|
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.getNonPrivateTraitMethods(descriptor).entrySet()) {
|
||||||
FunctionDescriptor interfaceFun = entry.getKey();
|
FunctionDescriptor interfaceFun = entry.getKey();
|
||||||
|
|||||||
@@ -53,30 +53,6 @@ public class JvmCodegenUtil {
|
|||||||
private JvmCodegenUtil() {
|
private JvmCodegenUtil() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isInterfaceWithoutDefaults(@NotNull DeclarationDescriptor descriptor, @NotNull GenerationState state) {
|
|
||||||
return isInterfaceWithoutDefaults(descriptor, state.isJvm8Target());
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isInterfaceWithoutDefaults(
|
|
||||||
@NotNull DeclarationDescriptor descriptor,
|
|
||||||
boolean isJvm8PlusTarget
|
|
||||||
) {
|
|
||||||
if (!DescriptorUtils.isInterface(descriptor)) return false;
|
|
||||||
|
|
||||||
if (descriptor instanceof DeserializedClassDescriptor) {
|
|
||||||
SourceElement source = ((DeserializedClassDescriptor) descriptor).getSource();
|
|
||||||
if (source instanceof KotlinJvmBinarySourceElement) {
|
|
||||||
KotlinJvmBinaryClass binaryClass = ((KotlinJvmBinarySourceElement) source).getBinaryClass();
|
|
||||||
assert binaryClass instanceof FileBasedKotlinClass :
|
|
||||||
"KotlinJvmBinaryClass should be subclass of FileBasedKotlinClass, but " + binaryClass;
|
|
||||||
return ((FileBasedKotlinClass) binaryClass).getClassVersion() == Opcodes.V1_6;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//we can't determine is interface have default methods or not
|
|
||||||
//we need inspect all methods for jvm target 1.8+
|
|
||||||
return !isJvm8PlusTarget;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean isNonDefaultInterfaceMember(@NotNull CallableMemberDescriptor descriptor) {
|
public static boolean isNonDefaultInterfaceMember(@NotNull CallableMemberDescriptor descriptor) {
|
||||||
if (!isJvmInterface(descriptor.getContainingDeclaration())) {
|
if (!isJvmInterface(descriptor.getContainingDeclaration())) {
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import org.jetbrains.kotlin.backend.common.bridges.DescriptorBasedFunctionHandle
|
|||||||
import org.jetbrains.kotlin.backend.common.bridges.findAllReachableDeclarations
|
import org.jetbrains.kotlin.backend.common.bridges.findAllReachableDeclarations
|
||||||
import org.jetbrains.kotlin.backend.common.bridges.findConcreteSuperDeclaration
|
import org.jetbrains.kotlin.backend.common.bridges.findConcreteSuperDeclaration
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
||||||
@@ -45,16 +44,16 @@ class BridgeForBuiltinSpecial<out Signature : Any>(
|
|||||||
|
|
||||||
object BuiltinSpecialBridgesUtil {
|
object BuiltinSpecialBridgesUtil {
|
||||||
@JvmStatic fun <Signature : Any> generateBridgesForBuiltinSpecial(
|
@JvmStatic fun <Signature : Any> generateBridgesForBuiltinSpecial(
|
||||||
function: FunctionDescriptor,
|
function: FunctionDescriptor,
|
||||||
signatureByDescriptor: (FunctionDescriptor) -> Signature,
|
signatureByDescriptor: (FunctionDescriptor) -> Signature,
|
||||||
isBodyOwner: (DeclarationDescriptor) -> Boolean
|
areDeclarationAndDefinitionSame: (CallableMemberDescriptor) -> Boolean
|
||||||
): Set<BridgeForBuiltinSpecial<Signature>> {
|
): Set<BridgeForBuiltinSpecial<Signature>> {
|
||||||
|
|
||||||
val functionHandle = DescriptorBasedFunctionHandle(function, isBodyOwner)
|
val functionHandle = DescriptorBasedFunctionHandle(function, areDeclarationAndDefinitionSame)
|
||||||
val fake = !functionHandle.isDeclaration
|
val fake = !functionHandle.isDeclaration
|
||||||
val overriddenBuiltin = function.getOverriddenBuiltinReflectingJvmDescriptor()!!
|
val overriddenBuiltin = function.getOverriddenBuiltinReflectingJvmDescriptor()!!
|
||||||
|
|
||||||
val reachableDeclarations = findAllReachableDeclarations(function, isBodyOwner)
|
val reachableDeclarations = findAllReachableDeclarations(function, areDeclarationAndDefinitionSame)
|
||||||
|
|
||||||
// e.g. `getSize()I`
|
// e.g. `getSize()I`
|
||||||
val methodItself = signatureByDescriptor(function)
|
val methodItself = signatureByDescriptor(function)
|
||||||
@@ -78,8 +77,10 @@ object BuiltinSpecialBridgesUtil {
|
|||||||
|
|
||||||
if (fake) {
|
if (fake) {
|
||||||
for (overridden in function.overriddenDescriptors.map { it.original }) {
|
for (overridden in function.overriddenDescriptors.map { it.original }) {
|
||||||
if (!DescriptorBasedFunctionHandle(overridden, isBodyOwner).isAbstract) {
|
if (!DescriptorBasedFunctionHandle(overridden, areDeclarationAndDefinitionSame).isAbstract) {
|
||||||
commonBridges.removeAll(findAllReachableDeclarations(overridden, isBodyOwner).map(signatureByDescriptor))
|
commonBridges.removeAll(findAllReachableDeclarations(overridden,
|
||||||
|
areDeclarationAndDefinitionSame
|
||||||
|
).map(signatureByDescriptor))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -88,7 +89,7 @@ object BuiltinSpecialBridgesUtil {
|
|||||||
|
|
||||||
val superImplementationDescriptor =
|
val superImplementationDescriptor =
|
||||||
if (specialBridge != null && fake && !functionHandle.isAbstract)
|
if (specialBridge != null && fake && !functionHandle.isAbstract)
|
||||||
findSuperImplementationForStubDelegation(function, isBodyOwner, signatureByDescriptor)
|
findSuperImplementationForStubDelegation(function, areDeclarationAndDefinitionSame, signatureByDescriptor)
|
||||||
else
|
else
|
||||||
null
|
null
|
||||||
|
|
||||||
@@ -137,11 +138,11 @@ object BuiltinSpecialBridgesUtil {
|
|||||||
* Also note that there is no special bridges for final declarations, thus no stubs either
|
* Also note that there is no special bridges for final declarations, thus no stubs either
|
||||||
*/
|
*/
|
||||||
private fun <Signature> findSuperImplementationForStubDelegation(
|
private fun <Signature> findSuperImplementationForStubDelegation(
|
||||||
function: FunctionDescriptor,
|
function: FunctionDescriptor,
|
||||||
isBodyOwner: (DeclarationDescriptor) -> Boolean,
|
areDeclarationAndDefinitionSame: (CallableMemberDescriptor) -> Boolean,
|
||||||
signatureByDescriptor: (FunctionDescriptor) -> Signature
|
signatureByDescriptor: (FunctionDescriptor) -> Signature
|
||||||
): FunctionDescriptor? {
|
): FunctionDescriptor? {
|
||||||
val implementation = findConcreteSuperDeclaration(DescriptorBasedFunctionHandle(function, isBodyOwner)).descriptor
|
val implementation = findConcreteSuperDeclaration(DescriptorBasedFunctionHandle(function, areDeclarationAndDefinitionSame)).descriptor
|
||||||
|
|
||||||
// Implementation from interface will be generated by common mechanism
|
// Implementation from interface will be generated by common mechanism
|
||||||
if (DescriptorUtils.isInterface(implementation.containingDeclaration)) return null
|
if (DescriptorUtils.isInterface(implementation.containingDeclaration)) return null
|
||||||
@@ -157,10 +158,15 @@ private fun <Signature> findSuperImplementationForStubDelegation(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun findAllReachableDeclarations(
|
private fun findAllReachableDeclarations(
|
||||||
functionDescriptor: FunctionDescriptor,
|
functionDescriptor: FunctionDescriptor,
|
||||||
isBodyOwner: (DeclarationDescriptor) -> Boolean
|
areDeclarationAndDefinitionSame: (CallableMemberDescriptor) -> Boolean
|
||||||
): MutableSet<FunctionDescriptor> =
|
): MutableSet<FunctionDescriptor> =
|
||||||
findAllReachableDeclarations(DescriptorBasedFunctionHandle(functionDescriptor, isBodyOwner)).map { it.descriptor }.toMutableSet()
|
findAllReachableDeclarations(
|
||||||
|
DescriptorBasedFunctionHandle(
|
||||||
|
functionDescriptor,
|
||||||
|
areDeclarationAndDefinitionSame
|
||||||
|
)
|
||||||
|
).map { it.descriptor }.toMutableSet()
|
||||||
|
|
||||||
private fun <Signature> CallableMemberDescriptor.getSpecialBridgeSignatureIfExists(
|
private fun <Signature> CallableMemberDescriptor.getSpecialBridgeSignatureIfExists(
|
||||||
signatureByDescriptor: (FunctionDescriptor) -> Signature
|
signatureByDescriptor: (FunctionDescriptor) -> Signature
|
||||||
|
|||||||
+8
-6
@@ -34,11 +34,11 @@ import org.jetbrains.kotlin.codegen.AsmUtil.isAbstractMethod
|
|||||||
import org.jetbrains.kotlin.codegen.BuiltinSpecialBridgesUtil
|
import org.jetbrains.kotlin.codegen.BuiltinSpecialBridgesUtil
|
||||||
import org.jetbrains.kotlin.codegen.FunctionCodegen.isMethodOfAny
|
import org.jetbrains.kotlin.codegen.FunctionCodegen.isMethodOfAny
|
||||||
import org.jetbrains.kotlin.codegen.FunctionCodegen.isThereOverriddenInKotlinClass
|
import org.jetbrains.kotlin.codegen.FunctionCodegen.isThereOverriddenInKotlinClass
|
||||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil
|
|
||||||
import org.jetbrains.kotlin.codegen.JvmCodegenUtil.getDirectMember
|
import org.jetbrains.kotlin.codegen.JvmCodegenUtil.getDirectMember
|
||||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||||
import org.jetbrains.kotlin.codegen.descriptors.FileClassDescriptor
|
import org.jetbrains.kotlin.codegen.descriptors.FileClassDescriptor
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper
|
||||||
|
import org.jetbrains.kotlin.config.JvmTarget
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION
|
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
||||||
@@ -60,7 +60,9 @@ import org.jetbrains.kotlin.load.java.getOverriddenBuiltinReflectingJvmDescripto
|
|||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils.getSourceFromDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
|
import org.jetbrains.kotlin.resolve.DescriptorUtils.isInterface
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes.OBJECT_TYPE
|
||||||
|
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmDefaultAnnotation
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes
|
import org.jetbrains.org.objectweb.asm.Opcodes
|
||||||
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
import org.jetbrains.org.objectweb.asm.Opcodes.*
|
||||||
@@ -73,12 +75,12 @@ class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
|||||||
|
|
||||||
private val typeMapper = state.typeMapper
|
private val typeMapper = state.typeMapper
|
||||||
|
|
||||||
private val IS_PURE_INTERFACE_CHECKER = fun(descriptor: DeclarationDescriptor): Boolean =
|
private val DECLARATION_AND_DEFINITION_CHECKER = fun(descriptor: CallableMemberDescriptor): Boolean =
|
||||||
JvmCodegenUtil.isInterfaceWithoutDefaults(descriptor, state)
|
!isInterface(descriptor.containingDeclaration) || state.target !== JvmTarget.JVM_1_6 && descriptor.hasJvmDefaultAnnotation()
|
||||||
|
|
||||||
override fun lower(irClass: IrClass) {
|
override fun lower(irClass: IrClass) {
|
||||||
val classDescriptor = irClass.descriptor
|
val classDescriptor = irClass.descriptor
|
||||||
if (IS_PURE_INTERFACE_CHECKER(classDescriptor) || classDescriptor is FileClassDescriptor) return
|
if (classDescriptor is FileClassDescriptor) return
|
||||||
|
|
||||||
if (classDescriptor is DefaultImplsClassDescriptor) {
|
if (classDescriptor is DefaultImplsClassDescriptor) {
|
||||||
return /*TODO?*/
|
return /*TODO?*/
|
||||||
@@ -133,7 +135,7 @@ class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
|||||||
bridgesToGenerate = generateBridgesForFunctionDescriptor(
|
bridgesToGenerate = generateBridgesForFunctionDescriptor(
|
||||||
descriptor,
|
descriptor,
|
||||||
getSignatureMapper(typeMapper),
|
getSignatureMapper(typeMapper),
|
||||||
IS_PURE_INTERFACE_CHECKER
|
DECLARATION_AND_DEFINITION_CHECKER
|
||||||
)
|
)
|
||||||
if (!bridgesToGenerate.isEmpty()) {
|
if (!bridgesToGenerate.isEmpty()) {
|
||||||
val origin = if (descriptor.kind == DECLARATION) getSourceFromDescriptor(descriptor) else null
|
val origin = if (descriptor.kind == DECLARATION) getSourceFromDescriptor(descriptor) else null
|
||||||
@@ -148,7 +150,7 @@ class BridgeLowering(val context: JvmBackendContext) : ClassLoweringPass {
|
|||||||
val specials = BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(
|
val specials = BuiltinSpecialBridgesUtil.generateBridgesForBuiltinSpecial(
|
||||||
descriptor,
|
descriptor,
|
||||||
getSignatureMapper(typeMapper),
|
getSignatureMapper(typeMapper),
|
||||||
IS_PURE_INTERFACE_CHECKER
|
DECLARATION_AND_DEFINITION_CHECKER
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!specials.isEmpty()) {
|
if (!specials.isEmpty()) {
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
interface Test<T> {
|
||||||
|
fun test(p: T): T {
|
||||||
|
return null!!
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(p: T): T {
|
||||||
|
return null!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Test2: Test<String> {
|
||||||
|
override fun test(p: String): String {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun foo(p: String): String {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestClass : Test2
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
checkNoMethod(Test2::class.java, "foo", Any::class.java)
|
||||||
|
checkNoMethod(Test2::class.java, "test", Any::class.java)
|
||||||
|
|
||||||
|
checkMethodExists(TestClass::class.java, "test", Any::class.java)
|
||||||
|
checkMethodExists(TestClass::class.java, "test", String::class.java)
|
||||||
|
checkMethodExists(TestClass::class.java, "foo", Any::class.java)
|
||||||
|
checkMethodExists(TestClass::class.java, "foo", String::class.java)
|
||||||
|
|
||||||
|
|
||||||
|
val test2DefaultImpls = java.lang.Class.forName("Test2\$DefaultImpls")
|
||||||
|
checkMethodExists(test2DefaultImpls, "test", Test2::class.java, String::class.java)
|
||||||
|
checkMethodExists(test2DefaultImpls, "foo", Test2::class.java, String::class.java)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkNoMethod(clazz: Class<*>, name: String, vararg parameterTypes: Class<*>) {
|
||||||
|
try {
|
||||||
|
clazz.getDeclaredMethod(name, *parameterTypes)
|
||||||
|
}
|
||||||
|
catch (e: NoSuchMethodException) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
throw AssertionError("fail: method $name was found in " + clazz)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkMethodExists(clazz: Class<*>, name: String, vararg parameterTypes: Class<*>) {
|
||||||
|
try {
|
||||||
|
clazz.getDeclaredMethod(name, *parameterTypes)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
catch (e: NoSuchMethodException) {
|
||||||
|
throw AssertionError("fail: method $name was not found in " + clazz, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// TARGET_BACKEND: JVM
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
interface Test<T> {
|
||||||
|
var T.foo: T
|
||||||
|
get() = null!!
|
||||||
|
set(value) {
|
||||||
|
null!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Test2 : Test<String> {
|
||||||
|
|
||||||
|
override var String.foo: String
|
||||||
|
get() = ""
|
||||||
|
set(value) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestClass : Test2
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
checkNoMethod(Test2::class.java, "setFoo", Any::class.java, Any::class.java)
|
||||||
|
|
||||||
|
checkMethodExists(TestClass::class.java, "getFoo", String::class.java)
|
||||||
|
checkMethodExists(TestClass::class.java, "getFoo", Any::class.java)
|
||||||
|
checkMethodExists(TestClass::class.java, "setFoo", Any::class.java, Any::class.java)
|
||||||
|
checkMethodExists(TestClass::class.java, "setFoo", String::class.java, String::class.java)
|
||||||
|
|
||||||
|
val test2DefaultImpls = java.lang.Class.forName("Test2\$DefaultImpls")
|
||||||
|
checkMethodExists(test2DefaultImpls, "getFoo", Test2::class.java, String::class.java)
|
||||||
|
checkMethodExists(test2DefaultImpls, "setFoo", Test2::class.java, String::class.java, String::class.java)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkNoMethod(clazz: Class<*>, name: String, vararg parameterTypes: Class<*>) {
|
||||||
|
try {
|
||||||
|
clazz.getDeclaredMethod(name, *parameterTypes)
|
||||||
|
}
|
||||||
|
catch (e: NoSuchMethodException) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
throw AssertionError("fail: method $name was found in " + clazz)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkMethodExists(clazz: Class<*>, name: String, vararg parameterTypes: Class<*>) {
|
||||||
|
try {
|
||||||
|
clazz.getDeclaredMethod(name, *parameterTypes)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
catch (e: NoSuchMethodException) {
|
||||||
|
throw AssertionError("fail: method $name was not found in " + clazz, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
// !API_VERSION: 1.3
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
interface Test<T> {
|
||||||
|
@kotlin.annotations.JvmDefault
|
||||||
|
fun test(p: T): T {
|
||||||
|
return null!!
|
||||||
|
}
|
||||||
|
|
||||||
|
fun foo(p: T): T {
|
||||||
|
return null!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Test2: Test<String> {
|
||||||
|
@kotlin.annotations.JvmDefault
|
||||||
|
override fun test(p: String): String {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun foo(p: String): String {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestClass : Test2
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
checkNoMethod(Test2::class.java, "foo", Any::class.java)
|
||||||
|
checkMethodExists(Test2::class.java, "test", Any::class.java)
|
||||||
|
|
||||||
|
checkNoMethod(TestClass::class.java, "test", Any::class.java)
|
||||||
|
checkMethodExists(TestClass::class.java, "foo", String::class.java)
|
||||||
|
checkMethodExists(TestClass::class.java, "foo", Any::class.java)
|
||||||
|
|
||||||
|
|
||||||
|
val test2DefaultImpls = java.lang.Class.forName("Test2\$DefaultImpls")
|
||||||
|
checkNoMethod(test2DefaultImpls, "test", Any::class.java)
|
||||||
|
checkNoMethod(test2DefaultImpls, "test", String::class.java)
|
||||||
|
checkMethodExists(test2DefaultImpls, "foo", Test2::class.java, String::class.java)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkNoMethod(clazz: Class<*>, name: String, vararg parameterTypes: Class<*>) {
|
||||||
|
try {
|
||||||
|
clazz.getDeclaredMethod(name, *parameterTypes)
|
||||||
|
}
|
||||||
|
catch (e: NoSuchMethodException) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
throw AssertionError("fail: method $name was found in " + clazz)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkMethodExists(clazz: Class<*>, name: String, vararg parameterTypes: Class<*>) {
|
||||||
|
try {
|
||||||
|
clazz.getDeclaredMethod(name, *parameterTypes)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
catch (e: NoSuchMethodException) {
|
||||||
|
throw AssertionError("fail: method $name was not found in " + clazz, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
// !API_VERSION: 1.3
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// WITH_RUNTIME
|
||||||
|
|
||||||
|
interface Test<T> {
|
||||||
|
@kotlin.annotations.JvmDefault
|
||||||
|
var test: T
|
||||||
|
get() = null!!
|
||||||
|
set(value) {
|
||||||
|
null!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var result = "fail"
|
||||||
|
|
||||||
|
interface Test2 : Test<String> {
|
||||||
|
@kotlin.annotations.JvmDefault
|
||||||
|
override var test: String
|
||||||
|
get() = result
|
||||||
|
set(value) {
|
||||||
|
result = value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestClass : Test2
|
||||||
|
|
||||||
|
fun <T> execute(t: Test<T>, p: T): T {
|
||||||
|
t.test = p
|
||||||
|
return t.test
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return execute(TestClass(), "OK")
|
||||||
|
}
|
||||||
+80
@@ -0,0 +1,80 @@
|
|||||||
|
// !API_VERSION: 1.3
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// FULL_JDK
|
||||||
|
|
||||||
|
interface Test<T> {
|
||||||
|
@kotlin.annotations.JvmDefault
|
||||||
|
var T.test: T
|
||||||
|
get() = null!!
|
||||||
|
set(value) {
|
||||||
|
null!!
|
||||||
|
}
|
||||||
|
|
||||||
|
var T.foo: T
|
||||||
|
get() = null!!
|
||||||
|
set(value) {
|
||||||
|
null!!
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Test2 : Test<String> {
|
||||||
|
@kotlin.annotations.JvmDefault
|
||||||
|
override var String.test: String
|
||||||
|
get() = ""
|
||||||
|
set(value) {}
|
||||||
|
|
||||||
|
override var String.foo: String
|
||||||
|
get() = ""
|
||||||
|
set(value) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestClass : Test2
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
checkMethodExists(Test2::class.java, "getTest", String::class.java)
|
||||||
|
checkMethodExists(Test2::class.java, "getTest", Any::class.java)
|
||||||
|
checkMethodExists(Test2::class.java, "setTest", Any::class.java, Any::class.java)
|
||||||
|
checkMethodExists(Test2::class.java, "setTest", String::class.java, String::class.java)
|
||||||
|
|
||||||
|
checkNoMethod(Test2::class.java, "setFoo", Any::class.java, Any::class.java)
|
||||||
|
|
||||||
|
checkNoMethod(TestClass::class.java, "getTest", String::class.java)
|
||||||
|
checkNoMethod(TestClass::class.java, "getTest", Any::class.java)
|
||||||
|
checkNoMethod(TestClass::class.java, "setTest", Any::class.java, Any::class.java)
|
||||||
|
checkNoMethod(TestClass::class.java, "setTest", String::class.java, String::class.java)
|
||||||
|
|
||||||
|
checkMethodExists(TestClass::class.java, "getFoo", String::class.java)
|
||||||
|
checkMethodExists(TestClass::class.java, "getFoo", Any::class.java)
|
||||||
|
checkMethodExists(TestClass::class.java, "setFoo", Any::class.java, Any::class.java)
|
||||||
|
checkMethodExists(TestClass::class.java, "setFoo", String::class.java, String::class.java)
|
||||||
|
|
||||||
|
val test2DefaultImpls = java.lang.Class.forName("Test2\$DefaultImpls")
|
||||||
|
checkNoMethod(test2DefaultImpls, "getTest", String::class.java)
|
||||||
|
checkNoMethod(test2DefaultImpls, "getTest", Any::class.java)
|
||||||
|
checkNoMethod(test2DefaultImpls, "setTest", Any::class.java, Any::class.java)
|
||||||
|
checkNoMethod(test2DefaultImpls, "setTest", String::class.java, String::class.java)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkNoMethod(clazz: Class<*>, name: String, vararg parameterTypes: Class<*>) {
|
||||||
|
try {
|
||||||
|
clazz.getDeclaredMethod(name, *parameterTypes)
|
||||||
|
}
|
||||||
|
catch (e: NoSuchMethodException) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
throw AssertionError("fail: method $name was found in " + clazz)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkMethodExists(clazz: Class<*>, name: String, vararg parameterTypes: Class<*>) {
|
||||||
|
try {
|
||||||
|
clazz.getDeclaredMethod(name, *parameterTypes)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
catch (e: NoSuchMethodException) {
|
||||||
|
throw AssertionError("fail: method $name was not found in " + clazz, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
// !API_VERSION: 1.3
|
||||||
|
// JVM_TARGET: 1.8
|
||||||
|
// WITH_RUNTIME
|
||||||
|
// FULL_JDK
|
||||||
|
// FILE: Test.java
|
||||||
|
public interface Test<T> {
|
||||||
|
default T test(T p) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: kotlin.kt
|
||||||
|
|
||||||
|
interface Test2: Test<String> {
|
||||||
|
@kotlin.annotations.JvmDefault
|
||||||
|
override fun test(p: String): String {
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
fun forDefaultImpls() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TestClass : Test2
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
checkMethodExists(Test2::class.java, "test", String::class.java)
|
||||||
|
checkMethodExists(Test2::class.java, "test", Any::class.java)
|
||||||
|
|
||||||
|
checkNoMethod(TestClass::class.java, "test", String::class.java)
|
||||||
|
checkNoMethod(TestClass::class.java, "test", Any::class.java)
|
||||||
|
|
||||||
|
val test2DefaultImpls = java.lang.Class.forName("Test2\$DefaultImpls")
|
||||||
|
checkNoMethod(test2DefaultImpls, "test", Any::class.java)
|
||||||
|
checkNoMethod(test2DefaultImpls, "test", String::class.java)
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkNoMethod(clazz: Class<*>, name: String, vararg parameterTypes: Class<*>) {
|
||||||
|
try {
|
||||||
|
clazz.getDeclaredMethod(name, *parameterTypes)
|
||||||
|
}
|
||||||
|
catch (e: NoSuchMethodException) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
throw AssertionError("fail: method $name was found in " + clazz)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun checkMethodExists(clazz: Class<*>, name: String, vararg parameterTypes: Class<*>) {
|
||||||
|
try {
|
||||||
|
clazz.getDeclaredMethod(name, *parameterTypes)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
catch (e: NoSuchMethodException) {
|
||||||
|
throw AssertionError("fail: method $name was not found in " + clazz, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -43,7 +43,7 @@ fun box(): String {
|
|||||||
|
|
||||||
fun checkNoMethod(clazz: Class<*>, name: String) {
|
fun checkNoMethod(clazz: Class<*>, name: String) {
|
||||||
try {
|
try {
|
||||||
clazz.getDeclaredMethod("test")
|
clazz.getDeclaredMethod(name)
|
||||||
}
|
}
|
||||||
catch (e: NoSuchMethodException) {
|
catch (e: NoSuchMethodException) {
|
||||||
return
|
return
|
||||||
|
|||||||
Generated
+12
@@ -1127,6 +1127,18 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/bridges"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/bridges"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("bridgeInInterface.kt")
|
||||||
|
public void testBridgeInInterface() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/bridgeInInterface.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("bridgeInInterfaceWithProperties.kt")
|
||||||
|
public void testBridgeInInterfaceWithProperties() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/bridgeInInterfaceWithProperties.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("complexMultiInheritance.kt")
|
@TestMetadata("complexMultiInheritance.kt")
|
||||||
public void testComplexMultiInheritance() throws Exception {
|
public void testComplexMultiInheritance() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/complexMultiInheritance.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/complexMultiInheritance.kt");
|
||||||
|
|||||||
Generated
+24
@@ -371,6 +371,30 @@ public class BlackBoxWithJava8CodegenTestGenerated extends AbstractBlackBoxCodeg
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("bridgeInInterface2.kt")
|
||||||
|
public void testBridgeInInterface2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/jvm8/defaults/bridgeInInterface2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("bridgeInInterfaceWithProperties.kt")
|
||||||
|
public void testBridgeInInterfaceWithProperties() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/jvm8/defaults/bridgeInInterfaceWithProperties.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("bridgeInInterfaceWithProperties2.kt")
|
||||||
|
public void testBridgeInInterfaceWithProperties2() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/jvm8/defaults/bridgeInInterfaceWithProperties2.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("bridgeWithJava.kt")
|
||||||
|
public void testBridgeWithJava() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/jvm8/defaults/bridgeWithJava.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("callableReference.kt")
|
@TestMetadata("callableReference.kt")
|
||||||
public void testCallableReference() throws Exception {
|
public void testCallableReference() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/jvm8/defaults/callableReference.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/java8/box/jvm8/defaults/callableReference.kt");
|
||||||
|
|||||||
+12
@@ -1127,6 +1127,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/bridges"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/bridges"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("bridgeInInterface.kt")
|
||||||
|
public void testBridgeInInterface() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/bridgeInInterface.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("bridgeInInterfaceWithProperties.kt")
|
||||||
|
public void testBridgeInInterfaceWithProperties() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/bridgeInInterfaceWithProperties.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("complexMultiInheritance.kt")
|
@TestMetadata("complexMultiInheritance.kt")
|
||||||
public void testComplexMultiInheritance() throws Exception {
|
public void testComplexMultiInheritance() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/complexMultiInheritance.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/complexMultiInheritance.kt");
|
||||||
|
|||||||
+12
@@ -1127,6 +1127,18 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/bridges"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/bridges"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JVM, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("bridgeInInterface.kt")
|
||||||
|
public void testBridgeInInterface() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/bridgeInInterface.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("bridgeInInterfaceWithProperties.kt")
|
||||||
|
public void testBridgeInInterfaceWithProperties() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/bridgeInInterfaceWithProperties.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("complexMultiInheritance.kt")
|
@TestMetadata("complexMultiInheritance.kt")
|
||||||
public void testComplexMultiInheritance() throws Exception {
|
public void testComplexMultiInheritance() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/complexMultiInheritance.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/complexMultiInheritance.kt");
|
||||||
|
|||||||
+6
@@ -1471,6 +1471,12 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/bridges"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/box/bridges"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.JS, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("bridgeInInterfaceWithProperties.kt")
|
||||||
|
public void testBridgeInInterfaceWithProperties() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/bridgeInInterfaceWithProperties.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("complexMultiInheritance.kt")
|
@TestMetadata("complexMultiInheritance.kt")
|
||||||
public void testComplexMultiInheritance() throws Exception {
|
public void testComplexMultiInheritance() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/complexMultiInheritance.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/box/bridges/complexMultiInheritance.kt");
|
||||||
|
|||||||
+1
-1
@@ -245,7 +245,7 @@ class ClassModelGenerator(val context: TranslationContext) {
|
|||||||
if (memberDescriptor is FunctionDescriptor) {
|
if (memberDescriptor is FunctionDescriptor) {
|
||||||
val bridgesToGenerate = generateBridgesForFunctionDescriptor(memberDescriptor, identity()) {
|
val bridgesToGenerate = generateBridgesForFunctionDescriptor(memberDescriptor, identity()) {
|
||||||
//There is no DefaultImpls in js backend so if method non-abstract it should be recognized as non-abstract on bridges calculation
|
//There is no DefaultImpls in js backend so if method non-abstract it should be recognized as non-abstract on bridges calculation
|
||||||
false
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
for (bridge in bridgesToGenerate) {
|
for (bridge in bridgesToGenerate) {
|
||||||
|
|||||||
Reference in New Issue
Block a user