Do not treat annotation classes as interfaces in bridges codegen
From Kotlin's point of view, everything in annotation classes is non-abstract. A class inheriting from an annotation has a non-abstract fake override for each property of the annotation class constructor. But because members of annotation classes themselves were considered as abstract in the bridge-generating code (see DescriptorBasedFunctionHandle.isAbstract), there was a situation where a concrete fake override has only one declaration among overridden descriptors and it was abstract. This situation is invalid (a concrete fake override must have exactly one concrete super-declaration), therefore an exception was thrown. The fix is to avoid considering annotation class members abstract for the purposes of bridge generation. It's reasonably safe because no bridges should be ever generated for annotation subclasses anyway, because annotations can only have members with simple return types (final and non-generic). Note that in KT-19928, the problem is reproducible because of an incorrect "inexact analysis" in light classes where "Target" is resolved to an annotation class kotlin.annotation.Target. This behavior of the analysis in light classes seems to do no harm otherwise, so it's not a goal of this commit to change anything in that regard #KT-19928 Fixed
This commit is contained in:
@@ -77,7 +77,6 @@ import java.util.Set;
|
||||
|
||||
import static org.jetbrains.kotlin.builtins.KotlinBuiltIns.isNullableAny;
|
||||
import static org.jetbrains.kotlin.codegen.AsmUtil.*;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isAnnotationOrJvmInterfaceWithoutDefaults;
|
||||
import static org.jetbrains.kotlin.codegen.JvmCodegenUtil.isJvm8InterfaceWithDefaultsMember;
|
||||
import static org.jetbrains.kotlin.codegen.serialization.JvmSerializationBindings.METHOD_FOR_FUNCTION;
|
||||
import static org.jetbrains.kotlin.descriptors.CallableMemberDescriptor.Kind.DECLARATION;
|
||||
@@ -101,7 +100,7 @@ public class FunctionCodegen {
|
||||
private final Function1<DeclarationDescriptor, Boolean> IS_PURE_INTERFACE_CHECKER = new Function1<DeclarationDescriptor, Boolean>() {
|
||||
@Override
|
||||
public Boolean invoke(DeclarationDescriptor descriptor) {
|
||||
return JvmCodegenUtil.isAnnotationOrJvmInterfaceWithoutDefaults(descriptor, state);
|
||||
return JvmCodegenUtil.isInterfaceWithoutDefaults(descriptor, state);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -866,7 +865,7 @@ public class FunctionCodegen {
|
||||
public void generateBridges(@NotNull FunctionDescriptor descriptor) {
|
||||
if (descriptor instanceof ConstructorDescriptor) return;
|
||||
if (owner.getContextKind() == OwnerKind.DEFAULT_IMPLS) return;
|
||||
if (isAnnotationOrJvmInterfaceWithoutDefaults(descriptor.getContainingDeclaration(), state)) return;
|
||||
if (IS_PURE_INTERFACE_CHECKER.invoke(descriptor.getContainingDeclaration())) return;
|
||||
|
||||
// equals(Any?), hashCode(), toString() never need bridges
|
||||
if (isMethodOfAny(descriptor)) return;
|
||||
|
||||
@@ -1338,7 +1338,7 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
}
|
||||
|
||||
private void generateTraitMethods() {
|
||||
if (isAnnotationOrJvmInterfaceWithoutDefaults(descriptor, state)) return;
|
||||
if (isInterfaceWithoutDefaults(descriptor, state)) return;
|
||||
|
||||
List<FunctionDescriptor> restrictedInheritance = new ArrayList<>();
|
||||
for (Map.Entry<FunctionDescriptor, FunctionDescriptor> entry : CodegenUtil.getNonPrivateTraitMethods(descriptor).entrySet()) {
|
||||
|
||||
@@ -42,7 +42,6 @@ import org.jetbrains.kotlin.resolve.BindingContext;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils;
|
||||
import org.jetbrains.kotlin.resolve.DescriptorUtils;
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil;
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmConstantsKt;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedCallableMemberDescriptor;
|
||||
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedClassDescriptor;
|
||||
@@ -63,15 +62,12 @@ public class JvmCodegenUtil {
|
||||
private JvmCodegenUtil() {
|
||||
}
|
||||
|
||||
public static boolean isAnnotationOrJvmInterfaceWithoutDefaults(@NotNull DeclarationDescriptor descriptor, @NotNull GenerationState state) {
|
||||
return isAnnotationOrJvmInterfaceWithoutDefaults(descriptor, state.isJvm8Target(), state.isJvm8TargetWithDefaults());
|
||||
public static boolean isInterfaceWithoutDefaults(@NotNull DeclarationDescriptor descriptor, @NotNull GenerationState state) {
|
||||
return isInterfaceWithoutDefaults(descriptor, state.isJvm8Target(), state.isJvm8TargetWithDefaults());
|
||||
}
|
||||
|
||||
private static boolean isAnnotationOrJvmInterfaceWithoutDefaults(@NotNull DeclarationDescriptor descriptor, boolean isJvm8Target, boolean isJvm8TargetWithDefaults) {
|
||||
if (!isJvmInterface(descriptor)) {
|
||||
return false;
|
||||
}
|
||||
if (ANNOTATION_CLASS == ((ClassDescriptor) descriptor).getKind()) return true;
|
||||
private static boolean isInterfaceWithoutDefaults(@NotNull DeclarationDescriptor descriptor, boolean isJvm8Target, boolean isJvm8TargetWithDefaults) {
|
||||
if (!DescriptorUtils.isInterface(descriptor)) return false;
|
||||
|
||||
if (descriptor instanceof DeserializedClassDescriptor) {
|
||||
SourceElement source = ((DeserializedClassDescriptor) descriptor).getSource();
|
||||
@@ -91,7 +87,7 @@ public class JvmCodegenUtil {
|
||||
}
|
||||
|
||||
public static boolean isJvm8InterfaceWithDefaults(@NotNull DeclarationDescriptor descriptor, boolean isJvm8Target, boolean isJvm8TargetWithDefaults) {
|
||||
return DescriptorUtils.isInterface(descriptor) && !isAnnotationOrJvmInterfaceWithoutDefaults(descriptor, isJvm8Target, isJvm8TargetWithDefaults);
|
||||
return DescriptorUtils.isInterface(descriptor) && !isInterfaceWithoutDefaults(descriptor, isJvm8Target, isJvm8TargetWithDefaults);
|
||||
}
|
||||
|
||||
public static boolean isJvm8InterfaceWithDefaultsMember(@NotNull CallableMemberDescriptor descriptor, @NotNull GenerationState state) {
|
||||
|
||||
Reference in New Issue
Block a user